summaryrefslogtreecommitdiffstats
path: root/sys/compat
diff options
context:
space:
mode:
Diffstat (limited to 'sys/compat')
-rw-r--r--sys/compat/freebsd32/Makefile21
-rw-r--r--sys/compat/freebsd32/freebsd32.h372
-rw-r--r--sys/compat/freebsd32/freebsd32_ioctl.c404
-rw-r--r--sys/compat/freebsd32/freebsd32_ioctl.h126
-rw-r--r--sys/compat/freebsd32/freebsd32_ipc.h160
-rw-r--r--sys/compat/freebsd32/freebsd32_misc.c2900
-rw-r--r--sys/compat/freebsd32/freebsd32_proto.h1151
-rw-r--r--sys/compat/freebsd32/freebsd32_signal.h102
-rw-r--r--sys/compat/freebsd32/freebsd32_syscall.h447
-rw-r--r--sys/compat/freebsd32/freebsd32_syscalls.c576
-rw-r--r--sys/compat/freebsd32/freebsd32_sysent.c613
-rw-r--r--sys/compat/freebsd32/freebsd32_systrace_args.c10486
-rw-r--r--sys/compat/freebsd32/freebsd32_util.h118
-rw-r--r--sys/compat/freebsd32/syscalls.conf11
-rw-r--r--sys/compat/freebsd32/syscalls.master1048
-rw-r--r--sys/compat/ia32/ia32_genassym.c29
-rw-r--r--sys/compat/ia32/ia32_signal.h208
-rw-r--r--sys/compat/ia32/ia32_sysvec.c228
-rw-r--r--sys/compat/ia32/ia32_util.h64
-rw-r--r--sys/compat/linprocfs/linprocfs.c1456
-rw-r--r--sys/compat/linsysfs/linsysfs.c284
-rw-r--r--sys/compat/linux/check_error.d144
-rw-r--r--sys/compat/linux/check_internal_locks.d132
-rw-r--r--sys/compat/linux/linux_dtrace.h95
-rw-r--r--sys/compat/linux/linux_emul.c474
-rw-r--r--sys/compat/linux/linux_emul.h121
-rw-r--r--sys/compat/linux/linux_file.c1617
-rw-r--r--sys/compat/linux/linux_file.h57
-rw-r--r--sys/compat/linux/linux_fork.c300
-rw-r--r--sys/compat/linux/linux_futex.c1228
-rw-r--r--sys/compat/linux/linux_futex.h81
-rw-r--r--sys/compat/linux/linux_getcwd.c469
-rw-r--r--sys/compat/linux/linux_ioctl.c3532
-rw-r--r--sys/compat/linux/linux_ioctl.h767
-rw-r--r--sys/compat/linux/linux_ipc.c899
-rw-r--r--sys/compat/linux/linux_ipc.h182
-rw-r--r--sys/compat/linux/linux_mib.c858
-rw-r--r--sys/compat/linux/linux_mib.h50
-rw-r--r--sys/compat/linux/linux_misc.c1927
-rw-r--r--sys/compat/linux/linux_misc.h125
-rw-r--r--sys/compat/linux/linux_signal.c656
-rw-r--r--sys/compat/linux/linux_signal.h49
-rw-r--r--sys/compat/linux/linux_socket.c1709
-rw-r--r--sys/compat/linux/linux_socket.h159
-rw-r--r--sys/compat/linux/linux_stats.c627
-rw-r--r--sys/compat/linux/linux_sysctl.c194
-rw-r--r--sys/compat/linux/linux_sysproto.h36
-rw-r--r--sys/compat/linux/linux_time.c417
-rw-r--r--sys/compat/linux/linux_uid16.c441
-rw-r--r--sys/compat/linux/linux_util.c333
-rw-r--r--sys/compat/linux/linux_util.h141
-rw-r--r--sys/compat/linux/linux_videodev2_compat.h137
-rw-r--r--sys/compat/linux/linux_videodev_compat.h59
-rw-r--r--sys/compat/linux/stats_timing.d94
-rw-r--r--sys/compat/linux/trace_futexes.d182
-rw-r--r--sys/compat/ndis/cfg_var.h47
-rw-r--r--sys/compat/ndis/hal_var.h53
-rw-r--r--sys/compat/ndis/kern_ndis.c1433
-rw-r--r--sys/compat/ndis/kern_windrv.c988
-rw-r--r--sys/compat/ndis/ndis_var.h1767
-rw-r--r--sys/compat/ndis/ntoskrnl_var.h1529
-rw-r--r--sys/compat/ndis/pe_var.h549
-rw-r--r--sys/compat/ndis/resource_var.h199
-rw-r--r--sys/compat/ndis/subr_hal.c481
-rw-r--r--sys/compat/ndis/subr_ndis.c3371
-rw-r--r--sys/compat/ndis/subr_ntoskrnl.c4457
-rw-r--r--sys/compat/ndis/subr_pe.c642
-rw-r--r--sys/compat/ndis/subr_usbd.c1458
-rw-r--r--sys/compat/ndis/usbd_var.h222
-rw-r--r--sys/compat/ndis/winx32_wrap.S385
-rw-r--r--sys/compat/ndis/winx64_wrap.S179
-rw-r--r--sys/compat/netbsd/dvcfg.h65
-rw-r--r--sys/compat/svr4/Makefile17
-rw-r--r--sys/compat/svr4/imgact_svr4.c238
-rw-r--r--sys/compat/svr4/svr4.h39
-rw-r--r--sys/compat/svr4/svr4_acl.h46
-rw-r--r--sys/compat/svr4/svr4_dirent.h53
-rw-r--r--sys/compat/svr4/svr4_errno.h172
-rw-r--r--sys/compat/svr4/svr4_exec.h70
-rw-r--r--sys/compat/svr4/svr4_fcntl.c724
-rw-r--r--sys/compat/svr4/svr4_fcntl.h134
-rw-r--r--sys/compat/svr4/svr4_filio.c251
-rw-r--r--sys/compat/svr4/svr4_filio.h45
-rw-r--r--sys/compat/svr4/svr4_fuser.h97
-rw-r--r--sys/compat/svr4/svr4_hrt.h87
-rw-r--r--sys/compat/svr4/svr4_ioctl.c163
-rw-r--r--sys/compat/svr4/svr4_ioctl.h60
-rw-r--r--sys/compat/svr4/svr4_ipc.c707
-rw-r--r--sys/compat/svr4/svr4_ipc.h176
-rw-r--r--sys/compat/svr4/svr4_misc.c1658
-rw-r--r--sys/compat/svr4/svr4_mman.h47
-rw-r--r--sys/compat/svr4/svr4_proto.h596
-rw-r--r--sys/compat/svr4/svr4_resource.c321
-rw-r--r--sys/compat/svr4/svr4_resource.h109
-rw-r--r--sys/compat/svr4/svr4_siginfo.h111
-rw-r--r--sys/compat/svr4/svr4_signal.c577
-rw-r--r--sys/compat/svr4/svr4_signal.h144
-rw-r--r--sys/compat/svr4/svr4_socket.c242
-rw-r--r--sys/compat/svr4/svr4_socket.h58
-rw-r--r--sys/compat/svr4/svr4_sockio.c168
-rw-r--r--sys/compat/svr4/svr4_sockio.h93
-rw-r--r--sys/compat/svr4/svr4_sockmod.h83
-rw-r--r--sys/compat/svr4/svr4_stat.c699
-rw-r--r--sys/compat/svr4/svr4_stat.h105
-rw-r--r--sys/compat/svr4/svr4_statvfs.h72
-rw-r--r--sys/compat/svr4/svr4_stream.c2038
-rw-r--r--sys/compat/svr4/svr4_stropts.h179
-rw-r--r--sys/compat/svr4/svr4_syscall.h147
-rw-r--r--sys/compat/svr4/svr4_syscallnames.c260
-rw-r--r--sys/compat/svr4/svr4_sysconfig.h78
-rw-r--r--sys/compat/svr4/svr4_sysent.c272
-rw-r--r--sys/compat/svr4/svr4_systeminfo.h50
-rw-r--r--sys/compat/svr4/svr4_sysvec.c314
-rw-r--r--sys/compat/svr4/svr4_termios.c612
-rw-r--r--sys/compat/svr4/svr4_termios.h224
-rw-r--r--sys/compat/svr4/svr4_time.h41
-rw-r--r--sys/compat/svr4/svr4_timod.h87
-rw-r--r--sys/compat/svr4/svr4_types.h81
-rw-r--r--sys/compat/svr4/svr4_ucontext.h74
-rw-r--r--sys/compat/svr4/svr4_ulimit.h41
-rw-r--r--sys/compat/svr4/svr4_ustat.h43
-rw-r--r--sys/compat/svr4/svr4_util.h64
-rw-r--r--sys/compat/svr4/svr4_utsname.h44
-rw-r--r--sys/compat/svr4/svr4_wait.h56
-rw-r--r--sys/compat/svr4/syscalls.conf11
-rw-r--r--sys/compat/svr4/syscalls.master396
-rw-r--r--sys/compat/x86bios/x86bios.c853
-rw-r--r--sys/compat/x86bios/x86bios.h157
128 files changed, 71205 insertions, 0 deletions
diff --git a/sys/compat/freebsd32/Makefile b/sys/compat/freebsd32/Makefile
new file mode 100644
index 0000000..34d3e81
--- /dev/null
+++ b/sys/compat/freebsd32/Makefile
@@ -0,0 +1,21 @@
+# Makefile for syscall tables
+#
+# $FreeBSD$
+
+all:
+ @echo "make sysent only"
+
+sysent: freebsd32_sysent.c freebsd32_syscall.h freebsd32_proto.h freebsd32_systrace_args.c
+
+freebsd32_sysent.c freebsd32_syscalls.c freebsd32_syscall.h freebsd32_proto.h freebsd32_systrace_args.c : \
+ ../../kern/makesyscalls.sh syscalls.master syscalls.conf
+ -mv -f freebsd32_sysent.c freebsd32_sysent.c.bak
+ -mv -f freebsd32_syscalls.c freebsd32_syscalls.c.bak
+ -mv -f freebsd32_syscall.h freebsd32_syscall.h.bak
+ -mv -f freebsd32_proto.h freebsd32_proto.h.bak
+ -mv -f freebsd32_systrace_args.c freebsd32_systrace_args.c.bak
+ sh ../../kern/makesyscalls.sh syscalls.master syscalls.conf
+
+clean:
+ rm -f freebsd32_sysent.c freebsd32_syscalls.c freebsd32_syscall.h freebsd32_proto.h
+ rm -f freebsd32_systrace_args.c
diff --git a/sys/compat/freebsd32/freebsd32.h b/sys/compat/freebsd32/freebsd32.h
new file mode 100644
index 0000000..a95b0e5
--- /dev/null
+++ b/sys/compat/freebsd32/freebsd32.h
@@ -0,0 +1,372 @@
+/*-
+ * Copyright (c) 2001 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _COMPAT_FREEBSD32_FREEBSD32_H_
+#define _COMPAT_FREEBSD32_FREEBSD32_H_
+
+#include <sys/procfs.h>
+#include <sys/socket.h>
+#include <sys/user.h>
+
+#define PTRIN(v) (void *)(uintptr_t) (v)
+#define PTROUT(v) (u_int32_t)(uintptr_t) (v)
+
+#define CP(src,dst,fld) do { (dst).fld = (src).fld; } while (0)
+#define PTRIN_CP(src,dst,fld) \
+ do { (dst).fld = PTRIN((src).fld); } while (0)
+#define PTROUT_CP(src,dst,fld) \
+ do { (dst).fld = PTROUT((src).fld); } while (0)
+
+/*
+ * Being a newer port, 32-bit FreeBSD/MIPS uses 64-bit time_t.
+ */
+#ifdef __mips__
+typedef int64_t time32_t;
+#else
+typedef int32_t time32_t;
+#endif
+
+struct timeval32 {
+ time32_t tv_sec;
+ int32_t tv_usec;
+};
+#define TV_CP(src,dst,fld) do { \
+ CP((src).fld,(dst).fld,tv_sec); \
+ CP((src).fld,(dst).fld,tv_usec); \
+} while (0)
+
+struct timespec32 {
+ time32_t tv_sec;
+ int32_t tv_nsec;
+};
+#define TS_CP(src,dst,fld) do { \
+ CP((src).fld,(dst).fld,tv_sec); \
+ CP((src).fld,(dst).fld,tv_nsec); \
+} while (0)
+
+struct rusage32 {
+ struct timeval32 ru_utime;
+ struct timeval32 ru_stime;
+ int32_t ru_maxrss;
+ int32_t ru_ixrss;
+ int32_t ru_idrss;
+ int32_t ru_isrss;
+ int32_t ru_minflt;
+ int32_t ru_majflt;
+ int32_t ru_nswap;
+ int32_t ru_inblock;
+ int32_t ru_oublock;
+ int32_t ru_msgsnd;
+ int32_t ru_msgrcv;
+ int32_t ru_nsignals;
+ int32_t ru_nvcsw;
+ int32_t ru_nivcsw;
+};
+
+struct wrusage32 {
+ struct rusage32 wru_self;
+ struct rusage32 wru_children;
+};
+
+struct itimerval32 {
+ struct timeval32 it_interval;
+ struct timeval32 it_value;
+};
+
+#define FREEBSD4_MNAMELEN (88 - 2 * sizeof(int32_t)) /* size of on/from name bufs */
+
+/* 4.x version */
+struct statfs32 {
+ int32_t f_spare2;
+ int32_t f_bsize;
+ int32_t f_iosize;
+ int32_t f_blocks;
+ int32_t f_bfree;
+ int32_t f_bavail;
+ int32_t f_files;
+ int32_t f_ffree;
+ fsid_t f_fsid;
+ uid_t f_owner;
+ int32_t f_type;
+ int32_t f_flags;
+ int32_t f_syncwrites;
+ int32_t f_asyncwrites;
+ char f_fstypename[MFSNAMELEN];
+ char f_mntonname[FREEBSD4_MNAMELEN];
+ int32_t f_syncreads;
+ int32_t f_asyncreads;
+ int16_t f_spares1;
+ char f_mntfromname[FREEBSD4_MNAMELEN];
+ int16_t f_spares2 __packed;
+ int32_t f_spare[2];
+};
+
+struct kevent32 {
+ u_int32_t ident; /* identifier for this event */
+ short filter; /* filter for event */
+ u_short flags;
+ u_int fflags;
+ int32_t data;
+ u_int32_t udata; /* opaque user data identifier */
+};
+
+struct iovec32 {
+ u_int32_t iov_base;
+ int iov_len;
+};
+
+struct msghdr32 {
+ u_int32_t msg_name;
+ socklen_t msg_namelen;
+ u_int32_t msg_iov;
+ int msg_iovlen;
+ u_int32_t msg_control;
+ socklen_t msg_controllen;
+ int msg_flags;
+};
+
+struct stat32 {
+ dev_t st_dev;
+ ino_t st_ino;
+ mode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ dev_t st_rdev;
+ struct timespec32 st_atim;
+ struct timespec32 st_mtim;
+ struct timespec32 st_ctim;
+ off_t st_size;
+ int64_t st_blocks;
+ u_int32_t st_blksize;
+ u_int32_t st_flags;
+ u_int32_t st_gen;
+ struct timespec32 st_birthtim;
+ unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
+ unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec32));
+};
+
+struct ostat32 {
+ __uint16_t st_dev;
+ ino_t st_ino;
+ mode_t st_mode;
+ nlink_t st_nlink;
+ __uint16_t st_uid;
+ __uint16_t st_gid;
+ __uint16_t st_rdev;
+ __int32_t st_size;
+ struct timespec32 st_atim;
+ struct timespec32 st_mtim;
+ struct timespec32 st_ctim;
+ __int32_t st_blksize;
+ __int32_t st_blocks;
+ u_int32_t st_flags;
+ __uint32_t st_gen;
+};
+
+struct jail32_v0 {
+ u_int32_t version;
+ uint32_t path;
+ uint32_t hostname;
+ u_int32_t ip_number;
+};
+
+struct jail32 {
+ uint32_t version;
+ uint32_t path;
+ uint32_t hostname;
+ uint32_t jailname;
+ uint32_t ip4s;
+ uint32_t ip6s;
+ uint32_t ip4;
+ uint32_t ip6;
+};
+
+struct sigaction32 {
+ u_int32_t sa_u;
+ int sa_flags;
+ sigset_t sa_mask;
+};
+
+struct thr_param32 {
+ uint32_t start_func;
+ uint32_t arg;
+ uint32_t stack_base;
+ uint32_t stack_size;
+ uint32_t tls_base;
+ uint32_t tls_size;
+ uint32_t child_tid;
+ uint32_t parent_tid;
+ int32_t flags;
+ uint32_t rtp;
+ uint32_t spare[3];
+};
+
+struct i386_ldt_args32 {
+ uint32_t start;
+ uint32_t descs;
+ uint32_t num;
+};
+
+/*
+ * Alternative layouts for <sys/procfs.h>
+ */
+struct prstatus32 {
+ int pr_version;
+ u_int pr_statussz;
+ u_int pr_gregsetsz;
+ u_int pr_fpregsetsz;
+ int pr_osreldate;
+ int pr_cursig;
+ pid_t pr_pid;
+ struct reg32 pr_reg;
+};
+
+struct prpsinfo32 {
+ int pr_version;
+ u_int pr_psinfosz;
+ char pr_fname[PRFNAMESZ+1];
+ char pr_psargs[PRARGSZ+1];
+};
+
+struct thrmisc32 {
+ char pr_tname[MAXCOMLEN+1];
+ u_int _pad;
+};
+
+struct mq_attr32 {
+ int mq_flags;
+ int mq_maxmsg;
+ int mq_msgsize;
+ int mq_curmsgs;
+ int __reserved[4];
+};
+
+struct kinfo_proc32 {
+ int ki_structsize;
+ int ki_layout;
+ uint32_t ki_args;
+ uint32_t ki_paddr;
+ uint32_t ki_addr;
+ uint32_t ki_tracep;
+ uint32_t ki_textvp;
+ uint32_t ki_fd;
+ uint32_t ki_vmspace;
+ uint32_t ki_wchan;
+ pid_t ki_pid;
+ pid_t ki_ppid;
+ pid_t ki_pgid;
+ pid_t ki_tpgid;
+ pid_t ki_sid;
+ pid_t ki_tsid;
+ short ki_jobc;
+ short ki_spare_short1;
+ dev_t ki_tdev;
+ sigset_t ki_siglist;
+ sigset_t ki_sigmask;
+ sigset_t ki_sigignore;
+ sigset_t ki_sigcatch;
+ uid_t ki_uid;
+ uid_t ki_ruid;
+ uid_t ki_svuid;
+ gid_t ki_rgid;
+ gid_t ki_svgid;
+ short ki_ngroups;
+ short ki_spare_short2;
+ gid_t ki_groups[KI_NGROUPS];
+ uint32_t ki_size;
+ int32_t ki_rssize;
+ int32_t ki_swrss;
+ int32_t ki_tsize;
+ int32_t ki_dsize;
+ int32_t ki_ssize;
+ u_short ki_xstat;
+ u_short ki_acflag;
+ fixpt_t ki_pctcpu;
+ u_int ki_estcpu;
+ u_int ki_slptime;
+ u_int ki_swtime;
+ u_int ki_cow;
+ u_int64_t ki_runtime;
+ struct timeval32 ki_start;
+ struct timeval32 ki_childtime;
+ int ki_flag;
+ int ki_kiflag;
+ int ki_traceflag;
+ char ki_stat;
+ signed char ki_nice;
+ char ki_lock;
+ char ki_rqindex;
+ u_char ki_oncpu;
+ u_char ki_lastcpu;
+ char ki_tdname[TDNAMLEN+1];
+ char ki_wmesg[WMESGLEN+1];
+ char ki_login[LOGNAMELEN+1];
+ char ki_lockname[LOCKNAMELEN+1];
+ char ki_comm[COMMLEN+1];
+ char ki_emul[KI_EMULNAMELEN+1];
+ char ki_loginclass[LOGINCLASSLEN+1];
+ char ki_sparestrings[50];
+ int ki_spareints[KI_NSPARE_INT];
+ u_int ki_cr_flags;
+ int ki_jid;
+ int ki_numthreads;
+ lwpid_t ki_tid;
+ struct priority ki_pri;
+ struct rusage32 ki_rusage;
+ struct rusage32 ki_rusage_ch;
+ uint32_t ki_pcb;
+ uint32_t ki_kstack;
+ uint32_t ki_udata;
+ uint32_t ki_tdaddr;
+ uint32_t ki_spareptrs[KI_NSPARE_PTR]; /* spare room for growth */
+ int ki_sparelongs[KI_NSPARE_LONG];
+ int ki_sflag;
+ int ki_tdflags;
+};
+
+struct kld32_file_stat_1 {
+ int version; /* set to sizeof(struct kld_file_stat_1) */
+ char name[MAXPATHLEN];
+ int refs;
+ int id;
+ uint32_t address; /* load address */
+ uint32_t size; /* size in bytes */
+};
+
+struct kld32_file_stat {
+ int version; /* set to sizeof(struct kld_file_stat) */
+ char name[MAXPATHLEN];
+ int refs;
+ int id;
+ uint32_t address; /* load address */
+ uint32_t size; /* size in bytes */
+ char pathname[MAXPATHLEN];
+};
+
+#endif /* !_COMPAT_FREEBSD32_FREEBSD32_H_ */
diff --git a/sys/compat/freebsd32/freebsd32_ioctl.c b/sys/compat/freebsd32/freebsd32_ioctl.c
new file mode 100644
index 0000000..81f5c8e
--- /dev/null
+++ b/sys/compat/freebsd32/freebsd32_ioctl.c
@@ -0,0 +1,404 @@
+/*-
+ * Copyright (c) 2008 David E. O'Brien
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_compat.h"
+
+#include <sys/param.h>
+#include <sys/capability.h>
+#include <sys/cdio.h>
+#include <sys/fcntl.h>
+#include <sys/filio.h>
+#include <sys/file.h>
+#include <sys/ioccom.h>
+#include <sys/malloc.h>
+#include <sys/mdioctl.h>
+#include <sys/memrange.h>
+#include <sys/pciio.h>
+#include <sys/proc.h>
+#include <sys/syscall.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysctl.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <sys/systm.h>
+
+#include <compat/freebsd32/freebsd32.h>
+#include <compat/freebsd32/freebsd32_ioctl.h>
+#include <compat/freebsd32/freebsd32_proto.h>
+
+/* Cannot get exact size in 64-bit due to alignment issue of entire struct. */
+CTASSERT((sizeof(struct md_ioctl32)+4) == 436);
+CTASSERT(sizeof(struct ioc_read_toc_entry32) == 8);
+CTASSERT(sizeof(struct ioc_toc_header32) == 4);
+CTASSERT(sizeof(struct mem_range_op32) == 12);
+CTASSERT(sizeof(struct pci_conf_io32) == 36);
+CTASSERT(sizeof(struct pci_match_conf32) == 44);
+CTASSERT(sizeof(struct pci_conf32) == 44);
+
+
+static int
+freebsd32_ioctl_md(struct thread *td, struct freebsd32_ioctl_args *uap,
+ struct file *fp)
+{
+ struct md_ioctl mdv;
+ struct md_ioctl32 md32;
+ u_long com = 0;
+ int i, error;
+
+ if (uap->com & IOC_IN) {
+ if ((error = copyin(uap->data, &md32, sizeof(md32)))) {
+ return (error);
+ }
+ CP(md32, mdv, md_version);
+ CP(md32, mdv, md_unit);
+ CP(md32, mdv, md_type);
+ PTRIN_CP(md32, mdv, md_file);
+ CP(md32, mdv, md_mediasize);
+ CP(md32, mdv, md_sectorsize);
+ CP(md32, mdv, md_options);
+ CP(md32, mdv, md_base);
+ CP(md32, mdv, md_fwheads);
+ CP(md32, mdv, md_fwsectors);
+ } else if (uap->com & IOC_OUT) {
+ /*
+ * Zero the buffer so the user always
+ * gets back something deterministic.
+ */
+ bzero(&mdv, sizeof mdv);
+ }
+
+ switch (uap->com) {
+ case MDIOCATTACH_32:
+ com = MDIOCATTACH;
+ break;
+ case MDIOCDETACH_32:
+ com = MDIOCDETACH;
+ break;
+ case MDIOCQUERY_32:
+ com = MDIOCQUERY;
+ break;
+ case MDIOCLIST_32:
+ com = MDIOCLIST;
+ break;
+ default:
+ panic("%s: unknown MDIOC %#x", __func__, uap->com);
+ }
+ error = fo_ioctl(fp, com, (caddr_t)&mdv, td->td_ucred, td);
+ if (error == 0 && (com & IOC_OUT)) {
+ CP(mdv, md32, md_version);
+ CP(mdv, md32, md_unit);
+ CP(mdv, md32, md_type);
+ PTROUT_CP(mdv, md32, md_file);
+ CP(mdv, md32, md_mediasize);
+ CP(mdv, md32, md_sectorsize);
+ CP(mdv, md32, md_options);
+ CP(mdv, md32, md_base);
+ CP(mdv, md32, md_fwheads);
+ CP(mdv, md32, md_fwsectors);
+ if (com == MDIOCLIST) {
+ /*
+ * Use MDNPAD, and not MDNPAD32. Padding is
+ * allocated and used by compat32 ABI.
+ */
+ for (i = 0; i < MDNPAD; i++)
+ CP(mdv, md32, md_pad[i]);
+ }
+ error = copyout(&md32, uap->data, sizeof(md32));
+ }
+ return error;
+}
+
+
+static int
+freebsd32_ioctl_ioc_toc_header(struct thread *td,
+ struct freebsd32_ioctl_args *uap, struct file *fp)
+{
+ struct ioc_toc_header toch;
+ struct ioc_toc_header32 toch32;
+ int error;
+
+ if ((error = copyin(uap->data, &toch32, sizeof(toch32))))
+ return (error);
+ CP(toch32, toch, len);
+ CP(toch32, toch, starting_track);
+ CP(toch32, toch, ending_track);
+ error = fo_ioctl(fp, CDIOREADTOCHEADER, (caddr_t)&toch,
+ td->td_ucred, td);
+ return (error);
+}
+
+
+static int
+freebsd32_ioctl_ioc_read_toc(struct thread *td,
+ struct freebsd32_ioctl_args *uap, struct file *fp)
+{
+ struct ioc_read_toc_entry toce;
+ struct ioc_read_toc_entry32 toce32;
+ int error;
+
+ if ((error = copyin(uap->data, &toce32, sizeof(toce32))))
+ return (error);
+ CP(toce32, toce, address_format);
+ CP(toce32, toce, starting_track);
+ CP(toce32, toce, data_len);
+ PTRIN_CP(toce32, toce, data);
+
+ if ((error = fo_ioctl(fp, CDIOREADTOCENTRYS, (caddr_t)&toce,
+ td->td_ucred, td))) {
+ CP(toce, toce32, address_format);
+ CP(toce, toce32, starting_track);
+ CP(toce, toce32, data_len);
+ PTROUT_CP(toce, toce32, data);
+ error = copyout(&toce32, uap->data, sizeof(toce32));
+ }
+ return error;
+}
+
+static int
+freebsd32_ioctl_fiodgname(struct thread *td,
+ struct freebsd32_ioctl_args *uap, struct file *fp)
+{
+ struct fiodgname_arg fgn;
+ struct fiodgname_arg32 fgn32;
+ int error;
+
+ if ((error = copyin(uap->data, &fgn32, sizeof fgn32)) != 0)
+ return (error);
+ CP(fgn32, fgn, len);
+ PTRIN_CP(fgn32, fgn, buf);
+ error = fo_ioctl(fp, FIODGNAME, (caddr_t)&fgn, td->td_ucred, td);
+ return (error);
+}
+
+static int
+freebsd32_ioctl_memrange(struct thread *td,
+ struct freebsd32_ioctl_args *uap, struct file *fp)
+{
+ struct mem_range_op mro;
+ struct mem_range_op32 mro32;
+ int error;
+ u_long com;
+
+ if ((error = copyin(uap->data, &mro32, sizeof(mro32))) != 0)
+ return (error);
+
+ PTRIN_CP(mro32, mro, mo_desc);
+ CP(mro32, mro, mo_arg[0]);
+ CP(mro32, mro, mo_arg[1]);
+
+ com = 0;
+ switch (uap->com) {
+ case MEMRANGE_GET32:
+ com = MEMRANGE_GET;
+ break;
+
+ case MEMRANGE_SET32:
+ com = MEMRANGE_SET;
+ break;
+
+ default:
+ panic("%s: unknown MEMRANGE %#x", __func__, uap->com);
+ }
+
+ if ((error = fo_ioctl(fp, com, (caddr_t)&mro, td->td_ucred, td)) != 0)
+ return (error);
+
+ if ( (com & IOC_OUT) ) {
+ CP(mro, mro32, mo_arg[0]);
+ CP(mro, mro32, mo_arg[1]);
+
+ error = copyout(&mro32, uap->data, sizeof(mro32));
+ }
+
+ return (error);
+}
+
+static int
+freebsd32_ioctl_pciocgetconf(struct thread *td,
+ struct freebsd32_ioctl_args *uap, struct file *fp)
+{
+ struct pci_conf_io pci;
+ struct pci_conf_io32 pci32;
+ struct pci_match_conf32 pmc32;
+ struct pci_match_conf32 *pmc32p;
+ struct pci_match_conf pmc;
+ struct pci_match_conf *pmcp;
+ struct pci_conf32 pc32;
+ struct pci_conf32 *pc32p;
+ struct pci_conf pc;
+ struct pci_conf *pcp;
+ u_int32_t i;
+ u_int32_t npat_to_convert;
+ u_int32_t nmatch_to_convert;
+ vm_offset_t addr;
+ int error;
+
+ if ((error = copyin(uap->data, &pci32, sizeof(pci32))) != 0)
+ return (error);
+
+ CP(pci32, pci, num_patterns);
+ CP(pci32, pci, offset);
+ CP(pci32, pci, generation);
+
+ npat_to_convert = pci32.pat_buf_len / sizeof(struct pci_match_conf32);
+ pci.pat_buf_len = npat_to_convert * sizeof(struct pci_match_conf);
+ pci.patterns = NULL;
+ nmatch_to_convert = pci32.match_buf_len / sizeof(struct pci_conf32);
+ pci.match_buf_len = nmatch_to_convert * sizeof(struct pci_conf);
+ pci.matches = NULL;
+
+ if ((error = copyout_map(td, &addr, pci.pat_buf_len)) != 0)
+ goto cleanup;
+ pci.patterns = (struct pci_match_conf *)addr;
+ if ((error = copyout_map(td, &addr, pci.match_buf_len)) != 0)
+ goto cleanup;
+ pci.matches = (struct pci_conf *)addr;
+
+ npat_to_convert = min(npat_to_convert, pci.num_patterns);
+
+ for (i = 0, pmc32p = (struct pci_match_conf32 *)PTRIN(pci32.patterns),
+ pmcp = pci.patterns;
+ i < npat_to_convert; i++, pmc32p++, pmcp++) {
+ if ((error = copyin(pmc32p, &pmc32, sizeof(pmc32))) != 0)
+ goto cleanup;
+ CP(pmc32,pmc,pc_sel);
+ strlcpy(pmc.pd_name, pmc32.pd_name, sizeof(pmc.pd_name));
+ CP(pmc32,pmc,pd_unit);
+ CP(pmc32,pmc,pc_vendor);
+ CP(pmc32,pmc,pc_device);
+ CP(pmc32,pmc,pc_class);
+ CP(pmc32,pmc,flags);
+ if ((error = copyout(&pmc, pmcp, sizeof(pmc))) != 0)
+ goto cleanup;
+ }
+
+ if ((error = fo_ioctl(fp, PCIOCGETCONF, (caddr_t)&pci,
+ td->td_ucred, td)) != 0)
+ goto cleanup;
+
+ nmatch_to_convert = min(nmatch_to_convert, pci.num_matches);
+
+ for (i = 0, pcp = pci.matches,
+ pc32p = (struct pci_conf32 *)PTRIN(pci32.matches);
+ i < nmatch_to_convert; i++, pcp++, pc32p++) {
+ if ((error = copyin(pcp, &pc, sizeof(pc))) != 0)
+ goto cleanup;
+ CP(pc,pc32,pc_sel);
+ CP(pc,pc32,pc_hdr);
+ CP(pc,pc32,pc_subvendor);
+ CP(pc,pc32,pc_subdevice);
+ CP(pc,pc32,pc_vendor);
+ CP(pc,pc32,pc_device);
+ CP(pc,pc32,pc_class);
+ CP(pc,pc32,pc_subclass);
+ CP(pc,pc32,pc_progif);
+ CP(pc,pc32,pc_revid);
+ strlcpy(pc32.pd_name, pc.pd_name, sizeof(pc32.pd_name));
+ CP(pc,pc32,pd_unit);
+ if ((error = copyout(&pc32, pc32p, sizeof(pc32))) != 0)
+ goto cleanup;
+ }
+
+ CP(pci, pci32, num_matches);
+ CP(pci, pci32, offset);
+ CP(pci, pci32, generation);
+ CP(pci, pci32, status);
+
+ error = copyout(&pci32, uap->data, sizeof(pci32));
+
+cleanup:
+ if (pci.patterns)
+ copyout_unmap(td, (vm_offset_t)pci.patterns, pci.pat_buf_len);
+ if (pci.matches)
+ copyout_unmap(td, (vm_offset_t)pci.matches, pci.match_buf_len);
+
+ return (error);
+}
+
+int
+freebsd32_ioctl(struct thread *td, struct freebsd32_ioctl_args *uap)
+{
+ struct ioctl_args ap /*{
+ int fd;
+ u_long com;
+ caddr_t data;
+ }*/ ;
+ struct file *fp;
+ int error;
+
+ if ((error = fget(td, uap->fd, CAP_IOCTL, &fp)) != 0)
+ return (error);
+ if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
+ fdrop(fp, td);
+ return (EBADF);
+ }
+
+ switch (uap->com) {
+ case MDIOCATTACH_32: /* FALLTHROUGH */
+ case MDIOCDETACH_32: /* FALLTHROUGH */
+ case MDIOCQUERY_32: /* FALLTHROUGH */
+ case MDIOCLIST_32:
+ error = freebsd32_ioctl_md(td, uap, fp);
+ break;
+
+ case CDIOREADTOCENTRYS_32:
+ error = freebsd32_ioctl_ioc_read_toc(td, uap, fp);
+ break;
+
+ case CDIOREADTOCHEADER_32:
+ error = freebsd32_ioctl_ioc_toc_header(td, uap, fp);
+ break;
+
+ case FIODGNAME_32:
+ error = freebsd32_ioctl_fiodgname(td, uap, fp);
+ break;
+
+ case MEMRANGE_GET32: /* FALLTHROUGH */
+ case MEMRANGE_SET32:
+ error = freebsd32_ioctl_memrange(td, uap, fp);
+ break;
+
+ case PCIOCGETCONF_32:
+ error = freebsd32_ioctl_pciocgetconf(td, uap, fp);
+ break;
+
+ default:
+ fdrop(fp, td);
+ ap.fd = uap->fd;
+ ap.com = uap->com;
+ PTRIN_CP(*uap, ap, data);
+ return sys_ioctl(td, &ap);
+ }
+
+ fdrop(fp, td);
+ return error;
+}
diff --git a/sys/compat/freebsd32/freebsd32_ioctl.h b/sys/compat/freebsd32/freebsd32_ioctl.h
new file mode 100644
index 0000000..e0beb73
--- /dev/null
+++ b/sys/compat/freebsd32/freebsd32_ioctl.h
@@ -0,0 +1,126 @@
+/*-
+ * Copyright (c) 2008 David E. O'Brien
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _COMPAT_FREEBSD32_IOCTL_H_
+#define _COMPAT_FREEBSD32_IOCTL_H_
+
+typedef __uint32_t caddr_t32;
+
+struct ioc_toc_header32 {
+ u_short len;
+ u_char starting_track;
+ u_char ending_track;
+};
+
+struct ioc_read_toc_entry32 {
+ u_char address_format;
+ u_char starting_track;
+ u_short data_len;
+ uint32_t data; /* struct cd_toc_entry* */
+};
+
+#define MDNPAD32 MDNPAD - 1
+struct md_ioctl32 {
+ unsigned md_version; /* Structure layout version */
+ unsigned md_unit; /* unit number */
+ enum md_types md_type; /* type of disk */
+ caddr_t32 md_file; /* pathname of file to mount */
+ off_t md_mediasize; /* size of disk in bytes */
+ unsigned md_sectorsize; /* sectorsize */
+ unsigned md_options; /* options */
+ u_int64_t md_base; /* base address */
+ int md_fwheads; /* firmware heads */
+ int md_fwsectors; /* firmware sectors */
+ int md_pad[MDNPAD32]; /* padding for future ideas */
+};
+
+struct fiodgname_arg32 {
+ int len;
+ caddr_t32 buf;
+};
+
+struct mem_range_op32
+{
+ caddr_t32 mo_desc;
+ int mo_arg[2];
+};
+
+struct pci_conf32 {
+ struct pcisel pc_sel; /* domain+bus+slot+function */
+ u_int8_t pc_hdr; /* PCI header type */
+ u_int16_t pc_subvendor; /* card vendor ID */
+ u_int16_t pc_subdevice; /* card device ID, assigned by
+ card vendor */
+ u_int16_t pc_vendor; /* chip vendor ID */
+ u_int16_t pc_device; /* chip device ID, assigned by
+ chip vendor */
+ u_int8_t pc_class; /* chip PCI class */
+ u_int8_t pc_subclass; /* chip PCI subclass */
+ u_int8_t pc_progif; /* chip PCI programming interface */
+ u_int8_t pc_revid; /* chip revision ID */
+ char pd_name[PCI_MAXNAMELEN + 1]; /* device name */
+ u_int32_t pd_unit; /* device unit number */
+};
+
+struct pci_match_conf32 {
+ struct pcisel pc_sel; /* domain+bus+slot+function */
+ char pd_name[PCI_MAXNAMELEN + 1]; /* device name */
+ u_int32_t pd_unit; /* Unit number */
+ u_int16_t pc_vendor; /* PCI Vendor ID */
+ u_int16_t pc_device; /* PCI Device ID */
+ u_int8_t pc_class; /* PCI class */
+ u_int32_t flags; /* Matching expression */
+};
+
+struct pci_conf_io32 {
+ u_int32_t pat_buf_len; /* pattern buffer length */
+ u_int32_t num_patterns; /* number of patterns */
+ caddr_t32 patterns; /* struct pci_match_conf ptr */
+ u_int32_t match_buf_len; /* match buffer length */
+ u_int32_t num_matches; /* number of matches returned */
+ caddr_t32 matches; /* struct pci_conf ptr */
+ u_int32_t offset; /* offset into device list */
+ u_int32_t generation; /* device list generation */
+ u_int32_t status; /* request status */
+};
+
+#define CDIOREADTOCENTRYS_32 _IOWR('c', 5, struct ioc_read_toc_entry32)
+#define CDIOREADTOCHEADER_32 _IOR('c', 4, struct ioc_toc_header32)
+#define MDIOCATTACH_32 _IOC(IOC_INOUT, 'm', 0, sizeof(struct md_ioctl32) + 4)
+#define MDIOCDETACH_32 _IOC(IOC_INOUT, 'm', 1, sizeof(struct md_ioctl32) + 4)
+#define MDIOCQUERY_32 _IOC(IOC_INOUT, 'm', 2, sizeof(struct md_ioctl32) + 4)
+#define MDIOCLIST_32 _IOC(IOC_INOUT, 'm', 3, sizeof(struct md_ioctl32) + 4)
+#define FIODGNAME_32 _IOW('f', 120, struct fiodgname_arg32)
+#define MEMRANGE_GET32 _IOWR('m', 50, struct mem_range_op32)
+#define MEMRANGE_SET32 _IOW('m', 51, struct mem_range_op32)
+#define PCIOCGETCONF_32 _IOWR('p', 5, struct pci_conf_io32)
+
+#endif /* _COMPAT_FREEBSD32_IOCTL_H_ */
diff --git a/sys/compat/freebsd32/freebsd32_ipc.h b/sys/compat/freebsd32/freebsd32_ipc.h
new file mode 100644
index 0000000..320a63f
--- /dev/null
+++ b/sys/compat/freebsd32/freebsd32_ipc.h
@@ -0,0 +1,160 @@
+/*-
+ * Copyright (c) 2002 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _COMPAT_FREEBSD32_FREEBSD32_IPC_H_
+#define _COMPAT_FREEBSD32_FREEBSD32_IPC_H_
+
+struct ipc_perm32 {
+ uid_t cuid;
+ gid_t cgid;
+ uid_t uid;
+ gid_t gid;
+ mode_t mode;
+ uint16_t seq;
+ uint32_t key;
+};
+
+struct semid_ds32 {
+ struct ipc_perm32 sem_perm;
+ uint32_t sem_base;
+ unsigned short sem_nsems;
+ int32_t sem_otime;
+ int32_t sem_ctime;
+};
+
+union semun32 {
+ int val;
+ uint32_t buf;
+ uint32_t array;
+};
+
+struct msqid_ds32 {
+ struct ipc_perm32 msg_perm;
+ uint32_t msg_first;
+ uint32_t msg_last;
+ uint32_t msg_cbytes;
+ uint32_t msg_qnum;
+ uint32_t msg_qbytes;
+ pid_t msg_lspid;
+ pid_t msg_lrpid;
+ int32_t msg_stime;
+ int32_t msg_rtime;
+ int32_t msg_ctime;
+};
+
+struct shmid_ds32 {
+ struct ipc_perm32 shm_perm;
+ int32_t shm_segsz;
+ pid_t shm_lpid;
+ pid_t shm_cpid;
+ int shm_nattch;
+ int32_t shm_atime;
+ int32_t shm_dtime;
+ int32_t shm_ctime;
+};
+
+struct shm_info32 {
+ int32_t used_ids;
+ uint32_t shm_tot;
+ uint32_t shm_rss;
+ uint32_t shm_swp;
+ uint32_t swap_attempts;
+ uint32_t swap_successes;
+};
+
+struct shminfo32 {
+ uint32_t shmmax;
+ uint32_t shmmin;
+ uint32_t shmmni;
+ uint32_t shmseg;
+ uint32_t shmall;
+};
+
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+struct ipc_perm32_old {
+ uint16_t cuid;
+ uint16_t cgid;
+ uint16_t uid;
+ uint16_t gid;
+ uint16_t mode;
+ uint16_t seq;
+ uint32_t key;
+};
+
+struct semid_ds32_old {
+ struct ipc_perm32_old sem_perm;
+ uint32_t sem_base;
+ unsigned short sem_nsems;
+ int32_t sem_otime;
+ int32_t sem_pad1;
+ int32_t sem_ctime;
+ int32_t sem_pad2;
+ int32_t sem_pad3[4];
+};
+
+struct msqid_ds32_old {
+ struct ipc_perm32_old msg_perm;
+ uint32_t msg_first;
+ uint32_t msg_last;
+ uint32_t msg_cbytes;
+ uint32_t msg_qnum;
+ uint32_t msg_qbytes;
+ pid_t msg_lspid;
+ pid_t msg_lrpid;
+ int32_t msg_stime;
+ int32_t msg_pad1;
+ int32_t msg_rtime;
+ int32_t msg_pad2;
+ int32_t msg_ctime;
+ int32_t msg_pad3;
+ int32_t msg_pad4[4];
+};
+
+struct shmid_ds32_old {
+ struct ipc_perm32_old shm_perm;
+ int32_t shm_segsz;
+ pid_t shm_lpid;
+ pid_t shm_cpid;
+ int16_t shm_nattch;
+ int32_t shm_atime;
+ int32_t shm_dtime;
+ int32_t shm_ctime;
+ uint32_t shm_internal;
+};
+
+void freebsd32_ipcperm_old_in(struct ipc_perm32_old *ip32,
+ struct ipc_perm *ip);
+void freebsd32_ipcperm_old_out(struct ipc_perm *ip,
+ struct ipc_perm32_old *ip32);
+#endif
+
+void freebsd32_ipcperm_in(struct ipc_perm32 *ip32, struct ipc_perm *ip);
+void freebsd32_ipcperm_out(struct ipc_perm *ip, struct ipc_perm32 *ip32);
+
+#endif /* !_COMPAT_FREEBSD32_FREEBSD32_IPC_H_ */
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
new file mode 100644
index 0000000..dd8d4f7
--- /dev/null
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -0,0 +1,2900 @@
+/*-
+ * Copyright (c) 2002 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_compat.h"
+#include "opt_inet.h"
+#include "opt_inet6.h"
+
+#define __ELF_WORD_SIZE 32
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/clock.h>
+#include <sys/exec.h>
+#include <sys/fcntl.h>
+#include <sys/filedesc.h>
+#include <sys/imgact.h>
+#include <sys/jail.h>
+#include <sys/kernel.h>
+#include <sys/limits.h>
+#include <sys/linker.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/file.h> /* Must come after sys/malloc.h */
+#include <sys/imgact.h>
+#include <sys/mbuf.h>
+#include <sys/mman.h>
+#include <sys/module.h>
+#include <sys/mount.h>
+#include <sys/mutex.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
+#include <sys/selinfo.h>
+#include <sys/eventvar.h> /* Must come after sys/selinfo.h */
+#include <sys/pipe.h> /* Must come after sys/selinfo.h */
+#include <sys/signal.h>
+#include <sys/signalvar.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysctl.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <sys/systm.h>
+#include <sys/thr.h>
+#include <sys/unistd.h>
+#include <sys/ucontext.h>
+#include <sys/vnode.h>
+#include <sys/wait.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <sys/sem.h>
+#include <sys/shm.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#endif
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+
+#include <machine/cpu.h>
+#include <machine/elf.h>
+
+#include <security/audit/audit.h>
+
+#include <compat/freebsd32/freebsd32_util.h>
+#include <compat/freebsd32/freebsd32.h>
+#include <compat/freebsd32/freebsd32_ipc.h>
+#include <compat/freebsd32/freebsd32_signal.h>
+#include <compat/freebsd32/freebsd32_proto.h>
+
+FEATURE(compat_freebsd_32bit, "Compatible with 32-bit FreeBSD");
+
+#ifndef __mips__
+CTASSERT(sizeof(struct timeval32) == 8);
+CTASSERT(sizeof(struct timespec32) == 8);
+CTASSERT(sizeof(struct itimerval32) == 16);
+#endif
+CTASSERT(sizeof(struct statfs32) == 256);
+#ifndef __mips__
+CTASSERT(sizeof(struct rusage32) == 72);
+#endif
+CTASSERT(sizeof(struct sigaltstack32) == 12);
+CTASSERT(sizeof(struct kevent32) == 20);
+CTASSERT(sizeof(struct iovec32) == 8);
+CTASSERT(sizeof(struct msghdr32) == 28);
+#ifndef __mips__
+CTASSERT(sizeof(struct stat32) == 96);
+#endif
+CTASSERT(sizeof(struct sigaction32) == 24);
+
+static int freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count);
+static int freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count);
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define PAIR32TO64(type, name) ((name ## 2) | ((type)(name ## 1) << 32))
+#define RETVAL_HI 0
+#define RETVAL_LO 1
+#else
+#define PAIR32TO64(type, name) ((name ## 1) | ((type)(name ## 2) << 32))
+#define RETVAL_HI 1
+#define RETVAL_LO 0
+#endif
+
+void
+freebsd32_rusage_out(const struct rusage *s, struct rusage32 *s32)
+{
+
+ TV_CP(*s, *s32, ru_utime);
+ TV_CP(*s, *s32, ru_stime);
+ CP(*s, *s32, ru_maxrss);
+ CP(*s, *s32, ru_ixrss);
+ CP(*s, *s32, ru_idrss);
+ CP(*s, *s32, ru_isrss);
+ CP(*s, *s32, ru_minflt);
+ CP(*s, *s32, ru_majflt);
+ CP(*s, *s32, ru_nswap);
+ CP(*s, *s32, ru_inblock);
+ CP(*s, *s32, ru_oublock);
+ CP(*s, *s32, ru_msgsnd);
+ CP(*s, *s32, ru_msgrcv);
+ CP(*s, *s32, ru_nsignals);
+ CP(*s, *s32, ru_nvcsw);
+ CP(*s, *s32, ru_nivcsw);
+}
+
+int
+freebsd32_wait4(struct thread *td, struct freebsd32_wait4_args *uap)
+{
+ int error, status;
+ struct rusage32 ru32;
+ struct rusage ru, *rup;
+
+ if (uap->rusage != NULL)
+ rup = &ru;
+ else
+ rup = NULL;
+ error = kern_wait(td, uap->pid, &status, uap->options, rup);
+ if (error)
+ return (error);
+ if (uap->status != NULL)
+ error = copyout(&status, uap->status, sizeof(status));
+ if (uap->rusage != NULL && error == 0) {
+ freebsd32_rusage_out(&ru, &ru32);
+ error = copyout(&ru32, uap->rusage, sizeof(ru32));
+ }
+ return (error);
+}
+
+int
+freebsd32_wait6(struct thread *td, struct freebsd32_wait6_args *uap)
+{
+ struct wrusage32 wru32;
+ struct __wrusage wru, *wrup;
+ struct siginfo32 si32;
+ struct __siginfo si, *sip;
+ int error, status;
+
+ if (uap->wrusage != NULL)
+ wrup = &wru;
+ else
+ wrup = NULL;
+ if (uap->info != NULL) {
+ sip = &si;
+ bzero(sip, sizeof(*sip));
+ } else
+ sip = NULL;
+ error = kern_wait6(td, uap->idtype, PAIR32TO64(id_t, uap->id),
+ &status, uap->options, wrup, sip);
+ if (error != 0)
+ return (error);
+ if (uap->status != NULL)
+ error = copyout(&status, uap->status, sizeof(status));
+ if (uap->wrusage != NULL && error == 0) {
+ freebsd32_rusage_out(&wru.wru_self, &wru32.wru_self);
+ freebsd32_rusage_out(&wru.wru_children, &wru32.wru_children);
+ error = copyout(&wru32, uap->wrusage, sizeof(wru32));
+ }
+ if (uap->info != NULL && error == 0) {
+ siginfo_to_siginfo32 (&si, &si32);
+ error = copyout(&si32, uap->info, sizeof(si32));
+ }
+ return (error);
+}
+
+#ifdef COMPAT_FREEBSD4
+static void
+copy_statfs(struct statfs *in, struct statfs32 *out)
+{
+
+ statfs_scale_blocks(in, INT32_MAX);
+ bzero(out, sizeof(*out));
+ CP(*in, *out, f_bsize);
+ out->f_iosize = MIN(in->f_iosize, INT32_MAX);
+ CP(*in, *out, f_blocks);
+ CP(*in, *out, f_bfree);
+ CP(*in, *out, f_bavail);
+ out->f_files = MIN(in->f_files, INT32_MAX);
+ out->f_ffree = MIN(in->f_ffree, INT32_MAX);
+ CP(*in, *out, f_fsid);
+ CP(*in, *out, f_owner);
+ CP(*in, *out, f_type);
+ CP(*in, *out, f_flags);
+ out->f_syncwrites = MIN(in->f_syncwrites, INT32_MAX);
+ out->f_asyncwrites = MIN(in->f_asyncwrites, INT32_MAX);
+ strlcpy(out->f_fstypename,
+ in->f_fstypename, MFSNAMELEN);
+ strlcpy(out->f_mntonname,
+ in->f_mntonname, min(MNAMELEN, FREEBSD4_MNAMELEN));
+ out->f_syncreads = MIN(in->f_syncreads, INT32_MAX);
+ out->f_asyncreads = MIN(in->f_asyncreads, INT32_MAX);
+ strlcpy(out->f_mntfromname,
+ in->f_mntfromname, min(MNAMELEN, FREEBSD4_MNAMELEN));
+}
+#endif
+
+#ifdef COMPAT_FREEBSD4
+int
+freebsd4_freebsd32_getfsstat(struct thread *td, struct freebsd4_freebsd32_getfsstat_args *uap)
+{
+ struct statfs *buf, *sp;
+ struct statfs32 stat32;
+ size_t count, size;
+ int error;
+
+ count = uap->bufsize / sizeof(struct statfs32);
+ size = count * sizeof(struct statfs);
+ error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
+ if (size > 0) {
+ count = td->td_retval[0];
+ sp = buf;
+ while (count > 0 && error == 0) {
+ copy_statfs(sp, &stat32);
+ error = copyout(&stat32, uap->buf, sizeof(stat32));
+ sp++;
+ uap->buf++;
+ count--;
+ }
+ free(buf, M_TEMP);
+ }
+ return (error);
+}
+#endif
+
+int
+freebsd32_sigaltstack(struct thread *td,
+ struct freebsd32_sigaltstack_args *uap)
+{
+ struct sigaltstack32 s32;
+ struct sigaltstack ss, oss, *ssp;
+ int error;
+
+ if (uap->ss != NULL) {
+ error = copyin(uap->ss, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ PTRIN_CP(s32, ss, ss_sp);
+ CP(s32, ss, ss_size);
+ CP(s32, ss, ss_flags);
+ ssp = &ss;
+ } else
+ ssp = NULL;
+ error = kern_sigaltstack(td, ssp, &oss);
+ if (error == 0 && uap->oss != NULL) {
+ PTROUT_CP(oss, s32, ss_sp);
+ CP(oss, s32, ss_size);
+ CP(oss, s32, ss_flags);
+ error = copyout(&s32, uap->oss, sizeof(s32));
+ }
+ return (error);
+}
+
+/*
+ * Custom version of exec_copyin_args() so that we can translate
+ * the pointers.
+ */
+int
+freebsd32_exec_copyin_args(struct image_args *args, char *fname,
+ enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv)
+{
+ char *argp, *envp;
+ u_int32_t *p32, arg;
+ size_t length;
+ int error;
+
+ bzero(args, sizeof(*args));
+ if (argv == NULL)
+ return (EFAULT);
+
+ /*
+ * Allocate demand-paged memory for the file name, argument, and
+ * environment strings.
+ */
+ error = exec_alloc_args(args);
+ if (error != 0)
+ return (error);
+
+ /*
+ * Copy the file name.
+ */
+ if (fname != NULL) {
+ args->fname = args->buf;
+ error = (segflg == UIO_SYSSPACE) ?
+ copystr(fname, args->fname, PATH_MAX, &length) :
+ copyinstr(fname, args->fname, PATH_MAX, &length);
+ if (error != 0)
+ goto err_exit;
+ } else
+ length = 0;
+
+ args->begin_argv = args->buf + length;
+ args->endp = args->begin_argv;
+ args->stringspace = ARG_MAX;
+
+ /*
+ * extract arguments first
+ */
+ p32 = argv;
+ for (;;) {
+ error = copyin(p32++, &arg, sizeof(arg));
+ if (error)
+ goto err_exit;
+ if (arg == 0)
+ break;
+ argp = PTRIN(arg);
+ error = copyinstr(argp, args->endp, args->stringspace, &length);
+ if (error) {
+ if (error == ENAMETOOLONG)
+ error = E2BIG;
+ goto err_exit;
+ }
+ args->stringspace -= length;
+ args->endp += length;
+ args->argc++;
+ }
+
+ args->begin_envv = args->endp;
+
+ /*
+ * extract environment strings
+ */
+ if (envv) {
+ p32 = envv;
+ for (;;) {
+ error = copyin(p32++, &arg, sizeof(arg));
+ if (error)
+ goto err_exit;
+ if (arg == 0)
+ break;
+ envp = PTRIN(arg);
+ error = copyinstr(envp, args->endp, args->stringspace,
+ &length);
+ if (error) {
+ if (error == ENAMETOOLONG)
+ error = E2BIG;
+ goto err_exit;
+ }
+ args->stringspace -= length;
+ args->endp += length;
+ args->envc++;
+ }
+ }
+
+ return (0);
+
+err_exit:
+ exec_free_args(args);
+ return (error);
+}
+
+int
+freebsd32_execve(struct thread *td, struct freebsd32_execve_args *uap)
+{
+ struct image_args eargs;
+ int error;
+
+ error = freebsd32_exec_copyin_args(&eargs, uap->fname, UIO_USERSPACE,
+ uap->argv, uap->envv);
+ if (error == 0)
+ error = kern_execve(td, &eargs, NULL);
+ return (error);
+}
+
+int
+freebsd32_fexecve(struct thread *td, struct freebsd32_fexecve_args *uap)
+{
+ struct image_args eargs;
+ int error;
+
+ error = freebsd32_exec_copyin_args(&eargs, NULL, UIO_SYSSPACE,
+ uap->argv, uap->envv);
+ if (error == 0) {
+ eargs.fd = uap->fd;
+ error = kern_execve(td, &eargs, NULL);
+ }
+ return (error);
+}
+
+#ifdef __ia64__
+static int
+freebsd32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
+ int prot, int fd, off_t pos)
+{
+ vm_map_t map;
+ vm_map_entry_t entry;
+ int rv;
+
+ map = &td->td_proc->p_vmspace->vm_map;
+ if (fd != -1)
+ prot |= VM_PROT_WRITE;
+
+ if (vm_map_lookup_entry(map, start, &entry)) {
+ if ((entry->protection & prot) != prot) {
+ rv = vm_map_protect(map,
+ trunc_page(start),
+ round_page(end),
+ entry->protection | prot,
+ FALSE);
+ if (rv != KERN_SUCCESS)
+ return (EINVAL);
+ }
+ } else {
+ vm_offset_t addr = trunc_page(start);
+ rv = vm_map_find(map, 0, 0,
+ &addr, PAGE_SIZE, FALSE, prot,
+ VM_PROT_ALL, 0);
+ if (rv != KERN_SUCCESS)
+ return (EINVAL);
+ }
+
+ if (fd != -1) {
+ struct pread_args r;
+ r.fd = fd;
+ r.buf = (void *) start;
+ r.nbyte = end - start;
+ r.offset = pos;
+ return (sys_pread(td, &r));
+ } else {
+ while (start < end) {
+ subyte((void *) start, 0);
+ start++;
+ }
+ return (0);
+ }
+}
+#endif
+
+int
+freebsd32_mprotect(struct thread *td, struct freebsd32_mprotect_args *uap)
+{
+ struct mprotect_args ap;
+
+ ap.addr = PTRIN(uap->addr);
+ ap.len = uap->len;
+ ap.prot = uap->prot;
+#if defined(__amd64__) || defined(__ia64__)
+ if (i386_read_exec && (ap.prot & PROT_READ) != 0)
+ ap.prot |= PROT_EXEC;
+#endif
+ return (sys_mprotect(td, &ap));
+}
+
+int
+freebsd32_mmap(struct thread *td, struct freebsd32_mmap_args *uap)
+{
+ struct mmap_args ap;
+ vm_offset_t addr = (vm_offset_t) uap->addr;
+ vm_size_t len = uap->len;
+ int prot = uap->prot;
+ int flags = uap->flags;
+ int fd = uap->fd;
+ off_t pos = PAIR32TO64(off_t,uap->pos);
+#ifdef __ia64__
+ vm_size_t pageoff;
+ int error;
+
+ /*
+ * Attempt to handle page size hassles.
+ */
+ pageoff = (pos & PAGE_MASK);
+ if (flags & MAP_FIXED) {
+ vm_offset_t start, end;
+ start = addr;
+ end = addr + len;
+
+ if (start != trunc_page(start)) {
+ error = freebsd32_mmap_partial(td, start,
+ round_page(start), prot,
+ fd, pos);
+ if (fd != -1)
+ pos += round_page(start) - start;
+ start = round_page(start);
+ }
+ if (end != round_page(end)) {
+ vm_offset_t t = trunc_page(end);
+ error = freebsd32_mmap_partial(td, t, end,
+ prot, fd,
+ pos + t - start);
+ end = trunc_page(end);
+ }
+ if (end > start && fd != -1 && (pos & PAGE_MASK)) {
+ /*
+ * We can't map this region at all. The specified
+ * address doesn't have the same alignment as the file
+ * position. Fake the mapping by simply reading the
+ * entire region into memory. First we need to make
+ * sure the region exists.
+ */
+ vm_map_t map;
+ struct pread_args r;
+ int rv;
+
+ prot |= VM_PROT_WRITE;
+ map = &td->td_proc->p_vmspace->vm_map;
+ rv = vm_map_remove(map, start, end);
+ if (rv != KERN_SUCCESS)
+ return (EINVAL);
+ rv = vm_map_find(map, 0, 0,
+ &start, end - start, FALSE,
+ prot, VM_PROT_ALL, 0);
+ if (rv != KERN_SUCCESS)
+ return (EINVAL);
+ r.fd = fd;
+ r.buf = (void *) start;
+ r.nbyte = end - start;
+ r.offset = pos;
+ error = sys_pread(td, &r);
+ if (error)
+ return (error);
+
+ td->td_retval[0] = addr;
+ return (0);
+ }
+ if (end == start) {
+ /*
+ * After dealing with the ragged ends, there
+ * might be none left.
+ */
+ td->td_retval[0] = addr;
+ return (0);
+ }
+ addr = start;
+ len = end - start;
+ }
+#endif
+
+#if defined(__amd64__) || defined(__ia64__)
+ if (i386_read_exec && (prot & PROT_READ))
+ prot |= PROT_EXEC;
+#endif
+
+ ap.addr = (void *) addr;
+ ap.len = len;
+ ap.prot = prot;
+ ap.flags = flags;
+ ap.fd = fd;
+ ap.pos = pos;
+
+ return (sys_mmap(td, &ap));
+}
+
+#ifdef COMPAT_FREEBSD6
+int
+freebsd6_freebsd32_mmap(struct thread *td, struct freebsd6_freebsd32_mmap_args *uap)
+{
+ struct freebsd32_mmap_args ap;
+
+ ap.addr = uap->addr;
+ ap.len = uap->len;
+ ap.prot = uap->prot;
+ ap.flags = uap->flags;
+ ap.fd = uap->fd;
+ ap.pos1 = uap->pos1;
+ ap.pos2 = uap->pos2;
+
+ return (freebsd32_mmap(td, &ap));
+}
+#endif
+
+int
+freebsd32_setitimer(struct thread *td, struct freebsd32_setitimer_args *uap)
+{
+ struct itimerval itv, oitv, *itvp;
+ struct itimerval32 i32;
+ int error;
+
+ if (uap->itv != NULL) {
+ error = copyin(uap->itv, &i32, sizeof(i32));
+ if (error)
+ return (error);
+ TV_CP(i32, itv, it_interval);
+ TV_CP(i32, itv, it_value);
+ itvp = &itv;
+ } else
+ itvp = NULL;
+ error = kern_setitimer(td, uap->which, itvp, &oitv);
+ if (error || uap->oitv == NULL)
+ return (error);
+ TV_CP(oitv, i32, it_interval);
+ TV_CP(oitv, i32, it_value);
+ return (copyout(&i32, uap->oitv, sizeof(i32)));
+}
+
+int
+freebsd32_getitimer(struct thread *td, struct freebsd32_getitimer_args *uap)
+{
+ struct itimerval itv;
+ struct itimerval32 i32;
+ int error;
+
+ error = kern_getitimer(td, uap->which, &itv);
+ if (error || uap->itv == NULL)
+ return (error);
+ TV_CP(itv, i32, it_interval);
+ TV_CP(itv, i32, it_value);
+ return (copyout(&i32, uap->itv, sizeof(i32)));
+}
+
+int
+freebsd32_select(struct thread *td, struct freebsd32_select_args *uap)
+{
+ struct timeval32 tv32;
+ struct timeval tv, *tvp;
+ int error;
+
+ if (uap->tv != NULL) {
+ error = copyin(uap->tv, &tv32, sizeof(tv32));
+ if (error)
+ return (error);
+ CP(tv32, tv, tv_sec);
+ CP(tv32, tv, tv_usec);
+ tvp = &tv;
+ } else
+ tvp = NULL;
+ /*
+ * XXX Do pointers need PTRIN()?
+ */
+ return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp,
+ sizeof(int32_t) * 8));
+}
+
+int
+freebsd32_pselect(struct thread *td, struct freebsd32_pselect_args *uap)
+{
+ struct timespec32 ts32;
+ struct timespec ts;
+ struct timeval tv, *tvp;
+ sigset_t set, *uset;
+ int error;
+
+ if (uap->ts != NULL) {
+ error = copyin(uap->ts, &ts32, sizeof(ts32));
+ if (error != 0)
+ return (error);
+ CP(ts32, ts, tv_sec);
+ CP(ts32, ts, tv_nsec);
+ TIMESPEC_TO_TIMEVAL(&tv, &ts);
+ tvp = &tv;
+ } else
+ tvp = NULL;
+ if (uap->sm != NULL) {
+ error = copyin(uap->sm, &set, sizeof(set));
+ if (error != 0)
+ return (error);
+ uset = &set;
+ } else
+ uset = NULL;
+ /*
+ * XXX Do pointers need PTRIN()?
+ */
+ error = kern_pselect(td, uap->nd, uap->in, uap->ou, uap->ex, tvp,
+ uset, sizeof(int32_t) * 8);
+ return (error);
+}
+
+/*
+ * Copy 'count' items into the destination list pointed to by uap->eventlist.
+ */
+static int
+freebsd32_kevent_copyout(void *arg, struct kevent *kevp, int count)
+{
+ struct freebsd32_kevent_args *uap;
+ struct kevent32 ks32[KQ_NEVENTS];
+ int i, error = 0;
+
+ KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
+ uap = (struct freebsd32_kevent_args *)arg;
+
+ for (i = 0; i < count; i++) {
+ CP(kevp[i], ks32[i], ident);
+ CP(kevp[i], ks32[i], filter);
+ CP(kevp[i], ks32[i], flags);
+ CP(kevp[i], ks32[i], fflags);
+ CP(kevp[i], ks32[i], data);
+ PTROUT_CP(kevp[i], ks32[i], udata);
+ }
+ error = copyout(ks32, uap->eventlist, count * sizeof *ks32);
+ if (error == 0)
+ uap->eventlist += count;
+ return (error);
+}
+
+/*
+ * Copy 'count' items from the list pointed to by uap->changelist.
+ */
+static int
+freebsd32_kevent_copyin(void *arg, struct kevent *kevp, int count)
+{
+ struct freebsd32_kevent_args *uap;
+ struct kevent32 ks32[KQ_NEVENTS];
+ int i, error = 0;
+
+ KASSERT(count <= KQ_NEVENTS, ("count (%d) > KQ_NEVENTS", count));
+ uap = (struct freebsd32_kevent_args *)arg;
+
+ error = copyin(uap->changelist, ks32, count * sizeof *ks32);
+ if (error)
+ goto done;
+ uap->changelist += count;
+
+ for (i = 0; i < count; i++) {
+ CP(ks32[i], kevp[i], ident);
+ CP(ks32[i], kevp[i], filter);
+ CP(ks32[i], kevp[i], flags);
+ CP(ks32[i], kevp[i], fflags);
+ CP(ks32[i], kevp[i], data);
+ PTRIN_CP(ks32[i], kevp[i], udata);
+ }
+done:
+ return (error);
+}
+
+int
+freebsd32_kevent(struct thread *td, struct freebsd32_kevent_args *uap)
+{
+ struct timespec32 ts32;
+ struct timespec ts, *tsp;
+ struct kevent_copyops k_ops = { uap,
+ freebsd32_kevent_copyout,
+ freebsd32_kevent_copyin};
+ int error;
+
+
+ if (uap->timeout) {
+ error = copyin(uap->timeout, &ts32, sizeof(ts32));
+ if (error)
+ return (error);
+ CP(ts32, ts, tv_sec);
+ CP(ts32, ts, tv_nsec);
+ tsp = &ts;
+ } else
+ tsp = NULL;
+ error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents,
+ &k_ops, tsp);
+ return (error);
+}
+
+int
+freebsd32_gettimeofday(struct thread *td,
+ struct freebsd32_gettimeofday_args *uap)
+{
+ struct timeval atv;
+ struct timeval32 atv32;
+ struct timezone rtz;
+ int error = 0;
+
+ if (uap->tp) {
+ microtime(&atv);
+ CP(atv, atv32, tv_sec);
+ CP(atv, atv32, tv_usec);
+ error = copyout(&atv32, uap->tp, sizeof (atv32));
+ }
+ if (error == 0 && uap->tzp != NULL) {
+ rtz.tz_minuteswest = tz_minuteswest;
+ rtz.tz_dsttime = tz_dsttime;
+ error = copyout(&rtz, uap->tzp, sizeof (rtz));
+ }
+ return (error);
+}
+
+int
+freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
+{
+ struct rusage32 s32;
+ struct rusage s;
+ int error;
+
+ error = kern_getrusage(td, uap->who, &s);
+ if (error)
+ return (error);
+ if (uap->rusage != NULL) {
+ freebsd32_rusage_out(&s, &s32);
+ error = copyout(&s32, uap->rusage, sizeof(s32));
+ }
+ return (error);
+}
+
+static int
+freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
+{
+ struct iovec32 iov32;
+ struct iovec *iov;
+ struct uio *uio;
+ u_int iovlen;
+ int error, i;
+
+ *uiop = NULL;
+ if (iovcnt > UIO_MAXIOV)
+ return (EINVAL);
+ iovlen = iovcnt * sizeof(struct iovec);
+ uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
+ iov = (struct iovec *)(uio + 1);
+ for (i = 0; i < iovcnt; i++) {
+ error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
+ if (error) {
+ free(uio, M_IOV);
+ return (error);
+ }
+ iov[i].iov_base = PTRIN(iov32.iov_base);
+ iov[i].iov_len = iov32.iov_len;
+ }
+ uio->uio_iov = iov;
+ uio->uio_iovcnt = iovcnt;
+ uio->uio_segflg = UIO_USERSPACE;
+ uio->uio_offset = -1;
+ uio->uio_resid = 0;
+ for (i = 0; i < iovcnt; i++) {
+ if (iov->iov_len > INT_MAX - uio->uio_resid) {
+ free(uio, M_IOV);
+ return (EINVAL);
+ }
+ uio->uio_resid += iov->iov_len;
+ iov++;
+ }
+ *uiop = uio;
+ return (0);
+}
+
+int
+freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
+{
+ struct uio *auio;
+ int error;
+
+ error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
+ if (error)
+ return (error);
+ error = kern_readv(td, uap->fd, auio);
+ free(auio, M_IOV);
+ return (error);
+}
+
+int
+freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
+{
+ struct uio *auio;
+ int error;
+
+ error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
+ if (error)
+ return (error);
+ error = kern_writev(td, uap->fd, auio);
+ free(auio, M_IOV);
+ return (error);
+}
+
+int
+freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
+{
+ struct uio *auio;
+ int error;
+
+ error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
+ if (error)
+ return (error);
+ error = kern_preadv(td, uap->fd, auio, PAIR32TO64(off_t,uap->offset));
+ free(auio, M_IOV);
+ return (error);
+}
+
+int
+freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
+{
+ struct uio *auio;
+ int error;
+
+ error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
+ if (error)
+ return (error);
+ error = kern_pwritev(td, uap->fd, auio, PAIR32TO64(off_t,uap->offset));
+ free(auio, M_IOV);
+ return (error);
+}
+
+int
+freebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp,
+ int error)
+{
+ struct iovec32 iov32;
+ struct iovec *iov;
+ u_int iovlen;
+ int i;
+
+ *iovp = NULL;
+ if (iovcnt > UIO_MAXIOV)
+ return (error);
+ iovlen = iovcnt * sizeof(struct iovec);
+ iov = malloc(iovlen, M_IOV, M_WAITOK);
+ for (i = 0; i < iovcnt; i++) {
+ error = copyin(&iovp32[i], &iov32, sizeof(struct iovec32));
+ if (error) {
+ free(iov, M_IOV);
+ return (error);
+ }
+ iov[i].iov_base = PTRIN(iov32.iov_base);
+ iov[i].iov_len = iov32.iov_len;
+ }
+ *iovp = iov;
+ return (0);
+}
+
+static int
+freebsd32_copyinmsghdr(struct msghdr32 *msg32, struct msghdr *msg)
+{
+ struct msghdr32 m32;
+ int error;
+
+ error = copyin(msg32, &m32, sizeof(m32));
+ if (error)
+ return (error);
+ msg->msg_name = PTRIN(m32.msg_name);
+ msg->msg_namelen = m32.msg_namelen;
+ msg->msg_iov = PTRIN(m32.msg_iov);
+ msg->msg_iovlen = m32.msg_iovlen;
+ msg->msg_control = PTRIN(m32.msg_control);
+ msg->msg_controllen = m32.msg_controllen;
+ msg->msg_flags = m32.msg_flags;
+ return (0);
+}
+
+static int
+freebsd32_copyoutmsghdr(struct msghdr *msg, struct msghdr32 *msg32)
+{
+ struct msghdr32 m32;
+ int error;
+
+ m32.msg_name = PTROUT(msg->msg_name);
+ m32.msg_namelen = msg->msg_namelen;
+ m32.msg_iov = PTROUT(msg->msg_iov);
+ m32.msg_iovlen = msg->msg_iovlen;
+ m32.msg_control = PTROUT(msg->msg_control);
+ m32.msg_controllen = msg->msg_controllen;
+ m32.msg_flags = msg->msg_flags;
+ error = copyout(&m32, msg32, sizeof(m32));
+ return (error);
+}
+
+#ifndef __mips__
+#define FREEBSD32_ALIGNBYTES (sizeof(int) - 1)
+#else
+#define FREEBSD32_ALIGNBYTES (sizeof(long) - 1)
+#endif
+#define FREEBSD32_ALIGN(p) \
+ (((u_long)(p) + FREEBSD32_ALIGNBYTES) & ~FREEBSD32_ALIGNBYTES)
+#define FREEBSD32_CMSG_SPACE(l) \
+ (FREEBSD32_ALIGN(sizeof(struct cmsghdr)) + FREEBSD32_ALIGN(l))
+
+#define FREEBSD32_CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + \
+ FREEBSD32_ALIGN(sizeof(struct cmsghdr)))
+static int
+freebsd32_copy_msg_out(struct msghdr *msg, struct mbuf *control)
+{
+ struct cmsghdr *cm;
+ void *data;
+ socklen_t clen, datalen;
+ int error;
+ caddr_t ctlbuf;
+ int len, maxlen, copylen;
+ struct mbuf *m;
+ error = 0;
+
+ len = msg->msg_controllen;
+ maxlen = msg->msg_controllen;
+ msg->msg_controllen = 0;
+
+ m = control;
+ ctlbuf = msg->msg_control;
+
+ while (m && len > 0) {
+ cm = mtod(m, struct cmsghdr *);
+ clen = m->m_len;
+
+ while (cm != NULL) {
+
+ if (sizeof(struct cmsghdr) > clen ||
+ cm->cmsg_len > clen) {
+ error = EINVAL;
+ break;
+ }
+
+ data = CMSG_DATA(cm);
+ datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
+
+ /* Adjust message length */
+ cm->cmsg_len = FREEBSD32_ALIGN(sizeof(struct cmsghdr)) +
+ datalen;
+
+
+ /* Copy cmsghdr */
+ copylen = sizeof(struct cmsghdr);
+ if (len < copylen) {
+ msg->msg_flags |= MSG_CTRUNC;
+ copylen = len;
+ }
+
+ error = copyout(cm,ctlbuf,copylen);
+ if (error)
+ goto exit;
+
+ ctlbuf += FREEBSD32_ALIGN(copylen);
+ len -= FREEBSD32_ALIGN(copylen);
+
+ if (len <= 0)
+ break;
+
+ /* Copy data */
+ copylen = datalen;
+ if (len < copylen) {
+ msg->msg_flags |= MSG_CTRUNC;
+ copylen = len;
+ }
+
+ error = copyout(data,ctlbuf,copylen);
+ if (error)
+ goto exit;
+
+ ctlbuf += FREEBSD32_ALIGN(copylen);
+ len -= FREEBSD32_ALIGN(copylen);
+
+ if (CMSG_SPACE(datalen) < clen) {
+ clen -= CMSG_SPACE(datalen);
+ cm = (struct cmsghdr *)
+ ((caddr_t)cm + CMSG_SPACE(datalen));
+ } else {
+ clen = 0;
+ cm = NULL;
+ }
+ }
+ m = m->m_next;
+ }
+
+ msg->msg_controllen = (len <= 0) ? maxlen : ctlbuf - (caddr_t)msg->msg_control;
+
+exit:
+ return (error);
+
+}
+
+int
+freebsd32_recvmsg(td, uap)
+ struct thread *td;
+ struct freebsd32_recvmsg_args /* {
+ int s;
+ struct msghdr32 *msg;
+ int flags;
+ } */ *uap;
+{
+ struct msghdr msg;
+ struct msghdr32 m32;
+ struct iovec *uiov, *iov;
+ struct mbuf *control = NULL;
+ struct mbuf **controlp;
+
+ int error;
+ error = copyin(uap->msg, &m32, sizeof(m32));
+ if (error)
+ return (error);
+ error = freebsd32_copyinmsghdr(uap->msg, &msg);
+ if (error)
+ return (error);
+ error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
+ EMSGSIZE);
+ if (error)
+ return (error);
+ msg.msg_flags = uap->flags;
+ uiov = msg.msg_iov;
+ msg.msg_iov = iov;
+
+ controlp = (msg.msg_control != NULL) ? &control : NULL;
+ error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, controlp);
+ if (error == 0) {
+ msg.msg_iov = uiov;
+
+ if (control != NULL)
+ error = freebsd32_copy_msg_out(&msg, control);
+ else
+ msg.msg_controllen = 0;
+
+ if (error == 0)
+ error = freebsd32_copyoutmsghdr(&msg, uap->msg);
+ }
+ free(iov, M_IOV);
+
+ if (control != NULL)
+ m_freem(control);
+
+ return (error);
+}
+
+
+static int
+freebsd32_convert_msg_in(struct mbuf **controlp)
+{
+ struct mbuf *control = *controlp;
+ struct cmsghdr *cm = mtod(control, struct cmsghdr *);
+ void *data;
+ socklen_t clen = control->m_len, datalen;
+ int error;
+
+ error = 0;
+ *controlp = NULL;
+
+ while (cm != NULL) {
+ if (sizeof(struct cmsghdr) > clen || cm->cmsg_len > clen) {
+ error = EINVAL;
+ break;
+ }
+
+ data = FREEBSD32_CMSG_DATA(cm);
+ datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
+
+ *controlp = sbcreatecontrol(data, datalen, cm->cmsg_type,
+ cm->cmsg_level);
+ controlp = &(*controlp)->m_next;
+
+ if (FREEBSD32_CMSG_SPACE(datalen) < clen) {
+ clen -= FREEBSD32_CMSG_SPACE(datalen);
+ cm = (struct cmsghdr *)
+ ((caddr_t)cm + FREEBSD32_CMSG_SPACE(datalen));
+ } else {
+ clen = 0;
+ cm = NULL;
+ }
+ }
+
+ m_freem(control);
+ return (error);
+}
+
+
+int
+freebsd32_sendmsg(struct thread *td,
+ struct freebsd32_sendmsg_args *uap)
+{
+ struct msghdr msg;
+ struct msghdr32 m32;
+ struct iovec *iov;
+ struct mbuf *control = NULL;
+ struct sockaddr *to = NULL;
+ int error;
+
+ error = copyin(uap->msg, &m32, sizeof(m32));
+ if (error)
+ return (error);
+ error = freebsd32_copyinmsghdr(uap->msg, &msg);
+ if (error)
+ return (error);
+ error = freebsd32_copyiniov(PTRIN(m32.msg_iov), m32.msg_iovlen, &iov,
+ EMSGSIZE);
+ if (error)
+ return (error);
+ msg.msg_iov = iov;
+ if (msg.msg_name != NULL) {
+ error = getsockaddr(&to, msg.msg_name, msg.msg_namelen);
+ if (error) {
+ to = NULL;
+ goto out;
+ }
+ msg.msg_name = to;
+ }
+
+ if (msg.msg_control) {
+ if (msg.msg_controllen < sizeof(struct cmsghdr)) {
+ error = EINVAL;
+ goto out;
+ }
+
+ error = sockargs(&control, msg.msg_control,
+ msg.msg_controllen, MT_CONTROL);
+ if (error)
+ goto out;
+
+ error = freebsd32_convert_msg_in(&control);
+ if (error)
+ goto out;
+ }
+
+ error = kern_sendit(td, uap->s, &msg, uap->flags, control,
+ UIO_USERSPACE);
+
+out:
+ free(iov, M_IOV);
+ if (to)
+ free(to, M_SONAME);
+ return (error);
+}
+
+int
+freebsd32_recvfrom(struct thread *td,
+ struct freebsd32_recvfrom_args *uap)
+{
+ struct msghdr msg;
+ struct iovec aiov;
+ int error;
+
+ if (uap->fromlenaddr) {
+ error = copyin(PTRIN(uap->fromlenaddr), &msg.msg_namelen,
+ sizeof(msg.msg_namelen));
+ if (error)
+ return (error);
+ } else {
+ msg.msg_namelen = 0;
+ }
+
+ msg.msg_name = PTRIN(uap->from);
+ msg.msg_iov = &aiov;
+ msg.msg_iovlen = 1;
+ aiov.iov_base = PTRIN(uap->buf);
+ aiov.iov_len = uap->len;
+ msg.msg_control = NULL;
+ msg.msg_flags = uap->flags;
+ error = kern_recvit(td, uap->s, &msg, UIO_USERSPACE, NULL);
+ if (error == 0 && uap->fromlenaddr)
+ error = copyout(&msg.msg_namelen, PTRIN(uap->fromlenaddr),
+ sizeof (msg.msg_namelen));
+ return (error);
+}
+
+int
+freebsd32_settimeofday(struct thread *td,
+ struct freebsd32_settimeofday_args *uap)
+{
+ struct timeval32 tv32;
+ struct timeval tv, *tvp;
+ struct timezone tz, *tzp;
+ int error;
+
+ if (uap->tv) {
+ error = copyin(uap->tv, &tv32, sizeof(tv32));
+ if (error)
+ return (error);
+ CP(tv32, tv, tv_sec);
+ CP(tv32, tv, tv_usec);
+ tvp = &tv;
+ } else
+ tvp = NULL;
+ if (uap->tzp) {
+ error = copyin(uap->tzp, &tz, sizeof(tz));
+ if (error)
+ return (error);
+ tzp = &tz;
+ } else
+ tzp = NULL;
+ return (kern_settimeofday(td, tvp, tzp));
+}
+
+int
+freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
+{
+ struct timeval32 s32[2];
+ struct timeval s[2], *sp;
+ int error;
+
+ if (uap->tptr != NULL) {
+ error = copyin(uap->tptr, s32, sizeof(s32));
+ if (error)
+ return (error);
+ CP(s32[0], s[0], tv_sec);
+ CP(s32[0], s[0], tv_usec);
+ CP(s32[1], s[1], tv_sec);
+ CP(s32[1], s[1], tv_usec);
+ sp = s;
+ } else
+ sp = NULL;
+ return (kern_utimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
+}
+
+int
+freebsd32_lutimes(struct thread *td, struct freebsd32_lutimes_args *uap)
+{
+ struct timeval32 s32[2];
+ struct timeval s[2], *sp;
+ int error;
+
+ if (uap->tptr != NULL) {
+ error = copyin(uap->tptr, s32, sizeof(s32));
+ if (error)
+ return (error);
+ CP(s32[0], s[0], tv_sec);
+ CP(s32[0], s[0], tv_usec);
+ CP(s32[1], s[1], tv_sec);
+ CP(s32[1], s[1], tv_usec);
+ sp = s;
+ } else
+ sp = NULL;
+ return (kern_lutimes(td, uap->path, UIO_USERSPACE, sp, UIO_SYSSPACE));
+}
+
+int
+freebsd32_futimes(struct thread *td, struct freebsd32_futimes_args *uap)
+{
+ struct timeval32 s32[2];
+ struct timeval s[2], *sp;
+ int error;
+
+ if (uap->tptr != NULL) {
+ error = copyin(uap->tptr, s32, sizeof(s32));
+ if (error)
+ return (error);
+ CP(s32[0], s[0], tv_sec);
+ CP(s32[0], s[0], tv_usec);
+ CP(s32[1], s[1], tv_sec);
+ CP(s32[1], s[1], tv_usec);
+ sp = s;
+ } else
+ sp = NULL;
+ return (kern_futimes(td, uap->fd, sp, UIO_SYSSPACE));
+}
+
+int
+freebsd32_futimesat(struct thread *td, struct freebsd32_futimesat_args *uap)
+{
+ struct timeval32 s32[2];
+ struct timeval s[2], *sp;
+ int error;
+
+ if (uap->times != NULL) {
+ error = copyin(uap->times, s32, sizeof(s32));
+ if (error)
+ return (error);
+ CP(s32[0], s[0], tv_sec);
+ CP(s32[0], s[0], tv_usec);
+ CP(s32[1], s[1], tv_sec);
+ CP(s32[1], s[1], tv_usec);
+ sp = s;
+ } else
+ sp = NULL;
+ return (kern_utimesat(td, uap->fd, uap->path, UIO_USERSPACE,
+ sp, UIO_SYSSPACE));
+}
+
+int
+freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
+{
+ struct timeval32 tv32;
+ struct timeval delta, olddelta, *deltap;
+ int error;
+
+ if (uap->delta) {
+ error = copyin(uap->delta, &tv32, sizeof(tv32));
+ if (error)
+ return (error);
+ CP(tv32, delta, tv_sec);
+ CP(tv32, delta, tv_usec);
+ deltap = &delta;
+ } else
+ deltap = NULL;
+ error = kern_adjtime(td, deltap, &olddelta);
+ if (uap->olddelta && error == 0) {
+ CP(olddelta, tv32, tv_sec);
+ CP(olddelta, tv32, tv_usec);
+ error = copyout(&tv32, uap->olddelta, sizeof(tv32));
+ }
+ return (error);
+}
+
+#ifdef COMPAT_FREEBSD4
+int
+freebsd4_freebsd32_statfs(struct thread *td, struct freebsd4_freebsd32_statfs_args *uap)
+{
+ struct statfs32 s32;
+ struct statfs s;
+ int error;
+
+ error = kern_statfs(td, uap->path, UIO_USERSPACE, &s);
+ if (error)
+ return (error);
+ copy_statfs(&s, &s32);
+ return (copyout(&s32, uap->buf, sizeof(s32)));
+}
+#endif
+
+#ifdef COMPAT_FREEBSD4
+int
+freebsd4_freebsd32_fstatfs(struct thread *td, struct freebsd4_freebsd32_fstatfs_args *uap)
+{
+ struct statfs32 s32;
+ struct statfs s;
+ int error;
+
+ error = kern_fstatfs(td, uap->fd, &s);
+ if (error)
+ return (error);
+ copy_statfs(&s, &s32);
+ return (copyout(&s32, uap->buf, sizeof(s32)));
+}
+#endif
+
+#ifdef COMPAT_FREEBSD4
+int
+freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatfs_args *uap)
+{
+ struct statfs32 s32;
+ struct statfs s;
+ fhandle_t fh;
+ int error;
+
+ if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
+ return (error);
+ error = kern_fhstatfs(td, fh, &s);
+ if (error)
+ return (error);
+ copy_statfs(&s, &s32);
+ return (copyout(&s32, uap->buf, sizeof(s32)));
+}
+#endif
+
+int
+freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap)
+{
+ struct pread_args ap;
+
+ ap.fd = uap->fd;
+ ap.buf = uap->buf;
+ ap.nbyte = uap->nbyte;
+ ap.offset = PAIR32TO64(off_t,uap->offset);
+ return (sys_pread(td, &ap));
+}
+
+int
+freebsd32_pwrite(struct thread *td, struct freebsd32_pwrite_args *uap)
+{
+ struct pwrite_args ap;
+
+ ap.fd = uap->fd;
+ ap.buf = uap->buf;
+ ap.nbyte = uap->nbyte;
+ ap.offset = PAIR32TO64(off_t,uap->offset);
+ return (sys_pwrite(td, &ap));
+}
+
+#ifdef COMPAT_43
+int
+ofreebsd32_lseek(struct thread *td, struct ofreebsd32_lseek_args *uap)
+{
+ struct lseek_args nuap;
+
+ nuap.fd = uap->fd;
+ nuap.offset = uap->offset;
+ nuap.whence = uap->whence;
+ return (sys_lseek(td, &nuap));
+}
+#endif
+
+int
+freebsd32_lseek(struct thread *td, struct freebsd32_lseek_args *uap)
+{
+ int error;
+ struct lseek_args ap;
+ off_t pos;
+
+ ap.fd = uap->fd;
+ ap.offset = PAIR32TO64(off_t,uap->offset);
+ ap.whence = uap->whence;
+ error = sys_lseek(td, &ap);
+ /* Expand the quad return into two parts for eax and edx */
+ pos = *(off_t *)(td->td_retval);
+ td->td_retval[RETVAL_LO] = pos & 0xffffffff; /* %eax */
+ td->td_retval[RETVAL_HI] = pos >> 32; /* %edx */
+ return error;
+}
+
+int
+freebsd32_truncate(struct thread *td, struct freebsd32_truncate_args *uap)
+{
+ struct truncate_args ap;
+
+ ap.path = uap->path;
+ ap.length = PAIR32TO64(off_t,uap->length);
+ return (sys_truncate(td, &ap));
+}
+
+int
+freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap)
+{
+ struct ftruncate_args ap;
+
+ ap.fd = uap->fd;
+ ap.length = PAIR32TO64(off_t,uap->length);
+ return (sys_ftruncate(td, &ap));
+}
+
+#ifdef COMPAT_43
+int
+ofreebsd32_getdirentries(struct thread *td,
+ struct ofreebsd32_getdirentries_args *uap)
+{
+ struct ogetdirentries_args ap;
+ int error;
+ long loff;
+ int32_t loff_cut;
+
+ ap.fd = uap->fd;
+ ap.buf = uap->buf;
+ ap.count = uap->count;
+ ap.basep = NULL;
+ error = kern_ogetdirentries(td, &ap, &loff);
+ if (error == 0) {
+ loff_cut = loff;
+ error = copyout(&loff_cut, uap->basep, sizeof(int32_t));
+ }
+ return (error);
+}
+#endif
+
+int
+freebsd32_getdirentries(struct thread *td,
+ struct freebsd32_getdirentries_args *uap)
+{
+ long base;
+ int32_t base32;
+ int error;
+
+ error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base,
+ NULL, UIO_USERSPACE);
+ if (error)
+ return (error);
+ if (uap->basep != NULL) {
+ base32 = base;
+ error = copyout(&base32, uap->basep, sizeof(int32_t));
+ }
+ return (error);
+}
+
+#ifdef COMPAT_FREEBSD6
+/* versions with the 'int pad' argument */
+int
+freebsd6_freebsd32_pread(struct thread *td, struct freebsd6_freebsd32_pread_args *uap)
+{
+ struct pread_args ap;
+
+ ap.fd = uap->fd;
+ ap.buf = uap->buf;
+ ap.nbyte = uap->nbyte;
+ ap.offset = PAIR32TO64(off_t,uap->offset);
+ return (sys_pread(td, &ap));
+}
+
+int
+freebsd6_freebsd32_pwrite(struct thread *td, struct freebsd6_freebsd32_pwrite_args *uap)
+{
+ struct pwrite_args ap;
+
+ ap.fd = uap->fd;
+ ap.buf = uap->buf;
+ ap.nbyte = uap->nbyte;
+ ap.offset = PAIR32TO64(off_t,uap->offset);
+ return (sys_pwrite(td, &ap));
+}
+
+int
+freebsd6_freebsd32_lseek(struct thread *td, struct freebsd6_freebsd32_lseek_args *uap)
+{
+ int error;
+ struct lseek_args ap;
+ off_t pos;
+
+ ap.fd = uap->fd;
+ ap.offset = PAIR32TO64(off_t,uap->offset);
+ ap.whence = uap->whence;
+ error = sys_lseek(td, &ap);
+ /* Expand the quad return into two parts for eax and edx */
+ pos = *(off_t *)(td->td_retval);
+ td->td_retval[RETVAL_LO] = pos & 0xffffffff; /* %eax */
+ td->td_retval[RETVAL_HI] = pos >> 32; /* %edx */
+ return error;
+}
+
+int
+freebsd6_freebsd32_truncate(struct thread *td, struct freebsd6_freebsd32_truncate_args *uap)
+{
+ struct truncate_args ap;
+
+ ap.path = uap->path;
+ ap.length = PAIR32TO64(off_t,uap->length);
+ return (sys_truncate(td, &ap));
+}
+
+int
+freebsd6_freebsd32_ftruncate(struct thread *td, struct freebsd6_freebsd32_ftruncate_args *uap)
+{
+ struct ftruncate_args ap;
+
+ ap.fd = uap->fd;
+ ap.length = PAIR32TO64(off_t,uap->length);
+ return (sys_ftruncate(td, &ap));
+}
+#endif /* COMPAT_FREEBSD6 */
+
+struct sf_hdtr32 {
+ uint32_t headers;
+ int hdr_cnt;
+ uint32_t trailers;
+ int trl_cnt;
+};
+
+static int
+freebsd32_do_sendfile(struct thread *td,
+ struct freebsd32_sendfile_args *uap, int compat)
+{
+ struct sendfile_args ap;
+ struct sf_hdtr32 hdtr32;
+ struct sf_hdtr hdtr;
+ struct uio *hdr_uio, *trl_uio;
+ struct iovec32 *iov32;
+ int error;
+
+ hdr_uio = trl_uio = NULL;
+
+ ap.fd = uap->fd;
+ ap.s = uap->s;
+ ap.offset = PAIR32TO64(off_t,uap->offset);
+ ap.nbytes = uap->nbytes;
+ ap.hdtr = (struct sf_hdtr *)uap->hdtr; /* XXX not used */
+ ap.sbytes = uap->sbytes;
+ ap.flags = uap->flags;
+
+ if (uap->hdtr != NULL) {
+ error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32));
+ if (error)
+ goto out;
+ PTRIN_CP(hdtr32, hdtr, headers);
+ CP(hdtr32, hdtr, hdr_cnt);
+ PTRIN_CP(hdtr32, hdtr, trailers);
+ CP(hdtr32, hdtr, trl_cnt);
+
+ if (hdtr.headers != NULL) {
+ iov32 = PTRIN(hdtr32.headers);
+ error = freebsd32_copyinuio(iov32,
+ hdtr32.hdr_cnt, &hdr_uio);
+ if (error)
+ goto out;
+ }
+ if (hdtr.trailers != NULL) {
+ iov32 = PTRIN(hdtr32.trailers);
+ error = freebsd32_copyinuio(iov32,
+ hdtr32.trl_cnt, &trl_uio);
+ if (error)
+ goto out;
+ }
+ }
+
+ error = kern_sendfile(td, &ap, hdr_uio, trl_uio, compat);
+out:
+ if (hdr_uio)
+ free(hdr_uio, M_IOV);
+ if (trl_uio)
+ free(trl_uio, M_IOV);
+ return (error);
+}
+
+#ifdef COMPAT_FREEBSD4
+int
+freebsd4_freebsd32_sendfile(struct thread *td,
+ struct freebsd4_freebsd32_sendfile_args *uap)
+{
+ return (freebsd32_do_sendfile(td,
+ (struct freebsd32_sendfile_args *)uap, 1));
+}
+#endif
+
+int
+freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
+{
+
+ return (freebsd32_do_sendfile(td, uap, 0));
+}
+
+static void
+copy_stat(struct stat *in, struct stat32 *out)
+{
+
+ CP(*in, *out, st_dev);
+ CP(*in, *out, st_ino);
+ CP(*in, *out, st_mode);
+ CP(*in, *out, st_nlink);
+ CP(*in, *out, st_uid);
+ CP(*in, *out, st_gid);
+ CP(*in, *out, st_rdev);
+ TS_CP(*in, *out, st_atim);
+ TS_CP(*in, *out, st_mtim);
+ TS_CP(*in, *out, st_ctim);
+ CP(*in, *out, st_size);
+ CP(*in, *out, st_blocks);
+ CP(*in, *out, st_blksize);
+ CP(*in, *out, st_flags);
+ CP(*in, *out, st_gen);
+ TS_CP(*in, *out, st_birthtim);
+}
+
+#ifdef COMPAT_43
+static void
+copy_ostat(struct stat *in, struct ostat32 *out)
+{
+
+ CP(*in, *out, st_dev);
+ CP(*in, *out, st_ino);
+ CP(*in, *out, st_mode);
+ CP(*in, *out, st_nlink);
+ CP(*in, *out, st_uid);
+ CP(*in, *out, st_gid);
+ CP(*in, *out, st_rdev);
+ CP(*in, *out, st_size);
+ TS_CP(*in, *out, st_atim);
+ TS_CP(*in, *out, st_mtim);
+ TS_CP(*in, *out, st_ctim);
+ CP(*in, *out, st_blksize);
+ CP(*in, *out, st_blocks);
+ CP(*in, *out, st_flags);
+ CP(*in, *out, st_gen);
+}
+#endif
+
+int
+freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
+{
+ struct stat sb;
+ struct stat32 sb32;
+ int error;
+
+ error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
+ if (error)
+ return (error);
+ copy_stat(&sb, &sb32);
+ error = copyout(&sb32, uap->ub, sizeof (sb32));
+ return (error);
+}
+
+#ifdef COMPAT_43
+int
+ofreebsd32_stat(struct thread *td, struct ofreebsd32_stat_args *uap)
+{
+ struct stat sb;
+ struct ostat32 sb32;
+ int error;
+
+ error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
+ if (error)
+ return (error);
+ copy_ostat(&sb, &sb32);
+ error = copyout(&sb32, uap->ub, sizeof (sb32));
+ return (error);
+}
+#endif
+
+int
+freebsd32_fstat(struct thread *td, struct freebsd32_fstat_args *uap)
+{
+ struct stat ub;
+ struct stat32 ub32;
+ int error;
+
+ error = kern_fstat(td, uap->fd, &ub);
+ if (error)
+ return (error);
+ copy_stat(&ub, &ub32);
+ error = copyout(&ub32, uap->ub, sizeof(ub32));
+ return (error);
+}
+
+#ifdef COMPAT_43
+int
+ofreebsd32_fstat(struct thread *td, struct ofreebsd32_fstat_args *uap)
+{
+ struct stat ub;
+ struct ostat32 ub32;
+ int error;
+
+ error = kern_fstat(td, uap->fd, &ub);
+ if (error)
+ return (error);
+ copy_ostat(&ub, &ub32);
+ error = copyout(&ub32, uap->ub, sizeof(ub32));
+ return (error);
+}
+#endif
+
+int
+freebsd32_fstatat(struct thread *td, struct freebsd32_fstatat_args *uap)
+{
+ struct stat ub;
+ struct stat32 ub32;
+ int error;
+
+ error = kern_statat(td, uap->flag, uap->fd, uap->path, UIO_USERSPACE, &ub);
+ if (error)
+ return (error);
+ copy_stat(&ub, &ub32);
+ error = copyout(&ub32, uap->buf, sizeof(ub32));
+ return (error);
+}
+
+int
+freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
+{
+ struct stat sb;
+ struct stat32 sb32;
+ int error;
+
+ error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
+ if (error)
+ return (error);
+ copy_stat(&sb, &sb32);
+ error = copyout(&sb32, uap->ub, sizeof (sb32));
+ return (error);
+}
+
+#ifdef COMPAT_43
+int
+ofreebsd32_lstat(struct thread *td, struct ofreebsd32_lstat_args *uap)
+{
+ struct stat sb;
+ struct ostat32 sb32;
+ int error;
+
+ error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
+ if (error)
+ return (error);
+ copy_ostat(&sb, &sb32);
+ error = copyout(&sb32, uap->ub, sizeof (sb32));
+ return (error);
+}
+#endif
+
+int
+freebsd32_sysctl(struct thread *td, struct freebsd32_sysctl_args *uap)
+{
+ int error, name[CTL_MAXNAME];
+ size_t j, oldlen;
+
+ if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
+ return (EINVAL);
+ error = copyin(uap->name, name, uap->namelen * sizeof(int));
+ if (error)
+ return (error);
+ if (uap->oldlenp)
+ oldlen = fuword32(uap->oldlenp);
+ else
+ oldlen = 0;
+ error = userland_sysctl(td, name, uap->namelen,
+ uap->old, &oldlen, 1,
+ uap->new, uap->newlen, &j, SCTL_MASK32);
+ if (error && error != ENOMEM)
+ return (error);
+ if (uap->oldlenp)
+ suword32(uap->oldlenp, j);
+ return (0);
+}
+
+int
+freebsd32_jail(struct thread *td, struct freebsd32_jail_args *uap)
+{
+ uint32_t version;
+ int error;
+ struct jail j;
+
+ error = copyin(uap->jail, &version, sizeof(uint32_t));
+ if (error)
+ return (error);
+
+ switch (version) {
+ case 0:
+ {
+ /* FreeBSD single IPv4 jails. */
+ struct jail32_v0 j32_v0;
+
+ bzero(&j, sizeof(struct jail));
+ error = copyin(uap->jail, &j32_v0, sizeof(struct jail32_v0));
+ if (error)
+ return (error);
+ CP(j32_v0, j, version);
+ PTRIN_CP(j32_v0, j, path);
+ PTRIN_CP(j32_v0, j, hostname);
+ j.ip4s = j32_v0.ip_number;
+ break;
+ }
+
+ case 1:
+ /*
+ * Version 1 was used by multi-IPv4 jail implementations
+ * that never made it into the official kernel.
+ */
+ return (EINVAL);
+
+ case 2: /* JAIL_API_VERSION */
+ {
+ /* FreeBSD multi-IPv4/IPv6,noIP jails. */
+ struct jail32 j32;
+
+ error = copyin(uap->jail, &j32, sizeof(struct jail32));
+ if (error)
+ return (error);
+ CP(j32, j, version);
+ PTRIN_CP(j32, j, path);
+ PTRIN_CP(j32, j, hostname);
+ PTRIN_CP(j32, j, jailname);
+ CP(j32, j, ip4s);
+ CP(j32, j, ip6s);
+ PTRIN_CP(j32, j, ip4);
+ PTRIN_CP(j32, j, ip6);
+ break;
+ }
+
+ default:
+ /* Sci-Fi jails are not supported, sorry. */
+ return (EINVAL);
+ }
+ return (kern_jail(td, &j));
+}
+
+int
+freebsd32_jail_set(struct thread *td, struct freebsd32_jail_set_args *uap)
+{
+ struct uio *auio;
+ int error;
+
+ /* Check that we have an even number of iovecs. */
+ if (uap->iovcnt & 1)
+ return (EINVAL);
+
+ error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
+ if (error)
+ return (error);
+ error = kern_jail_set(td, auio, uap->flags);
+ free(auio, M_IOV);
+ return (error);
+}
+
+int
+freebsd32_jail_get(struct thread *td, struct freebsd32_jail_get_args *uap)
+{
+ struct iovec32 iov32;
+ struct uio *auio;
+ int error, i;
+
+ /* Check that we have an even number of iovecs. */
+ if (uap->iovcnt & 1)
+ return (EINVAL);
+
+ error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
+ if (error)
+ return (error);
+ error = kern_jail_get(td, auio, uap->flags);
+ if (error == 0)
+ for (i = 0; i < uap->iovcnt; i++) {
+ PTROUT_CP(auio->uio_iov[i], iov32, iov_base);
+ CP(auio->uio_iov[i], iov32, iov_len);
+ error = copyout(&iov32, uap->iovp + i, sizeof(iov32));
+ if (error != 0)
+ break;
+ }
+ free(auio, M_IOV);
+ return (error);
+}
+
+int
+freebsd32_sigaction(struct thread *td, struct freebsd32_sigaction_args *uap)
+{
+ struct sigaction32 s32;
+ struct sigaction sa, osa, *sap;
+ int error;
+
+ if (uap->act) {
+ error = copyin(uap->act, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ sa.sa_handler = PTRIN(s32.sa_u);
+ CP(s32, sa, sa_flags);
+ CP(s32, sa, sa_mask);
+ sap = &sa;
+ } else
+ sap = NULL;
+ error = kern_sigaction(td, uap->sig, sap, &osa, 0);
+ if (error == 0 && uap->oact != NULL) {
+ s32.sa_u = PTROUT(osa.sa_handler);
+ CP(osa, s32, sa_flags);
+ CP(osa, s32, sa_mask);
+ error = copyout(&s32, uap->oact, sizeof(s32));
+ }
+ return (error);
+}
+
+#ifdef COMPAT_FREEBSD4
+int
+freebsd4_freebsd32_sigaction(struct thread *td,
+ struct freebsd4_freebsd32_sigaction_args *uap)
+{
+ struct sigaction32 s32;
+ struct sigaction sa, osa, *sap;
+ int error;
+
+ if (uap->act) {
+ error = copyin(uap->act, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ sa.sa_handler = PTRIN(s32.sa_u);
+ CP(s32, sa, sa_flags);
+ CP(s32, sa, sa_mask);
+ sap = &sa;
+ } else
+ sap = NULL;
+ error = kern_sigaction(td, uap->sig, sap, &osa, KSA_FREEBSD4);
+ if (error == 0 && uap->oact != NULL) {
+ s32.sa_u = PTROUT(osa.sa_handler);
+ CP(osa, s32, sa_flags);
+ CP(osa, s32, sa_mask);
+ error = copyout(&s32, uap->oact, sizeof(s32));
+ }
+ return (error);
+}
+#endif
+
+#ifdef COMPAT_43
+struct osigaction32 {
+ u_int32_t sa_u;
+ osigset_t sa_mask;
+ int sa_flags;
+};
+
+#define ONSIG 32
+
+int
+ofreebsd32_sigaction(struct thread *td,
+ struct ofreebsd32_sigaction_args *uap)
+{
+ struct osigaction32 s32;
+ struct sigaction sa, osa, *sap;
+ int error;
+
+ if (uap->signum <= 0 || uap->signum >= ONSIG)
+ return (EINVAL);
+
+ if (uap->nsa) {
+ error = copyin(uap->nsa, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ sa.sa_handler = PTRIN(s32.sa_u);
+ CP(s32, sa, sa_flags);
+ OSIG2SIG(s32.sa_mask, sa.sa_mask);
+ sap = &sa;
+ } else
+ sap = NULL;
+ error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
+ if (error == 0 && uap->osa != NULL) {
+ s32.sa_u = PTROUT(osa.sa_handler);
+ CP(osa, s32, sa_flags);
+ SIG2OSIG(osa.sa_mask, s32.sa_mask);
+ error = copyout(&s32, uap->osa, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ofreebsd32_sigprocmask(struct thread *td,
+ struct ofreebsd32_sigprocmask_args *uap)
+{
+ sigset_t set, oset;
+ int error;
+
+ OSIG2SIG(uap->mask, set);
+ error = kern_sigprocmask(td, uap->how, &set, &oset, SIGPROCMASK_OLD);
+ SIG2OSIG(oset, td->td_retval[0]);
+ return (error);
+}
+
+int
+ofreebsd32_sigpending(struct thread *td,
+ struct ofreebsd32_sigpending_args *uap)
+{
+ struct proc *p = td->td_proc;
+ sigset_t siglist;
+
+ PROC_LOCK(p);
+ siglist = p->p_siglist;
+ SIGSETOR(siglist, td->td_siglist);
+ PROC_UNLOCK(p);
+ SIG2OSIG(siglist, td->td_retval[0]);
+ return (0);
+}
+
+struct sigvec32 {
+ u_int32_t sv_handler;
+ int sv_mask;
+ int sv_flags;
+};
+
+int
+ofreebsd32_sigvec(struct thread *td,
+ struct ofreebsd32_sigvec_args *uap)
+{
+ struct sigvec32 vec;
+ struct sigaction sa, osa, *sap;
+ int error;
+
+ if (uap->signum <= 0 || uap->signum >= ONSIG)
+ return (EINVAL);
+
+ if (uap->nsv) {
+ error = copyin(uap->nsv, &vec, sizeof(vec));
+ if (error)
+ return (error);
+ sa.sa_handler = PTRIN(vec.sv_handler);
+ OSIG2SIG(vec.sv_mask, sa.sa_mask);
+ sa.sa_flags = vec.sv_flags;
+ sa.sa_flags ^= SA_RESTART;
+ sap = &sa;
+ } else
+ sap = NULL;
+ error = kern_sigaction(td, uap->signum, sap, &osa, KSA_OSIGSET);
+ if (error == 0 && uap->osv != NULL) {
+ vec.sv_handler = PTROUT(osa.sa_handler);
+ SIG2OSIG(osa.sa_mask, vec.sv_mask);
+ vec.sv_flags = osa.sa_flags;
+ vec.sv_flags &= ~SA_NOCLDWAIT;
+ vec.sv_flags ^= SA_RESTART;
+ error = copyout(&vec, uap->osv, sizeof(vec));
+ }
+ return (error);
+}
+
+int
+ofreebsd32_sigblock(struct thread *td,
+ struct ofreebsd32_sigblock_args *uap)
+{
+ sigset_t set, oset;
+
+ OSIG2SIG(uap->mask, set);
+ kern_sigprocmask(td, SIG_BLOCK, &set, &oset, 0);
+ SIG2OSIG(oset, td->td_retval[0]);
+ return (0);
+}
+
+int
+ofreebsd32_sigsetmask(struct thread *td,
+ struct ofreebsd32_sigsetmask_args *uap)
+{
+ sigset_t set, oset;
+
+ OSIG2SIG(uap->mask, set);
+ kern_sigprocmask(td, SIG_SETMASK, &set, &oset, 0);
+ SIG2OSIG(oset, td->td_retval[0]);
+ return (0);
+}
+
+int
+ofreebsd32_sigsuspend(struct thread *td,
+ struct ofreebsd32_sigsuspend_args *uap)
+{
+ sigset_t mask;
+
+ OSIG2SIG(uap->mask, mask);
+ return (kern_sigsuspend(td, mask));
+}
+
+struct sigstack32 {
+ u_int32_t ss_sp;
+ int ss_onstack;
+};
+
+int
+ofreebsd32_sigstack(struct thread *td,
+ struct ofreebsd32_sigstack_args *uap)
+{
+ struct sigstack32 s32;
+ struct sigstack nss, oss;
+ int error = 0, unss;
+
+ if (uap->nss != NULL) {
+ error = copyin(uap->nss, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ nss.ss_sp = PTRIN(s32.ss_sp);
+ CP(s32, nss, ss_onstack);
+ unss = 1;
+ } else {
+ unss = 0;
+ }
+ oss.ss_sp = td->td_sigstk.ss_sp;
+ oss.ss_onstack = sigonstack(cpu_getstack(td));
+ if (unss) {
+ td->td_sigstk.ss_sp = nss.ss_sp;
+ td->td_sigstk.ss_size = 0;
+ td->td_sigstk.ss_flags |= (nss.ss_onstack & SS_ONSTACK);
+ td->td_pflags |= TDP_ALTSTACK;
+ }
+ if (uap->oss != NULL) {
+ s32.ss_sp = PTROUT(oss.ss_sp);
+ CP(oss, s32, ss_onstack);
+ error = copyout(&s32, uap->oss, sizeof(s32));
+ }
+ return (error);
+}
+#endif
+
+int
+freebsd32_nanosleep(struct thread *td, struct freebsd32_nanosleep_args *uap)
+{
+ struct timespec32 rmt32, rqt32;
+ struct timespec rmt, rqt;
+ int error;
+
+ error = copyin(uap->rqtp, &rqt32, sizeof(rqt32));
+ if (error)
+ return (error);
+
+ CP(rqt32, rqt, tv_sec);
+ CP(rqt32, rqt, tv_nsec);
+
+ if (uap->rmtp &&
+ !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE))
+ return (EFAULT);
+ error = kern_nanosleep(td, &rqt, &rmt);
+ if (error && uap->rmtp) {
+ int error2;
+
+ CP(rmt, rmt32, tv_sec);
+ CP(rmt, rmt32, tv_nsec);
+
+ error2 = copyout(&rmt32, uap->rmtp, sizeof(rmt32));
+ if (error2)
+ error = error2;
+ }
+ return (error);
+}
+
+int
+freebsd32_clock_gettime(struct thread *td,
+ struct freebsd32_clock_gettime_args *uap)
+{
+ struct timespec ats;
+ struct timespec32 ats32;
+ int error;
+
+ error = kern_clock_gettime(td, uap->clock_id, &ats);
+ if (error == 0) {
+ CP(ats, ats32, tv_sec);
+ CP(ats, ats32, tv_nsec);
+ error = copyout(&ats32, uap->tp, sizeof(ats32));
+ }
+ return (error);
+}
+
+int
+freebsd32_clock_settime(struct thread *td,
+ struct freebsd32_clock_settime_args *uap)
+{
+ struct timespec ats;
+ struct timespec32 ats32;
+ int error;
+
+ error = copyin(uap->tp, &ats32, sizeof(ats32));
+ if (error)
+ return (error);
+ CP(ats32, ats, tv_sec);
+ CP(ats32, ats, tv_nsec);
+
+ return (kern_clock_settime(td, uap->clock_id, &ats));
+}
+
+int
+freebsd32_clock_getres(struct thread *td,
+ struct freebsd32_clock_getres_args *uap)
+{
+ struct timespec ts;
+ struct timespec32 ts32;
+ int error;
+
+ if (uap->tp == NULL)
+ return (0);
+ error = kern_clock_getres(td, uap->clock_id, &ts);
+ if (error == 0) {
+ CP(ts, ts32, tv_sec);
+ CP(ts, ts32, tv_nsec);
+ error = copyout(&ts32, uap->tp, sizeof(ts32));
+ }
+ return (error);
+}
+
+int
+freebsd32_thr_new(struct thread *td,
+ struct freebsd32_thr_new_args *uap)
+{
+ struct thr_param32 param32;
+ struct thr_param param;
+ int error;
+
+ if (uap->param_size < 0 ||
+ uap->param_size > sizeof(struct thr_param32))
+ return (EINVAL);
+ bzero(&param, sizeof(struct thr_param));
+ bzero(&param32, sizeof(struct thr_param32));
+ error = copyin(uap->param, &param32, uap->param_size);
+ if (error != 0)
+ return (error);
+ param.start_func = PTRIN(param32.start_func);
+ param.arg = PTRIN(param32.arg);
+ param.stack_base = PTRIN(param32.stack_base);
+ param.stack_size = param32.stack_size;
+ param.tls_base = PTRIN(param32.tls_base);
+ param.tls_size = param32.tls_size;
+ param.child_tid = PTRIN(param32.child_tid);
+ param.parent_tid = PTRIN(param32.parent_tid);
+ param.flags = param32.flags;
+ param.rtp = PTRIN(param32.rtp);
+ param.spare[0] = PTRIN(param32.spare[0]);
+ param.spare[1] = PTRIN(param32.spare[1]);
+ param.spare[2] = PTRIN(param32.spare[2]);
+
+ return (kern_thr_new(td, &param));
+}
+
+int
+freebsd32_thr_suspend(struct thread *td, struct freebsd32_thr_suspend_args *uap)
+{
+ struct timespec32 ts32;
+ struct timespec ts, *tsp;
+ int error;
+
+ error = 0;
+ tsp = NULL;
+ if (uap->timeout != NULL) {
+ error = copyin((const void *)uap->timeout, (void *)&ts32,
+ sizeof(struct timespec32));
+ if (error != 0)
+ return (error);
+ ts.tv_sec = ts32.tv_sec;
+ ts.tv_nsec = ts32.tv_nsec;
+ tsp = &ts;
+ }
+ return (kern_thr_suspend(td, tsp));
+}
+
+void
+siginfo_to_siginfo32(const siginfo_t *src, struct siginfo32 *dst)
+{
+ bzero(dst, sizeof(*dst));
+ dst->si_signo = src->si_signo;
+ dst->si_errno = src->si_errno;
+ dst->si_code = src->si_code;
+ dst->si_pid = src->si_pid;
+ dst->si_uid = src->si_uid;
+ dst->si_status = src->si_status;
+ dst->si_addr = (uintptr_t)src->si_addr;
+ dst->si_value.sigval_int = src->si_value.sival_int;
+ dst->si_timerid = src->si_timerid;
+ dst->si_overrun = src->si_overrun;
+}
+
+int
+freebsd32_sigtimedwait(struct thread *td, struct freebsd32_sigtimedwait_args *uap)
+{
+ struct timespec32 ts32;
+ struct timespec ts;
+ struct timespec *timeout;
+ sigset_t set;
+ ksiginfo_t ksi;
+ struct siginfo32 si32;
+ int error;
+
+ if (uap->timeout) {
+ error = copyin(uap->timeout, &ts32, sizeof(ts32));
+ if (error)
+ return (error);
+ ts.tv_sec = ts32.tv_sec;
+ ts.tv_nsec = ts32.tv_nsec;
+ timeout = &ts;
+ } else
+ timeout = NULL;
+
+ error = copyin(uap->set, &set, sizeof(set));
+ if (error)
+ return (error);
+
+ error = kern_sigtimedwait(td, set, &ksi, timeout);
+ if (error)
+ return (error);
+
+ if (uap->info) {
+ siginfo_to_siginfo32(&ksi.ksi_info, &si32);
+ error = copyout(&si32, uap->info, sizeof(struct siginfo32));
+ }
+
+ if (error == 0)
+ td->td_retval[0] = ksi.ksi_signo;
+ return (error);
+}
+
+/*
+ * MPSAFE
+ */
+int
+freebsd32_sigwaitinfo(struct thread *td, struct freebsd32_sigwaitinfo_args *uap)
+{
+ ksiginfo_t ksi;
+ struct siginfo32 si32;
+ sigset_t set;
+ int error;
+
+ error = copyin(uap->set, &set, sizeof(set));
+ if (error)
+ return (error);
+
+ error = kern_sigtimedwait(td, set, &ksi, NULL);
+ if (error)
+ return (error);
+
+ if (uap->info) {
+ siginfo_to_siginfo32(&ksi.ksi_info, &si32);
+ error = copyout(&si32, uap->info, sizeof(struct siginfo32));
+ }
+ if (error == 0)
+ td->td_retval[0] = ksi.ksi_signo;
+ return (error);
+}
+
+int
+freebsd32_cpuset_setid(struct thread *td,
+ struct freebsd32_cpuset_setid_args *uap)
+{
+ struct cpuset_setid_args ap;
+
+ ap.which = uap->which;
+ ap.id = PAIR32TO64(id_t,uap->id);
+ ap.setid = uap->setid;
+
+ return (sys_cpuset_setid(td, &ap));
+}
+
+int
+freebsd32_cpuset_getid(struct thread *td,
+ struct freebsd32_cpuset_getid_args *uap)
+{
+ struct cpuset_getid_args ap;
+
+ ap.level = uap->level;
+ ap.which = uap->which;
+ ap.id = PAIR32TO64(id_t,uap->id);
+ ap.setid = uap->setid;
+
+ return (sys_cpuset_getid(td, &ap));
+}
+
+int
+freebsd32_cpuset_getaffinity(struct thread *td,
+ struct freebsd32_cpuset_getaffinity_args *uap)
+{
+ struct cpuset_getaffinity_args ap;
+
+ ap.level = uap->level;
+ ap.which = uap->which;
+ ap.id = PAIR32TO64(id_t,uap->id);
+ ap.cpusetsize = uap->cpusetsize;
+ ap.mask = uap->mask;
+
+ return (sys_cpuset_getaffinity(td, &ap));
+}
+
+int
+freebsd32_cpuset_setaffinity(struct thread *td,
+ struct freebsd32_cpuset_setaffinity_args *uap)
+{
+ struct cpuset_setaffinity_args ap;
+
+ ap.level = uap->level;
+ ap.which = uap->which;
+ ap.id = PAIR32TO64(id_t,uap->id);
+ ap.cpusetsize = uap->cpusetsize;
+ ap.mask = uap->mask;
+
+ return (sys_cpuset_setaffinity(td, &ap));
+}
+
+int
+freebsd32_nmount(struct thread *td,
+ struct freebsd32_nmount_args /* {
+ struct iovec *iovp;
+ unsigned int iovcnt;
+ int flags;
+ } */ *uap)
+{
+ struct uio *auio;
+ uint64_t flags;
+ int error;
+
+ /*
+ * Mount flags are now 64-bits. On 32-bit archtectures only
+ * 32-bits are passed in, but from here on everything handles
+ * 64-bit flags correctly.
+ */
+ flags = uap->flags;
+
+ AUDIT_ARG_FFLAGS(flags);
+
+ /*
+ * Filter out MNT_ROOTFS. We do not want clients of nmount() in
+ * userspace to set this flag, but we must filter it out if we want
+ * MNT_UPDATE on the root file system to work.
+ * MNT_ROOTFS should only be set by the kernel when mounting its
+ * root file system.
+ */
+ flags &= ~MNT_ROOTFS;
+
+ /*
+ * check that we have an even number of iovec's
+ * and that we have at least two options.
+ */
+ if ((uap->iovcnt & 1) || (uap->iovcnt < 4))
+ return (EINVAL);
+
+ error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
+ if (error)
+ return (error);
+ error = vfs_donmount(td, flags, auio);
+
+ free(auio, M_IOV);
+ return error;
+}
+
+#if 0
+int
+freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap)
+{
+ struct yyy32 *p32, s32;
+ struct yyy *p = NULL, s;
+ struct xxx_arg ap;
+ int error;
+
+ if (uap->zzz) {
+ error = copyin(uap->zzz, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ /* translate in */
+ p = &s;
+ }
+ error = kern_xxx(td, p);
+ if (error)
+ return (error);
+ if (uap->zzz) {
+ /* translate out */
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+#endif
+
+int
+syscall32_register(int *offset, struct sysent *new_sysent,
+ struct sysent *old_sysent)
+{
+ if (*offset == NO_SYSCALL) {
+ int i;
+
+ for (i = 1; i < SYS_MAXSYSCALL; ++i)
+ if (freebsd32_sysent[i].sy_call ==
+ (sy_call_t *)lkmnosys)
+ break;
+ if (i == SYS_MAXSYSCALL)
+ return (ENFILE);
+ *offset = i;
+ } else if (*offset < 0 || *offset >= SYS_MAXSYSCALL)
+ return (EINVAL);
+ else if (freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmnosys &&
+ freebsd32_sysent[*offset].sy_call != (sy_call_t *)lkmressys)
+ return (EEXIST);
+
+ *old_sysent = freebsd32_sysent[*offset];
+ freebsd32_sysent[*offset] = *new_sysent;
+ return 0;
+}
+
+int
+syscall32_deregister(int *offset, struct sysent *old_sysent)
+{
+
+ if (*offset)
+ freebsd32_sysent[*offset] = *old_sysent;
+ return 0;
+}
+
+int
+syscall32_module_handler(struct module *mod, int what, void *arg)
+{
+ struct syscall_module_data *data = (struct syscall_module_data*)arg;
+ modspecific_t ms;
+ int error;
+
+ switch (what) {
+ case MOD_LOAD:
+ error = syscall32_register(data->offset, data->new_sysent,
+ &data->old_sysent);
+ if (error) {
+ /* Leave a mark so we know to safely unload below. */
+ data->offset = NULL;
+ return error;
+ }
+ ms.intval = *data->offset;
+ MOD_XLOCK;
+ module_setspecific(mod, &ms);
+ MOD_XUNLOCK;
+ if (data->chainevh)
+ error = data->chainevh(mod, what, data->chainarg);
+ return (error);
+ case MOD_UNLOAD:
+ /*
+ * MOD_LOAD failed, so just return without calling the
+ * chained handler since we didn't pass along the MOD_LOAD
+ * event.
+ */
+ if (data->offset == NULL)
+ return (0);
+ if (data->chainevh) {
+ error = data->chainevh(mod, what, data->chainarg);
+ if (error)
+ return (error);
+ }
+ error = syscall32_deregister(data->offset, &data->old_sysent);
+ return (error);
+ default:
+ error = EOPNOTSUPP;
+ if (data->chainevh)
+ error = data->chainevh(mod, what, data->chainarg);
+ return (error);
+ }
+}
+
+int
+syscall32_helper_register(struct syscall_helper_data *sd)
+{
+ struct syscall_helper_data *sd1;
+ int error;
+
+ for (sd1 = sd; sd1->syscall_no != NO_SYSCALL; sd1++) {
+ error = syscall32_register(&sd1->syscall_no, &sd1->new_sysent,
+ &sd1->old_sysent);
+ if (error != 0) {
+ syscall32_helper_unregister(sd);
+ return (error);
+ }
+ sd1->registered = 1;
+ }
+ return (0);
+}
+
+int
+syscall32_helper_unregister(struct syscall_helper_data *sd)
+{
+ struct syscall_helper_data *sd1;
+
+ for (sd1 = sd; sd1->registered != 0; sd1++) {
+ syscall32_deregister(&sd1->syscall_no, &sd1->old_sysent);
+ sd1->registered = 0;
+ }
+ return (0);
+}
+
+register_t *
+freebsd32_copyout_strings(struct image_params *imgp)
+{
+ int argc, envc, i;
+ u_int32_t *vectp;
+ char *stringp, *destp;
+ u_int32_t *stack_base;
+ struct freebsd32_ps_strings *arginfo;
+ char canary[sizeof(long) * 8];
+ int32_t pagesizes32[MAXPAGESIZES];
+ size_t execpath_len;
+ int szsigcode;
+
+ /*
+ * Calculate string base and vector table pointers.
+ * Also deal with signal trampoline code for this exec type.
+ */
+ if (imgp->execpath != NULL && imgp->auxargs != NULL)
+ execpath_len = strlen(imgp->execpath) + 1;
+ else
+ execpath_len = 0;
+ arginfo = (struct freebsd32_ps_strings *)curproc->p_sysent->
+ sv_psstrings;
+ if (imgp->proc->p_sysent->sv_sigcode_base == 0)
+ szsigcode = *(imgp->proc->p_sysent->sv_szsigcode);
+ else
+ szsigcode = 0;
+ destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
+ roundup(execpath_len, sizeof(char *)) -
+ roundup(sizeof(canary), sizeof(char *)) -
+ roundup(sizeof(pagesizes32), sizeof(char *)) -
+ roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *));
+
+ /*
+ * install sigcode
+ */
+ if (szsigcode != 0)
+ copyout(imgp->proc->p_sysent->sv_sigcode,
+ ((caddr_t)arginfo - szsigcode), szsigcode);
+
+ /*
+ * Copy the image path for the rtld.
+ */
+ if (execpath_len != 0) {
+ imgp->execpathp = (uintptr_t)arginfo - szsigcode - execpath_len;
+ copyout(imgp->execpath, (void *)imgp->execpathp,
+ execpath_len);
+ }
+
+ /*
+ * Prepare the canary for SSP.
+ */
+ arc4rand(canary, sizeof(canary), 0);
+ imgp->canary = (uintptr_t)arginfo - szsigcode - execpath_len -
+ sizeof(canary);
+ copyout(canary, (void *)imgp->canary, sizeof(canary));
+ imgp->canarylen = sizeof(canary);
+
+ /*
+ * Prepare the pagesizes array.
+ */
+ for (i = 0; i < MAXPAGESIZES; i++)
+ pagesizes32[i] = (uint32_t)pagesizes[i];
+ imgp->pagesizes = (uintptr_t)arginfo - szsigcode - execpath_len -
+ roundup(sizeof(canary), sizeof(char *)) - sizeof(pagesizes32);
+ copyout(pagesizes32, (void *)imgp->pagesizes, sizeof(pagesizes32));
+ imgp->pagesizeslen = sizeof(pagesizes32);
+
+ /*
+ * If we have a valid auxargs ptr, prepare some room
+ * on the stack.
+ */
+ if (imgp->auxargs) {
+ /*
+ * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for
+ * lower compatibility.
+ */
+ imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size
+ : (AT_COUNT * 2);
+ /*
+ * The '+ 2' is for the null pointers at the end of each of
+ * the arg and env vector sets,and imgp->auxarg_size is room
+ * for argument of Runtime loader.
+ */
+ vectp = (u_int32_t *) (destp - (imgp->args->argc +
+ imgp->args->envc + 2 + imgp->auxarg_size + execpath_len) *
+ sizeof(u_int32_t));
+ } else
+ /*
+ * The '+ 2' is for the null pointers at the end of each of
+ * the arg and env vector sets
+ */
+ vectp = (u_int32_t *)
+ (destp - (imgp->args->argc + imgp->args->envc + 2) * sizeof(u_int32_t));
+
+ /*
+ * vectp also becomes our initial stack base
+ */
+ stack_base = vectp;
+
+ stringp = imgp->args->begin_argv;
+ argc = imgp->args->argc;
+ envc = imgp->args->envc;
+ /*
+ * Copy out strings - arguments and environment.
+ */
+ copyout(stringp, destp, ARG_MAX - imgp->args->stringspace);
+
+ /*
+ * Fill in "ps_strings" struct for ps, w, etc.
+ */
+ suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp);
+ suword32(&arginfo->ps_nargvstr, argc);
+
+ /*
+ * Fill in argument portion of vector table.
+ */
+ for (; argc > 0; --argc) {
+ suword32(vectp++, (u_int32_t)(intptr_t)destp);
+ while (*stringp++ != 0)
+ destp++;
+ destp++;
+ }
+
+ /* a null vector table pointer separates the argp's from the envp's */
+ suword32(vectp++, 0);
+
+ suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp);
+ suword32(&arginfo->ps_nenvstr, envc);
+
+ /*
+ * Fill in environment portion of vector table.
+ */
+ for (; envc > 0; --envc) {
+ suword32(vectp++, (u_int32_t)(intptr_t)destp);
+ while (*stringp++ != 0)
+ destp++;
+ destp++;
+ }
+
+ /* end of vector table is a null pointer */
+ suword32(vectp, 0);
+
+ return ((register_t *)stack_base);
+}
+
+int
+freebsd32_kldstat(struct thread *td, struct freebsd32_kldstat_args *uap)
+{
+ struct kld_file_stat stat;
+ struct kld32_file_stat stat32;
+ int error, version;
+
+ if ((error = copyin(&uap->stat->version, &version, sizeof(version)))
+ != 0)
+ return (error);
+ if (version != sizeof(struct kld32_file_stat_1) &&
+ version != sizeof(struct kld32_file_stat))
+ return (EINVAL);
+
+ error = kern_kldstat(td, uap->fileid, &stat);
+ if (error != 0)
+ return (error);
+
+ bcopy(&stat.name[0], &stat32.name[0], sizeof(stat.name));
+ CP(stat, stat32, refs);
+ CP(stat, stat32, id);
+ PTROUT_CP(stat, stat32, address);
+ CP(stat, stat32, size);
+ bcopy(&stat.pathname[0], &stat32.pathname[0], sizeof(stat.pathname));
+ return (copyout(&stat32, uap->stat, version));
+}
+
+int
+freebsd32_posix_fallocate(struct thread *td,
+ struct freebsd32_posix_fallocate_args *uap)
+{
+
+ return (kern_posix_fallocate(td, uap->fd,
+ PAIR32TO64(off_t, uap->offset), PAIR32TO64(off_t, uap->len)));
+}
+
+int
+freebsd32_posix_fadvise(struct thread *td,
+ struct freebsd32_posix_fadvise_args *uap)
+{
+
+ return (kern_posix_fadvise(td, uap->fd, PAIR32TO64(off_t, uap->offset),
+ PAIR32TO64(off_t, uap->len), uap->advice));
+}
diff --git a/sys/compat/freebsd32/freebsd32_proto.h b/sys/compat/freebsd32/freebsd32_proto.h
new file mode 100644
index 0000000..f1f444c
--- /dev/null
+++ b/sys/compat/freebsd32/freebsd32_proto.h
@@ -0,0 +1,1151 @@
+/*
+ * System call prototypes.
+ *
+ * DO NOT EDIT-- this file is automatically generated.
+ * $FreeBSD$
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 251526 2013-06-08 13:27:57Z glebius
+ */
+
+#ifndef _FREEBSD32_SYSPROTO_H_
+#define _FREEBSD32_SYSPROTO_H_
+
+#include <sys/signal.h>
+#include <sys/acl.h>
+#include <sys/cpuset.h>
+#include <sys/_ffcounter.h>
+#include <sys/_semaphore.h>
+#include <sys/ucontext.h>
+
+#include <bsm/audit_kevents.h>
+
+struct proc;
+
+struct thread;
+
+#define PAD_(t) (sizeof(register_t) <= sizeof(t) ? \
+ 0 : sizeof(register_t) - sizeof(t))
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define PADL_(t) 0
+#define PADR_(t) PAD_(t)
+#else
+#define PADL_(t) PAD_(t)
+#define PADR_(t) 0
+#endif
+
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
+#define PAD64_REQUIRED
+#endif
+struct freebsd32_wait4_args {
+ char pid_l_[PADL_(int)]; int pid; char pid_r_[PADR_(int)];
+ char status_l_[PADL_(int *)]; int * status; char status_r_[PADR_(int *)];
+ char options_l_[PADL_(int)]; int options; char options_r_[PADR_(int)];
+ char rusage_l_[PADL_(struct rusage32 *)]; struct rusage32 * rusage; char rusage_r_[PADR_(struct rusage32 *)];
+};
+struct freebsd32_recvmsg_args {
+ char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
+ char msg_l_[PADL_(struct msghdr32 *)]; struct msghdr32 * msg; char msg_r_[PADR_(struct msghdr32 *)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+};
+struct freebsd32_sendmsg_args {
+ char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
+ char msg_l_[PADL_(struct msghdr32 *)]; struct msghdr32 * msg; char msg_r_[PADR_(struct msghdr32 *)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+};
+struct freebsd32_recvfrom_args {
+ char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
+ char buf_l_[PADL_(uint32_t)]; uint32_t buf; char buf_r_[PADR_(uint32_t)];
+ char len_l_[PADL_(uint32_t)]; uint32_t len; char len_r_[PADR_(uint32_t)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+ char from_l_[PADL_(uint32_t)]; uint32_t from; char from_r_[PADR_(uint32_t)];
+ char fromlenaddr_l_[PADL_(uint32_t)]; uint32_t fromlenaddr; char fromlenaddr_r_[PADR_(uint32_t)];
+};
+struct ofreebsd32_sigpending_args {
+ register_t dummy;
+};
+struct freebsd32_sigaltstack_args {
+ char ss_l_[PADL_(struct sigaltstack32 *)]; struct sigaltstack32 * ss; char ss_r_[PADR_(struct sigaltstack32 *)];
+ char oss_l_[PADL_(struct sigaltstack32 *)]; struct sigaltstack32 * oss; char oss_r_[PADR_(struct sigaltstack32 *)];
+};
+struct freebsd32_ioctl_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char com_l_[PADL_(uint32_t)]; uint32_t com; char com_r_[PADR_(uint32_t)];
+ char data_l_[PADL_(struct md_ioctl32 *)]; struct md_ioctl32 * data; char data_r_[PADR_(struct md_ioctl32 *)];
+};
+struct freebsd32_execve_args {
+ char fname_l_[PADL_(char *)]; char * fname; char fname_r_[PADR_(char *)];
+ char argv_l_[PADL_(uint32_t *)]; uint32_t * argv; char argv_r_[PADR_(uint32_t *)];
+ char envv_l_[PADL_(uint32_t *)]; uint32_t * envv; char envv_r_[PADR_(uint32_t *)];
+};
+struct freebsd32_mprotect_args {
+ char addr_l_[PADL_(const void *)]; const void * addr; char addr_r_[PADR_(const void *)];
+ char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)];
+ char prot_l_[PADL_(int)]; int prot; char prot_r_[PADR_(int)];
+};
+struct freebsd32_setitimer_args {
+ char which_l_[PADL_(u_int)]; u_int which; char which_r_[PADR_(u_int)];
+ char itv_l_[PADL_(struct itimerval32 *)]; struct itimerval32 * itv; char itv_r_[PADR_(struct itimerval32 *)];
+ char oitv_l_[PADL_(struct itimerval32 *)]; struct itimerval32 * oitv; char oitv_r_[PADR_(struct itimerval32 *)];
+};
+struct freebsd32_getitimer_args {
+ char which_l_[PADL_(u_int)]; u_int which; char which_r_[PADR_(u_int)];
+ char itv_l_[PADL_(struct itimerval32 *)]; struct itimerval32 * itv; char itv_r_[PADR_(struct itimerval32 *)];
+};
+struct freebsd32_select_args {
+ char nd_l_[PADL_(int)]; int nd; char nd_r_[PADR_(int)];
+ char in_l_[PADL_(fd_set *)]; fd_set * in; char in_r_[PADR_(fd_set *)];
+ char ou_l_[PADL_(fd_set *)]; fd_set * ou; char ou_r_[PADR_(fd_set *)];
+ char ex_l_[PADL_(fd_set *)]; fd_set * ex; char ex_r_[PADR_(fd_set *)];
+ char tv_l_[PADL_(struct timeval32 *)]; struct timeval32 * tv; char tv_r_[PADR_(struct timeval32 *)];
+};
+struct freebsd32_gettimeofday_args {
+ char tp_l_[PADL_(struct timeval32 *)]; struct timeval32 * tp; char tp_r_[PADR_(struct timeval32 *)];
+ char tzp_l_[PADL_(struct timezone *)]; struct timezone * tzp; char tzp_r_[PADR_(struct timezone *)];
+};
+struct freebsd32_getrusage_args {
+ char who_l_[PADL_(int)]; int who; char who_r_[PADR_(int)];
+ char rusage_l_[PADL_(struct rusage32 *)]; struct rusage32 * rusage; char rusage_r_[PADR_(struct rusage32 *)];
+};
+struct freebsd32_readv_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char iovp_l_[PADL_(struct iovec32 *)]; struct iovec32 * iovp; char iovp_r_[PADR_(struct iovec32 *)];
+ char iovcnt_l_[PADL_(u_int)]; u_int iovcnt; char iovcnt_r_[PADR_(u_int)];
+};
+struct freebsd32_writev_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char iovp_l_[PADL_(struct iovec32 *)]; struct iovec32 * iovp; char iovp_r_[PADR_(struct iovec32 *)];
+ char iovcnt_l_[PADL_(u_int)]; u_int iovcnt; char iovcnt_r_[PADR_(u_int)];
+};
+struct freebsd32_settimeofday_args {
+ char tv_l_[PADL_(struct timeval32 *)]; struct timeval32 * tv; char tv_r_[PADR_(struct timeval32 *)];
+ char tzp_l_[PADL_(struct timezone *)]; struct timezone * tzp; char tzp_r_[PADR_(struct timezone *)];
+};
+struct freebsd32_utimes_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char tptr_l_[PADL_(struct timeval32 *)]; struct timeval32 * tptr; char tptr_r_[PADR_(struct timeval32 *)];
+};
+struct freebsd32_adjtime_args {
+ char delta_l_[PADL_(struct timeval32 *)]; struct timeval32 * delta; char delta_r_[PADR_(struct timeval32 *)];
+ char olddelta_l_[PADL_(struct timeval32 *)]; struct timeval32 * olddelta; char olddelta_r_[PADR_(struct timeval32 *)];
+};
+struct freebsd32_sysarch_args {
+ char op_l_[PADL_(int)]; int op; char op_r_[PADR_(int)];
+ char parms_l_[PADL_(char *)]; char * parms; char parms_r_[PADR_(char *)];
+};
+struct freebsd32_semsys_args {
+ char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)];
+ char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)];
+ char a3_l_[PADL_(int)]; int a3; char a3_r_[PADR_(int)];
+ char a4_l_[PADL_(int)]; int a4; char a4_r_[PADR_(int)];
+ char a5_l_[PADL_(int)]; int a5; char a5_r_[PADR_(int)];
+};
+struct freebsd32_msgsys_args {
+ char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)];
+ char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)];
+ char a3_l_[PADL_(int)]; int a3; char a3_r_[PADR_(int)];
+ char a4_l_[PADL_(int)]; int a4; char a4_r_[PADR_(int)];
+ char a5_l_[PADL_(int)]; int a5; char a5_r_[PADR_(int)];
+ char a6_l_[PADL_(int)]; int a6; char a6_r_[PADR_(int)];
+};
+struct freebsd32_shmsys_args {
+ char which_l_[PADL_(uint32_t)]; uint32_t which; char which_r_[PADR_(uint32_t)];
+ char a2_l_[PADL_(uint32_t)]; uint32_t a2; char a2_r_[PADR_(uint32_t)];
+ char a3_l_[PADL_(uint32_t)]; uint32_t a3; char a3_r_[PADR_(uint32_t)];
+ char a4_l_[PADL_(uint32_t)]; uint32_t a4; char a4_r_[PADR_(uint32_t)];
+};
+struct freebsd32_stat_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char ub_l_[PADL_(struct stat32 *)]; struct stat32 * ub; char ub_r_[PADR_(struct stat32 *)];
+};
+struct freebsd32_fstat_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char ub_l_[PADL_(struct stat32 *)]; struct stat32 * ub; char ub_r_[PADR_(struct stat32 *)];
+};
+struct freebsd32_lstat_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char ub_l_[PADL_(struct stat32 *)]; struct stat32 * ub; char ub_r_[PADR_(struct stat32 *)];
+};
+struct freebsd32_getdirentries_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)];
+ char count_l_[PADL_(u_int)]; u_int count; char count_r_[PADR_(u_int)];
+ char basep_l_[PADL_(int32_t *)]; int32_t * basep; char basep_r_[PADR_(int32_t *)];
+};
+struct freebsd32_sysctl_args {
+ char name_l_[PADL_(int *)]; int * name; char name_r_[PADR_(int *)];
+ char namelen_l_[PADL_(u_int)]; u_int namelen; char namelen_r_[PADR_(u_int)];
+ char old_l_[PADL_(void *)]; void * old; char old_r_[PADR_(void *)];
+ char oldlenp_l_[PADL_(uint32_t *)]; uint32_t * oldlenp; char oldlenp_r_[PADR_(uint32_t *)];
+ char new_l_[PADL_(void *)]; void * new; char new_r_[PADR_(void *)];
+ char newlen_l_[PADL_(uint32_t)]; uint32_t newlen; char newlen_r_[PADR_(uint32_t)];
+};
+struct freebsd32_futimes_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char tptr_l_[PADL_(struct timeval32 *)]; struct timeval32 * tptr; char tptr_r_[PADR_(struct timeval32 *)];
+};
+struct freebsd32_msgsnd_args {
+ char msqid_l_[PADL_(int)]; int msqid; char msqid_r_[PADR_(int)];
+ char msgp_l_[PADL_(void *)]; void * msgp; char msgp_r_[PADR_(void *)];
+ char msgsz_l_[PADL_(size_t)]; size_t msgsz; char msgsz_r_[PADR_(size_t)];
+ char msgflg_l_[PADL_(int)]; int msgflg; char msgflg_r_[PADR_(int)];
+};
+struct freebsd32_msgrcv_args {
+ char msqid_l_[PADL_(int)]; int msqid; char msqid_r_[PADR_(int)];
+ char msgp_l_[PADL_(void *)]; void * msgp; char msgp_r_[PADR_(void *)];
+ char msgsz_l_[PADL_(size_t)]; size_t msgsz; char msgsz_r_[PADR_(size_t)];
+ char msgtyp_l_[PADL_(long)]; long msgtyp; char msgtyp_r_[PADR_(long)];
+ char msgflg_l_[PADL_(int)]; int msgflg; char msgflg_r_[PADR_(int)];
+};
+struct freebsd32_clock_gettime_args {
+ char clock_id_l_[PADL_(clockid_t)]; clockid_t clock_id; char clock_id_r_[PADR_(clockid_t)];
+ char tp_l_[PADL_(struct timespec32 *)]; struct timespec32 * tp; char tp_r_[PADR_(struct timespec32 *)];
+};
+struct freebsd32_clock_settime_args {
+ char clock_id_l_[PADL_(clockid_t)]; clockid_t clock_id; char clock_id_r_[PADR_(clockid_t)];
+ char tp_l_[PADL_(const struct timespec32 *)]; const struct timespec32 * tp; char tp_r_[PADR_(const struct timespec32 *)];
+};
+struct freebsd32_clock_getres_args {
+ char clock_id_l_[PADL_(clockid_t)]; clockid_t clock_id; char clock_id_r_[PADR_(clockid_t)];
+ char tp_l_[PADL_(struct timespec32 *)]; struct timespec32 * tp; char tp_r_[PADR_(struct timespec32 *)];
+};
+struct freebsd32_nanosleep_args {
+ char rqtp_l_[PADL_(const struct timespec32 *)]; const struct timespec32 * rqtp; char rqtp_r_[PADR_(const struct timespec32 *)];
+ char rmtp_l_[PADL_(struct timespec32 *)]; struct timespec32 * rmtp; char rmtp_r_[PADR_(struct timespec32 *)];
+};
+struct freebsd32_aio_read_args {
+ char aiocbp_l_[PADL_(struct aiocb32 *)]; struct aiocb32 * aiocbp; char aiocbp_r_[PADR_(struct aiocb32 *)];
+};
+struct freebsd32_aio_write_args {
+ char aiocbp_l_[PADL_(struct aiocb32 *)]; struct aiocb32 * aiocbp; char aiocbp_r_[PADR_(struct aiocb32 *)];
+};
+struct freebsd32_lio_listio_args {
+ char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)];
+ char acb_list_l_[PADL_(struct aiocb32 *const *)]; struct aiocb32 *const * acb_list; char acb_list_r_[PADR_(struct aiocb32 *const *)];
+ char nent_l_[PADL_(int)]; int nent; char nent_r_[PADR_(int)];
+ char sig_l_[PADL_(struct sigevent *)]; struct sigevent * sig; char sig_r_[PADR_(struct sigevent *)];
+};
+struct freebsd32_lutimes_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char tptr_l_[PADL_(struct timeval32 *)]; struct timeval32 * tptr; char tptr_r_[PADR_(struct timeval32 *)];
+};
+struct freebsd32_preadv_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char iovp_l_[PADL_(struct iovec32 *)]; struct iovec32 * iovp; char iovp_r_[PADR_(struct iovec32 *)];
+ char iovcnt_l_[PADL_(u_int)]; u_int iovcnt; char iovcnt_r_[PADR_(u_int)];
+ char offset1_l_[PADL_(uint32_t)]; uint32_t offset1; char offset1_r_[PADR_(uint32_t)];
+ char offset2_l_[PADL_(uint32_t)]; uint32_t offset2; char offset2_r_[PADR_(uint32_t)];
+};
+struct freebsd32_pwritev_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char iovp_l_[PADL_(struct iovec32 *)]; struct iovec32 * iovp; char iovp_r_[PADR_(struct iovec32 *)];
+ char iovcnt_l_[PADL_(u_int)]; u_int iovcnt; char iovcnt_r_[PADR_(u_int)];
+ char offset1_l_[PADL_(uint32_t)]; uint32_t offset1; char offset1_r_[PADR_(uint32_t)];
+ char offset2_l_[PADL_(uint32_t)]; uint32_t offset2; char offset2_r_[PADR_(uint32_t)];
+};
+struct freebsd32_modstat_args {
+ char modid_l_[PADL_(int)]; int modid; char modid_r_[PADR_(int)];
+ char stat_l_[PADL_(struct module_stat32 *)]; struct module_stat32 * stat; char stat_r_[PADR_(struct module_stat32 *)];
+};
+struct freebsd32_kldstat_args {
+ char fileid_l_[PADL_(int)]; int fileid; char fileid_r_[PADR_(int)];
+ char stat_l_[PADL_(struct kld32_file_stat *)]; struct kld32_file_stat * stat; char stat_r_[PADR_(struct kld32_file_stat *)];
+};
+struct freebsd32_aio_return_args {
+ char aiocbp_l_[PADL_(struct aiocb32 *)]; struct aiocb32 * aiocbp; char aiocbp_r_[PADR_(struct aiocb32 *)];
+};
+struct freebsd32_aio_suspend_args {
+ char aiocbp_l_[PADL_(struct aiocb32 *const *)]; struct aiocb32 *const * aiocbp; char aiocbp_r_[PADR_(struct aiocb32 *const *)];
+ char nent_l_[PADL_(int)]; int nent; char nent_r_[PADR_(int)];
+ char timeout_l_[PADL_(const struct timespec32 *)]; const struct timespec32 * timeout; char timeout_r_[PADR_(const struct timespec32 *)];
+};
+struct freebsd32_aio_cancel_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char aiocbp_l_[PADL_(struct aiocb32 *)]; struct aiocb32 * aiocbp; char aiocbp_r_[PADR_(struct aiocb32 *)];
+};
+struct freebsd32_aio_error_args {
+ char aiocbp_l_[PADL_(struct aiocb32 *)]; struct aiocb32 * aiocbp; char aiocbp_r_[PADR_(struct aiocb32 *)];
+};
+struct freebsd32_oaio_read_args {
+ char aiocbp_l_[PADL_(struct oaiocb32 *)]; struct oaiocb32 * aiocbp; char aiocbp_r_[PADR_(struct oaiocb32 *)];
+};
+struct freebsd32_oaio_write_args {
+ char aiocbp_l_[PADL_(struct oaiocb32 *)]; struct oaiocb32 * aiocbp; char aiocbp_r_[PADR_(struct oaiocb32 *)];
+};
+struct freebsd32_olio_listio_args {
+ char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)];
+ char acb_list_l_[PADL_(struct oaiocb32 *const *)]; struct oaiocb32 *const * acb_list; char acb_list_r_[PADR_(struct oaiocb32 *const *)];
+ char nent_l_[PADL_(int)]; int nent; char nent_r_[PADR_(int)];
+ char sig_l_[PADL_(struct osigevent32 *)]; struct osigevent32 * sig; char sig_r_[PADR_(struct osigevent32 *)];
+};
+struct freebsd32_jail_args {
+ char jail_l_[PADL_(struct jail32 *)]; struct jail32 * jail; char jail_r_[PADR_(struct jail32 *)];
+};
+struct freebsd32_sigtimedwait_args {
+ char set_l_[PADL_(const sigset_t *)]; const sigset_t * set; char set_r_[PADR_(const sigset_t *)];
+ char info_l_[PADL_(siginfo_t *)]; siginfo_t * info; char info_r_[PADR_(siginfo_t *)];
+ char timeout_l_[PADL_(const struct timespec *)]; const struct timespec * timeout; char timeout_r_[PADR_(const struct timespec *)];
+};
+struct freebsd32_sigwaitinfo_args {
+ char set_l_[PADL_(const sigset_t *)]; const sigset_t * set; char set_r_[PADR_(const sigset_t *)];
+ char info_l_[PADL_(siginfo_t *)]; siginfo_t * info; char info_r_[PADR_(siginfo_t *)];
+};
+struct freebsd32_aio_waitcomplete_args {
+ char aiocbp_l_[PADL_(struct aiocb32 **)]; struct aiocb32 ** aiocbp; char aiocbp_r_[PADR_(struct aiocb32 **)];
+ char timeout_l_[PADL_(struct timespec32 *)]; struct timespec32 * timeout; char timeout_r_[PADR_(struct timespec32 *)];
+};
+struct freebsd32_kevent_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char changelist_l_[PADL_(const struct kevent32 *)]; const struct kevent32 * changelist; char changelist_r_[PADR_(const struct kevent32 *)];
+ char nchanges_l_[PADL_(int)]; int nchanges; char nchanges_r_[PADR_(int)];
+ char eventlist_l_[PADL_(struct kevent32 *)]; struct kevent32 * eventlist; char eventlist_r_[PADR_(struct kevent32 *)];
+ char nevents_l_[PADL_(int)]; int nevents; char nevents_r_[PADR_(int)];
+ char timeout_l_[PADL_(const struct timespec32 *)]; const struct timespec32 * timeout; char timeout_r_[PADR_(const struct timespec32 *)];
+};
+struct freebsd32_nmount_args {
+ char iovp_l_[PADL_(struct iovec32 *)]; struct iovec32 * iovp; char iovp_r_[PADR_(struct iovec32 *)];
+ char iovcnt_l_[PADL_(unsigned int)]; unsigned int iovcnt; char iovcnt_r_[PADR_(unsigned int)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+};
+struct freebsd32_sendfile_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
+ char offset1_l_[PADL_(uint32_t)]; uint32_t offset1; char offset1_r_[PADR_(uint32_t)];
+ char offset2_l_[PADL_(uint32_t)]; uint32_t offset2; char offset2_r_[PADR_(uint32_t)];
+ char nbytes_l_[PADL_(size_t)]; size_t nbytes; char nbytes_r_[PADR_(size_t)];
+ char hdtr_l_[PADL_(struct sf_hdtr32 *)]; struct sf_hdtr32 * hdtr; char hdtr_r_[PADR_(struct sf_hdtr32 *)];
+ char sbytes_l_[PADL_(off_t *)]; off_t * sbytes; char sbytes_r_[PADR_(off_t *)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+};
+struct freebsd32_ksem_init_args {
+ char idp_l_[PADL_(semid_t *)]; semid_t * idp; char idp_r_[PADR_(semid_t *)];
+ char value_l_[PADL_(unsigned int)]; unsigned int value; char value_r_[PADR_(unsigned int)];
+};
+struct freebsd32_ksem_open_args {
+ char idp_l_[PADL_(semid_t *)]; semid_t * idp; char idp_r_[PADR_(semid_t *)];
+ char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)];
+ char oflag_l_[PADL_(int)]; int oflag; char oflag_r_[PADR_(int)];
+ char mode_l_[PADL_(mode_t)]; mode_t mode; char mode_r_[PADR_(mode_t)];
+ char value_l_[PADL_(unsigned int)]; unsigned int value; char value_r_[PADR_(unsigned int)];
+};
+struct freebsd32_sigaction_args {
+ char sig_l_[PADL_(int)]; int sig; char sig_r_[PADR_(int)];
+ char act_l_[PADL_(struct sigaction32 *)]; struct sigaction32 * act; char act_r_[PADR_(struct sigaction32 *)];
+ char oact_l_[PADL_(struct sigaction32 *)]; struct sigaction32 * oact; char oact_r_[PADR_(struct sigaction32 *)];
+};
+struct freebsd32_sigreturn_args {
+ char sigcntxp_l_[PADL_(const struct freebsd32_ucontext *)]; const struct freebsd32_ucontext * sigcntxp; char sigcntxp_r_[PADR_(const struct freebsd32_ucontext *)];
+};
+struct freebsd32_getcontext_args {
+ char ucp_l_[PADL_(struct freebsd32_ucontext *)]; struct freebsd32_ucontext * ucp; char ucp_r_[PADR_(struct freebsd32_ucontext *)];
+};
+struct freebsd32_setcontext_args {
+ char ucp_l_[PADL_(const struct freebsd32_ucontext *)]; const struct freebsd32_ucontext * ucp; char ucp_r_[PADR_(const struct freebsd32_ucontext *)];
+};
+struct freebsd32_swapcontext_args {
+ char oucp_l_[PADL_(struct freebsd32_ucontext *)]; struct freebsd32_ucontext * oucp; char oucp_r_[PADR_(struct freebsd32_ucontext *)];
+ char ucp_l_[PADL_(const struct freebsd32_ucontext *)]; const struct freebsd32_ucontext * ucp; char ucp_r_[PADR_(const struct freebsd32_ucontext *)];
+};
+struct freebsd32_umtx_lock_args {
+ char umtx_l_[PADL_(struct umtx *)]; struct umtx * umtx; char umtx_r_[PADR_(struct umtx *)];
+};
+struct freebsd32_umtx_unlock_args {
+ char umtx_l_[PADL_(struct umtx *)]; struct umtx * umtx; char umtx_r_[PADR_(struct umtx *)];
+};
+struct freebsd32_ksem_timedwait_args {
+ char id_l_[PADL_(semid_t)]; semid_t id; char id_r_[PADR_(semid_t)];
+ char abstime_l_[PADL_(const struct timespec32 *)]; const struct timespec32 * abstime; char abstime_r_[PADR_(const struct timespec32 *)];
+};
+struct freebsd32_thr_suspend_args {
+ char timeout_l_[PADL_(const struct timespec32 *)]; const struct timespec32 * timeout; char timeout_r_[PADR_(const struct timespec32 *)];
+};
+struct freebsd32_umtx_op_args {
+ char obj_l_[PADL_(void *)]; void * obj; char obj_r_[PADR_(void *)];
+ char op_l_[PADL_(int)]; int op; char op_r_[PADR_(int)];
+ char val_l_[PADL_(u_long)]; u_long val; char val_r_[PADR_(u_long)];
+ char uaddr_l_[PADL_(void *)]; void * uaddr; char uaddr_r_[PADR_(void *)];
+ char uaddr2_l_[PADL_(void *)]; void * uaddr2; char uaddr2_r_[PADR_(void *)];
+};
+struct freebsd32_thr_new_args {
+ char param_l_[PADL_(struct thr_param32 *)]; struct thr_param32 * param; char param_r_[PADR_(struct thr_param32 *)];
+ char param_size_l_[PADL_(int)]; int param_size; char param_size_r_[PADR_(int)];
+};
+struct freebsd32_kmq_open_args {
+ char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+ char mode_l_[PADL_(mode_t)]; mode_t mode; char mode_r_[PADR_(mode_t)];
+ char attr_l_[PADL_(const struct mq_attr32 *)]; const struct mq_attr32 * attr; char attr_r_[PADR_(const struct mq_attr32 *)];
+};
+struct freebsd32_kmq_setattr_args {
+ char mqd_l_[PADL_(int)]; int mqd; char mqd_r_[PADR_(int)];
+ char attr_l_[PADL_(const struct mq_attr32 *)]; const struct mq_attr32 * attr; char attr_r_[PADR_(const struct mq_attr32 *)];
+ char oattr_l_[PADL_(struct mq_attr32 *)]; struct mq_attr32 * oattr; char oattr_r_[PADR_(struct mq_attr32 *)];
+};
+struct freebsd32_kmq_timedreceive_args {
+ char mqd_l_[PADL_(int)]; int mqd; char mqd_r_[PADR_(int)];
+ char msg_ptr_l_[PADL_(char *)]; char * msg_ptr; char msg_ptr_r_[PADR_(char *)];
+ char msg_len_l_[PADL_(size_t)]; size_t msg_len; char msg_len_r_[PADR_(size_t)];
+ char msg_prio_l_[PADL_(unsigned *)]; unsigned * msg_prio; char msg_prio_r_[PADR_(unsigned *)];
+ char abs_timeout_l_[PADL_(const struct timespec32 *)]; const struct timespec32 * abs_timeout; char abs_timeout_r_[PADR_(const struct timespec32 *)];
+};
+struct freebsd32_kmq_timedsend_args {
+ char mqd_l_[PADL_(int)]; int mqd; char mqd_r_[PADR_(int)];
+ char msg_ptr_l_[PADL_(const char *)]; const char * msg_ptr; char msg_ptr_r_[PADR_(const char *)];
+ char msg_len_l_[PADL_(size_t)]; size_t msg_len; char msg_len_r_[PADR_(size_t)];
+ char msg_prio_l_[PADL_(unsigned)]; unsigned msg_prio; char msg_prio_r_[PADR_(unsigned)];
+ char abs_timeout_l_[PADL_(const struct timespec32 *)]; const struct timespec32 * abs_timeout; char abs_timeout_r_[PADR_(const struct timespec32 *)];
+};
+struct freebsd32_aio_fsync_args {
+ char op_l_[PADL_(int)]; int op; char op_r_[PADR_(int)];
+ char aiocbp_l_[PADL_(struct aiocb32 *)]; struct aiocb32 * aiocbp; char aiocbp_r_[PADR_(struct aiocb32 *)];
+};
+#ifdef PAD64_REQUIRED
+struct freebsd32_pread_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char buf_l_[PADL_(void *)]; void * buf; char buf_r_[PADR_(void *)];
+ char nbyte_l_[PADL_(size_t)]; size_t nbyte; char nbyte_r_[PADR_(size_t)];
+ char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)];
+ char offset1_l_[PADL_(uint32_t)]; uint32_t offset1; char offset1_r_[PADR_(uint32_t)];
+ char offset2_l_[PADL_(uint32_t)]; uint32_t offset2; char offset2_r_[PADR_(uint32_t)];
+};
+struct freebsd32_pwrite_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char buf_l_[PADL_(const void *)]; const void * buf; char buf_r_[PADR_(const void *)];
+ char nbyte_l_[PADL_(size_t)]; size_t nbyte; char nbyte_r_[PADR_(size_t)];
+ char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)];
+ char offset1_l_[PADL_(uint32_t)]; uint32_t offset1; char offset1_r_[PADR_(uint32_t)];
+ char offset2_l_[PADL_(uint32_t)]; uint32_t offset2; char offset2_r_[PADR_(uint32_t)];
+};
+struct freebsd32_mmap_args {
+ char addr_l_[PADL_(caddr_t)]; caddr_t addr; char addr_r_[PADR_(caddr_t)];
+ char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)];
+ char prot_l_[PADL_(int)]; int prot; char prot_r_[PADR_(int)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)];
+ char pos1_l_[PADL_(uint32_t)]; uint32_t pos1; char pos1_r_[PADR_(uint32_t)];
+ char pos2_l_[PADL_(uint32_t)]; uint32_t pos2; char pos2_r_[PADR_(uint32_t)];
+};
+struct freebsd32_lseek_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)];
+ char offset1_l_[PADL_(uint32_t)]; uint32_t offset1; char offset1_r_[PADR_(uint32_t)];
+ char offset2_l_[PADL_(uint32_t)]; uint32_t offset2; char offset2_r_[PADR_(uint32_t)];
+ char whence_l_[PADL_(int)]; int whence; char whence_r_[PADR_(int)];
+};
+struct freebsd32_truncate_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)];
+ char length1_l_[PADL_(uint32_t)]; uint32_t length1; char length1_r_[PADR_(uint32_t)];
+ char length2_l_[PADL_(uint32_t)]; uint32_t length2; char length2_r_[PADR_(uint32_t)];
+};
+struct freebsd32_ftruncate_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)];
+ char length1_l_[PADL_(uint32_t)]; uint32_t length1; char length1_r_[PADR_(uint32_t)];
+ char length2_l_[PADL_(uint32_t)]; uint32_t length2; char length2_r_[PADR_(uint32_t)];
+};
+#else
+struct freebsd32_pread_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char buf_l_[PADL_(void *)]; void * buf; char buf_r_[PADR_(void *)];
+ char nbyte_l_[PADL_(size_t)]; size_t nbyte; char nbyte_r_[PADR_(size_t)];
+ char offset1_l_[PADL_(uint32_t)]; uint32_t offset1; char offset1_r_[PADR_(uint32_t)];
+ char offset2_l_[PADL_(uint32_t)]; uint32_t offset2; char offset2_r_[PADR_(uint32_t)];
+};
+struct freebsd32_pwrite_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char buf_l_[PADL_(const void *)]; const void * buf; char buf_r_[PADR_(const void *)];
+ char nbyte_l_[PADL_(size_t)]; size_t nbyte; char nbyte_r_[PADR_(size_t)];
+ char offset1_l_[PADL_(uint32_t)]; uint32_t offset1; char offset1_r_[PADR_(uint32_t)];
+ char offset2_l_[PADL_(uint32_t)]; uint32_t offset2; char offset2_r_[PADR_(uint32_t)];
+};
+struct freebsd32_mmap_args {
+ char addr_l_[PADL_(caddr_t)]; caddr_t addr; char addr_r_[PADR_(caddr_t)];
+ char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)];
+ char prot_l_[PADL_(int)]; int prot; char prot_r_[PADR_(int)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char pos1_l_[PADL_(uint32_t)]; uint32_t pos1; char pos1_r_[PADR_(uint32_t)];
+ char pos2_l_[PADL_(uint32_t)]; uint32_t pos2; char pos2_r_[PADR_(uint32_t)];
+};
+struct freebsd32_lseek_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char offset1_l_[PADL_(uint32_t)]; uint32_t offset1; char offset1_r_[PADR_(uint32_t)];
+ char offset2_l_[PADL_(uint32_t)]; uint32_t offset2; char offset2_r_[PADR_(uint32_t)];
+ char whence_l_[PADL_(int)]; int whence; char whence_r_[PADR_(int)];
+};
+struct freebsd32_truncate_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char length1_l_[PADL_(uint32_t)]; uint32_t length1; char length1_r_[PADR_(uint32_t)];
+ char length2_l_[PADL_(uint32_t)]; uint32_t length2; char length2_r_[PADR_(uint32_t)];
+};
+struct freebsd32_ftruncate_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char length1_l_[PADL_(uint32_t)]; uint32_t length1; char length1_r_[PADR_(uint32_t)];
+ char length2_l_[PADL_(uint32_t)]; uint32_t length2; char length2_r_[PADR_(uint32_t)];
+};
+#endif
+#ifdef PAD64_REQUIRED
+struct freebsd32_cpuset_setid_args {
+ char which_l_[PADL_(cpuwhich_t)]; cpuwhich_t which; char which_r_[PADR_(cpuwhich_t)];
+ char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)];
+ char id1_l_[PADL_(uint32_t)]; uint32_t id1; char id1_r_[PADR_(uint32_t)];
+ char id2_l_[PADL_(uint32_t)]; uint32_t id2; char id2_r_[PADR_(uint32_t)];
+ char setid_l_[PADL_(cpusetid_t)]; cpusetid_t setid; char setid_r_[PADR_(cpusetid_t)];
+};
+#else
+struct freebsd32_cpuset_setid_args {
+ char which_l_[PADL_(cpuwhich_t)]; cpuwhich_t which; char which_r_[PADR_(cpuwhich_t)];
+ char id1_l_[PADL_(uint32_t)]; uint32_t id1; char id1_r_[PADR_(uint32_t)];
+ char id2_l_[PADL_(uint32_t)]; uint32_t id2; char id2_r_[PADR_(uint32_t)];
+ char setid_l_[PADL_(cpusetid_t)]; cpusetid_t setid; char setid_r_[PADR_(cpusetid_t)];
+};
+#endif
+struct freebsd32_cpuset_getid_args {
+ char level_l_[PADL_(cpulevel_t)]; cpulevel_t level; char level_r_[PADR_(cpulevel_t)];
+ char which_l_[PADL_(cpuwhich_t)]; cpuwhich_t which; char which_r_[PADR_(cpuwhich_t)];
+ char id1_l_[PADL_(uint32_t)]; uint32_t id1; char id1_r_[PADR_(uint32_t)];
+ char id2_l_[PADL_(uint32_t)]; uint32_t id2; char id2_r_[PADR_(uint32_t)];
+ char setid_l_[PADL_(cpusetid_t *)]; cpusetid_t * setid; char setid_r_[PADR_(cpusetid_t *)];
+};
+struct freebsd32_cpuset_getaffinity_args {
+ char level_l_[PADL_(cpulevel_t)]; cpulevel_t level; char level_r_[PADR_(cpulevel_t)];
+ char which_l_[PADL_(cpuwhich_t)]; cpuwhich_t which; char which_r_[PADR_(cpuwhich_t)];
+ char id1_l_[PADL_(uint32_t)]; uint32_t id1; char id1_r_[PADR_(uint32_t)];
+ char id2_l_[PADL_(uint32_t)]; uint32_t id2; char id2_r_[PADR_(uint32_t)];
+ char cpusetsize_l_[PADL_(size_t)]; size_t cpusetsize; char cpusetsize_r_[PADR_(size_t)];
+ char mask_l_[PADL_(cpuset_t *)]; cpuset_t * mask; char mask_r_[PADR_(cpuset_t *)];
+};
+struct freebsd32_cpuset_setaffinity_args {
+ char level_l_[PADL_(cpulevel_t)]; cpulevel_t level; char level_r_[PADR_(cpulevel_t)];
+ char which_l_[PADL_(cpuwhich_t)]; cpuwhich_t which; char which_r_[PADR_(cpuwhich_t)];
+ char id1_l_[PADL_(uint32_t)]; uint32_t id1; char id1_r_[PADR_(uint32_t)];
+ char id2_l_[PADL_(uint32_t)]; uint32_t id2; char id2_r_[PADR_(uint32_t)];
+ char cpusetsize_l_[PADL_(size_t)]; size_t cpusetsize; char cpusetsize_r_[PADR_(size_t)];
+ char mask_l_[PADL_(const cpuset_t *)]; const cpuset_t * mask; char mask_r_[PADR_(const cpuset_t *)];
+};
+struct freebsd32_fexecve_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char argv_l_[PADL_(uint32_t *)]; uint32_t * argv; char argv_r_[PADR_(uint32_t *)];
+ char envv_l_[PADL_(uint32_t *)]; uint32_t * envv; char envv_r_[PADR_(uint32_t *)];
+};
+struct freebsd32_fstatat_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char buf_l_[PADL_(struct stat *)]; struct stat * buf; char buf_r_[PADR_(struct stat *)];
+ char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)];
+};
+struct freebsd32_futimesat_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char times_l_[PADL_(struct timeval *)]; struct timeval * times; char times_r_[PADR_(struct timeval *)];
+};
+struct freebsd32_jail_get_args {
+ char iovp_l_[PADL_(struct iovec32 *)]; struct iovec32 * iovp; char iovp_r_[PADR_(struct iovec32 *)];
+ char iovcnt_l_[PADL_(unsigned int)]; unsigned int iovcnt; char iovcnt_r_[PADR_(unsigned int)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+};
+struct freebsd32_jail_set_args {
+ char iovp_l_[PADL_(struct iovec32 *)]; struct iovec32 * iovp; char iovp_r_[PADR_(struct iovec32 *)];
+ char iovcnt_l_[PADL_(unsigned int)]; unsigned int iovcnt; char iovcnt_r_[PADR_(unsigned int)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+};
+struct freebsd32_semctl_args {
+ char semid_l_[PADL_(int)]; int semid; char semid_r_[PADR_(int)];
+ char semnum_l_[PADL_(int)]; int semnum; char semnum_r_[PADR_(int)];
+ char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)];
+ char arg_l_[PADL_(union semun32 *)]; union semun32 * arg; char arg_r_[PADR_(union semun32 *)];
+};
+struct freebsd32_msgctl_args {
+ char msqid_l_[PADL_(int)]; int msqid; char msqid_r_[PADR_(int)];
+ char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)];
+ char buf_l_[PADL_(struct msqid_ds32 *)]; struct msqid_ds32 * buf; char buf_r_[PADR_(struct msqid_ds32 *)];
+};
+struct freebsd32_shmctl_args {
+ char shmid_l_[PADL_(int)]; int shmid; char shmid_r_[PADR_(int)];
+ char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)];
+ char buf_l_[PADL_(struct shmid_ds32 *)]; struct shmid_ds32 * buf; char buf_r_[PADR_(struct shmid_ds32 *)];
+};
+struct freebsd32_pselect_args {
+ char nd_l_[PADL_(int)]; int nd; char nd_r_[PADR_(int)];
+ char in_l_[PADL_(fd_set *)]; fd_set * in; char in_r_[PADR_(fd_set *)];
+ char ou_l_[PADL_(fd_set *)]; fd_set * ou; char ou_r_[PADR_(fd_set *)];
+ char ex_l_[PADL_(fd_set *)]; fd_set * ex; char ex_r_[PADR_(fd_set *)];
+ char ts_l_[PADL_(const struct timespec32 *)]; const struct timespec32 * ts; char ts_r_[PADR_(const struct timespec32 *)];
+ char sm_l_[PADL_(const sigset_t *)]; const sigset_t * sm; char sm_r_[PADR_(const sigset_t *)];
+};
+#ifdef PAD64_REQUIRED
+struct freebsd32_posix_fallocate_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)];
+ char offset1_l_[PADL_(uint32_t)]; uint32_t offset1; char offset1_r_[PADR_(uint32_t)];
+ char offset2_l_[PADL_(uint32_t)]; uint32_t offset2; char offset2_r_[PADR_(uint32_t)];
+ char len1_l_[PADL_(uint32_t)]; uint32_t len1; char len1_r_[PADR_(uint32_t)];
+ char len2_l_[PADL_(uint32_t)]; uint32_t len2; char len2_r_[PADR_(uint32_t)];
+};
+struct freebsd32_posix_fadvise_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)];
+ char offset1_l_[PADL_(uint32_t)]; uint32_t offset1; char offset1_r_[PADR_(uint32_t)];
+ char offset2_l_[PADL_(uint32_t)]; uint32_t offset2; char offset2_r_[PADR_(uint32_t)];
+ char len1_l_[PADL_(uint32_t)]; uint32_t len1; char len1_r_[PADR_(uint32_t)];
+ char len2_l_[PADL_(uint32_t)]; uint32_t len2; char len2_r_[PADR_(uint32_t)];
+ char advice_l_[PADL_(int)]; int advice; char advice_r_[PADR_(int)];
+};
+struct freebsd32_wait6_args {
+ char idtype_l_[PADL_(int)]; int idtype; char idtype_r_[PADR_(int)];
+ char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)];
+ char id1_l_[PADL_(uint32_t)]; uint32_t id1; char id1_r_[PADR_(uint32_t)];
+ char id2_l_[PADL_(uint32_t)]; uint32_t id2; char id2_r_[PADR_(uint32_t)];
+ char status_l_[PADL_(int *)]; int * status; char status_r_[PADR_(int *)];
+ char options_l_[PADL_(int)]; int options; char options_r_[PADR_(int)];
+ char wrusage_l_[PADL_(struct wrusage32 *)]; struct wrusage32 * wrusage; char wrusage_r_[PADR_(struct wrusage32 *)];
+ char info_l_[PADL_(siginfo_t *)]; siginfo_t * info; char info_r_[PADR_(siginfo_t *)];
+};
+#else
+struct freebsd32_posix_fallocate_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char offset1_l_[PADL_(uint32_t)]; uint32_t offset1; char offset1_r_[PADR_(uint32_t)];
+ char offset2_l_[PADL_(uint32_t)]; uint32_t offset2; char offset2_r_[PADR_(uint32_t)];
+ char len1_l_[PADL_(uint32_t)]; uint32_t len1; char len1_r_[PADR_(uint32_t)];
+ char len2_l_[PADL_(uint32_t)]; uint32_t len2; char len2_r_[PADR_(uint32_t)];
+};
+struct freebsd32_posix_fadvise_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char offset1_l_[PADL_(uint32_t)]; uint32_t offset1; char offset1_r_[PADR_(uint32_t)];
+ char offset2_l_[PADL_(uint32_t)]; uint32_t offset2; char offset2_r_[PADR_(uint32_t)];
+ char len1_l_[PADL_(uint32_t)]; uint32_t len1; char len1_r_[PADR_(uint32_t)];
+ char len2_l_[PADL_(uint32_t)]; uint32_t len2; char len2_r_[PADR_(uint32_t)];
+ char advice_l_[PADL_(int)]; int advice; char advice_r_[PADR_(int)];
+};
+struct freebsd32_wait6_args {
+ char idtype_l_[PADL_(int)]; int idtype; char idtype_r_[PADR_(int)];
+ char id1_l_[PADL_(uint32_t)]; uint32_t id1; char id1_r_[PADR_(uint32_t)];
+ char id2_l_[PADL_(uint32_t)]; uint32_t id2; char id2_r_[PADR_(uint32_t)];
+ char status_l_[PADL_(int *)]; int * status; char status_r_[PADR_(int *)];
+ char options_l_[PADL_(int)]; int options; char options_r_[PADR_(int)];
+ char wrusage_l_[PADL_(struct wrusage32 *)]; struct wrusage32 * wrusage; char wrusage_r_[PADR_(struct wrusage32 *)];
+ char info_l_[PADL_(siginfo_t *)]; siginfo_t * info; char info_r_[PADR_(siginfo_t *)];
+};
+#endif
+struct freebsd32_aio_mlock_args {
+ char aiocbp_l_[PADL_(struct aiocb32 *)]; struct aiocb32 * aiocbp; char aiocbp_r_[PADR_(struct aiocb32 *)];
+};
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
+#define PAD64_REQUIRED
+#endif
+int freebsd32_wait4(struct thread *, struct freebsd32_wait4_args *);
+int freebsd32_recvmsg(struct thread *, struct freebsd32_recvmsg_args *);
+int freebsd32_sendmsg(struct thread *, struct freebsd32_sendmsg_args *);
+int freebsd32_recvfrom(struct thread *, struct freebsd32_recvfrom_args *);
+int freebsd32_sigaltstack(struct thread *, struct freebsd32_sigaltstack_args *);
+int freebsd32_ioctl(struct thread *, struct freebsd32_ioctl_args *);
+int freebsd32_execve(struct thread *, struct freebsd32_execve_args *);
+int freebsd32_mprotect(struct thread *, struct freebsd32_mprotect_args *);
+int freebsd32_setitimer(struct thread *, struct freebsd32_setitimer_args *);
+int freebsd32_getitimer(struct thread *, struct freebsd32_getitimer_args *);
+int freebsd32_select(struct thread *, struct freebsd32_select_args *);
+int freebsd32_gettimeofday(struct thread *, struct freebsd32_gettimeofday_args *);
+int freebsd32_getrusage(struct thread *, struct freebsd32_getrusage_args *);
+int freebsd32_readv(struct thread *, struct freebsd32_readv_args *);
+int freebsd32_writev(struct thread *, struct freebsd32_writev_args *);
+int freebsd32_settimeofday(struct thread *, struct freebsd32_settimeofday_args *);
+int freebsd32_utimes(struct thread *, struct freebsd32_utimes_args *);
+int freebsd32_adjtime(struct thread *, struct freebsd32_adjtime_args *);
+int freebsd32_sysarch(struct thread *, struct freebsd32_sysarch_args *);
+int freebsd32_semsys(struct thread *, struct freebsd32_semsys_args *);
+int freebsd32_msgsys(struct thread *, struct freebsd32_msgsys_args *);
+int freebsd32_shmsys(struct thread *, struct freebsd32_shmsys_args *);
+int freebsd32_stat(struct thread *, struct freebsd32_stat_args *);
+int freebsd32_fstat(struct thread *, struct freebsd32_fstat_args *);
+int freebsd32_lstat(struct thread *, struct freebsd32_lstat_args *);
+int freebsd32_getdirentries(struct thread *, struct freebsd32_getdirentries_args *);
+int freebsd32_sysctl(struct thread *, struct freebsd32_sysctl_args *);
+int freebsd32_futimes(struct thread *, struct freebsd32_futimes_args *);
+int freebsd32_msgsnd(struct thread *, struct freebsd32_msgsnd_args *);
+int freebsd32_msgrcv(struct thread *, struct freebsd32_msgrcv_args *);
+int freebsd32_clock_gettime(struct thread *, struct freebsd32_clock_gettime_args *);
+int freebsd32_clock_settime(struct thread *, struct freebsd32_clock_settime_args *);
+int freebsd32_clock_getres(struct thread *, struct freebsd32_clock_getres_args *);
+int freebsd32_nanosleep(struct thread *, struct freebsd32_nanosleep_args *);
+int freebsd32_aio_read(struct thread *, struct freebsd32_aio_read_args *);
+int freebsd32_aio_write(struct thread *, struct freebsd32_aio_write_args *);
+int freebsd32_lio_listio(struct thread *, struct freebsd32_lio_listio_args *);
+int freebsd32_lutimes(struct thread *, struct freebsd32_lutimes_args *);
+int freebsd32_preadv(struct thread *, struct freebsd32_preadv_args *);
+int freebsd32_pwritev(struct thread *, struct freebsd32_pwritev_args *);
+int freebsd32_modstat(struct thread *, struct freebsd32_modstat_args *);
+int freebsd32_kldstat(struct thread *, struct freebsd32_kldstat_args *);
+int freebsd32_aio_return(struct thread *, struct freebsd32_aio_return_args *);
+int freebsd32_aio_suspend(struct thread *, struct freebsd32_aio_suspend_args *);
+int freebsd32_aio_cancel(struct thread *, struct freebsd32_aio_cancel_args *);
+int freebsd32_aio_error(struct thread *, struct freebsd32_aio_error_args *);
+int freebsd32_oaio_read(struct thread *, struct freebsd32_oaio_read_args *);
+int freebsd32_oaio_write(struct thread *, struct freebsd32_oaio_write_args *);
+int freebsd32_olio_listio(struct thread *, struct freebsd32_olio_listio_args *);
+int freebsd32_jail(struct thread *, struct freebsd32_jail_args *);
+int freebsd32_sigtimedwait(struct thread *, struct freebsd32_sigtimedwait_args *);
+int freebsd32_sigwaitinfo(struct thread *, struct freebsd32_sigwaitinfo_args *);
+int freebsd32_aio_waitcomplete(struct thread *, struct freebsd32_aio_waitcomplete_args *);
+int freebsd32_kevent(struct thread *, struct freebsd32_kevent_args *);
+int freebsd32_nmount(struct thread *, struct freebsd32_nmount_args *);
+int freebsd32_sendfile(struct thread *, struct freebsd32_sendfile_args *);
+int freebsd32_ksem_init(struct thread *, struct freebsd32_ksem_init_args *);
+int freebsd32_ksem_open(struct thread *, struct freebsd32_ksem_open_args *);
+int freebsd32_sigaction(struct thread *, struct freebsd32_sigaction_args *);
+int freebsd32_sigreturn(struct thread *, struct freebsd32_sigreturn_args *);
+int freebsd32_getcontext(struct thread *, struct freebsd32_getcontext_args *);
+int freebsd32_setcontext(struct thread *, struct freebsd32_setcontext_args *);
+int freebsd32_swapcontext(struct thread *, struct freebsd32_swapcontext_args *);
+int freebsd32_umtx_lock(struct thread *, struct freebsd32_umtx_lock_args *);
+int freebsd32_umtx_unlock(struct thread *, struct freebsd32_umtx_unlock_args *);
+int freebsd32_ksem_timedwait(struct thread *, struct freebsd32_ksem_timedwait_args *);
+int freebsd32_thr_suspend(struct thread *, struct freebsd32_thr_suspend_args *);
+int freebsd32_umtx_op(struct thread *, struct freebsd32_umtx_op_args *);
+int freebsd32_thr_new(struct thread *, struct freebsd32_thr_new_args *);
+int freebsd32_kmq_open(struct thread *, struct freebsd32_kmq_open_args *);
+int freebsd32_kmq_setattr(struct thread *, struct freebsd32_kmq_setattr_args *);
+int freebsd32_kmq_timedreceive(struct thread *, struct freebsd32_kmq_timedreceive_args *);
+int freebsd32_kmq_timedsend(struct thread *, struct freebsd32_kmq_timedsend_args *);
+int freebsd32_aio_fsync(struct thread *, struct freebsd32_aio_fsync_args *);
+#ifdef PAD64_REQUIRED
+int freebsd32_pread(struct thread *, struct freebsd32_pread_args *);
+int freebsd32_pwrite(struct thread *, struct freebsd32_pwrite_args *);
+int freebsd32_mmap(struct thread *, struct freebsd32_mmap_args *);
+int freebsd32_lseek(struct thread *, struct freebsd32_lseek_args *);
+int freebsd32_truncate(struct thread *, struct freebsd32_truncate_args *);
+int freebsd32_ftruncate(struct thread *, struct freebsd32_ftruncate_args *);
+#else
+int freebsd32_pread(struct thread *, struct freebsd32_pread_args *);
+int freebsd32_pwrite(struct thread *, struct freebsd32_pwrite_args *);
+int freebsd32_mmap(struct thread *, struct freebsd32_mmap_args *);
+int freebsd32_lseek(struct thread *, struct freebsd32_lseek_args *);
+int freebsd32_truncate(struct thread *, struct freebsd32_truncate_args *);
+int freebsd32_ftruncate(struct thread *, struct freebsd32_ftruncate_args *);
+#endif
+#ifdef PAD64_REQUIRED
+int freebsd32_cpuset_setid(struct thread *, struct freebsd32_cpuset_setid_args *);
+#else
+int freebsd32_cpuset_setid(struct thread *, struct freebsd32_cpuset_setid_args *);
+#endif
+int freebsd32_cpuset_getid(struct thread *, struct freebsd32_cpuset_getid_args *);
+int freebsd32_cpuset_getaffinity(struct thread *, struct freebsd32_cpuset_getaffinity_args *);
+int freebsd32_cpuset_setaffinity(struct thread *, struct freebsd32_cpuset_setaffinity_args *);
+int freebsd32_fexecve(struct thread *, struct freebsd32_fexecve_args *);
+int freebsd32_fstatat(struct thread *, struct freebsd32_fstatat_args *);
+int freebsd32_futimesat(struct thread *, struct freebsd32_futimesat_args *);
+int freebsd32_jail_get(struct thread *, struct freebsd32_jail_get_args *);
+int freebsd32_jail_set(struct thread *, struct freebsd32_jail_set_args *);
+int freebsd32_semctl(struct thread *, struct freebsd32_semctl_args *);
+int freebsd32_msgctl(struct thread *, struct freebsd32_msgctl_args *);
+int freebsd32_shmctl(struct thread *, struct freebsd32_shmctl_args *);
+int freebsd32_pselect(struct thread *, struct freebsd32_pselect_args *);
+#ifdef PAD64_REQUIRED
+int freebsd32_posix_fallocate(struct thread *, struct freebsd32_posix_fallocate_args *);
+int freebsd32_posix_fadvise(struct thread *, struct freebsd32_posix_fadvise_args *);
+int freebsd32_wait6(struct thread *, struct freebsd32_wait6_args *);
+#else
+int freebsd32_posix_fallocate(struct thread *, struct freebsd32_posix_fallocate_args *);
+int freebsd32_posix_fadvise(struct thread *, struct freebsd32_posix_fadvise_args *);
+int freebsd32_wait6(struct thread *, struct freebsd32_wait6_args *);
+#endif
+int freebsd32_aio_mlock(struct thread *, struct freebsd32_aio_mlock_args *);
+
+#ifdef COMPAT_43
+
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
+#define PAD64_REQUIRED
+#endif
+struct ofreebsd32_lseek_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char offset_l_[PADL_(int)]; int offset; char offset_r_[PADR_(int)];
+ char whence_l_[PADL_(int)]; int whence; char whence_r_[PADR_(int)];
+};
+struct ofreebsd32_stat_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char ub_l_[PADL_(struct ostat32 *)]; struct ostat32 * ub; char ub_r_[PADR_(struct ostat32 *)];
+};
+struct ofreebsd32_lstat_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char ub_l_[PADL_(struct ostat *)]; struct ostat * ub; char ub_r_[PADR_(struct ostat *)];
+};
+struct ofreebsd32_sigaction_args {
+ char signum_l_[PADL_(int)]; int signum; char signum_r_[PADR_(int)];
+ char nsa_l_[PADL_(struct osigaction32 *)]; struct osigaction32 * nsa; char nsa_r_[PADR_(struct osigaction32 *)];
+ char osa_l_[PADL_(struct osigaction32 *)]; struct osigaction32 * osa; char osa_r_[PADR_(struct osigaction32 *)];
+};
+struct ofreebsd32_sigprocmask_args {
+ char how_l_[PADL_(int)]; int how; char how_r_[PADR_(int)];
+ char mask_l_[PADL_(osigset_t)]; osigset_t mask; char mask_r_[PADR_(osigset_t)];
+};
+struct ofreebsd32_fstat_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char ub_l_[PADL_(struct ostat32 *)]; struct ostat32 * ub; char ub_r_[PADR_(struct ostat32 *)];
+};
+struct ofreebsd32_getpagesize_args {
+ char dummy_l_[PADL_(int32_t)]; int32_t dummy; char dummy_r_[PADR_(int32_t)];
+};
+struct ofreebsd32_sigreturn_args {
+ char sigcntxp_l_[PADL_(struct ia32_sigcontext3 *)]; struct ia32_sigcontext3 * sigcntxp; char sigcntxp_r_[PADR_(struct ia32_sigcontext3 *)];
+};
+struct ofreebsd32_sigvec_args {
+ char signum_l_[PADL_(int)]; int signum; char signum_r_[PADR_(int)];
+ char nsv_l_[PADL_(struct sigvec32 *)]; struct sigvec32 * nsv; char nsv_r_[PADR_(struct sigvec32 *)];
+ char osv_l_[PADL_(struct sigvec32 *)]; struct sigvec32 * osv; char osv_r_[PADR_(struct sigvec32 *)];
+};
+struct ofreebsd32_sigblock_args {
+ char mask_l_[PADL_(int)]; int mask; char mask_r_[PADR_(int)];
+};
+struct ofreebsd32_sigsetmask_args {
+ char mask_l_[PADL_(int)]; int mask; char mask_r_[PADR_(int)];
+};
+struct ofreebsd32_sigsuspend_args {
+ char mask_l_[PADL_(int)]; int mask; char mask_r_[PADR_(int)];
+};
+struct ofreebsd32_sigstack_args {
+ char nss_l_[PADL_(struct sigstack32 *)]; struct sigstack32 * nss; char nss_r_[PADR_(struct sigstack32 *)];
+ char oss_l_[PADL_(struct sigstack32 *)]; struct sigstack32 * oss; char oss_r_[PADR_(struct sigstack32 *)];
+};
+struct ofreebsd32_getdirentries_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)];
+ char count_l_[PADL_(u_int)]; u_int count; char count_r_[PADR_(u_int)];
+ char basep_l_[PADL_(uint32_t *)]; uint32_t * basep; char basep_r_[PADR_(uint32_t *)];
+};
+#ifdef PAD64_REQUIRED
+#else
+#endif
+#ifdef PAD64_REQUIRED
+#else
+#endif
+#ifdef PAD64_REQUIRED
+#else
+#endif
+int ofreebsd32_lseek(struct thread *, struct ofreebsd32_lseek_args *);
+int ofreebsd32_stat(struct thread *, struct ofreebsd32_stat_args *);
+int ofreebsd32_lstat(struct thread *, struct ofreebsd32_lstat_args *);
+int ofreebsd32_sigaction(struct thread *, struct ofreebsd32_sigaction_args *);
+int ofreebsd32_sigprocmask(struct thread *, struct ofreebsd32_sigprocmask_args *);
+int ofreebsd32_sigpending(struct thread *, struct ofreebsd32_sigpending_args *);
+int ofreebsd32_fstat(struct thread *, struct ofreebsd32_fstat_args *);
+int ofreebsd32_getpagesize(struct thread *, struct ofreebsd32_getpagesize_args *);
+int ofreebsd32_sigreturn(struct thread *, struct ofreebsd32_sigreturn_args *);
+int ofreebsd32_sigvec(struct thread *, struct ofreebsd32_sigvec_args *);
+int ofreebsd32_sigblock(struct thread *, struct ofreebsd32_sigblock_args *);
+int ofreebsd32_sigsetmask(struct thread *, struct ofreebsd32_sigsetmask_args *);
+int ofreebsd32_sigsuspend(struct thread *, struct ofreebsd32_sigsuspend_args *);
+int ofreebsd32_sigstack(struct thread *, struct ofreebsd32_sigstack_args *);
+int ofreebsd32_getdirentries(struct thread *, struct ofreebsd32_getdirentries_args *);
+
+#endif /* COMPAT_43 */
+
+
+#ifdef COMPAT_FREEBSD4
+
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
+#define PAD64_REQUIRED
+#endif
+struct freebsd4_freebsd32_getfsstat_args {
+ char buf_l_[PADL_(struct statfs32 *)]; struct statfs32 * buf; char buf_r_[PADR_(struct statfs32 *)];
+ char bufsize_l_[PADL_(long)]; long bufsize; char bufsize_r_[PADR_(long)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+};
+struct freebsd4_freebsd32_statfs_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char buf_l_[PADL_(struct statfs32 *)]; struct statfs32 * buf; char buf_r_[PADR_(struct statfs32 *)];
+};
+struct freebsd4_freebsd32_fstatfs_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char buf_l_[PADL_(struct statfs32 *)]; struct statfs32 * buf; char buf_r_[PADR_(struct statfs32 *)];
+};
+struct freebsd4_freebsd32_fhstatfs_args {
+ char u_fhp_l_[PADL_(const struct fhandle *)]; const struct fhandle * u_fhp; char u_fhp_r_[PADR_(const struct fhandle *)];
+ char buf_l_[PADL_(struct statfs32 *)]; struct statfs32 * buf; char buf_r_[PADR_(struct statfs32 *)];
+};
+struct freebsd4_freebsd32_sendfile_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
+ char offset1_l_[PADL_(uint32_t)]; uint32_t offset1; char offset1_r_[PADR_(uint32_t)];
+ char offset2_l_[PADL_(uint32_t)]; uint32_t offset2; char offset2_r_[PADR_(uint32_t)];
+ char nbytes_l_[PADL_(size_t)]; size_t nbytes; char nbytes_r_[PADR_(size_t)];
+ char hdtr_l_[PADL_(struct sf_hdtr32 *)]; struct sf_hdtr32 * hdtr; char hdtr_r_[PADR_(struct sf_hdtr32 *)];
+ char sbytes_l_[PADL_(off_t *)]; off_t * sbytes; char sbytes_r_[PADR_(off_t *)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+};
+struct freebsd4_freebsd32_sigaction_args {
+ char sig_l_[PADL_(int)]; int sig; char sig_r_[PADR_(int)];
+ char act_l_[PADL_(struct sigaction32 *)]; struct sigaction32 * act; char act_r_[PADR_(struct sigaction32 *)];
+ char oact_l_[PADL_(struct sigaction32 *)]; struct sigaction32 * oact; char oact_r_[PADR_(struct sigaction32 *)];
+};
+struct freebsd4_freebsd32_sigreturn_args {
+ char sigcntxp_l_[PADL_(const struct freebsd4_freebsd32_ucontext *)]; const struct freebsd4_freebsd32_ucontext * sigcntxp; char sigcntxp_r_[PADR_(const struct freebsd4_freebsd32_ucontext *)];
+};
+#ifdef PAD64_REQUIRED
+#else
+#endif
+#ifdef PAD64_REQUIRED
+#else
+#endif
+#ifdef PAD64_REQUIRED
+#else
+#endif
+int freebsd4_freebsd32_getfsstat(struct thread *, struct freebsd4_freebsd32_getfsstat_args *);
+int freebsd4_freebsd32_statfs(struct thread *, struct freebsd4_freebsd32_statfs_args *);
+int freebsd4_freebsd32_fstatfs(struct thread *, struct freebsd4_freebsd32_fstatfs_args *);
+int freebsd4_freebsd32_fhstatfs(struct thread *, struct freebsd4_freebsd32_fhstatfs_args *);
+int freebsd4_freebsd32_sendfile(struct thread *, struct freebsd4_freebsd32_sendfile_args *);
+int freebsd4_freebsd32_sigaction(struct thread *, struct freebsd4_freebsd32_sigaction_args *);
+int freebsd4_freebsd32_sigreturn(struct thread *, struct freebsd4_freebsd32_sigreturn_args *);
+
+#endif /* COMPAT_FREEBSD4 */
+
+
+#ifdef COMPAT_FREEBSD6
+
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
+#define PAD64_REQUIRED
+#endif
+struct freebsd6_freebsd32_pread_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char buf_l_[PADL_(void *)]; void * buf; char buf_r_[PADR_(void *)];
+ char nbyte_l_[PADL_(size_t)]; size_t nbyte; char nbyte_r_[PADR_(size_t)];
+ char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)];
+ char offset1_l_[PADL_(uint32_t)]; uint32_t offset1; char offset1_r_[PADR_(uint32_t)];
+ char offset2_l_[PADL_(uint32_t)]; uint32_t offset2; char offset2_r_[PADR_(uint32_t)];
+};
+struct freebsd6_freebsd32_pwrite_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char buf_l_[PADL_(const void *)]; const void * buf; char buf_r_[PADR_(const void *)];
+ char nbyte_l_[PADL_(size_t)]; size_t nbyte; char nbyte_r_[PADR_(size_t)];
+ char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)];
+ char offset1_l_[PADL_(uint32_t)]; uint32_t offset1; char offset1_r_[PADR_(uint32_t)];
+ char offset2_l_[PADL_(uint32_t)]; uint32_t offset2; char offset2_r_[PADR_(uint32_t)];
+};
+struct freebsd6_freebsd32_mmap_args {
+ char addr_l_[PADL_(caddr_t)]; caddr_t addr; char addr_r_[PADR_(caddr_t)];
+ char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)];
+ char prot_l_[PADL_(int)]; int prot; char prot_r_[PADR_(int)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)];
+ char pos1_l_[PADL_(uint32_t)]; uint32_t pos1; char pos1_r_[PADR_(uint32_t)];
+ char pos2_l_[PADL_(uint32_t)]; uint32_t pos2; char pos2_r_[PADR_(uint32_t)];
+};
+struct freebsd6_freebsd32_lseek_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)];
+ char offset1_l_[PADL_(uint32_t)]; uint32_t offset1; char offset1_r_[PADR_(uint32_t)];
+ char offset2_l_[PADL_(uint32_t)]; uint32_t offset2; char offset2_r_[PADR_(uint32_t)];
+ char whence_l_[PADL_(int)]; int whence; char whence_r_[PADR_(int)];
+};
+struct freebsd6_freebsd32_truncate_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)];
+ char length1_l_[PADL_(uint32_t)]; uint32_t length1; char length1_r_[PADR_(uint32_t)];
+ char length2_l_[PADL_(uint32_t)]; uint32_t length2; char length2_r_[PADR_(uint32_t)];
+};
+struct freebsd6_freebsd32_ftruncate_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)];
+ char length1_l_[PADL_(uint32_t)]; uint32_t length1; char length1_r_[PADR_(uint32_t)];
+ char length2_l_[PADL_(uint32_t)]; uint32_t length2; char length2_r_[PADR_(uint32_t)];
+};
+#ifdef PAD64_REQUIRED
+#else
+#endif
+#ifdef PAD64_REQUIRED
+#else
+#endif
+#ifdef PAD64_REQUIRED
+#else
+#endif
+int freebsd6_freebsd32_pread(struct thread *, struct freebsd6_freebsd32_pread_args *);
+int freebsd6_freebsd32_pwrite(struct thread *, struct freebsd6_freebsd32_pwrite_args *);
+int freebsd6_freebsd32_mmap(struct thread *, struct freebsd6_freebsd32_mmap_args *);
+int freebsd6_freebsd32_lseek(struct thread *, struct freebsd6_freebsd32_lseek_args *);
+int freebsd6_freebsd32_truncate(struct thread *, struct freebsd6_freebsd32_truncate_args *);
+int freebsd6_freebsd32_ftruncate(struct thread *, struct freebsd6_freebsd32_ftruncate_args *);
+
+#endif /* COMPAT_FREEBSD6 */
+
+
+#ifdef COMPAT_FREEBSD7
+
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
+#define PAD64_REQUIRED
+#endif
+struct freebsd7_freebsd32_semctl_args {
+ char semid_l_[PADL_(int)]; int semid; char semid_r_[PADR_(int)];
+ char semnum_l_[PADL_(int)]; int semnum; char semnum_r_[PADR_(int)];
+ char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)];
+ char arg_l_[PADL_(union semun32 *)]; union semun32 * arg; char arg_r_[PADR_(union semun32 *)];
+};
+struct freebsd7_freebsd32_msgctl_args {
+ char msqid_l_[PADL_(int)]; int msqid; char msqid_r_[PADR_(int)];
+ char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)];
+ char buf_l_[PADL_(struct msqid_ds32_old *)]; struct msqid_ds32_old * buf; char buf_r_[PADR_(struct msqid_ds32_old *)];
+};
+struct freebsd7_freebsd32_shmctl_args {
+ char shmid_l_[PADL_(int)]; int shmid; char shmid_r_[PADR_(int)];
+ char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)];
+ char buf_l_[PADL_(struct shmid_ds32_old *)]; struct shmid_ds32_old * buf; char buf_r_[PADR_(struct shmid_ds32_old *)];
+};
+#ifdef PAD64_REQUIRED
+#else
+#endif
+#ifdef PAD64_REQUIRED
+#else
+#endif
+#ifdef PAD64_REQUIRED
+#else
+#endif
+int freebsd7_freebsd32_semctl(struct thread *, struct freebsd7_freebsd32_semctl_args *);
+int freebsd7_freebsd32_msgctl(struct thread *, struct freebsd7_freebsd32_msgctl_args *);
+int freebsd7_freebsd32_shmctl(struct thread *, struct freebsd7_freebsd32_shmctl_args *);
+
+#endif /* COMPAT_FREEBSD7 */
+
+#define FREEBSD32_SYS_AUE_freebsd32_wait4 AUE_WAIT4
+#define FREEBSD32_SYS_AUE_freebsd4_freebsd32_getfsstat AUE_GETFSSTAT
+#define FREEBSD32_SYS_AUE_ofreebsd32_lseek AUE_LSEEK
+#define FREEBSD32_SYS_AUE_freebsd32_recvmsg AUE_RECVMSG
+#define FREEBSD32_SYS_AUE_freebsd32_sendmsg AUE_SENDMSG
+#define FREEBSD32_SYS_AUE_freebsd32_recvfrom AUE_RECVFROM
+#define FREEBSD32_SYS_AUE_ofreebsd32_stat AUE_STAT
+#define FREEBSD32_SYS_AUE_ofreebsd32_lstat AUE_LSTAT
+#define FREEBSD32_SYS_AUE_ofreebsd32_sigaction AUE_SIGACTION
+#define FREEBSD32_SYS_AUE_ofreebsd32_sigprocmask AUE_SIGPROCMASK
+#define FREEBSD32_SYS_AUE_ofreebsd32_sigpending AUE_SIGPENDING
+#define FREEBSD32_SYS_AUE_freebsd32_sigaltstack AUE_SIGALTSTACK
+#define FREEBSD32_SYS_AUE_freebsd32_ioctl AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_execve AUE_EXECVE
+#define FREEBSD32_SYS_AUE_ofreebsd32_fstat AUE_FSTAT
+#define FREEBSD32_SYS_AUE_ofreebsd32_getpagesize AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_mprotect AUE_MPROTECT
+#define FREEBSD32_SYS_AUE_freebsd32_setitimer AUE_SETITIMER
+#define FREEBSD32_SYS_AUE_freebsd32_getitimer AUE_GETITIMER
+#define FREEBSD32_SYS_AUE_freebsd32_select AUE_SELECT
+#define FREEBSD32_SYS_AUE_ofreebsd32_sigreturn AUE_NULL
+#define FREEBSD32_SYS_AUE_ofreebsd32_sigvec AUE_O_SIGVEC
+#define FREEBSD32_SYS_AUE_ofreebsd32_sigblock AUE_O_SIGBLOCK
+#define FREEBSD32_SYS_AUE_ofreebsd32_sigsetmask AUE_O_SIGSETMASK
+#define FREEBSD32_SYS_AUE_ofreebsd32_sigsuspend AUE_SIGSUSPEND
+#define FREEBSD32_SYS_AUE_ofreebsd32_sigstack AUE_O_SIGSTACK
+#define FREEBSD32_SYS_AUE_freebsd32_gettimeofday AUE_GETTIMEOFDAY
+#define FREEBSD32_SYS_AUE_freebsd32_getrusage AUE_GETRUSAGE
+#define FREEBSD32_SYS_AUE_freebsd32_readv AUE_READV
+#define FREEBSD32_SYS_AUE_freebsd32_writev AUE_WRITEV
+#define FREEBSD32_SYS_AUE_freebsd32_settimeofday AUE_SETTIMEOFDAY
+#define FREEBSD32_SYS_AUE_freebsd32_utimes AUE_UTIMES
+#define FREEBSD32_SYS_AUE_freebsd32_adjtime AUE_ADJTIME
+#define FREEBSD32_SYS_AUE_ofreebsd32_getdirentries AUE_GETDIRENTRIES
+#define FREEBSD32_SYS_AUE_freebsd4_freebsd32_statfs AUE_STATFS
+#define FREEBSD32_SYS_AUE_freebsd4_freebsd32_fstatfs AUE_FSTATFS
+#define FREEBSD32_SYS_AUE_freebsd32_sysarch AUE_SYSARCH
+#define FREEBSD32_SYS_AUE_freebsd32_semsys AUE_SEMSYS
+#define FREEBSD32_SYS_AUE_freebsd32_msgsys AUE_MSGSYS
+#define FREEBSD32_SYS_AUE_freebsd32_shmsys AUE_SHMSYS
+#define FREEBSD32_SYS_AUE_freebsd6_freebsd32_pread AUE_PREAD
+#define FREEBSD32_SYS_AUE_freebsd6_freebsd32_pwrite AUE_PWRITE
+#define FREEBSD32_SYS_AUE_freebsd32_stat AUE_STAT
+#define FREEBSD32_SYS_AUE_freebsd32_fstat AUE_FSTAT
+#define FREEBSD32_SYS_AUE_freebsd32_lstat AUE_LSTAT
+#define FREEBSD32_SYS_AUE_freebsd32_getdirentries AUE_GETDIRENTRIES
+#define FREEBSD32_SYS_AUE_freebsd6_freebsd32_mmap AUE_MMAP
+#define FREEBSD32_SYS_AUE_freebsd6_freebsd32_lseek AUE_LSEEK
+#define FREEBSD32_SYS_AUE_freebsd6_freebsd32_truncate AUE_TRUNCATE
+#define FREEBSD32_SYS_AUE_freebsd6_freebsd32_ftruncate AUE_FTRUNCATE
+#define FREEBSD32_SYS_AUE_freebsd32_sysctl AUE_SYSCTL
+#define FREEBSD32_SYS_AUE_freebsd32_futimes AUE_FUTIMES
+#define FREEBSD32_SYS_AUE_freebsd7_freebsd32_semctl AUE_SEMCTL
+#define FREEBSD32_SYS_AUE_freebsd7_freebsd32_msgctl AUE_MSGCTL
+#define FREEBSD32_SYS_AUE_freebsd32_msgsnd AUE_MSGSND
+#define FREEBSD32_SYS_AUE_freebsd32_msgrcv AUE_MSGRCV
+#define FREEBSD32_SYS_AUE_freebsd7_freebsd32_shmctl AUE_SHMCTL
+#define FREEBSD32_SYS_AUE_freebsd32_clock_gettime AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_clock_settime AUE_CLOCK_SETTIME
+#define FREEBSD32_SYS_AUE_freebsd32_clock_getres AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_nanosleep AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_aio_read AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_aio_write AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_lio_listio AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_lutimes AUE_LUTIMES
+#define FREEBSD32_SYS_AUE_freebsd32_preadv AUE_PREADV
+#define FREEBSD32_SYS_AUE_freebsd32_pwritev AUE_PWRITEV
+#define FREEBSD32_SYS_AUE_freebsd4_freebsd32_fhstatfs AUE_FHSTATFS
+#define FREEBSD32_SYS_AUE_freebsd32_modstat AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_kldstat AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_aio_return AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_aio_suspend AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_aio_cancel AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_aio_error AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_oaio_read AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_oaio_write AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_olio_listio AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd4_freebsd32_sendfile AUE_SENDFILE
+#define FREEBSD32_SYS_AUE_freebsd32_jail AUE_JAIL
+#define FREEBSD32_SYS_AUE_freebsd4_freebsd32_sigaction AUE_SIGACTION
+#define FREEBSD32_SYS_AUE_freebsd4_freebsd32_sigreturn AUE_SIGRETURN
+#define FREEBSD32_SYS_AUE_freebsd32_sigtimedwait AUE_SIGWAIT
+#define FREEBSD32_SYS_AUE_freebsd32_sigwaitinfo AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_aio_waitcomplete AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_kevent AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_nmount AUE_NMOUNT
+#define FREEBSD32_SYS_AUE_freebsd32_sendfile AUE_SENDFILE
+#define FREEBSD32_SYS_AUE_freebsd32_ksem_init AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_ksem_open AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_sigaction AUE_SIGACTION
+#define FREEBSD32_SYS_AUE_freebsd32_sigreturn AUE_SIGRETURN
+#define FREEBSD32_SYS_AUE_freebsd32_getcontext AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_setcontext AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_swapcontext AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_umtx_lock AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_umtx_unlock AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_ksem_timedwait AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_thr_suspend AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_umtx_op AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_thr_new AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_kmq_open AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_kmq_setattr AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_kmq_timedreceive AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_kmq_timedsend AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_aio_fsync AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_pread AUE_PREAD
+#define FREEBSD32_SYS_AUE_freebsd32_pwrite AUE_PWRITE
+#define FREEBSD32_SYS_AUE_freebsd32_mmap AUE_MMAP
+#define FREEBSD32_SYS_AUE_freebsd32_lseek AUE_LSEEK
+#define FREEBSD32_SYS_AUE_freebsd32_truncate AUE_TRUNCATE
+#define FREEBSD32_SYS_AUE_freebsd32_ftruncate AUE_FTRUNCATE
+#define FREEBSD32_SYS_AUE_freebsd32_pread AUE_PREAD
+#define FREEBSD32_SYS_AUE_freebsd32_pwrite AUE_PWRITE
+#define FREEBSD32_SYS_AUE_freebsd32_mmap AUE_MMAP
+#define FREEBSD32_SYS_AUE_freebsd32_lseek AUE_LSEEK
+#define FREEBSD32_SYS_AUE_freebsd32_truncate AUE_TRUNCATE
+#define FREEBSD32_SYS_AUE_freebsd32_ftruncate AUE_FTRUNCATE
+#define FREEBSD32_SYS_AUE_freebsd32_cpuset_setid AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_cpuset_setid AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_cpuset_getid AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_cpuset_getaffinity AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_cpuset_setaffinity AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_fexecve AUE_FEXECVE
+#define FREEBSD32_SYS_AUE_freebsd32_fstatat AUE_FSTATAT
+#define FREEBSD32_SYS_AUE_freebsd32_futimesat AUE_FUTIMESAT
+#define FREEBSD32_SYS_AUE_freebsd32_jail_get AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_jail_set AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_semctl AUE_SEMCTL
+#define FREEBSD32_SYS_AUE_freebsd32_msgctl AUE_MSGCTL
+#define FREEBSD32_SYS_AUE_freebsd32_shmctl AUE_SHMCTL
+#define FREEBSD32_SYS_AUE_freebsd32_pselect AUE_SELECT
+#define FREEBSD32_SYS_AUE_freebsd32_posix_fallocate AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_posix_fadvise AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_wait6 AUE_WAIT6
+#define FREEBSD32_SYS_AUE_freebsd32_posix_fallocate AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_posix_fadvise AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32_wait6 AUE_WAIT6
+#define FREEBSD32_SYS_AUE_freebsd32_aio_mlock AUE_NULL
+
+#undef PAD_
+#undef PADL_
+#undef PADR_
+
+#endif /* !_FREEBSD32_SYSPROTO_H_ */
diff --git a/sys/compat/freebsd32/freebsd32_signal.h b/sys/compat/freebsd32/freebsd32_signal.h
new file mode 100644
index 0000000..d31a8ae
--- /dev/null
+++ b/sys/compat/freebsd32/freebsd32_signal.h
@@ -0,0 +1,102 @@
+/*-
+ * Copyright (c) 2006 David Xu <davidxu@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _COMPAT_FREEBSD32_SIGNAL_H_
+#define _COMPAT_FREEBSD32_SIGNAL_H_
+
+struct sigaltstack32 {
+ u_int32_t ss_sp; /* signal stack base */
+ u_int32_t ss_size; /* signal stack length */
+ int ss_flags; /* SS_DISABLE and/or SS_ONSTACK */
+};
+
+union sigval32 {
+ int sival_int;
+ u_int32_t sival_ptr;
+ /* 6.0 compatibility */
+ int sigval_int;
+ u_int32_t sigval_ptr;
+};
+
+struct siginfo32 {
+ int si_signo; /* signal number */
+ int si_errno; /* errno association */
+ int si_code; /* signal code */
+ int32_t si_pid; /* sending process */
+ u_int32_t si_uid; /* sender's ruid */
+ int si_status; /* exit value */
+ u_int32_t si_addr; /* faulting instruction */
+ union sigval32 si_value; /* signal value */
+ union {
+ struct {
+ int _trapno;/* machine specific trap code */
+ } _fault;
+ struct {
+ int _timerid;
+ int _overrun;
+ } _timer;
+ struct {
+ int _mqd;
+ } _mesgq;
+ struct {
+ int _band; /* band event for SIGPOLL */
+ } _poll; /* was this ever used ? */
+ struct {
+ int __spare1__;
+ int __spare2__[7];
+ } __spare__;
+ } _reason;
+};
+
+struct osigevent32 {
+ int sigev_notify; /* Notification type */
+ union {
+ int __sigev_signo; /* Signal number */
+ int __sigev_notify_kqueue;
+ } __sigev_u;
+ union sigval32 sigev_value; /* Signal value */
+};
+
+struct sigevent32 {
+ int sigev_notify; /* Notification type */
+ int sigev_signo; /* Signal number */
+ union sigval32 sigev_value; /* Signal value */
+ union {
+ __lwpid_t _threadid;
+ struct {
+ uint32_t _function;
+ uint32_t _attribute;
+ } _sigev_thread;
+ unsigned short _kevent_flags;
+ uint32_t __spare__[8];
+ } _sigev_un;
+};
+
+void siginfo_to_siginfo32(const siginfo_t *src, struct siginfo32 *dst);
+
+#endif /* !_COMPAT_FREEBSD32_SIGNAL_H_ */
diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h
new file mode 100644
index 0000000..8c36fee
--- /dev/null
+++ b/sys/compat/freebsd32/freebsd32_syscall.h
@@ -0,0 +1,447 @@
+/*
+ * System call numbers.
+ *
+ * DO NOT EDIT-- this file is automatically generated.
+ * $FreeBSD$
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 251526 2013-06-08 13:27:57Z glebius
+ */
+
+#define FREEBSD32_SYS_syscall 0
+#define FREEBSD32_SYS_exit 1
+#define FREEBSD32_SYS_fork 2
+#define FREEBSD32_SYS_read 3
+#define FREEBSD32_SYS_write 4
+#define FREEBSD32_SYS_open 5
+#define FREEBSD32_SYS_close 6
+#define FREEBSD32_SYS_freebsd32_wait4 7
+ /* 8 is obsolete old creat */
+#define FREEBSD32_SYS_link 9
+#define FREEBSD32_SYS_unlink 10
+ /* 11 is obsolete execv */
+#define FREEBSD32_SYS_chdir 12
+#define FREEBSD32_SYS_fchdir 13
+#define FREEBSD32_SYS_mknod 14
+#define FREEBSD32_SYS_chmod 15
+#define FREEBSD32_SYS_chown 16
+#define FREEBSD32_SYS_break 17
+#define FREEBSD32_SYS_freebsd4_freebsd32_getfsstat 18
+ /* 19 is old freebsd32_lseek */
+#define FREEBSD32_SYS_getpid 20
+#define FREEBSD32_SYS_mount 21
+#define FREEBSD32_SYS_unmount 22
+#define FREEBSD32_SYS_setuid 23
+#define FREEBSD32_SYS_getuid 24
+#define FREEBSD32_SYS_geteuid 25
+#define FREEBSD32_SYS_ptrace 26
+#define FREEBSD32_SYS_freebsd32_recvmsg 27
+#define FREEBSD32_SYS_freebsd32_sendmsg 28
+#define FREEBSD32_SYS_freebsd32_recvfrom 29
+#define FREEBSD32_SYS_accept 30
+#define FREEBSD32_SYS_getpeername 31
+#define FREEBSD32_SYS_getsockname 32
+#define FREEBSD32_SYS_access 33
+#define FREEBSD32_SYS_chflags 34
+#define FREEBSD32_SYS_fchflags 35
+#define FREEBSD32_SYS_sync 36
+#define FREEBSD32_SYS_kill 37
+ /* 38 is old freebsd32_stat */
+#define FREEBSD32_SYS_getppid 39
+ /* 40 is old freebsd32_lstat */
+#define FREEBSD32_SYS_dup 41
+#define FREEBSD32_SYS_pipe 42
+#define FREEBSD32_SYS_getegid 43
+#define FREEBSD32_SYS_profil 44
+#define FREEBSD32_SYS_ktrace 45
+ /* 46 is old freebsd32_sigaction */
+#define FREEBSD32_SYS_getgid 47
+ /* 48 is old freebsd32_sigprocmask */
+#define FREEBSD32_SYS_getlogin 49
+#define FREEBSD32_SYS_setlogin 50
+#define FREEBSD32_SYS_acct 51
+ /* 52 is old freebsd32_sigpending */
+#define FREEBSD32_SYS_freebsd32_sigaltstack 53
+#define FREEBSD32_SYS_freebsd32_ioctl 54
+#define FREEBSD32_SYS_reboot 55
+#define FREEBSD32_SYS_revoke 56
+#define FREEBSD32_SYS_symlink 57
+#define FREEBSD32_SYS_readlink 58
+#define FREEBSD32_SYS_freebsd32_execve 59
+#define FREEBSD32_SYS_umask 60
+#define FREEBSD32_SYS_chroot 61
+ /* 62 is old freebsd32_fstat */
+ /* 63 is obsolete ogetkerninfo */
+ /* 64 is old freebsd32_getpagesize */
+#define FREEBSD32_SYS_msync 65
+#define FREEBSD32_SYS_vfork 66
+ /* 67 is obsolete vread */
+ /* 68 is obsolete vwrite */
+#define FREEBSD32_SYS_sbrk 69
+#define FREEBSD32_SYS_sstk 70
+ /* 71 is old mmap */
+#define FREEBSD32_SYS_vadvise 72
+#define FREEBSD32_SYS_munmap 73
+#define FREEBSD32_SYS_freebsd32_mprotect 74
+#define FREEBSD32_SYS_madvise 75
+ /* 76 is obsolete vhangup */
+ /* 77 is obsolete vlimit */
+#define FREEBSD32_SYS_mincore 78
+#define FREEBSD32_SYS_getgroups 79
+#define FREEBSD32_SYS_setgroups 80
+#define FREEBSD32_SYS_getpgrp 81
+#define FREEBSD32_SYS_setpgid 82
+#define FREEBSD32_SYS_freebsd32_setitimer 83
+ /* 84 is obsolete owait */
+#define FREEBSD32_SYS_swapon 85
+#define FREEBSD32_SYS_freebsd32_getitimer 86
+ /* 87 is obsolete ogethostname */
+ /* 88 is obsolete osethostname */
+#define FREEBSD32_SYS_getdtablesize 89
+#define FREEBSD32_SYS_dup2 90
+#define FREEBSD32_SYS_fcntl 92
+#define FREEBSD32_SYS_freebsd32_select 93
+#define FREEBSD32_SYS_fsync 95
+#define FREEBSD32_SYS_setpriority 96
+#define FREEBSD32_SYS_socket 97
+#define FREEBSD32_SYS_connect 98
+ /* 99 is obsolete oaccept */
+#define FREEBSD32_SYS_getpriority 100
+ /* 101 is obsolete osend */
+ /* 102 is obsolete orecv */
+ /* 103 is old freebsd32_sigreturn */
+#define FREEBSD32_SYS_bind 104
+#define FREEBSD32_SYS_setsockopt 105
+#define FREEBSD32_SYS_listen 106
+ /* 107 is obsolete vtimes */
+ /* 108 is old freebsd32_sigvec */
+ /* 109 is old freebsd32_sigblock */
+ /* 110 is old freebsd32_sigsetmask */
+ /* 111 is old freebsd32_sigsuspend */
+ /* 112 is old freebsd32_sigstack */
+ /* 113 is obsolete orecvmsg */
+ /* 114 is obsolete osendmsg */
+ /* 115 is obsolete vtrace */
+#define FREEBSD32_SYS_freebsd32_gettimeofday 116
+#define FREEBSD32_SYS_freebsd32_getrusage 117
+#define FREEBSD32_SYS_getsockopt 118
+#define FREEBSD32_SYS_freebsd32_readv 120
+#define FREEBSD32_SYS_freebsd32_writev 121
+#define FREEBSD32_SYS_freebsd32_settimeofday 122
+#define FREEBSD32_SYS_fchown 123
+#define FREEBSD32_SYS_fchmod 124
+ /* 125 is obsolete orecvfrom */
+#define FREEBSD32_SYS_setreuid 126
+#define FREEBSD32_SYS_setregid 127
+#define FREEBSD32_SYS_rename 128
+ /* 129 is old truncate */
+ /* 130 is old ftruncate */
+#define FREEBSD32_SYS_flock 131
+#define FREEBSD32_SYS_mkfifo 132
+#define FREEBSD32_SYS_sendto 133
+#define FREEBSD32_SYS_shutdown 134
+#define FREEBSD32_SYS_socketpair 135
+#define FREEBSD32_SYS_mkdir 136
+#define FREEBSD32_SYS_rmdir 137
+#define FREEBSD32_SYS_freebsd32_utimes 138
+ /* 139 is obsolete 4.2 sigreturn */
+#define FREEBSD32_SYS_freebsd32_adjtime 140
+ /* 141 is obsolete ogetpeername */
+ /* 142 is obsolete ogethostid */
+ /* 143 is obsolete sethostid */
+ /* 144 is obsolete getrlimit */
+ /* 145 is obsolete setrlimit */
+ /* 146 is obsolete killpg */
+#define FREEBSD32_SYS_setsid 147
+#define FREEBSD32_SYS_quotactl 148
+ /* 149 is obsolete oquota */
+ /* 150 is obsolete ogetsockname */
+ /* 156 is old freebsd32_getdirentries */
+#define FREEBSD32_SYS_freebsd4_freebsd32_statfs 157
+#define FREEBSD32_SYS_freebsd4_freebsd32_fstatfs 158
+#define FREEBSD32_SYS_getfh 161
+ /* 162 is obsolete getdomainname */
+ /* 163 is obsolete setdomainname */
+ /* 164 is obsolete uname */
+#define FREEBSD32_SYS_freebsd32_sysarch 165
+#define FREEBSD32_SYS_rtprio 166
+#define FREEBSD32_SYS_freebsd32_semsys 169
+#define FREEBSD32_SYS_freebsd32_msgsys 170
+#define FREEBSD32_SYS_freebsd32_shmsys 171
+#define FREEBSD32_SYS_freebsd6_freebsd32_pread 173
+#define FREEBSD32_SYS_freebsd6_freebsd32_pwrite 174
+#define FREEBSD32_SYS_ntp_adjtime 176
+#define FREEBSD32_SYS_setgid 181
+#define FREEBSD32_SYS_setegid 182
+#define FREEBSD32_SYS_seteuid 183
+#define FREEBSD32_SYS_freebsd32_stat 188
+#define FREEBSD32_SYS_freebsd32_fstat 189
+#define FREEBSD32_SYS_freebsd32_lstat 190
+#define FREEBSD32_SYS_pathconf 191
+#define FREEBSD32_SYS_fpathconf 192
+#define FREEBSD32_SYS_getrlimit 194
+#define FREEBSD32_SYS_setrlimit 195
+#define FREEBSD32_SYS_freebsd32_getdirentries 196
+#define FREEBSD32_SYS_freebsd6_freebsd32_mmap 197
+#define FREEBSD32_SYS___syscall 198
+#define FREEBSD32_SYS_freebsd6_freebsd32_lseek 199
+#define FREEBSD32_SYS_freebsd6_freebsd32_truncate 200
+#define FREEBSD32_SYS_freebsd6_freebsd32_ftruncate 201
+#define FREEBSD32_SYS_freebsd32_sysctl 202
+#define FREEBSD32_SYS_mlock 203
+#define FREEBSD32_SYS_munlock 204
+#define FREEBSD32_SYS_undelete 205
+#define FREEBSD32_SYS_freebsd32_futimes 206
+#define FREEBSD32_SYS_getpgid 207
+#define FREEBSD32_SYS_poll 209
+#define FREEBSD32_SYS_freebsd7_freebsd32_semctl 220
+#define FREEBSD32_SYS_semget 221
+#define FREEBSD32_SYS_semop 222
+#define FREEBSD32_SYS_freebsd7_freebsd32_msgctl 224
+#define FREEBSD32_SYS_msgget 225
+#define FREEBSD32_SYS_freebsd32_msgsnd 226
+#define FREEBSD32_SYS_freebsd32_msgrcv 227
+#define FREEBSD32_SYS_shmat 228
+#define FREEBSD32_SYS_freebsd7_freebsd32_shmctl 229
+#define FREEBSD32_SYS_shmdt 230
+#define FREEBSD32_SYS_shmget 231
+#define FREEBSD32_SYS_freebsd32_clock_gettime 232
+#define FREEBSD32_SYS_freebsd32_clock_settime 233
+#define FREEBSD32_SYS_freebsd32_clock_getres 234
+#define FREEBSD32_SYS_freebsd32_nanosleep 240
+#define FREEBSD32_SYS_ffclock_getcounter 241
+#define FREEBSD32_SYS_ffclock_setestimate 242
+#define FREEBSD32_SYS_ffclock_getestimate 243
+#define FREEBSD32_SYS_clock_getcpuclockid2 247
+#define FREEBSD32_SYS_minherit 250
+#define FREEBSD32_SYS_rfork 251
+#define FREEBSD32_SYS_openbsd_poll 252
+#define FREEBSD32_SYS_issetugid 253
+#define FREEBSD32_SYS_lchown 254
+#define FREEBSD32_SYS_freebsd32_aio_read 255
+#define FREEBSD32_SYS_freebsd32_aio_write 256
+#define FREEBSD32_SYS_freebsd32_lio_listio 257
+#define FREEBSD32_SYS_getdents 272
+#define FREEBSD32_SYS_lchmod 274
+#define FREEBSD32_SYS_netbsd_lchown 275
+#define FREEBSD32_SYS_freebsd32_lutimes 276
+#define FREEBSD32_SYS_netbsd_msync 277
+#define FREEBSD32_SYS_nstat 278
+#define FREEBSD32_SYS_nfstat 279
+#define FREEBSD32_SYS_nlstat 280
+#define FREEBSD32_SYS_freebsd32_preadv 289
+#define FREEBSD32_SYS_freebsd32_pwritev 290
+#define FREEBSD32_SYS_freebsd4_freebsd32_fhstatfs 297
+#define FREEBSD32_SYS_fhopen 298
+#define FREEBSD32_SYS_fhstat 299
+#define FREEBSD32_SYS_modnext 300
+#define FREEBSD32_SYS_freebsd32_modstat 301
+#define FREEBSD32_SYS_modfnext 302
+#define FREEBSD32_SYS_modfind 303
+#define FREEBSD32_SYS_kldload 304
+#define FREEBSD32_SYS_kldunload 305
+#define FREEBSD32_SYS_kldfind 306
+#define FREEBSD32_SYS_kldnext 307
+#define FREEBSD32_SYS_freebsd32_kldstat 308
+#define FREEBSD32_SYS_kldfirstmod 309
+#define FREEBSD32_SYS_getsid 310
+#define FREEBSD32_SYS_setresuid 311
+#define FREEBSD32_SYS_setresgid 312
+ /* 313 is obsolete signanosleep */
+#define FREEBSD32_SYS_freebsd32_aio_return 314
+#define FREEBSD32_SYS_freebsd32_aio_suspend 315
+#define FREEBSD32_SYS_freebsd32_aio_cancel 316
+#define FREEBSD32_SYS_freebsd32_aio_error 317
+#define FREEBSD32_SYS_freebsd32_oaio_read 318
+#define FREEBSD32_SYS_freebsd32_oaio_write 319
+#define FREEBSD32_SYS_freebsd32_olio_listio 320
+#define FREEBSD32_SYS_yield 321
+ /* 322 is obsolete thr_sleep */
+ /* 323 is obsolete thr_wakeup */
+#define FREEBSD32_SYS_mlockall 324
+#define FREEBSD32_SYS_munlockall 325
+#define FREEBSD32_SYS___getcwd 326
+#define FREEBSD32_SYS_sched_setparam 327
+#define FREEBSD32_SYS_sched_getparam 328
+#define FREEBSD32_SYS_sched_setscheduler 329
+#define FREEBSD32_SYS_sched_getscheduler 330
+#define FREEBSD32_SYS_sched_yield 331
+#define FREEBSD32_SYS_sched_get_priority_max 332
+#define FREEBSD32_SYS_sched_get_priority_min 333
+#define FREEBSD32_SYS_sched_rr_get_interval 334
+#define FREEBSD32_SYS_utrace 335
+#define FREEBSD32_SYS_freebsd4_freebsd32_sendfile 336
+#define FREEBSD32_SYS_kldsym 337
+#define FREEBSD32_SYS_freebsd32_jail 338
+#define FREEBSD32_SYS_sigprocmask 340
+#define FREEBSD32_SYS_sigsuspend 341
+#define FREEBSD32_SYS_freebsd4_freebsd32_sigaction 342
+#define FREEBSD32_SYS_sigpending 343
+#define FREEBSD32_SYS_freebsd4_freebsd32_sigreturn 344
+#define FREEBSD32_SYS_freebsd32_sigtimedwait 345
+#define FREEBSD32_SYS_freebsd32_sigwaitinfo 346
+#define FREEBSD32_SYS___acl_get_file 347
+#define FREEBSD32_SYS___acl_set_file 348
+#define FREEBSD32_SYS___acl_get_fd 349
+#define FREEBSD32_SYS___acl_set_fd 350
+#define FREEBSD32_SYS___acl_delete_file 351
+#define FREEBSD32_SYS___acl_delete_fd 352
+#define FREEBSD32_SYS___acl_aclcheck_file 353
+#define FREEBSD32_SYS___acl_aclcheck_fd 354
+#define FREEBSD32_SYS_extattrctl 355
+#define FREEBSD32_SYS_extattr_set_file 356
+#define FREEBSD32_SYS_extattr_get_file 357
+#define FREEBSD32_SYS_extattr_delete_file 358
+#define FREEBSD32_SYS_freebsd32_aio_waitcomplete 359
+#define FREEBSD32_SYS_getresuid 360
+#define FREEBSD32_SYS_getresgid 361
+#define FREEBSD32_SYS_kqueue 362
+#define FREEBSD32_SYS_freebsd32_kevent 363
+#define FREEBSD32_SYS_extattr_set_fd 371
+#define FREEBSD32_SYS_extattr_get_fd 372
+#define FREEBSD32_SYS_extattr_delete_fd 373
+#define FREEBSD32_SYS___setugid 374
+#define FREEBSD32_SYS_eaccess 376
+#define FREEBSD32_SYS_freebsd32_nmount 378
+#define FREEBSD32_SYS_kenv 390
+#define FREEBSD32_SYS_lchflags 391
+#define FREEBSD32_SYS_uuidgen 392
+#define FREEBSD32_SYS_freebsd32_sendfile 393
+#define FREEBSD32_SYS_getfsstat 395
+#define FREEBSD32_SYS_statfs 396
+#define FREEBSD32_SYS_fstatfs 397
+#define FREEBSD32_SYS_fhstatfs 398
+#define FREEBSD32_SYS_ksem_close 400
+#define FREEBSD32_SYS_ksem_post 401
+#define FREEBSD32_SYS_ksem_wait 402
+#define FREEBSD32_SYS_ksem_trywait 403
+#define FREEBSD32_SYS_freebsd32_ksem_init 404
+#define FREEBSD32_SYS_freebsd32_ksem_open 405
+#define FREEBSD32_SYS_ksem_unlink 406
+#define FREEBSD32_SYS_ksem_getvalue 407
+#define FREEBSD32_SYS_ksem_destroy 408
+#define FREEBSD32_SYS_extattr_set_link 412
+#define FREEBSD32_SYS_extattr_get_link 413
+#define FREEBSD32_SYS_extattr_delete_link 414
+#define FREEBSD32_SYS_freebsd32_sigaction 416
+#define FREEBSD32_SYS_freebsd32_sigreturn 417
+#define FREEBSD32_SYS_freebsd32_getcontext 421
+#define FREEBSD32_SYS_freebsd32_setcontext 422
+#define FREEBSD32_SYS_freebsd32_swapcontext 423
+#define FREEBSD32_SYS___acl_get_link 425
+#define FREEBSD32_SYS___acl_set_link 426
+#define FREEBSD32_SYS___acl_delete_link 427
+#define FREEBSD32_SYS___acl_aclcheck_link 428
+#define FREEBSD32_SYS_sigwait 429
+#define FREEBSD32_SYS_thr_exit 431
+#define FREEBSD32_SYS_thr_self 432
+#define FREEBSD32_SYS_thr_kill 433
+#define FREEBSD32_SYS_freebsd32_umtx_lock 434
+#define FREEBSD32_SYS_freebsd32_umtx_unlock 435
+#define FREEBSD32_SYS_jail_attach 436
+#define FREEBSD32_SYS_extattr_list_fd 437
+#define FREEBSD32_SYS_extattr_list_file 438
+#define FREEBSD32_SYS_extattr_list_link 439
+#define FREEBSD32_SYS_freebsd32_ksem_timedwait 441
+#define FREEBSD32_SYS_freebsd32_thr_suspend 442
+#define FREEBSD32_SYS_thr_wake 443
+#define FREEBSD32_SYS_kldunloadf 444
+#define FREEBSD32_SYS_audit 445
+#define FREEBSD32_SYS_auditon 446
+#define FREEBSD32_SYS_getauid 447
+#define FREEBSD32_SYS_setauid 448
+#define FREEBSD32_SYS_getaudit 449
+#define FREEBSD32_SYS_setaudit 450
+#define FREEBSD32_SYS_getaudit_addr 451
+#define FREEBSD32_SYS_setaudit_addr 452
+#define FREEBSD32_SYS_auditctl 453
+#define FREEBSD32_SYS_freebsd32_umtx_op 454
+#define FREEBSD32_SYS_freebsd32_thr_new 455
+#define FREEBSD32_SYS_sigqueue 456
+#define FREEBSD32_SYS_freebsd32_kmq_open 457
+#define FREEBSD32_SYS_freebsd32_kmq_setattr 458
+#define FREEBSD32_SYS_freebsd32_kmq_timedreceive 459
+#define FREEBSD32_SYS_freebsd32_kmq_timedsend 460
+#define FREEBSD32_SYS_kmq_notify 461
+#define FREEBSD32_SYS_kmq_unlink 462
+#define FREEBSD32_SYS_abort2 463
+#define FREEBSD32_SYS_thr_set_name 464
+#define FREEBSD32_SYS_freebsd32_aio_fsync 465
+#define FREEBSD32_SYS_rtprio_thread 466
+#define FREEBSD32_SYS_sctp_peeloff 471
+#define FREEBSD32_SYS_sctp_generic_sendmsg 472
+#define FREEBSD32_SYS_sctp_generic_sendmsg_iov 473
+#define FREEBSD32_SYS_sctp_generic_recvmsg 474
+#define FREEBSD32_SYS_freebsd32_pread 475
+#define FREEBSD32_SYS_freebsd32_pwrite 476
+#define FREEBSD32_SYS_freebsd32_mmap 477
+#define FREEBSD32_SYS_freebsd32_lseek 478
+#define FREEBSD32_SYS_freebsd32_truncate 479
+#define FREEBSD32_SYS_freebsd32_ftruncate 480
+#define FREEBSD32_SYS_freebsd32_pread 475
+#define FREEBSD32_SYS_freebsd32_pwrite 476
+#define FREEBSD32_SYS_freebsd32_mmap 477
+#define FREEBSD32_SYS_freebsd32_lseek 478
+#define FREEBSD32_SYS_freebsd32_truncate 479
+#define FREEBSD32_SYS_freebsd32_ftruncate 480
+#define FREEBSD32_SYS_thr_kill2 481
+#define FREEBSD32_SYS_shm_open 482
+#define FREEBSD32_SYS_shm_unlink 483
+#define FREEBSD32_SYS_cpuset 484
+#define FREEBSD32_SYS_freebsd32_cpuset_setid 485
+#define FREEBSD32_SYS_freebsd32_cpuset_setid 485
+#define FREEBSD32_SYS_freebsd32_cpuset_getid 486
+#define FREEBSD32_SYS_freebsd32_cpuset_getaffinity 487
+#define FREEBSD32_SYS_freebsd32_cpuset_setaffinity 488
+#define FREEBSD32_SYS_faccessat 489
+#define FREEBSD32_SYS_fchmodat 490
+#define FREEBSD32_SYS_fchownat 491
+#define FREEBSD32_SYS_freebsd32_fexecve 492
+#define FREEBSD32_SYS_freebsd32_fstatat 493
+#define FREEBSD32_SYS_freebsd32_futimesat 494
+#define FREEBSD32_SYS_linkat 495
+#define FREEBSD32_SYS_mkdirat 496
+#define FREEBSD32_SYS_mkfifoat 497
+#define FREEBSD32_SYS_mknodat 498
+#define FREEBSD32_SYS_openat 499
+#define FREEBSD32_SYS_readlinkat 500
+#define FREEBSD32_SYS_renameat 501
+#define FREEBSD32_SYS_symlinkat 502
+#define FREEBSD32_SYS_unlinkat 503
+#define FREEBSD32_SYS_posix_openpt 504
+#define FREEBSD32_SYS_freebsd32_jail_get 506
+#define FREEBSD32_SYS_freebsd32_jail_set 507
+#define FREEBSD32_SYS_jail_remove 508
+#define FREEBSD32_SYS_closefrom 509
+#define FREEBSD32_SYS_freebsd32_semctl 510
+#define FREEBSD32_SYS_freebsd32_msgctl 511
+#define FREEBSD32_SYS_freebsd32_shmctl 512
+#define FREEBSD32_SYS_lpathconf 513
+#define FREEBSD32_SYS_cap_new 514
+#define FREEBSD32_SYS_cap_rights_get 515
+#define FREEBSD32_SYS_cap_enter 516
+#define FREEBSD32_SYS_cap_getmode 517
+#define FREEBSD32_SYS_freebsd32_pselect 522
+#define FREEBSD32_SYS_getloginclass 523
+#define FREEBSD32_SYS_setloginclass 524
+#define FREEBSD32_SYS_rctl_get_racct 525
+#define FREEBSD32_SYS_rctl_get_rules 526
+#define FREEBSD32_SYS_rctl_get_limits 527
+#define FREEBSD32_SYS_rctl_add_rule 528
+#define FREEBSD32_SYS_rctl_remove_rule 529
+#define FREEBSD32_SYS_freebsd32_posix_fallocate 530
+#define FREEBSD32_SYS_freebsd32_posix_fadvise 531
+#define FREEBSD32_SYS_freebsd32_wait6 532
+#define FREEBSD32_SYS_freebsd32_posix_fallocate 530
+#define FREEBSD32_SYS_freebsd32_posix_fadvise 531
+#define FREEBSD32_SYS_freebsd32_wait6 532
+#define FREEBSD32_SYS_cap_rights_limit 533
+#define FREEBSD32_SYS_cap_ioctls_limit 534
+#define FREEBSD32_SYS_cap_ioctls_get 535
+#define FREEBSD32_SYS_cap_fcntls_limit 536
+#define FREEBSD32_SYS_cap_fcntls_get 537
+#define FREEBSD32_SYS_bindat 538
+#define FREEBSD32_SYS_connectat 539
+#define FREEBSD32_SYS_chflagsat 540
+#define FREEBSD32_SYS_accept4 541
+#define FREEBSD32_SYS_pipe2 542
+#define FREEBSD32_SYS_freebsd32_aio_mlock 543
+#define FREEBSD32_SYS_MAXSYSCALL 544
diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c
new file mode 100644
index 0000000..9b643f9
--- /dev/null
+++ b/sys/compat/freebsd32/freebsd32_syscalls.c
@@ -0,0 +1,576 @@
+/*
+ * System call names.
+ *
+ * DO NOT EDIT-- this file is automatically generated.
+ * $FreeBSD$
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 251526 2013-06-08 13:27:57Z glebius
+ */
+
+const char *freebsd32_syscallnames[] = {
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
+#define PAD64_REQUIRED
+#endif
+ "syscall", /* 0 = syscall */
+ "exit", /* 1 = exit */
+ "fork", /* 2 = fork */
+ "read", /* 3 = read */
+ "write", /* 4 = write */
+ "open", /* 5 = open */
+ "close", /* 6 = close */
+ "freebsd32_wait4", /* 7 = freebsd32_wait4 */
+ "obs_old", /* 8 = obsolete old creat */
+ "link", /* 9 = link */
+ "unlink", /* 10 = unlink */
+ "obs_execv", /* 11 = obsolete execv */
+ "chdir", /* 12 = chdir */
+ "fchdir", /* 13 = fchdir */
+ "mknod", /* 14 = mknod */
+ "chmod", /* 15 = chmod */
+ "chown", /* 16 = chown */
+ "break", /* 17 = break */
+ "compat4.freebsd32_getfsstat", /* 18 = freebsd4 freebsd32_getfsstat */
+ "compat.freebsd32_lseek", /* 19 = old freebsd32_lseek */
+ "getpid", /* 20 = getpid */
+ "mount", /* 21 = mount */
+ "unmount", /* 22 = unmount */
+ "setuid", /* 23 = setuid */
+ "getuid", /* 24 = getuid */
+ "geteuid", /* 25 = geteuid */
+ "ptrace", /* 26 = ptrace */
+ "freebsd32_recvmsg", /* 27 = freebsd32_recvmsg */
+ "freebsd32_sendmsg", /* 28 = freebsd32_sendmsg */
+ "freebsd32_recvfrom", /* 29 = freebsd32_recvfrom */
+ "accept", /* 30 = accept */
+ "getpeername", /* 31 = getpeername */
+ "getsockname", /* 32 = getsockname */
+ "access", /* 33 = access */
+ "chflags", /* 34 = chflags */
+ "fchflags", /* 35 = fchflags */
+ "sync", /* 36 = sync */
+ "kill", /* 37 = kill */
+ "compat.freebsd32_stat", /* 38 = old freebsd32_stat */
+ "getppid", /* 39 = getppid */
+ "compat.freebsd32_lstat", /* 40 = old freebsd32_lstat */
+ "dup", /* 41 = dup */
+ "pipe", /* 42 = pipe */
+ "getegid", /* 43 = getegid */
+ "profil", /* 44 = profil */
+ "ktrace", /* 45 = ktrace */
+ "compat.freebsd32_sigaction", /* 46 = old freebsd32_sigaction */
+ "getgid", /* 47 = getgid */
+ "compat.freebsd32_sigprocmask", /* 48 = old freebsd32_sigprocmask */
+ "getlogin", /* 49 = getlogin */
+ "setlogin", /* 50 = setlogin */
+ "acct", /* 51 = acct */
+ "compat.freebsd32_sigpending", /* 52 = old freebsd32_sigpending */
+ "freebsd32_sigaltstack", /* 53 = freebsd32_sigaltstack */
+ "freebsd32_ioctl", /* 54 = freebsd32_ioctl */
+ "reboot", /* 55 = reboot */
+ "revoke", /* 56 = revoke */
+ "symlink", /* 57 = symlink */
+ "readlink", /* 58 = readlink */
+ "freebsd32_execve", /* 59 = freebsd32_execve */
+ "umask", /* 60 = umask */
+ "chroot", /* 61 = chroot */
+ "compat.freebsd32_fstat", /* 62 = old freebsd32_fstat */
+ "obs_ogetkerninfo", /* 63 = obsolete ogetkerninfo */
+ "compat.freebsd32_getpagesize", /* 64 = old freebsd32_getpagesize */
+ "msync", /* 65 = msync */
+ "vfork", /* 66 = vfork */
+ "obs_vread", /* 67 = obsolete vread */
+ "obs_vwrite", /* 68 = obsolete vwrite */
+ "sbrk", /* 69 = sbrk */
+ "sstk", /* 70 = sstk */
+ "compat.mmap", /* 71 = old mmap */
+ "vadvise", /* 72 = vadvise */
+ "munmap", /* 73 = munmap */
+ "freebsd32_mprotect", /* 74 = freebsd32_mprotect */
+ "madvise", /* 75 = madvise */
+ "obs_vhangup", /* 76 = obsolete vhangup */
+ "obs_vlimit", /* 77 = obsolete vlimit */
+ "mincore", /* 78 = mincore */
+ "getgroups", /* 79 = getgroups */
+ "setgroups", /* 80 = setgroups */
+ "getpgrp", /* 81 = getpgrp */
+ "setpgid", /* 82 = setpgid */
+ "freebsd32_setitimer", /* 83 = freebsd32_setitimer */
+ "obs_owait", /* 84 = obsolete owait */
+ "swapon", /* 85 = swapon */
+ "freebsd32_getitimer", /* 86 = freebsd32_getitimer */
+ "obs_ogethostname", /* 87 = obsolete ogethostname */
+ "obs_osethostname", /* 88 = obsolete osethostname */
+ "getdtablesize", /* 89 = getdtablesize */
+ "dup2", /* 90 = dup2 */
+ "#91", /* 91 = getdopt */
+ "fcntl", /* 92 = fcntl */
+ "freebsd32_select", /* 93 = freebsd32_select */
+ "#94", /* 94 = setdopt */
+ "fsync", /* 95 = fsync */
+ "setpriority", /* 96 = setpriority */
+ "socket", /* 97 = socket */
+ "connect", /* 98 = connect */
+ "obs_oaccept", /* 99 = obsolete oaccept */
+ "getpriority", /* 100 = getpriority */
+ "obs_osend", /* 101 = obsolete osend */
+ "obs_orecv", /* 102 = obsolete orecv */
+ "compat.freebsd32_sigreturn", /* 103 = old freebsd32_sigreturn */
+ "bind", /* 104 = bind */
+ "setsockopt", /* 105 = setsockopt */
+ "listen", /* 106 = listen */
+ "obs_vtimes", /* 107 = obsolete vtimes */
+ "compat.freebsd32_sigvec", /* 108 = old freebsd32_sigvec */
+ "compat.freebsd32_sigblock", /* 109 = old freebsd32_sigblock */
+ "compat.freebsd32_sigsetmask", /* 110 = old freebsd32_sigsetmask */
+ "compat.freebsd32_sigsuspend", /* 111 = old freebsd32_sigsuspend */
+ "compat.freebsd32_sigstack", /* 112 = old freebsd32_sigstack */
+ "obs_orecvmsg", /* 113 = obsolete orecvmsg */
+ "obs_osendmsg", /* 114 = obsolete osendmsg */
+ "obs_vtrace", /* 115 = obsolete vtrace */
+ "freebsd32_gettimeofday", /* 116 = freebsd32_gettimeofday */
+ "freebsd32_getrusage", /* 117 = freebsd32_getrusage */
+ "getsockopt", /* 118 = getsockopt */
+ "#119", /* 119 = resuba */
+ "freebsd32_readv", /* 120 = freebsd32_readv */
+ "freebsd32_writev", /* 121 = freebsd32_writev */
+ "freebsd32_settimeofday", /* 122 = freebsd32_settimeofday */
+ "fchown", /* 123 = fchown */
+ "fchmod", /* 124 = fchmod */
+ "obs_orecvfrom", /* 125 = obsolete orecvfrom */
+ "setreuid", /* 126 = setreuid */
+ "setregid", /* 127 = setregid */
+ "rename", /* 128 = rename */
+ "compat.truncate", /* 129 = old truncate */
+ "compat.ftruncate", /* 130 = old ftruncate */
+ "flock", /* 131 = flock */
+ "mkfifo", /* 132 = mkfifo */
+ "sendto", /* 133 = sendto */
+ "shutdown", /* 134 = shutdown */
+ "socketpair", /* 135 = socketpair */
+ "mkdir", /* 136 = mkdir */
+ "rmdir", /* 137 = rmdir */
+ "freebsd32_utimes", /* 138 = freebsd32_utimes */
+ "obs_4.2", /* 139 = obsolete 4.2 sigreturn */
+ "freebsd32_adjtime", /* 140 = freebsd32_adjtime */
+ "obs_ogetpeername", /* 141 = obsolete ogetpeername */
+ "obs_ogethostid", /* 142 = obsolete ogethostid */
+ "obs_sethostid", /* 143 = obsolete sethostid */
+ "obs_getrlimit", /* 144 = obsolete getrlimit */
+ "obs_setrlimit", /* 145 = obsolete setrlimit */
+ "obs_killpg", /* 146 = obsolete killpg */
+ "setsid", /* 147 = setsid */
+ "quotactl", /* 148 = quotactl */
+ "obs_oquota", /* 149 = obsolete oquota */
+ "obs_ogetsockname", /* 150 = obsolete ogetsockname */
+ "#151", /* 151 = sem_lock */
+ "#152", /* 152 = sem_wakeup */
+ "#153", /* 153 = asyncdaemon */
+ "#154", /* 154 = nlm_syscall */
+ "#155", /* 155 = nfssvc */
+ "compat.freebsd32_getdirentries", /* 156 = old freebsd32_getdirentries */
+ "compat4.freebsd32_statfs", /* 157 = freebsd4 freebsd32_statfs */
+ "compat4.freebsd32_fstatfs", /* 158 = freebsd4 freebsd32_fstatfs */
+ "#159", /* 159 = nosys */
+ "#160", /* 160 = lgetfh */
+ "getfh", /* 161 = getfh */
+ "obs_getdomainname", /* 162 = obsolete getdomainname */
+ "obs_setdomainname", /* 163 = obsolete setdomainname */
+ "obs_uname", /* 164 = obsolete uname */
+ "freebsd32_sysarch", /* 165 = freebsd32_sysarch */
+ "rtprio", /* 166 = rtprio */
+ "#167", /* 167 = nosys */
+ "#168", /* 168 = nosys */
+ "freebsd32_semsys", /* 169 = freebsd32_semsys */
+ "freebsd32_msgsys", /* 170 = freebsd32_msgsys */
+ "freebsd32_shmsys", /* 171 = freebsd32_shmsys */
+ "#172", /* 172 = nosys */
+ "compat6.freebsd32_pread", /* 173 = freebsd6 freebsd32_pread */
+ "compat6.freebsd32_pwrite", /* 174 = freebsd6 freebsd32_pwrite */
+ "#175", /* 175 = nosys */
+ "ntp_adjtime", /* 176 = ntp_adjtime */
+ "#177", /* 177 = sfork */
+ "#178", /* 178 = getdescriptor */
+ "#179", /* 179 = setdescriptor */
+ "#180", /* 180 = nosys */
+ "setgid", /* 181 = setgid */
+ "setegid", /* 182 = setegid */
+ "seteuid", /* 183 = seteuid */
+ "#184", /* 184 = lfs_bmapv */
+ "#185", /* 185 = lfs_markv */
+ "#186", /* 186 = lfs_segclean */
+ "#187", /* 187 = lfs_segwait */
+ "freebsd32_stat", /* 188 = freebsd32_stat */
+ "freebsd32_fstat", /* 189 = freebsd32_fstat */
+ "freebsd32_lstat", /* 190 = freebsd32_lstat */
+ "pathconf", /* 191 = pathconf */
+ "fpathconf", /* 192 = fpathconf */
+ "#193", /* 193 = nosys */
+ "getrlimit", /* 194 = getrlimit */
+ "setrlimit", /* 195 = setrlimit */
+ "freebsd32_getdirentries", /* 196 = freebsd32_getdirentries */
+ "compat6.freebsd32_mmap", /* 197 = freebsd6 freebsd32_mmap */
+ "__syscall", /* 198 = __syscall */
+ "compat6.freebsd32_lseek", /* 199 = freebsd6 freebsd32_lseek */
+ "compat6.freebsd32_truncate", /* 200 = freebsd6 freebsd32_truncate */
+ "compat6.freebsd32_ftruncate", /* 201 = freebsd6 freebsd32_ftruncate */
+ "freebsd32_sysctl", /* 202 = freebsd32_sysctl */
+ "mlock", /* 203 = mlock */
+ "munlock", /* 204 = munlock */
+ "undelete", /* 205 = undelete */
+ "freebsd32_futimes", /* 206 = freebsd32_futimes */
+ "getpgid", /* 207 = getpgid */
+ "#208", /* 208 = newreboot */
+ "poll", /* 209 = poll */
+ "lkmnosys", /* 210 = lkmnosys */
+ "lkmnosys", /* 211 = lkmnosys */
+ "lkmnosys", /* 212 = lkmnosys */
+ "lkmnosys", /* 213 = lkmnosys */
+ "lkmnosys", /* 214 = lkmnosys */
+ "lkmnosys", /* 215 = lkmnosys */
+ "lkmnosys", /* 216 = lkmnosys */
+ "lkmnosys", /* 217 = lkmnosys */
+ "lkmnosys", /* 218 = lkmnosys */
+ "lkmnosys", /* 219 = lkmnosys */
+ "compat7.freebsd32_semctl", /* 220 = freebsd7 freebsd32_semctl */
+ "semget", /* 221 = semget */
+ "semop", /* 222 = semop */
+ "#223", /* 223 = semconfig */
+ "compat7.freebsd32_msgctl", /* 224 = freebsd7 freebsd32_msgctl */
+ "msgget", /* 225 = msgget */
+ "freebsd32_msgsnd", /* 226 = freebsd32_msgsnd */
+ "freebsd32_msgrcv", /* 227 = freebsd32_msgrcv */
+ "shmat", /* 228 = shmat */
+ "compat7.freebsd32_shmctl", /* 229 = freebsd7 freebsd32_shmctl */
+ "shmdt", /* 230 = shmdt */
+ "shmget", /* 231 = shmget */
+ "freebsd32_clock_gettime", /* 232 = freebsd32_clock_gettime */
+ "freebsd32_clock_settime", /* 233 = freebsd32_clock_settime */
+ "freebsd32_clock_getres", /* 234 = freebsd32_clock_getres */
+ "#235", /* 235 = timer_create */
+ "#236", /* 236 = timer_delete */
+ "#237", /* 237 = timer_settime */
+ "#238", /* 238 = timer_gettime */
+ "#239", /* 239 = timer_getoverrun */
+ "freebsd32_nanosleep", /* 240 = freebsd32_nanosleep */
+ "ffclock_getcounter", /* 241 = ffclock_getcounter */
+ "ffclock_setestimate", /* 242 = ffclock_setestimate */
+ "ffclock_getestimate", /* 243 = ffclock_getestimate */
+ "#244", /* 244 = nosys */
+ "#245", /* 245 = nosys */
+ "#246", /* 246 = nosys */
+ "clock_getcpuclockid2", /* 247 = clock_getcpuclockid2 */
+ "#248", /* 248 = ntp_gettime */
+ "#249", /* 249 = nosys */
+ "minherit", /* 250 = minherit */
+ "rfork", /* 251 = rfork */
+ "openbsd_poll", /* 252 = openbsd_poll */
+ "issetugid", /* 253 = issetugid */
+ "lchown", /* 254 = lchown */
+ "freebsd32_aio_read", /* 255 = freebsd32_aio_read */
+ "freebsd32_aio_write", /* 256 = freebsd32_aio_write */
+ "freebsd32_lio_listio", /* 257 = freebsd32_lio_listio */
+ "#258", /* 258 = nosys */
+ "#259", /* 259 = nosys */
+ "#260", /* 260 = nosys */
+ "#261", /* 261 = nosys */
+ "#262", /* 262 = nosys */
+ "#263", /* 263 = nosys */
+ "#264", /* 264 = nosys */
+ "#265", /* 265 = nosys */
+ "#266", /* 266 = nosys */
+ "#267", /* 267 = nosys */
+ "#268", /* 268 = nosys */
+ "#269", /* 269 = nosys */
+ "#270", /* 270 = nosys */
+ "#271", /* 271 = nosys */
+ "getdents", /* 272 = getdents */
+ "#273", /* 273 = nosys */
+ "lchmod", /* 274 = lchmod */
+ "netbsd_lchown", /* 275 = netbsd_lchown */
+ "freebsd32_lutimes", /* 276 = freebsd32_lutimes */
+ "netbsd_msync", /* 277 = netbsd_msync */
+ "nstat", /* 278 = nstat */
+ "nfstat", /* 279 = nfstat */
+ "nlstat", /* 280 = nlstat */
+ "#281", /* 281 = nosys */
+ "#282", /* 282 = nosys */
+ "#283", /* 283 = nosys */
+ "#284", /* 284 = nosys */
+ "#285", /* 285 = nosys */
+ "#286", /* 286 = nosys */
+ "#287", /* 287 = nosys */
+ "#288", /* 288 = nosys */
+ "freebsd32_preadv", /* 289 = freebsd32_preadv */
+ "freebsd32_pwritev", /* 290 = freebsd32_pwritev */
+ "#291", /* 291 = nosys */
+ "#292", /* 292 = nosys */
+ "#293", /* 293 = nosys */
+ "#294", /* 294 = nosys */
+ "#295", /* 295 = nosys */
+ "#296", /* 296 = nosys */
+ "compat4.freebsd32_fhstatfs", /* 297 = freebsd4 freebsd32_fhstatfs */
+ "fhopen", /* 298 = fhopen */
+ "fhstat", /* 299 = fhstat */
+ "modnext", /* 300 = modnext */
+ "freebsd32_modstat", /* 301 = freebsd32_modstat */
+ "modfnext", /* 302 = modfnext */
+ "modfind", /* 303 = modfind */
+ "kldload", /* 304 = kldload */
+ "kldunload", /* 305 = kldunload */
+ "kldfind", /* 306 = kldfind */
+ "kldnext", /* 307 = kldnext */
+ "freebsd32_kldstat", /* 308 = freebsd32_kldstat */
+ "kldfirstmod", /* 309 = kldfirstmod */
+ "getsid", /* 310 = getsid */
+ "setresuid", /* 311 = setresuid */
+ "setresgid", /* 312 = setresgid */
+ "obs_signanosleep", /* 313 = obsolete signanosleep */
+ "freebsd32_aio_return", /* 314 = freebsd32_aio_return */
+ "freebsd32_aio_suspend", /* 315 = freebsd32_aio_suspend */
+ "freebsd32_aio_cancel", /* 316 = freebsd32_aio_cancel */
+ "freebsd32_aio_error", /* 317 = freebsd32_aio_error */
+ "freebsd32_oaio_read", /* 318 = freebsd32_oaio_read */
+ "freebsd32_oaio_write", /* 319 = freebsd32_oaio_write */
+ "freebsd32_olio_listio", /* 320 = freebsd32_olio_listio */
+ "yield", /* 321 = yield */
+ "obs_thr_sleep", /* 322 = obsolete thr_sleep */
+ "obs_thr_wakeup", /* 323 = obsolete thr_wakeup */
+ "mlockall", /* 324 = mlockall */
+ "munlockall", /* 325 = munlockall */
+ "__getcwd", /* 326 = __getcwd */
+ "sched_setparam", /* 327 = sched_setparam */
+ "sched_getparam", /* 328 = sched_getparam */
+ "sched_setscheduler", /* 329 = sched_setscheduler */
+ "sched_getscheduler", /* 330 = sched_getscheduler */
+ "sched_yield", /* 331 = sched_yield */
+ "sched_get_priority_max", /* 332 = sched_get_priority_max */
+ "sched_get_priority_min", /* 333 = sched_get_priority_min */
+ "sched_rr_get_interval", /* 334 = sched_rr_get_interval */
+ "utrace", /* 335 = utrace */
+ "compat4.freebsd32_sendfile", /* 336 = freebsd4 freebsd32_sendfile */
+ "kldsym", /* 337 = kldsym */
+ "freebsd32_jail", /* 338 = freebsd32_jail */
+ "#339", /* 339 = pioctl */
+ "sigprocmask", /* 340 = sigprocmask */
+ "sigsuspend", /* 341 = sigsuspend */
+ "compat4.freebsd32_sigaction", /* 342 = freebsd4 freebsd32_sigaction */
+ "sigpending", /* 343 = sigpending */
+ "compat4.freebsd32_sigreturn", /* 344 = freebsd4 freebsd32_sigreturn */
+ "freebsd32_sigtimedwait", /* 345 = freebsd32_sigtimedwait */
+ "freebsd32_sigwaitinfo", /* 346 = freebsd32_sigwaitinfo */
+ "__acl_get_file", /* 347 = __acl_get_file */
+ "__acl_set_file", /* 348 = __acl_set_file */
+ "__acl_get_fd", /* 349 = __acl_get_fd */
+ "__acl_set_fd", /* 350 = __acl_set_fd */
+ "__acl_delete_file", /* 351 = __acl_delete_file */
+ "__acl_delete_fd", /* 352 = __acl_delete_fd */
+ "__acl_aclcheck_file", /* 353 = __acl_aclcheck_file */
+ "__acl_aclcheck_fd", /* 354 = __acl_aclcheck_fd */
+ "extattrctl", /* 355 = extattrctl */
+ "extattr_set_file", /* 356 = extattr_set_file */
+ "extattr_get_file", /* 357 = extattr_get_file */
+ "extattr_delete_file", /* 358 = extattr_delete_file */
+ "freebsd32_aio_waitcomplete", /* 359 = freebsd32_aio_waitcomplete */
+ "getresuid", /* 360 = getresuid */
+ "getresgid", /* 361 = getresgid */
+ "kqueue", /* 362 = kqueue */
+ "freebsd32_kevent", /* 363 = freebsd32_kevent */
+ "#364", /* 364 = __cap_get_proc */
+ "#365", /* 365 = __cap_set_proc */
+ "#366", /* 366 = __cap_get_fd */
+ "#367", /* 367 = __cap_get_file */
+ "#368", /* 368 = __cap_set_fd */
+ "#369", /* 369 = __cap_set_file */
+ "#370", /* 370 = nosys */
+ "extattr_set_fd", /* 371 = extattr_set_fd */
+ "extattr_get_fd", /* 372 = extattr_get_fd */
+ "extattr_delete_fd", /* 373 = extattr_delete_fd */
+ "__setugid", /* 374 = __setugid */
+ "#375", /* 375 = nfsclnt */
+ "eaccess", /* 376 = eaccess */
+ "#377", /* 377 = afs_syscall */
+ "freebsd32_nmount", /* 378 = freebsd32_nmount */
+ "#379", /* 379 = kse_exit */
+ "#380", /* 380 = kse_wakeup */
+ "#381", /* 381 = kse_create */
+ "#382", /* 382 = kse_thr_interrupt */
+ "#383", /* 383 = kse_release */
+ "#384", /* 384 = __mac_get_proc */
+ "#385", /* 385 = __mac_set_proc */
+ "#386", /* 386 = __mac_get_fd */
+ "#387", /* 387 = __mac_get_file */
+ "#388", /* 388 = __mac_set_fd */
+ "#389", /* 389 = __mac_set_file */
+ "kenv", /* 390 = kenv */
+ "lchflags", /* 391 = lchflags */
+ "uuidgen", /* 392 = uuidgen */
+ "freebsd32_sendfile", /* 393 = freebsd32_sendfile */
+ "#394", /* 394 = mac_syscall */
+ "getfsstat", /* 395 = getfsstat */
+ "statfs", /* 396 = statfs */
+ "fstatfs", /* 397 = fstatfs */
+ "fhstatfs", /* 398 = fhstatfs */
+ "#399", /* 399 = nosys */
+ "ksem_close", /* 400 = ksem_close */
+ "ksem_post", /* 401 = ksem_post */
+ "ksem_wait", /* 402 = ksem_wait */
+ "ksem_trywait", /* 403 = ksem_trywait */
+ "freebsd32_ksem_init", /* 404 = freebsd32_ksem_init */
+ "freebsd32_ksem_open", /* 405 = freebsd32_ksem_open */
+ "ksem_unlink", /* 406 = ksem_unlink */
+ "ksem_getvalue", /* 407 = ksem_getvalue */
+ "ksem_destroy", /* 408 = ksem_destroy */
+ "#409", /* 409 = __mac_get_pid */
+ "#410", /* 410 = __mac_get_link */
+ "#411", /* 411 = __mac_set_link */
+ "extattr_set_link", /* 412 = extattr_set_link */
+ "extattr_get_link", /* 413 = extattr_get_link */
+ "extattr_delete_link", /* 414 = extattr_delete_link */
+ "#415", /* 415 = __mac_execve */
+ "freebsd32_sigaction", /* 416 = freebsd32_sigaction */
+ "freebsd32_sigreturn", /* 417 = freebsd32_sigreturn */
+ "#418", /* 418 = __xstat */
+ "#419", /* 419 = __xfstat */
+ "#420", /* 420 = __xlstat */
+ "freebsd32_getcontext", /* 421 = freebsd32_getcontext */
+ "freebsd32_setcontext", /* 422 = freebsd32_setcontext */
+ "freebsd32_swapcontext", /* 423 = freebsd32_swapcontext */
+ "#424", /* 424 = swapoff */
+ "__acl_get_link", /* 425 = __acl_get_link */
+ "__acl_set_link", /* 426 = __acl_set_link */
+ "__acl_delete_link", /* 427 = __acl_delete_link */
+ "__acl_aclcheck_link", /* 428 = __acl_aclcheck_link */
+ "sigwait", /* 429 = sigwait */
+ "#430", /* 430 = thr_create; */
+ "thr_exit", /* 431 = thr_exit */
+ "thr_self", /* 432 = thr_self */
+ "thr_kill", /* 433 = thr_kill */
+ "freebsd32_umtx_lock", /* 434 = freebsd32_umtx_lock */
+ "freebsd32_umtx_unlock", /* 435 = freebsd32_umtx_unlock */
+ "jail_attach", /* 436 = jail_attach */
+ "extattr_list_fd", /* 437 = extattr_list_fd */
+ "extattr_list_file", /* 438 = extattr_list_file */
+ "extattr_list_link", /* 439 = extattr_list_link */
+ "#440", /* 440 = kse_switchin */
+ "freebsd32_ksem_timedwait", /* 441 = freebsd32_ksem_timedwait */
+ "freebsd32_thr_suspend", /* 442 = freebsd32_thr_suspend */
+ "thr_wake", /* 443 = thr_wake */
+ "kldunloadf", /* 444 = kldunloadf */
+ "audit", /* 445 = audit */
+ "auditon", /* 446 = auditon */
+ "getauid", /* 447 = getauid */
+ "setauid", /* 448 = setauid */
+ "getaudit", /* 449 = getaudit */
+ "setaudit", /* 450 = setaudit */
+ "getaudit_addr", /* 451 = getaudit_addr */
+ "setaudit_addr", /* 452 = setaudit_addr */
+ "auditctl", /* 453 = auditctl */
+ "freebsd32_umtx_op", /* 454 = freebsd32_umtx_op */
+ "freebsd32_thr_new", /* 455 = freebsd32_thr_new */
+ "sigqueue", /* 456 = sigqueue */
+ "freebsd32_kmq_open", /* 457 = freebsd32_kmq_open */
+ "freebsd32_kmq_setattr", /* 458 = freebsd32_kmq_setattr */
+ "freebsd32_kmq_timedreceive", /* 459 = freebsd32_kmq_timedreceive */
+ "freebsd32_kmq_timedsend", /* 460 = freebsd32_kmq_timedsend */
+ "kmq_notify", /* 461 = kmq_notify */
+ "kmq_unlink", /* 462 = kmq_unlink */
+ "abort2", /* 463 = abort2 */
+ "thr_set_name", /* 464 = thr_set_name */
+ "freebsd32_aio_fsync", /* 465 = freebsd32_aio_fsync */
+ "rtprio_thread", /* 466 = rtprio_thread */
+ "#467", /* 467 = nosys */
+ "#468", /* 468 = nosys */
+ "#469", /* 469 = __getpath_fromfd */
+ "#470", /* 470 = __getpath_fromaddr */
+ "sctp_peeloff", /* 471 = sctp_peeloff */
+ "sctp_generic_sendmsg", /* 472 = sctp_generic_sendmsg */
+ "sctp_generic_sendmsg_iov", /* 473 = sctp_generic_sendmsg_iov */
+ "sctp_generic_recvmsg", /* 474 = sctp_generic_recvmsg */
+#ifdef PAD64_REQUIRED
+ "freebsd32_pread", /* 475 = freebsd32_pread */
+ "freebsd32_pwrite", /* 476 = freebsd32_pwrite */
+ "freebsd32_mmap", /* 477 = freebsd32_mmap */
+ "freebsd32_lseek", /* 478 = freebsd32_lseek */
+ "freebsd32_truncate", /* 479 = freebsd32_truncate */
+ "freebsd32_ftruncate", /* 480 = freebsd32_ftruncate */
+#else
+ "freebsd32_pread", /* 475 = freebsd32_pread */
+ "freebsd32_pwrite", /* 476 = freebsd32_pwrite */
+ "freebsd32_mmap", /* 477 = freebsd32_mmap */
+ "freebsd32_lseek", /* 478 = freebsd32_lseek */
+ "freebsd32_truncate", /* 479 = freebsd32_truncate */
+ "freebsd32_ftruncate", /* 480 = freebsd32_ftruncate */
+#endif
+ "thr_kill2", /* 481 = thr_kill2 */
+ "shm_open", /* 482 = shm_open */
+ "shm_unlink", /* 483 = shm_unlink */
+ "cpuset", /* 484 = cpuset */
+#ifdef PAD64_REQUIRED
+ "freebsd32_cpuset_setid", /* 485 = freebsd32_cpuset_setid */
+#else
+ "freebsd32_cpuset_setid", /* 485 = freebsd32_cpuset_setid */
+#endif
+ "freebsd32_cpuset_getid", /* 486 = freebsd32_cpuset_getid */
+ "freebsd32_cpuset_getaffinity", /* 487 = freebsd32_cpuset_getaffinity */
+ "freebsd32_cpuset_setaffinity", /* 488 = freebsd32_cpuset_setaffinity */
+ "faccessat", /* 489 = faccessat */
+ "fchmodat", /* 490 = fchmodat */
+ "fchownat", /* 491 = fchownat */
+ "freebsd32_fexecve", /* 492 = freebsd32_fexecve */
+ "freebsd32_fstatat", /* 493 = freebsd32_fstatat */
+ "freebsd32_futimesat", /* 494 = freebsd32_futimesat */
+ "linkat", /* 495 = linkat */
+ "mkdirat", /* 496 = mkdirat */
+ "mkfifoat", /* 497 = mkfifoat */
+ "mknodat", /* 498 = mknodat */
+ "openat", /* 499 = openat */
+ "readlinkat", /* 500 = readlinkat */
+ "renameat", /* 501 = renameat */
+ "symlinkat", /* 502 = symlinkat */
+ "unlinkat", /* 503 = unlinkat */
+ "posix_openpt", /* 504 = posix_openpt */
+ "#505", /* 505 = gssd_syscall */
+ "freebsd32_jail_get", /* 506 = freebsd32_jail_get */
+ "freebsd32_jail_set", /* 507 = freebsd32_jail_set */
+ "jail_remove", /* 508 = jail_remove */
+ "closefrom", /* 509 = closefrom */
+ "freebsd32_semctl", /* 510 = freebsd32_semctl */
+ "freebsd32_msgctl", /* 511 = freebsd32_msgctl */
+ "freebsd32_shmctl", /* 512 = freebsd32_shmctl */
+ "lpathconf", /* 513 = lpathconf */
+ "cap_new", /* 514 = cap_new */
+ "cap_rights_get", /* 515 = cap_rights_get */
+ "cap_enter", /* 516 = cap_enter */
+ "cap_getmode", /* 517 = cap_getmode */
+ "#518", /* 518 = pdfork */
+ "#519", /* 519 = pdkill */
+ "#520", /* 520 = pdgetpid */
+ "#521", /* 521 = pdwait */
+ "freebsd32_pselect", /* 522 = freebsd32_pselect */
+ "getloginclass", /* 523 = getloginclass */
+ "setloginclass", /* 524 = setloginclass */
+ "rctl_get_racct", /* 525 = rctl_get_racct */
+ "rctl_get_rules", /* 526 = rctl_get_rules */
+ "rctl_get_limits", /* 527 = rctl_get_limits */
+ "rctl_add_rule", /* 528 = rctl_add_rule */
+ "rctl_remove_rule", /* 529 = rctl_remove_rule */
+#ifdef PAD64_REQUIRED
+ "freebsd32_posix_fallocate", /* 530 = freebsd32_posix_fallocate */
+ "freebsd32_posix_fadvise", /* 531 = freebsd32_posix_fadvise */
+ "freebsd32_wait6", /* 532 = freebsd32_wait6 */
+#else
+ "freebsd32_posix_fallocate", /* 530 = freebsd32_posix_fallocate */
+ "freebsd32_posix_fadvise", /* 531 = freebsd32_posix_fadvise */
+ "freebsd32_wait6", /* 532 = freebsd32_wait6 */
+#endif
+ "cap_rights_limit", /* 533 = cap_rights_limit */
+ "cap_ioctls_limit", /* 534 = cap_ioctls_limit */
+ "cap_ioctls_get", /* 535 = cap_ioctls_get */
+ "cap_fcntls_limit", /* 536 = cap_fcntls_limit */
+ "cap_fcntls_get", /* 537 = cap_fcntls_get */
+ "bindat", /* 538 = bindat */
+ "connectat", /* 539 = connectat */
+ "chflagsat", /* 540 = chflagsat */
+ "accept4", /* 541 = accept4 */
+ "pipe2", /* 542 = pipe2 */
+ "freebsd32_aio_mlock", /* 543 = freebsd32_aio_mlock */
+};
diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c
new file mode 100644
index 0000000..d37e8e9
--- /dev/null
+++ b/sys/compat/freebsd32/freebsd32_sysent.c
@@ -0,0 +1,613 @@
+/*
+ * System call switch table.
+ *
+ * DO NOT EDIT-- this file is automatically generated.
+ * $FreeBSD$
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 251526 2013-06-08 13:27:57Z glebius
+ */
+
+#include "opt_compat.h"
+
+#include <sys/param.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <sys/mount.h>
+#include <sys/socket.h>
+#include <compat/freebsd32/freebsd32.h>
+#include <compat/freebsd32/freebsd32_proto.h>
+
+#define AS(name) (sizeof(struct name) / sizeof(register_t))
+
+#ifdef COMPAT_43
+#define compat(n, name) n, (sy_call_t *)__CONCAT(o,name)
+#else
+#define compat(n, name) 0, (sy_call_t *)nosys
+#endif
+
+#ifdef COMPAT_FREEBSD4
+#define compat4(n, name) n, (sy_call_t *)__CONCAT(freebsd4_,name)
+#else
+#define compat4(n, name) 0, (sy_call_t *)nosys
+#endif
+
+#ifdef COMPAT_FREEBSD6
+#define compat6(n, name) n, (sy_call_t *)__CONCAT(freebsd6_,name)
+#else
+#define compat6(n, name) 0, (sy_call_t *)nosys
+#endif
+
+#ifdef COMPAT_FREEBSD7
+#define compat7(n, name) n, (sy_call_t *)__CONCAT(freebsd7_,name)
+#else
+#define compat7(n, name) 0, (sy_call_t *)nosys
+#endif
+
+/* The casts are bogus but will do for now. */
+struct sysent freebsd32_sysent[] = {
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
+#define PAD64_REQUIRED
+#endif
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 0 = syscall */
+ { AS(sys_exit_args), (sy_call_t *)sys_sys_exit, AUE_EXIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 1 = exit */
+ { 0, (sy_call_t *)sys_fork, AUE_FORK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 2 = fork */
+ { AS(read_args), (sy_call_t *)sys_read, AUE_READ, NULL, 0, 0, 0, SY_THR_STATIC }, /* 3 = read */
+ { AS(write_args), (sy_call_t *)sys_write, AUE_WRITE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 4 = write */
+ { AS(open_args), (sy_call_t *)sys_open, AUE_OPEN_RWTC, NULL, 0, 0, 0, SY_THR_STATIC }, /* 5 = open */
+ { AS(close_args), (sy_call_t *)sys_close, AUE_CLOSE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 6 = close */
+ { AS(freebsd32_wait4_args), (sy_call_t *)freebsd32_wait4, AUE_WAIT4, NULL, 0, 0, 0, SY_THR_STATIC }, /* 7 = freebsd32_wait4 */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 8 = obsolete old creat */
+ { AS(link_args), (sy_call_t *)sys_link, AUE_LINK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 9 = link */
+ { AS(unlink_args), (sy_call_t *)sys_unlink, AUE_UNLINK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 10 = unlink */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 11 = obsolete execv */
+ { AS(chdir_args), (sy_call_t *)sys_chdir, AUE_CHDIR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 12 = chdir */
+ { AS(fchdir_args), (sy_call_t *)sys_fchdir, AUE_FCHDIR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 13 = fchdir */
+ { AS(mknod_args), (sy_call_t *)sys_mknod, AUE_MKNOD, NULL, 0, 0, 0, SY_THR_STATIC }, /* 14 = mknod */
+ { AS(chmod_args), (sy_call_t *)sys_chmod, AUE_CHMOD, NULL, 0, 0, 0, SY_THR_STATIC }, /* 15 = chmod */
+ { AS(chown_args), (sy_call_t *)sys_chown, AUE_CHOWN, NULL, 0, 0, 0, SY_THR_STATIC }, /* 16 = chown */
+ { AS(obreak_args), (sy_call_t *)sys_obreak, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 17 = break */
+ { compat4(AS(freebsd4_freebsd32_getfsstat_args),freebsd32_getfsstat), AUE_GETFSSTAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 18 = freebsd4 freebsd32_getfsstat */
+ { compat(AS(ofreebsd32_lseek_args),freebsd32_lseek), AUE_LSEEK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 19 = old freebsd32_lseek */
+ { 0, (sy_call_t *)sys_getpid, AUE_GETPID, NULL, 0, 0, 0, SY_THR_STATIC }, /* 20 = getpid */
+ { AS(mount_args), (sy_call_t *)sys_mount, AUE_MOUNT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 21 = mount */
+ { AS(unmount_args), (sy_call_t *)sys_unmount, AUE_UMOUNT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 22 = unmount */
+ { AS(setuid_args), (sy_call_t *)sys_setuid, AUE_SETUID, NULL, 0, 0, 0, SY_THR_STATIC }, /* 23 = setuid */
+ { 0, (sy_call_t *)sys_getuid, AUE_GETUID, NULL, 0, 0, 0, SY_THR_STATIC }, /* 24 = getuid */
+ { 0, (sy_call_t *)sys_geteuid, AUE_GETEUID, NULL, 0, 0, 0, SY_THR_STATIC }, /* 25 = geteuid */
+ { AS(ptrace_args), (sy_call_t *)sys_ptrace, AUE_PTRACE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 26 = ptrace */
+ { AS(freebsd32_recvmsg_args), (sy_call_t *)freebsd32_recvmsg, AUE_RECVMSG, NULL, 0, 0, 0, SY_THR_STATIC }, /* 27 = freebsd32_recvmsg */
+ { AS(freebsd32_sendmsg_args), (sy_call_t *)freebsd32_sendmsg, AUE_SENDMSG, NULL, 0, 0, 0, SY_THR_STATIC }, /* 28 = freebsd32_sendmsg */
+ { AS(freebsd32_recvfrom_args), (sy_call_t *)freebsd32_recvfrom, AUE_RECVFROM, NULL, 0, 0, 0, SY_THR_STATIC }, /* 29 = freebsd32_recvfrom */
+ { AS(accept_args), (sy_call_t *)sys_accept, AUE_ACCEPT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 30 = accept */
+ { AS(getpeername_args), (sy_call_t *)sys_getpeername, AUE_GETPEERNAME, NULL, 0, 0, 0, SY_THR_STATIC }, /* 31 = getpeername */
+ { AS(getsockname_args), (sy_call_t *)sys_getsockname, AUE_GETSOCKNAME, NULL, 0, 0, 0, SY_THR_STATIC }, /* 32 = getsockname */
+ { AS(access_args), (sy_call_t *)sys_access, AUE_ACCESS, NULL, 0, 0, 0, SY_THR_STATIC }, /* 33 = access */
+ { AS(chflags_args), (sy_call_t *)sys_chflags, AUE_CHFLAGS, NULL, 0, 0, 0, SY_THR_STATIC }, /* 34 = chflags */
+ { AS(fchflags_args), (sy_call_t *)sys_fchflags, AUE_FCHFLAGS, NULL, 0, 0, 0, SY_THR_STATIC }, /* 35 = fchflags */
+ { 0, (sy_call_t *)sys_sync, AUE_SYNC, NULL, 0, 0, 0, SY_THR_STATIC }, /* 36 = sync */
+ { AS(kill_args), (sy_call_t *)sys_kill, AUE_KILL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 37 = kill */
+ { compat(AS(ofreebsd32_stat_args),freebsd32_stat), AUE_STAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 38 = old freebsd32_stat */
+ { 0, (sy_call_t *)sys_getppid, AUE_GETPPID, NULL, 0, 0, 0, SY_THR_STATIC }, /* 39 = getppid */
+ { compat(AS(ofreebsd32_lstat_args),freebsd32_lstat), AUE_LSTAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 40 = old freebsd32_lstat */
+ { AS(dup_args), (sy_call_t *)sys_dup, AUE_DUP, NULL, 0, 0, 0, SY_THR_STATIC }, /* 41 = dup */
+ { 0, (sy_call_t *)sys_pipe, AUE_PIPE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 42 = pipe */
+ { 0, (sy_call_t *)sys_getegid, AUE_GETEGID, NULL, 0, 0, 0, SY_THR_STATIC }, /* 43 = getegid */
+ { AS(profil_args), (sy_call_t *)sys_profil, AUE_PROFILE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 44 = profil */
+ { AS(ktrace_args), (sy_call_t *)sys_ktrace, AUE_KTRACE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 45 = ktrace */
+ { compat(AS(ofreebsd32_sigaction_args),freebsd32_sigaction), AUE_SIGACTION, NULL, 0, 0, 0, SY_THR_STATIC }, /* 46 = old freebsd32_sigaction */
+ { 0, (sy_call_t *)sys_getgid, AUE_GETGID, NULL, 0, 0, 0, SY_THR_STATIC }, /* 47 = getgid */
+ { compat(AS(ofreebsd32_sigprocmask_args),freebsd32_sigprocmask), AUE_SIGPROCMASK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 48 = old freebsd32_sigprocmask */
+ { AS(getlogin_args), (sy_call_t *)sys_getlogin, AUE_GETLOGIN, NULL, 0, 0, 0, SY_THR_STATIC }, /* 49 = getlogin */
+ { AS(setlogin_args), (sy_call_t *)sys_setlogin, AUE_SETLOGIN, NULL, 0, 0, 0, SY_THR_STATIC }, /* 50 = setlogin */
+ { AS(acct_args), (sy_call_t *)sys_acct, AUE_ACCT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 51 = acct */
+ { compat(0,freebsd32_sigpending), AUE_SIGPENDING, NULL, 0, 0, 0, SY_THR_STATIC }, /* 52 = old freebsd32_sigpending */
+ { AS(freebsd32_sigaltstack_args), (sy_call_t *)freebsd32_sigaltstack, AUE_SIGALTSTACK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 53 = freebsd32_sigaltstack */
+ { AS(freebsd32_ioctl_args), (sy_call_t *)freebsd32_ioctl, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 54 = freebsd32_ioctl */
+ { AS(reboot_args), (sy_call_t *)sys_reboot, AUE_REBOOT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 55 = reboot */
+ { AS(revoke_args), (sy_call_t *)sys_revoke, AUE_REVOKE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 56 = revoke */
+ { AS(symlink_args), (sy_call_t *)sys_symlink, AUE_SYMLINK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 57 = symlink */
+ { AS(readlink_args), (sy_call_t *)sys_readlink, AUE_READLINK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 58 = readlink */
+ { AS(freebsd32_execve_args), (sy_call_t *)freebsd32_execve, AUE_EXECVE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 59 = freebsd32_execve */
+ { AS(umask_args), (sy_call_t *)sys_umask, AUE_UMASK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 60 = umask */
+ { AS(chroot_args), (sy_call_t *)sys_chroot, AUE_CHROOT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 61 = chroot */
+ { compat(AS(ofreebsd32_fstat_args),freebsd32_fstat), AUE_FSTAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 62 = old freebsd32_fstat */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 63 = obsolete ogetkerninfo */
+ { compat(AS(ofreebsd32_getpagesize_args),freebsd32_getpagesize), AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 64 = old freebsd32_getpagesize */
+ { AS(msync_args), (sy_call_t *)sys_msync, AUE_MSYNC, NULL, 0, 0, 0, SY_THR_STATIC }, /* 65 = msync */
+ { 0, (sy_call_t *)sys_vfork, AUE_VFORK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 66 = vfork */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 67 = obsolete vread */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 68 = obsolete vwrite */
+ { AS(sbrk_args), (sy_call_t *)sys_sbrk, AUE_SBRK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 69 = sbrk */
+ { AS(sstk_args), (sy_call_t *)sys_sstk, AUE_SSTK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 70 = sstk */
+ { compat(AS(ommap_args),mmap), AUE_MMAP, NULL, 0, 0, 0, SY_THR_STATIC }, /* 71 = old mmap */
+ { AS(ovadvise_args), (sy_call_t *)sys_ovadvise, AUE_O_VADVISE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 72 = vadvise */
+ { AS(munmap_args), (sy_call_t *)sys_munmap, AUE_MUNMAP, NULL, 0, 0, 0, SY_THR_STATIC }, /* 73 = munmap */
+ { AS(freebsd32_mprotect_args), (sy_call_t *)freebsd32_mprotect, AUE_MPROTECT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 74 = freebsd32_mprotect */
+ { AS(madvise_args), (sy_call_t *)sys_madvise, AUE_MADVISE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 75 = madvise */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 76 = obsolete vhangup */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 77 = obsolete vlimit */
+ { AS(mincore_args), (sy_call_t *)sys_mincore, AUE_MINCORE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 78 = mincore */
+ { AS(getgroups_args), (sy_call_t *)sys_getgroups, AUE_GETGROUPS, NULL, 0, 0, 0, SY_THR_STATIC }, /* 79 = getgroups */
+ { AS(setgroups_args), (sy_call_t *)sys_setgroups, AUE_SETGROUPS, NULL, 0, 0, 0, SY_THR_STATIC }, /* 80 = setgroups */
+ { 0, (sy_call_t *)sys_getpgrp, AUE_GETPGRP, NULL, 0, 0, 0, SY_THR_STATIC }, /* 81 = getpgrp */
+ { AS(setpgid_args), (sy_call_t *)sys_setpgid, AUE_SETPGRP, NULL, 0, 0, 0, SY_THR_STATIC }, /* 82 = setpgid */
+ { AS(freebsd32_setitimer_args), (sy_call_t *)freebsd32_setitimer, AUE_SETITIMER, NULL, 0, 0, 0, SY_THR_STATIC }, /* 83 = freebsd32_setitimer */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 84 = obsolete owait */
+ { AS(swapon_args), (sy_call_t *)sys_swapon, AUE_SWAPON, NULL, 0, 0, 0, SY_THR_STATIC }, /* 85 = swapon */
+ { AS(freebsd32_getitimer_args), (sy_call_t *)freebsd32_getitimer, AUE_GETITIMER, NULL, 0, 0, 0, SY_THR_STATIC }, /* 86 = freebsd32_getitimer */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 87 = obsolete ogethostname */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 88 = obsolete osethostname */
+ { 0, (sy_call_t *)sys_getdtablesize, AUE_GETDTABLESIZE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 89 = getdtablesize */
+ { AS(dup2_args), (sy_call_t *)sys_dup2, AUE_DUP2, NULL, 0, 0, 0, SY_THR_STATIC }, /* 90 = dup2 */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 91 = getdopt */
+ { AS(fcntl_args), (sy_call_t *)sys_fcntl, AUE_FCNTL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 92 = fcntl */
+ { AS(freebsd32_select_args), (sy_call_t *)freebsd32_select, AUE_SELECT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 93 = freebsd32_select */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 94 = setdopt */
+ { AS(fsync_args), (sy_call_t *)sys_fsync, AUE_FSYNC, NULL, 0, 0, 0, SY_THR_STATIC }, /* 95 = fsync */
+ { AS(setpriority_args), (sy_call_t *)sys_setpriority, AUE_SETPRIORITY, NULL, 0, 0, 0, SY_THR_STATIC }, /* 96 = setpriority */
+ { AS(socket_args), (sy_call_t *)sys_socket, AUE_SOCKET, NULL, 0, 0, 0, SY_THR_STATIC }, /* 97 = socket */
+ { AS(connect_args), (sy_call_t *)sys_connect, AUE_CONNECT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 98 = connect */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 99 = obsolete oaccept */
+ { AS(getpriority_args), (sy_call_t *)sys_getpriority, AUE_GETPRIORITY, NULL, 0, 0, 0, SY_THR_STATIC }, /* 100 = getpriority */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 101 = obsolete osend */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 102 = obsolete orecv */
+ { compat(AS(ofreebsd32_sigreturn_args),freebsd32_sigreturn), AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 103 = old freebsd32_sigreturn */
+ { AS(bind_args), (sy_call_t *)sys_bind, AUE_BIND, NULL, 0, 0, 0, SY_THR_STATIC }, /* 104 = bind */
+ { AS(setsockopt_args), (sy_call_t *)sys_setsockopt, AUE_SETSOCKOPT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 105 = setsockopt */
+ { AS(listen_args), (sy_call_t *)sys_listen, AUE_LISTEN, NULL, 0, 0, 0, SY_THR_STATIC }, /* 106 = listen */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 107 = obsolete vtimes */
+ { compat(AS(ofreebsd32_sigvec_args),freebsd32_sigvec), AUE_O_SIGVEC, NULL, 0, 0, 0, SY_THR_STATIC }, /* 108 = old freebsd32_sigvec */
+ { compat(AS(ofreebsd32_sigblock_args),freebsd32_sigblock), AUE_O_SIGBLOCK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 109 = old freebsd32_sigblock */
+ { compat(AS(ofreebsd32_sigsetmask_args),freebsd32_sigsetmask), AUE_O_SIGSETMASK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 110 = old freebsd32_sigsetmask */
+ { compat(AS(ofreebsd32_sigsuspend_args),freebsd32_sigsuspend), AUE_SIGSUSPEND, NULL, 0, 0, 0, SY_THR_STATIC }, /* 111 = old freebsd32_sigsuspend */
+ { compat(AS(ofreebsd32_sigstack_args),freebsd32_sigstack), AUE_O_SIGSTACK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 112 = old freebsd32_sigstack */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 113 = obsolete orecvmsg */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 114 = obsolete osendmsg */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 115 = obsolete vtrace */
+ { AS(freebsd32_gettimeofday_args), (sy_call_t *)freebsd32_gettimeofday, AUE_GETTIMEOFDAY, NULL, 0, 0, 0, SY_THR_STATIC }, /* 116 = freebsd32_gettimeofday */
+ { AS(freebsd32_getrusage_args), (sy_call_t *)freebsd32_getrusage, AUE_GETRUSAGE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 117 = freebsd32_getrusage */
+ { AS(getsockopt_args), (sy_call_t *)sys_getsockopt, AUE_GETSOCKOPT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 118 = getsockopt */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 119 = resuba */
+ { AS(freebsd32_readv_args), (sy_call_t *)freebsd32_readv, AUE_READV, NULL, 0, 0, 0, SY_THR_STATIC }, /* 120 = freebsd32_readv */
+ { AS(freebsd32_writev_args), (sy_call_t *)freebsd32_writev, AUE_WRITEV, NULL, 0, 0, 0, SY_THR_STATIC }, /* 121 = freebsd32_writev */
+ { AS(freebsd32_settimeofday_args), (sy_call_t *)freebsd32_settimeofday, AUE_SETTIMEOFDAY, NULL, 0, 0, 0, SY_THR_STATIC }, /* 122 = freebsd32_settimeofday */
+ { AS(fchown_args), (sy_call_t *)sys_fchown, AUE_FCHOWN, NULL, 0, 0, 0, SY_THR_STATIC }, /* 123 = fchown */
+ { AS(fchmod_args), (sy_call_t *)sys_fchmod, AUE_FCHMOD, NULL, 0, 0, 0, SY_THR_STATIC }, /* 124 = fchmod */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 125 = obsolete orecvfrom */
+ { AS(setreuid_args), (sy_call_t *)sys_setreuid, AUE_SETREUID, NULL, 0, 0, 0, SY_THR_STATIC }, /* 126 = setreuid */
+ { AS(setregid_args), (sy_call_t *)sys_setregid, AUE_SETREGID, NULL, 0, 0, 0, SY_THR_STATIC }, /* 127 = setregid */
+ { AS(rename_args), (sy_call_t *)sys_rename, AUE_RENAME, NULL, 0, 0, 0, SY_THR_STATIC }, /* 128 = rename */
+ { compat(AS(otruncate_args),truncate), AUE_TRUNCATE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 129 = old truncate */
+ { compat(AS(oftruncate_args),ftruncate), AUE_FTRUNCATE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 130 = old ftruncate */
+ { AS(flock_args), (sy_call_t *)sys_flock, AUE_FLOCK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 131 = flock */
+ { AS(mkfifo_args), (sy_call_t *)sys_mkfifo, AUE_MKFIFO, NULL, 0, 0, 0, SY_THR_STATIC }, /* 132 = mkfifo */
+ { AS(sendto_args), (sy_call_t *)sys_sendto, AUE_SENDTO, NULL, 0, 0, 0, SY_THR_STATIC }, /* 133 = sendto */
+ { AS(shutdown_args), (sy_call_t *)sys_shutdown, AUE_SHUTDOWN, NULL, 0, 0, 0, SY_THR_STATIC }, /* 134 = shutdown */
+ { AS(socketpair_args), (sy_call_t *)sys_socketpair, AUE_SOCKETPAIR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 135 = socketpair */
+ { AS(mkdir_args), (sy_call_t *)sys_mkdir, AUE_MKDIR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 136 = mkdir */
+ { AS(rmdir_args), (sy_call_t *)sys_rmdir, AUE_RMDIR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 137 = rmdir */
+ { AS(freebsd32_utimes_args), (sy_call_t *)freebsd32_utimes, AUE_UTIMES, NULL, 0, 0, 0, SY_THR_STATIC }, /* 138 = freebsd32_utimes */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 139 = obsolete 4.2 sigreturn */
+ { AS(freebsd32_adjtime_args), (sy_call_t *)freebsd32_adjtime, AUE_ADJTIME, NULL, 0, 0, 0, SY_THR_STATIC }, /* 140 = freebsd32_adjtime */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 141 = obsolete ogetpeername */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 142 = obsolete ogethostid */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 143 = obsolete sethostid */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 144 = obsolete getrlimit */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 145 = obsolete setrlimit */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 146 = obsolete killpg */
+ { 0, (sy_call_t *)sys_setsid, AUE_SETSID, NULL, 0, 0, 0, SY_THR_STATIC }, /* 147 = setsid */
+ { AS(quotactl_args), (sy_call_t *)sys_quotactl, AUE_QUOTACTL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 148 = quotactl */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 149 = obsolete oquota */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 150 = obsolete ogetsockname */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 151 = sem_lock */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 152 = sem_wakeup */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 153 = asyncdaemon */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 154 = nlm_syscall */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 155 = nfssvc */
+ { compat(AS(ofreebsd32_getdirentries_args),freebsd32_getdirentries), AUE_GETDIRENTRIES, NULL, 0, 0, 0, SY_THR_STATIC }, /* 156 = old freebsd32_getdirentries */
+ { compat4(AS(freebsd4_freebsd32_statfs_args),freebsd32_statfs), AUE_STATFS, NULL, 0, 0, 0, SY_THR_STATIC }, /* 157 = freebsd4 freebsd32_statfs */
+ { compat4(AS(freebsd4_freebsd32_fstatfs_args),freebsd32_fstatfs), AUE_FSTATFS, NULL, 0, 0, 0, SY_THR_STATIC }, /* 158 = freebsd4 freebsd32_fstatfs */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 159 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 160 = lgetfh */
+ { AS(getfh_args), (sy_call_t *)sys_getfh, AUE_NFS_GETFH, NULL, 0, 0, 0, SY_THR_STATIC }, /* 161 = getfh */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 162 = obsolete getdomainname */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 163 = obsolete setdomainname */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 164 = obsolete uname */
+ { AS(freebsd32_sysarch_args), (sy_call_t *)freebsd32_sysarch, AUE_SYSARCH, NULL, 0, 0, 0, SY_THR_STATIC }, /* 165 = freebsd32_sysarch */
+ { AS(rtprio_args), (sy_call_t *)sys_rtprio, AUE_RTPRIO, NULL, 0, 0, 0, SY_THR_STATIC }, /* 166 = rtprio */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 167 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 168 = nosys */
+ { AS(freebsd32_semsys_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 169 = freebsd32_semsys */
+ { AS(freebsd32_msgsys_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 170 = freebsd32_msgsys */
+ { AS(freebsd32_shmsys_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 171 = freebsd32_shmsys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 172 = nosys */
+ { compat6(AS(freebsd6_freebsd32_pread_args),freebsd32_pread), AUE_PREAD, NULL, 0, 0, 0, SY_THR_STATIC }, /* 173 = freebsd6 freebsd32_pread */
+ { compat6(AS(freebsd6_freebsd32_pwrite_args),freebsd32_pwrite), AUE_PWRITE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 174 = freebsd6 freebsd32_pwrite */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 175 = nosys */
+ { AS(ntp_adjtime_args), (sy_call_t *)sys_ntp_adjtime, AUE_NTP_ADJTIME, NULL, 0, 0, 0, SY_THR_STATIC }, /* 176 = ntp_adjtime */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 177 = sfork */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 178 = getdescriptor */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 179 = setdescriptor */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 180 = nosys */
+ { AS(setgid_args), (sy_call_t *)sys_setgid, AUE_SETGID, NULL, 0, 0, 0, SY_THR_STATIC }, /* 181 = setgid */
+ { AS(setegid_args), (sy_call_t *)sys_setegid, AUE_SETEGID, NULL, 0, 0, 0, SY_THR_STATIC }, /* 182 = setegid */
+ { AS(seteuid_args), (sy_call_t *)sys_seteuid, AUE_SETEUID, NULL, 0, 0, 0, SY_THR_STATIC }, /* 183 = seteuid */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 184 = lfs_bmapv */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 185 = lfs_markv */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 186 = lfs_segclean */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 187 = lfs_segwait */
+ { AS(freebsd32_stat_args), (sy_call_t *)freebsd32_stat, AUE_STAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 188 = freebsd32_stat */
+ { AS(freebsd32_fstat_args), (sy_call_t *)freebsd32_fstat, AUE_FSTAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 189 = freebsd32_fstat */
+ { AS(freebsd32_lstat_args), (sy_call_t *)freebsd32_lstat, AUE_LSTAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 190 = freebsd32_lstat */
+ { AS(pathconf_args), (sy_call_t *)sys_pathconf, AUE_PATHCONF, NULL, 0, 0, 0, SY_THR_STATIC }, /* 191 = pathconf */
+ { AS(fpathconf_args), (sy_call_t *)sys_fpathconf, AUE_FPATHCONF, NULL, 0, 0, 0, SY_THR_STATIC }, /* 192 = fpathconf */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 193 = nosys */
+ { AS(__getrlimit_args), (sy_call_t *)sys_getrlimit, AUE_GETRLIMIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 194 = getrlimit */
+ { AS(__setrlimit_args), (sy_call_t *)sys_setrlimit, AUE_SETRLIMIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 195 = setrlimit */
+ { AS(freebsd32_getdirentries_args), (sy_call_t *)freebsd32_getdirentries, AUE_GETDIRENTRIES, NULL, 0, 0, 0, SY_THR_STATIC }, /* 196 = freebsd32_getdirentries */
+ { compat6(AS(freebsd6_freebsd32_mmap_args),freebsd32_mmap), AUE_MMAP, NULL, 0, 0, 0, SY_THR_STATIC }, /* 197 = freebsd6 freebsd32_mmap */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 198 = __syscall */
+ { compat6(AS(freebsd6_freebsd32_lseek_args),freebsd32_lseek), AUE_LSEEK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 199 = freebsd6 freebsd32_lseek */
+ { compat6(AS(freebsd6_freebsd32_truncate_args),freebsd32_truncate), AUE_TRUNCATE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 200 = freebsd6 freebsd32_truncate */
+ { compat6(AS(freebsd6_freebsd32_ftruncate_args),freebsd32_ftruncate), AUE_FTRUNCATE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 201 = freebsd6 freebsd32_ftruncate */
+ { AS(freebsd32_sysctl_args), (sy_call_t *)freebsd32_sysctl, AUE_SYSCTL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 202 = freebsd32_sysctl */
+ { AS(mlock_args), (sy_call_t *)sys_mlock, AUE_MLOCK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 203 = mlock */
+ { AS(munlock_args), (sy_call_t *)sys_munlock, AUE_MUNLOCK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 204 = munlock */
+ { AS(undelete_args), (sy_call_t *)sys_undelete, AUE_UNDELETE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 205 = undelete */
+ { AS(freebsd32_futimes_args), (sy_call_t *)freebsd32_futimes, AUE_FUTIMES, NULL, 0, 0, 0, SY_THR_STATIC }, /* 206 = freebsd32_futimes */
+ { AS(getpgid_args), (sy_call_t *)sys_getpgid, AUE_GETPGID, NULL, 0, 0, 0, SY_THR_STATIC }, /* 207 = getpgid */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 208 = newreboot */
+ { AS(poll_args), (sy_call_t *)sys_poll, AUE_POLL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 209 = poll */
+ { AS(nosys_args), (sy_call_t *)lkmnosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 210 = lkmnosys */
+ { AS(nosys_args), (sy_call_t *)lkmnosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 211 = lkmnosys */
+ { AS(nosys_args), (sy_call_t *)lkmnosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 212 = lkmnosys */
+ { AS(nosys_args), (sy_call_t *)lkmnosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 213 = lkmnosys */
+ { AS(nosys_args), (sy_call_t *)lkmnosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 214 = lkmnosys */
+ { AS(nosys_args), (sy_call_t *)lkmnosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 215 = lkmnosys */
+ { AS(nosys_args), (sy_call_t *)lkmnosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 216 = lkmnosys */
+ { AS(nosys_args), (sy_call_t *)lkmnosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 217 = lkmnosys */
+ { AS(nosys_args), (sy_call_t *)lkmnosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 218 = lkmnosys */
+ { AS(nosys_args), (sy_call_t *)lkmnosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 219 = lkmnosys */
+ { 0, (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 220 = freebsd7 freebsd32_semctl */
+ { AS(semget_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 221 = semget */
+ { AS(semop_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 222 = semop */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 223 = semconfig */
+ { 0, (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 224 = freebsd7 freebsd32_msgctl */
+ { AS(msgget_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 225 = msgget */
+ { AS(freebsd32_msgsnd_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 226 = freebsd32_msgsnd */
+ { AS(freebsd32_msgrcv_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 227 = freebsd32_msgrcv */
+ { AS(shmat_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 228 = shmat */
+ { 0, (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 229 = freebsd7 freebsd32_shmctl */
+ { AS(shmdt_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 230 = shmdt */
+ { AS(shmget_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 231 = shmget */
+ { AS(freebsd32_clock_gettime_args), (sy_call_t *)freebsd32_clock_gettime, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 232 = freebsd32_clock_gettime */
+ { AS(freebsd32_clock_settime_args), (sy_call_t *)freebsd32_clock_settime, AUE_CLOCK_SETTIME, NULL, 0, 0, 0, SY_THR_STATIC }, /* 233 = freebsd32_clock_settime */
+ { AS(freebsd32_clock_getres_args), (sy_call_t *)freebsd32_clock_getres, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 234 = freebsd32_clock_getres */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 235 = timer_create */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 236 = timer_delete */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 237 = timer_settime */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 238 = timer_gettime */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 239 = timer_getoverrun */
+ { AS(freebsd32_nanosleep_args), (sy_call_t *)freebsd32_nanosleep, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 240 = freebsd32_nanosleep */
+ { AS(ffclock_getcounter_args), (sy_call_t *)sys_ffclock_getcounter, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 241 = ffclock_getcounter */
+ { AS(ffclock_setestimate_args), (sy_call_t *)sys_ffclock_setestimate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 242 = ffclock_setestimate */
+ { AS(ffclock_getestimate_args), (sy_call_t *)sys_ffclock_getestimate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 243 = ffclock_getestimate */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 244 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 245 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 246 = nosys */
+ { AS(clock_getcpuclockid2_args), (sy_call_t *)sys_clock_getcpuclockid2, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 247 = clock_getcpuclockid2 */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 248 = ntp_gettime */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 249 = nosys */
+ { AS(minherit_args), (sy_call_t *)sys_minherit, AUE_MINHERIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 250 = minherit */
+ { AS(rfork_args), (sy_call_t *)sys_rfork, AUE_RFORK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 251 = rfork */
+ { AS(openbsd_poll_args), (sy_call_t *)sys_openbsd_poll, AUE_POLL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 252 = openbsd_poll */
+ { 0, (sy_call_t *)sys_issetugid, AUE_ISSETUGID, NULL, 0, 0, 0, SY_THR_STATIC }, /* 253 = issetugid */
+ { AS(lchown_args), (sy_call_t *)sys_lchown, AUE_LCHOWN, NULL, 0, 0, 0, SY_THR_STATIC }, /* 254 = lchown */
+ { AS(freebsd32_aio_read_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 255 = freebsd32_aio_read */
+ { AS(freebsd32_aio_write_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 256 = freebsd32_aio_write */
+ { AS(freebsd32_lio_listio_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 257 = freebsd32_lio_listio */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 258 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 259 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 260 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 261 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 262 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 263 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 264 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 265 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 266 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 267 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 268 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 269 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 270 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 271 = nosys */
+ { AS(getdents_args), (sy_call_t *)sys_getdents, AUE_O_GETDENTS, NULL, 0, 0, 0, SY_THR_STATIC }, /* 272 = getdents */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 273 = nosys */
+ { AS(lchmod_args), (sy_call_t *)sys_lchmod, AUE_LCHMOD, NULL, 0, 0, 0, SY_THR_STATIC }, /* 274 = lchmod */
+ { AS(lchown_args), (sy_call_t *)sys_lchown, AUE_LCHOWN, NULL, 0, 0, 0, SY_THR_STATIC }, /* 275 = netbsd_lchown */
+ { AS(freebsd32_lutimes_args), (sy_call_t *)freebsd32_lutimes, AUE_LUTIMES, NULL, 0, 0, 0, SY_THR_STATIC }, /* 276 = freebsd32_lutimes */
+ { AS(msync_args), (sy_call_t *)sys_msync, AUE_MSYNC, NULL, 0, 0, 0, SY_THR_STATIC }, /* 277 = netbsd_msync */
+ { AS(nstat_args), (sy_call_t *)sys_nstat, AUE_STAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 278 = nstat */
+ { AS(nfstat_args), (sy_call_t *)sys_nfstat, AUE_FSTAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 279 = nfstat */
+ { AS(nlstat_args), (sy_call_t *)sys_nlstat, AUE_LSTAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 280 = nlstat */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 281 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 282 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 283 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 284 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 285 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 286 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 287 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 288 = nosys */
+ { AS(freebsd32_preadv_args), (sy_call_t *)freebsd32_preadv, AUE_PREADV, NULL, 0, 0, 0, SY_THR_STATIC }, /* 289 = freebsd32_preadv */
+ { AS(freebsd32_pwritev_args), (sy_call_t *)freebsd32_pwritev, AUE_PWRITEV, NULL, 0, 0, 0, SY_THR_STATIC }, /* 290 = freebsd32_pwritev */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 291 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 292 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 293 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 294 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 295 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 296 = nosys */
+ { compat4(AS(freebsd4_freebsd32_fhstatfs_args),freebsd32_fhstatfs), AUE_FHSTATFS, NULL, 0, 0, 0, SY_THR_STATIC }, /* 297 = freebsd4 freebsd32_fhstatfs */
+ { AS(fhopen_args), (sy_call_t *)sys_fhopen, AUE_FHOPEN, NULL, 0, 0, 0, SY_THR_STATIC }, /* 298 = fhopen */
+ { AS(fhstat_args), (sy_call_t *)sys_fhstat, AUE_FHSTAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 299 = fhstat */
+ { AS(modnext_args), (sy_call_t *)sys_modnext, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 300 = modnext */
+ { AS(freebsd32_modstat_args), (sy_call_t *)freebsd32_modstat, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 301 = freebsd32_modstat */
+ { AS(modfnext_args), (sy_call_t *)sys_modfnext, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 302 = modfnext */
+ { AS(modfind_args), (sy_call_t *)sys_modfind, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 303 = modfind */
+ { AS(kldload_args), (sy_call_t *)sys_kldload, AUE_MODLOAD, NULL, 0, 0, 0, SY_THR_STATIC }, /* 304 = kldload */
+ { AS(kldunload_args), (sy_call_t *)sys_kldunload, AUE_MODUNLOAD, NULL, 0, 0, 0, SY_THR_STATIC }, /* 305 = kldunload */
+ { AS(kldfind_args), (sy_call_t *)sys_kldfind, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 306 = kldfind */
+ { AS(kldnext_args), (sy_call_t *)sys_kldnext, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 307 = kldnext */
+ { AS(freebsd32_kldstat_args), (sy_call_t *)freebsd32_kldstat, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 308 = freebsd32_kldstat */
+ { AS(kldfirstmod_args), (sy_call_t *)sys_kldfirstmod, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 309 = kldfirstmod */
+ { AS(getsid_args), (sy_call_t *)sys_getsid, AUE_GETSID, NULL, 0, 0, 0, SY_THR_STATIC }, /* 310 = getsid */
+ { AS(setresuid_args), (sy_call_t *)sys_setresuid, AUE_SETRESUID, NULL, 0, 0, 0, SY_THR_STATIC }, /* 311 = setresuid */
+ { AS(setresgid_args), (sy_call_t *)sys_setresgid, AUE_SETRESGID, NULL, 0, 0, 0, SY_THR_STATIC }, /* 312 = setresgid */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 313 = obsolete signanosleep */
+ { AS(freebsd32_aio_return_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 314 = freebsd32_aio_return */
+ { AS(freebsd32_aio_suspend_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 315 = freebsd32_aio_suspend */
+ { AS(freebsd32_aio_cancel_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 316 = freebsd32_aio_cancel */
+ { AS(freebsd32_aio_error_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 317 = freebsd32_aio_error */
+ { AS(freebsd32_oaio_read_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 318 = freebsd32_oaio_read */
+ { AS(freebsd32_oaio_write_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 319 = freebsd32_oaio_write */
+ { AS(freebsd32_olio_listio_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 320 = freebsd32_olio_listio */
+ { 0, (sy_call_t *)sys_yield, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 321 = yield */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 322 = obsolete thr_sleep */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 323 = obsolete thr_wakeup */
+ { AS(mlockall_args), (sy_call_t *)sys_mlockall, AUE_MLOCKALL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 324 = mlockall */
+ { 0, (sy_call_t *)sys_munlockall, AUE_MUNLOCKALL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 325 = munlockall */
+ { AS(__getcwd_args), (sy_call_t *)sys___getcwd, AUE_GETCWD, NULL, 0, 0, 0, SY_THR_STATIC }, /* 326 = __getcwd */
+ { AS(sched_setparam_args), (sy_call_t *)sys_sched_setparam, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 327 = sched_setparam */
+ { AS(sched_getparam_args), (sy_call_t *)sys_sched_getparam, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 328 = sched_getparam */
+ { AS(sched_setscheduler_args), (sy_call_t *)sys_sched_setscheduler, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 329 = sched_setscheduler */
+ { AS(sched_getscheduler_args), (sy_call_t *)sys_sched_getscheduler, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 330 = sched_getscheduler */
+ { 0, (sy_call_t *)sys_sched_yield, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 331 = sched_yield */
+ { AS(sched_get_priority_max_args), (sy_call_t *)sys_sched_get_priority_max, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 332 = sched_get_priority_max */
+ { AS(sched_get_priority_min_args), (sy_call_t *)sys_sched_get_priority_min, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 333 = sched_get_priority_min */
+ { AS(sched_rr_get_interval_args), (sy_call_t *)sys_sched_rr_get_interval, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 334 = sched_rr_get_interval */
+ { AS(utrace_args), (sy_call_t *)sys_utrace, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 335 = utrace */
+ { compat4(AS(freebsd4_freebsd32_sendfile_args),freebsd32_sendfile), AUE_SENDFILE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 336 = freebsd4 freebsd32_sendfile */
+ { AS(kldsym_args), (sy_call_t *)sys_kldsym, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 337 = kldsym */
+ { AS(freebsd32_jail_args), (sy_call_t *)freebsd32_jail, AUE_JAIL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 338 = freebsd32_jail */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 339 = pioctl */
+ { AS(sigprocmask_args), (sy_call_t *)sys_sigprocmask, AUE_SIGPROCMASK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 340 = sigprocmask */
+ { AS(sigsuspend_args), (sy_call_t *)sys_sigsuspend, AUE_SIGSUSPEND, NULL, 0, 0, 0, SY_THR_STATIC }, /* 341 = sigsuspend */
+ { compat4(AS(freebsd4_freebsd32_sigaction_args),freebsd32_sigaction), AUE_SIGACTION, NULL, 0, 0, 0, SY_THR_STATIC }, /* 342 = freebsd4 freebsd32_sigaction */
+ { AS(sigpending_args), (sy_call_t *)sys_sigpending, AUE_SIGPENDING, NULL, 0, 0, 0, SY_THR_STATIC }, /* 343 = sigpending */
+ { compat4(AS(freebsd4_freebsd32_sigreturn_args),freebsd32_sigreturn), AUE_SIGRETURN, NULL, 0, 0, 0, SY_THR_STATIC }, /* 344 = freebsd4 freebsd32_sigreturn */
+ { AS(freebsd32_sigtimedwait_args), (sy_call_t *)freebsd32_sigtimedwait, AUE_SIGWAIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 345 = freebsd32_sigtimedwait */
+ { AS(freebsd32_sigwaitinfo_args), (sy_call_t *)freebsd32_sigwaitinfo, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 346 = freebsd32_sigwaitinfo */
+ { AS(__acl_get_file_args), (sy_call_t *)sys___acl_get_file, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 347 = __acl_get_file */
+ { AS(__acl_set_file_args), (sy_call_t *)sys___acl_set_file, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 348 = __acl_set_file */
+ { AS(__acl_get_fd_args), (sy_call_t *)sys___acl_get_fd, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 349 = __acl_get_fd */
+ { AS(__acl_set_fd_args), (sy_call_t *)sys___acl_set_fd, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 350 = __acl_set_fd */
+ { AS(__acl_delete_file_args), (sy_call_t *)sys___acl_delete_file, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 351 = __acl_delete_file */
+ { AS(__acl_delete_fd_args), (sy_call_t *)sys___acl_delete_fd, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 352 = __acl_delete_fd */
+ { AS(__acl_aclcheck_file_args), (sy_call_t *)sys___acl_aclcheck_file, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 353 = __acl_aclcheck_file */
+ { AS(__acl_aclcheck_fd_args), (sy_call_t *)sys___acl_aclcheck_fd, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 354 = __acl_aclcheck_fd */
+ { AS(extattrctl_args), (sy_call_t *)sys_extattrctl, AUE_EXTATTRCTL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 355 = extattrctl */
+ { AS(extattr_set_file_args), (sy_call_t *)sys_extattr_set_file, AUE_EXTATTR_SET_FILE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 356 = extattr_set_file */
+ { AS(extattr_get_file_args), (sy_call_t *)sys_extattr_get_file, AUE_EXTATTR_GET_FILE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 357 = extattr_get_file */
+ { AS(extattr_delete_file_args), (sy_call_t *)sys_extattr_delete_file, AUE_EXTATTR_DELETE_FILE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 358 = extattr_delete_file */
+ { AS(freebsd32_aio_waitcomplete_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 359 = freebsd32_aio_waitcomplete */
+ { AS(getresuid_args), (sy_call_t *)sys_getresuid, AUE_GETRESUID, NULL, 0, 0, 0, SY_THR_STATIC }, /* 360 = getresuid */
+ { AS(getresgid_args), (sy_call_t *)sys_getresgid, AUE_GETRESGID, NULL, 0, 0, 0, SY_THR_STATIC }, /* 361 = getresgid */
+ { 0, (sy_call_t *)sys_kqueue, AUE_KQUEUE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 362 = kqueue */
+ { AS(freebsd32_kevent_args), (sy_call_t *)freebsd32_kevent, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 363 = freebsd32_kevent */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 364 = __cap_get_proc */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 365 = __cap_set_proc */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 366 = __cap_get_fd */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 367 = __cap_get_file */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 368 = __cap_set_fd */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 369 = __cap_set_file */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 370 = nosys */
+ { AS(extattr_set_fd_args), (sy_call_t *)sys_extattr_set_fd, AUE_EXTATTR_SET_FD, NULL, 0, 0, 0, SY_THR_STATIC }, /* 371 = extattr_set_fd */
+ { AS(extattr_get_fd_args), (sy_call_t *)sys_extattr_get_fd, AUE_EXTATTR_GET_FD, NULL, 0, 0, 0, SY_THR_STATIC }, /* 372 = extattr_get_fd */
+ { AS(extattr_delete_fd_args), (sy_call_t *)sys_extattr_delete_fd, AUE_EXTATTR_DELETE_FD, NULL, 0, 0, 0, SY_THR_STATIC }, /* 373 = extattr_delete_fd */
+ { AS(__setugid_args), (sy_call_t *)sys___setugid, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 374 = __setugid */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 375 = nfsclnt */
+ { AS(eaccess_args), (sy_call_t *)sys_eaccess, AUE_EACCESS, NULL, 0, 0, 0, SY_THR_STATIC }, /* 376 = eaccess */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 377 = afs_syscall */
+ { AS(freebsd32_nmount_args), (sy_call_t *)freebsd32_nmount, AUE_NMOUNT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 378 = freebsd32_nmount */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 379 = kse_exit */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 380 = kse_wakeup */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 381 = kse_create */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 382 = kse_thr_interrupt */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 383 = kse_release */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 384 = __mac_get_proc */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 385 = __mac_set_proc */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 386 = __mac_get_fd */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 387 = __mac_get_file */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 388 = __mac_set_fd */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 389 = __mac_set_file */
+ { AS(kenv_args), (sy_call_t *)sys_kenv, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 390 = kenv */
+ { AS(lchflags_args), (sy_call_t *)sys_lchflags, AUE_LCHFLAGS, NULL, 0, 0, 0, SY_THR_STATIC }, /* 391 = lchflags */
+ { AS(uuidgen_args), (sy_call_t *)sys_uuidgen, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 392 = uuidgen */
+ { AS(freebsd32_sendfile_args), (sy_call_t *)freebsd32_sendfile, AUE_SENDFILE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 393 = freebsd32_sendfile */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 394 = mac_syscall */
+ { AS(getfsstat_args), (sy_call_t *)sys_getfsstat, AUE_GETFSSTAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 395 = getfsstat */
+ { AS(statfs_args), (sy_call_t *)sys_statfs, AUE_STATFS, NULL, 0, 0, 0, SY_THR_STATIC }, /* 396 = statfs */
+ { AS(fstatfs_args), (sy_call_t *)sys_fstatfs, AUE_FSTATFS, NULL, 0, 0, 0, SY_THR_STATIC }, /* 397 = fstatfs */
+ { AS(fhstatfs_args), (sy_call_t *)sys_fhstatfs, AUE_FHSTATFS, NULL, 0, 0, 0, SY_THR_STATIC }, /* 398 = fhstatfs */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 399 = nosys */
+ { AS(ksem_close_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 400 = ksem_close */
+ { AS(ksem_post_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 401 = ksem_post */
+ { AS(ksem_wait_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 402 = ksem_wait */
+ { AS(ksem_trywait_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 403 = ksem_trywait */
+ { AS(freebsd32_ksem_init_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 404 = freebsd32_ksem_init */
+ { AS(freebsd32_ksem_open_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 405 = freebsd32_ksem_open */
+ { AS(ksem_unlink_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 406 = ksem_unlink */
+ { AS(ksem_getvalue_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 407 = ksem_getvalue */
+ { AS(ksem_destroy_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 408 = ksem_destroy */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 409 = __mac_get_pid */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 410 = __mac_get_link */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 411 = __mac_set_link */
+ { AS(extattr_set_link_args), (sy_call_t *)sys_extattr_set_link, AUE_EXTATTR_SET_LINK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 412 = extattr_set_link */
+ { AS(extattr_get_link_args), (sy_call_t *)sys_extattr_get_link, AUE_EXTATTR_GET_LINK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 413 = extattr_get_link */
+ { AS(extattr_delete_link_args), (sy_call_t *)sys_extattr_delete_link, AUE_EXTATTR_DELETE_LINK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 414 = extattr_delete_link */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 415 = __mac_execve */
+ { AS(freebsd32_sigaction_args), (sy_call_t *)freebsd32_sigaction, AUE_SIGACTION, NULL, 0, 0, 0, SY_THR_STATIC }, /* 416 = freebsd32_sigaction */
+ { AS(freebsd32_sigreturn_args), (sy_call_t *)freebsd32_sigreturn, AUE_SIGRETURN, NULL, 0, 0, 0, SY_THR_STATIC }, /* 417 = freebsd32_sigreturn */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 418 = __xstat */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 419 = __xfstat */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 420 = __xlstat */
+ { AS(freebsd32_getcontext_args), (sy_call_t *)freebsd32_getcontext, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 421 = freebsd32_getcontext */
+ { AS(freebsd32_setcontext_args), (sy_call_t *)freebsd32_setcontext, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 422 = freebsd32_setcontext */
+ { AS(freebsd32_swapcontext_args), (sy_call_t *)freebsd32_swapcontext, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 423 = freebsd32_swapcontext */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 424 = swapoff */
+ { AS(__acl_get_link_args), (sy_call_t *)sys___acl_get_link, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 425 = __acl_get_link */
+ { AS(__acl_set_link_args), (sy_call_t *)sys___acl_set_link, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 426 = __acl_set_link */
+ { AS(__acl_delete_link_args), (sy_call_t *)sys___acl_delete_link, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 427 = __acl_delete_link */
+ { AS(__acl_aclcheck_link_args), (sy_call_t *)sys___acl_aclcheck_link, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 428 = __acl_aclcheck_link */
+ { AS(sigwait_args), (sy_call_t *)sys_sigwait, AUE_SIGWAIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 429 = sigwait */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 430 = thr_create; */
+ { AS(thr_exit_args), (sy_call_t *)sys_thr_exit, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 431 = thr_exit */
+ { AS(thr_self_args), (sy_call_t *)sys_thr_self, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 432 = thr_self */
+ { AS(thr_kill_args), (sy_call_t *)sys_thr_kill, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 433 = thr_kill */
+ { AS(freebsd32_umtx_lock_args), (sy_call_t *)freebsd32_umtx_lock, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 434 = freebsd32_umtx_lock */
+ { AS(freebsd32_umtx_unlock_args), (sy_call_t *)freebsd32_umtx_unlock, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 435 = freebsd32_umtx_unlock */
+ { AS(jail_attach_args), (sy_call_t *)sys_jail_attach, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 436 = jail_attach */
+ { AS(extattr_list_fd_args), (sy_call_t *)sys_extattr_list_fd, AUE_EXTATTR_LIST_FD, NULL, 0, 0, 0, SY_THR_STATIC }, /* 437 = extattr_list_fd */
+ { AS(extattr_list_file_args), (sy_call_t *)sys_extattr_list_file, AUE_EXTATTR_LIST_FILE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 438 = extattr_list_file */
+ { AS(extattr_list_link_args), (sy_call_t *)sys_extattr_list_link, AUE_EXTATTR_LIST_LINK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 439 = extattr_list_link */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 440 = kse_switchin */
+ { AS(freebsd32_ksem_timedwait_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 441 = freebsd32_ksem_timedwait */
+ { AS(freebsd32_thr_suspend_args), (sy_call_t *)freebsd32_thr_suspend, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 442 = freebsd32_thr_suspend */
+ { AS(thr_wake_args), (sy_call_t *)sys_thr_wake, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 443 = thr_wake */
+ { AS(kldunloadf_args), (sy_call_t *)sys_kldunloadf, AUE_MODUNLOAD, NULL, 0, 0, 0, SY_THR_STATIC }, /* 444 = kldunloadf */
+ { AS(audit_args), (sy_call_t *)sys_audit, AUE_AUDIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 445 = audit */
+ { AS(auditon_args), (sy_call_t *)sys_auditon, AUE_AUDITON, NULL, 0, 0, 0, SY_THR_STATIC }, /* 446 = auditon */
+ { AS(getauid_args), (sy_call_t *)sys_getauid, AUE_GETAUID, NULL, 0, 0, 0, SY_THR_STATIC }, /* 447 = getauid */
+ { AS(setauid_args), (sy_call_t *)sys_setauid, AUE_SETAUID, NULL, 0, 0, 0, SY_THR_STATIC }, /* 448 = setauid */
+ { AS(getaudit_args), (sy_call_t *)sys_getaudit, AUE_GETAUDIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 449 = getaudit */
+ { AS(setaudit_args), (sy_call_t *)sys_setaudit, AUE_SETAUDIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 450 = setaudit */
+ { AS(getaudit_addr_args), (sy_call_t *)sys_getaudit_addr, AUE_GETAUDIT_ADDR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 451 = getaudit_addr */
+ { AS(setaudit_addr_args), (sy_call_t *)sys_setaudit_addr, AUE_SETAUDIT_ADDR, NULL, 0, 0, 0, SY_THR_STATIC }, /* 452 = setaudit_addr */
+ { AS(auditctl_args), (sy_call_t *)sys_auditctl, AUE_AUDITCTL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 453 = auditctl */
+ { AS(freebsd32_umtx_op_args), (sy_call_t *)freebsd32_umtx_op, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 454 = freebsd32_umtx_op */
+ { AS(freebsd32_thr_new_args), (sy_call_t *)freebsd32_thr_new, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 455 = freebsd32_thr_new */
+ { AS(sigqueue_args), (sy_call_t *)sys_sigqueue, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 456 = sigqueue */
+ { AS(freebsd32_kmq_open_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 457 = freebsd32_kmq_open */
+ { AS(freebsd32_kmq_setattr_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 458 = freebsd32_kmq_setattr */
+ { AS(freebsd32_kmq_timedreceive_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 459 = freebsd32_kmq_timedreceive */
+ { AS(freebsd32_kmq_timedsend_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 460 = freebsd32_kmq_timedsend */
+ { AS(kmq_notify_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 461 = kmq_notify */
+ { AS(kmq_unlink_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 462 = kmq_unlink */
+ { AS(abort2_args), (sy_call_t *)sys_abort2, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 463 = abort2 */
+ { AS(thr_set_name_args), (sy_call_t *)sys_thr_set_name, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 464 = thr_set_name */
+ { AS(freebsd32_aio_fsync_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 465 = freebsd32_aio_fsync */
+ { AS(rtprio_thread_args), (sy_call_t *)sys_rtprio_thread, AUE_RTPRIO, NULL, 0, 0, 0, SY_THR_STATIC }, /* 466 = rtprio_thread */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 467 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 468 = nosys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 469 = __getpath_fromfd */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 470 = __getpath_fromaddr */
+ { AS(sctp_peeloff_args), (sy_call_t *)sys_sctp_peeloff, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 471 = sctp_peeloff */
+ { AS(sctp_generic_sendmsg_args), (sy_call_t *)sys_sctp_generic_sendmsg, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 472 = sctp_generic_sendmsg */
+ { AS(sctp_generic_sendmsg_iov_args), (sy_call_t *)sys_sctp_generic_sendmsg_iov, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 473 = sctp_generic_sendmsg_iov */
+ { AS(sctp_generic_recvmsg_args), (sy_call_t *)sys_sctp_generic_recvmsg, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 474 = sctp_generic_recvmsg */
+#ifdef PAD64_REQUIRED
+ { AS(freebsd32_pread_args), (sy_call_t *)freebsd32_pread, AUE_PREAD, NULL, 0, 0, 0, SY_THR_STATIC }, /* 475 = freebsd32_pread */
+ { AS(freebsd32_pwrite_args), (sy_call_t *)freebsd32_pwrite, AUE_PWRITE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 476 = freebsd32_pwrite */
+ { AS(freebsd32_mmap_args), (sy_call_t *)freebsd32_mmap, AUE_MMAP, NULL, 0, 0, 0, SY_THR_STATIC }, /* 477 = freebsd32_mmap */
+ { AS(freebsd32_lseek_args), (sy_call_t *)freebsd32_lseek, AUE_LSEEK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 478 = freebsd32_lseek */
+ { AS(freebsd32_truncate_args), (sy_call_t *)freebsd32_truncate, AUE_TRUNCATE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 479 = freebsd32_truncate */
+ { AS(freebsd32_ftruncate_args), (sy_call_t *)freebsd32_ftruncate, AUE_FTRUNCATE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 480 = freebsd32_ftruncate */
+#else
+ { AS(freebsd32_pread_args), (sy_call_t *)freebsd32_pread, AUE_PREAD, NULL, 0, 0, 0, SY_THR_STATIC }, /* 475 = freebsd32_pread */
+ { AS(freebsd32_pwrite_args), (sy_call_t *)freebsd32_pwrite, AUE_PWRITE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 476 = freebsd32_pwrite */
+ { AS(freebsd32_mmap_args), (sy_call_t *)freebsd32_mmap, AUE_MMAP, NULL, 0, 0, 0, SY_THR_STATIC }, /* 477 = freebsd32_mmap */
+ { AS(freebsd32_lseek_args), (sy_call_t *)freebsd32_lseek, AUE_LSEEK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 478 = freebsd32_lseek */
+ { AS(freebsd32_truncate_args), (sy_call_t *)freebsd32_truncate, AUE_TRUNCATE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 479 = freebsd32_truncate */
+ { AS(freebsd32_ftruncate_args), (sy_call_t *)freebsd32_ftruncate, AUE_FTRUNCATE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 480 = freebsd32_ftruncate */
+#endif
+ { AS(thr_kill2_args), (sy_call_t *)sys_thr_kill2, AUE_KILL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 481 = thr_kill2 */
+ { AS(shm_open_args), (sy_call_t *)sys_shm_open, AUE_SHMOPEN, NULL, 0, 0, 0, SY_THR_STATIC }, /* 482 = shm_open */
+ { AS(shm_unlink_args), (sy_call_t *)sys_shm_unlink, AUE_SHMUNLINK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 483 = shm_unlink */
+ { AS(cpuset_args), (sy_call_t *)sys_cpuset, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 484 = cpuset */
+#ifdef PAD64_REQUIRED
+ { AS(freebsd32_cpuset_setid_args), (sy_call_t *)freebsd32_cpuset_setid, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 485 = freebsd32_cpuset_setid */
+#else
+ { AS(freebsd32_cpuset_setid_args), (sy_call_t *)freebsd32_cpuset_setid, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 485 = freebsd32_cpuset_setid */
+#endif
+ { AS(freebsd32_cpuset_getid_args), (sy_call_t *)freebsd32_cpuset_getid, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 486 = freebsd32_cpuset_getid */
+ { AS(freebsd32_cpuset_getaffinity_args), (sy_call_t *)freebsd32_cpuset_getaffinity, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 487 = freebsd32_cpuset_getaffinity */
+ { AS(freebsd32_cpuset_setaffinity_args), (sy_call_t *)freebsd32_cpuset_setaffinity, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 488 = freebsd32_cpuset_setaffinity */
+ { AS(faccessat_args), (sy_call_t *)sys_faccessat, AUE_FACCESSAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 489 = faccessat */
+ { AS(fchmodat_args), (sy_call_t *)sys_fchmodat, AUE_FCHMODAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 490 = fchmodat */
+ { AS(fchownat_args), (sy_call_t *)sys_fchownat, AUE_FCHOWNAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 491 = fchownat */
+ { AS(freebsd32_fexecve_args), (sy_call_t *)freebsd32_fexecve, AUE_FEXECVE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 492 = freebsd32_fexecve */
+ { AS(freebsd32_fstatat_args), (sy_call_t *)freebsd32_fstatat, AUE_FSTATAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 493 = freebsd32_fstatat */
+ { AS(freebsd32_futimesat_args), (sy_call_t *)freebsd32_futimesat, AUE_FUTIMESAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 494 = freebsd32_futimesat */
+ { AS(linkat_args), (sy_call_t *)sys_linkat, AUE_LINKAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 495 = linkat */
+ { AS(mkdirat_args), (sy_call_t *)sys_mkdirat, AUE_MKDIRAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 496 = mkdirat */
+ { AS(mkfifoat_args), (sy_call_t *)sys_mkfifoat, AUE_MKFIFOAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 497 = mkfifoat */
+ { AS(mknodat_args), (sy_call_t *)sys_mknodat, AUE_MKNODAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 498 = mknodat */
+ { AS(openat_args), (sy_call_t *)sys_openat, AUE_OPENAT_RWTC, NULL, 0, 0, 0, SY_THR_STATIC }, /* 499 = openat */
+ { AS(readlinkat_args), (sy_call_t *)sys_readlinkat, AUE_READLINKAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 500 = readlinkat */
+ { AS(renameat_args), (sy_call_t *)sys_renameat, AUE_RENAMEAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 501 = renameat */
+ { AS(symlinkat_args), (sy_call_t *)sys_symlinkat, AUE_SYMLINKAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 502 = symlinkat */
+ { AS(unlinkat_args), (sy_call_t *)sys_unlinkat, AUE_UNLINKAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 503 = unlinkat */
+ { AS(posix_openpt_args), (sy_call_t *)sys_posix_openpt, AUE_POSIX_OPENPT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 504 = posix_openpt */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 505 = gssd_syscall */
+ { AS(freebsd32_jail_get_args), (sy_call_t *)freebsd32_jail_get, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 506 = freebsd32_jail_get */
+ { AS(freebsd32_jail_set_args), (sy_call_t *)freebsd32_jail_set, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 507 = freebsd32_jail_set */
+ { AS(jail_remove_args), (sy_call_t *)sys_jail_remove, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 508 = jail_remove */
+ { AS(closefrom_args), (sy_call_t *)sys_closefrom, AUE_CLOSEFROM, NULL, 0, 0, 0, SY_THR_STATIC }, /* 509 = closefrom */
+ { AS(freebsd32_semctl_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 510 = freebsd32_semctl */
+ { AS(freebsd32_msgctl_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 511 = freebsd32_msgctl */
+ { AS(freebsd32_shmctl_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 512 = freebsd32_shmctl */
+ { AS(lpathconf_args), (sy_call_t *)sys_lpathconf, AUE_LPATHCONF, NULL, 0, 0, 0, SY_THR_STATIC }, /* 513 = lpathconf */
+ { AS(cap_new_args), (sy_call_t *)sys_cap_new, AUE_CAP_NEW, NULL, 0, 0, 0, SY_THR_STATIC }, /* 514 = cap_new */
+ { AS(cap_rights_get_args), (sy_call_t *)sys_cap_rights_get, AUE_CAP_RIGHTS_GET, NULL, 0, 0, 0, SY_THR_STATIC }, /* 515 = cap_rights_get */
+ { 0, (sy_call_t *)sys_cap_enter, AUE_CAP_ENTER, NULL, 0, 0, 0, SY_THR_STATIC }, /* 516 = cap_enter */
+ { AS(cap_getmode_args), (sy_call_t *)sys_cap_getmode, AUE_CAP_GETMODE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 517 = cap_getmode */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 518 = pdfork */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 519 = pdkill */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 520 = pdgetpid */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 521 = pdwait */
+ { AS(freebsd32_pselect_args), (sy_call_t *)freebsd32_pselect, AUE_SELECT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 522 = freebsd32_pselect */
+ { AS(getloginclass_args), (sy_call_t *)sys_getloginclass, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 523 = getloginclass */
+ { AS(setloginclass_args), (sy_call_t *)sys_setloginclass, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 524 = setloginclass */
+ { AS(rctl_get_racct_args), (sy_call_t *)sys_rctl_get_racct, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 525 = rctl_get_racct */
+ { AS(rctl_get_rules_args), (sy_call_t *)sys_rctl_get_rules, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 526 = rctl_get_rules */
+ { AS(rctl_get_limits_args), (sy_call_t *)sys_rctl_get_limits, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 527 = rctl_get_limits */
+ { AS(rctl_add_rule_args), (sy_call_t *)sys_rctl_add_rule, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 528 = rctl_add_rule */
+ { AS(rctl_remove_rule_args), (sy_call_t *)sys_rctl_remove_rule, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 529 = rctl_remove_rule */
+#ifdef PAD64_REQUIRED
+ { AS(freebsd32_posix_fallocate_args), (sy_call_t *)freebsd32_posix_fallocate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 530 = freebsd32_posix_fallocate */
+ { AS(freebsd32_posix_fadvise_args), (sy_call_t *)freebsd32_posix_fadvise, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 531 = freebsd32_posix_fadvise */
+ { AS(freebsd32_wait6_args), (sy_call_t *)freebsd32_wait6, AUE_WAIT6, NULL, 0, 0, 0, SY_THR_STATIC }, /* 532 = freebsd32_wait6 */
+#else
+ { AS(freebsd32_posix_fallocate_args), (sy_call_t *)freebsd32_posix_fallocate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 530 = freebsd32_posix_fallocate */
+ { AS(freebsd32_posix_fadvise_args), (sy_call_t *)freebsd32_posix_fadvise, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 531 = freebsd32_posix_fadvise */
+ { AS(freebsd32_wait6_args), (sy_call_t *)freebsd32_wait6, AUE_WAIT6, NULL, 0, 0, 0, SY_THR_STATIC }, /* 532 = freebsd32_wait6 */
+#endif
+ { AS(cap_rights_limit_args), (sy_call_t *)sys_cap_rights_limit, AUE_CAP_RIGHTS_LIMIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 533 = cap_rights_limit */
+ { AS(cap_ioctls_limit_args), (sy_call_t *)sys_cap_ioctls_limit, AUE_CAP_IOCTLS_LIMIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 534 = cap_ioctls_limit */
+ { AS(cap_ioctls_get_args), (sy_call_t *)sys_cap_ioctls_get, AUE_CAP_IOCTLS_GET, NULL, 0, 0, 0, SY_THR_STATIC }, /* 535 = cap_ioctls_get */
+ { AS(cap_fcntls_limit_args), (sy_call_t *)sys_cap_fcntls_limit, AUE_CAP_FCNTLS_LIMIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 536 = cap_fcntls_limit */
+ { AS(cap_fcntls_get_args), (sy_call_t *)sys_cap_fcntls_get, AUE_CAP_FCNTLS_GET, NULL, 0, 0, 0, SY_THR_STATIC }, /* 537 = cap_fcntls_get */
+ { AS(bindat_args), (sy_call_t *)sys_bindat, AUE_BINDAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 538 = bindat */
+ { AS(connectat_args), (sy_call_t *)sys_connectat, AUE_CONNECTAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 539 = connectat */
+ { AS(chflagsat_args), (sy_call_t *)sys_chflagsat, AUE_CHFLAGSAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 540 = chflagsat */
+ { AS(accept4_args), (sy_call_t *)sys_accept4, AUE_ACCEPT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 541 = accept4 */
+ { AS(pipe2_args), (sy_call_t *)sys_pipe2, AUE_PIPE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 542 = pipe2 */
+ { AS(freebsd32_aio_mlock_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 543 = freebsd32_aio_mlock */
+};
diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c
new file mode 100644
index 0000000..7417f0e
--- /dev/null
+++ b/sys/compat/freebsd32/freebsd32_systrace_args.c
@@ -0,0 +1,10486 @@
+/*
+ * System call argument to DTrace register array converstion.
+ *
+ * DO NOT EDIT-- this file is automatically generated.
+ * $FreeBSD$
+ * This file is part of the DTrace syscall provider.
+ */
+
+static void
+systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
+{
+ int64_t *iarg = (int64_t *) uarg;
+ switch (sysnum) {
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
+#define PAD64_REQUIRED
+#endif
+ /* nosys */
+ case 0: {
+ *n_args = 0;
+ break;
+ }
+ /* sys_exit */
+ case 1: {
+ struct sys_exit_args *p = params;
+ iarg[0] = p->rval; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* fork */
+ case 2: {
+ *n_args = 0;
+ break;
+ }
+ /* read */
+ case 3: {
+ struct read_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->buf; /* void * */
+ uarg[2] = p->nbyte; /* size_t */
+ *n_args = 3;
+ break;
+ }
+ /* write */
+ case 4: {
+ struct write_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->buf; /* const void * */
+ uarg[2] = p->nbyte; /* size_t */
+ *n_args = 3;
+ break;
+ }
+ /* open */
+ case 5: {
+ struct open_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ iarg[1] = p->flags; /* int */
+ iarg[2] = p->mode; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* close */
+ case 6: {
+ struct close_args *p = params;
+ iarg[0] = p->fd; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_wait4 */
+ case 7: {
+ struct freebsd32_wait4_args *p = params;
+ iarg[0] = p->pid; /* int */
+ uarg[1] = (intptr_t) p->status; /* int * */
+ iarg[2] = p->options; /* int */
+ uarg[3] = (intptr_t) p->rusage; /* struct rusage32 * */
+ *n_args = 4;
+ break;
+ }
+ /* link */
+ case 9: {
+ struct link_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ uarg[1] = (intptr_t) p->link; /* char * */
+ *n_args = 2;
+ break;
+ }
+ /* unlink */
+ case 10: {
+ struct unlink_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ *n_args = 1;
+ break;
+ }
+ /* chdir */
+ case 12: {
+ struct chdir_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ *n_args = 1;
+ break;
+ }
+ /* fchdir */
+ case 13: {
+ struct fchdir_args *p = params;
+ iarg[0] = p->fd; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* mknod */
+ case 14: {
+ struct mknod_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ iarg[1] = p->mode; /* int */
+ iarg[2] = p->dev; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* chmod */
+ case 15: {
+ struct chmod_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ iarg[1] = p->mode; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* chown */
+ case 16: {
+ struct chown_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ iarg[1] = p->uid; /* int */
+ iarg[2] = p->gid; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* obreak */
+ case 17: {
+ struct obreak_args *p = params;
+ uarg[0] = (intptr_t) p->nsize; /* char * */
+ *n_args = 1;
+ break;
+ }
+ /* getpid */
+ case 20: {
+ *n_args = 0;
+ break;
+ }
+ /* mount */
+ case 21: {
+ struct mount_args *p = params;
+ uarg[0] = (intptr_t) p->type; /* char * */
+ uarg[1] = (intptr_t) p->path; /* char * */
+ iarg[2] = p->flags; /* int */
+ uarg[3] = (intptr_t) p->data; /* caddr_t */
+ *n_args = 4;
+ break;
+ }
+ /* unmount */
+ case 22: {
+ struct unmount_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ iarg[1] = p->flags; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* setuid */
+ case 23: {
+ struct setuid_args *p = params;
+ uarg[0] = p->uid; /* uid_t */
+ *n_args = 1;
+ break;
+ }
+ /* getuid */
+ case 24: {
+ *n_args = 0;
+ break;
+ }
+ /* geteuid */
+ case 25: {
+ *n_args = 0;
+ break;
+ }
+ /* ptrace */
+ case 26: {
+ struct ptrace_args *p = params;
+ iarg[0] = p->req; /* int */
+ iarg[1] = p->pid; /* pid_t */
+ uarg[2] = (intptr_t) p->addr; /* caddr_t */
+ iarg[3] = p->data; /* int */
+ *n_args = 4;
+ break;
+ }
+ /* freebsd32_recvmsg */
+ case 27: {
+ struct freebsd32_recvmsg_args *p = params;
+ iarg[0] = p->s; /* int */
+ uarg[1] = (intptr_t) p->msg; /* struct msghdr32 * */
+ iarg[2] = p->flags; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_sendmsg */
+ case 28: {
+ struct freebsd32_sendmsg_args *p = params;
+ iarg[0] = p->s; /* int */
+ uarg[1] = (intptr_t) p->msg; /* struct msghdr32 * */
+ iarg[2] = p->flags; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_recvfrom */
+ case 29: {
+ struct freebsd32_recvfrom_args *p = params;
+ iarg[0] = p->s; /* int */
+ uarg[1] = p->buf; /* uint32_t */
+ uarg[2] = p->len; /* uint32_t */
+ iarg[3] = p->flags; /* int */
+ uarg[4] = p->from; /* uint32_t */
+ uarg[5] = p->fromlenaddr; /* uint32_t */
+ *n_args = 6;
+ break;
+ }
+ /* accept */
+ case 30: {
+ struct accept_args *p = params;
+ iarg[0] = p->s; /* int */
+ uarg[1] = (intptr_t) p->name; /* caddr_t */
+ uarg[2] = (intptr_t) p->anamelen; /* int * */
+ *n_args = 3;
+ break;
+ }
+ /* getpeername */
+ case 31: {
+ struct getpeername_args *p = params;
+ iarg[0] = p->fdes; /* int */
+ uarg[1] = (intptr_t) p->asa; /* caddr_t */
+ uarg[2] = (intptr_t) p->alen; /* int * */
+ *n_args = 3;
+ break;
+ }
+ /* getsockname */
+ case 32: {
+ struct getsockname_args *p = params;
+ iarg[0] = p->fdes; /* int */
+ uarg[1] = (intptr_t) p->asa; /* caddr_t */
+ uarg[2] = (intptr_t) p->alen; /* int * */
+ *n_args = 3;
+ break;
+ }
+ /* access */
+ case 33: {
+ struct access_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ iarg[1] = p->amode; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* chflags */
+ case 34: {
+ struct chflags_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ uarg[1] = p->flags; /* u_long */
+ *n_args = 2;
+ break;
+ }
+ /* fchflags */
+ case 35: {
+ struct fchflags_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = p->flags; /* u_long */
+ *n_args = 2;
+ break;
+ }
+ /* sync */
+ case 36: {
+ *n_args = 0;
+ break;
+ }
+ /* kill */
+ case 37: {
+ struct kill_args *p = params;
+ iarg[0] = p->pid; /* int */
+ iarg[1] = p->signum; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* getppid */
+ case 39: {
+ *n_args = 0;
+ break;
+ }
+ /* dup */
+ case 41: {
+ struct dup_args *p = params;
+ uarg[0] = p->fd; /* u_int */
+ *n_args = 1;
+ break;
+ }
+ /* pipe */
+ case 42: {
+ *n_args = 0;
+ break;
+ }
+ /* getegid */
+ case 43: {
+ *n_args = 0;
+ break;
+ }
+ /* profil */
+ case 44: {
+ struct profil_args *p = params;
+ uarg[0] = (intptr_t) p->samples; /* caddr_t */
+ uarg[1] = p->size; /* size_t */
+ uarg[2] = p->offset; /* size_t */
+ uarg[3] = p->scale; /* u_int */
+ *n_args = 4;
+ break;
+ }
+ /* ktrace */
+ case 45: {
+ struct ktrace_args *p = params;
+ uarg[0] = (intptr_t) p->fname; /* const char * */
+ iarg[1] = p->ops; /* int */
+ iarg[2] = p->facs; /* int */
+ iarg[3] = p->pid; /* int */
+ *n_args = 4;
+ break;
+ }
+ /* getgid */
+ case 47: {
+ *n_args = 0;
+ break;
+ }
+ /* getlogin */
+ case 49: {
+ struct getlogin_args *p = params;
+ uarg[0] = (intptr_t) p->namebuf; /* char * */
+ uarg[1] = p->namelen; /* u_int */
+ *n_args = 2;
+ break;
+ }
+ /* setlogin */
+ case 50: {
+ struct setlogin_args *p = params;
+ uarg[0] = (intptr_t) p->namebuf; /* char * */
+ *n_args = 1;
+ break;
+ }
+ /* acct */
+ case 51: {
+ struct acct_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_sigaltstack */
+ case 53: {
+ struct freebsd32_sigaltstack_args *p = params;
+ uarg[0] = (intptr_t) p->ss; /* struct sigaltstack32 * */
+ uarg[1] = (intptr_t) p->oss; /* struct sigaltstack32 * */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_ioctl */
+ case 54: {
+ struct freebsd32_ioctl_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = p->com; /* uint32_t */
+ uarg[2] = (intptr_t) p->data; /* struct md_ioctl32 * */
+ *n_args = 3;
+ break;
+ }
+ /* reboot */
+ case 55: {
+ struct reboot_args *p = params;
+ iarg[0] = p->opt; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* revoke */
+ case 56: {
+ struct revoke_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ *n_args = 1;
+ break;
+ }
+ /* symlink */
+ case 57: {
+ struct symlink_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ uarg[1] = (intptr_t) p->link; /* char * */
+ *n_args = 2;
+ break;
+ }
+ /* readlink */
+ case 58: {
+ struct readlink_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ uarg[1] = (intptr_t) p->buf; /* char * */
+ uarg[2] = p->count; /* size_t */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_execve */
+ case 59: {
+ struct freebsd32_execve_args *p = params;
+ uarg[0] = (intptr_t) p->fname; /* char * */
+ uarg[1] = (intptr_t) p->argv; /* uint32_t * */
+ uarg[2] = (intptr_t) p->envv; /* uint32_t * */
+ *n_args = 3;
+ break;
+ }
+ /* umask */
+ case 60: {
+ struct umask_args *p = params;
+ iarg[0] = p->newmask; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* chroot */
+ case 61: {
+ struct chroot_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ *n_args = 1;
+ break;
+ }
+ /* msync */
+ case 65: {
+ struct msync_args *p = params;
+ uarg[0] = (intptr_t) p->addr; /* void * */
+ uarg[1] = p->len; /* size_t */
+ iarg[2] = p->flags; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* vfork */
+ case 66: {
+ *n_args = 0;
+ break;
+ }
+ /* sbrk */
+ case 69: {
+ struct sbrk_args *p = params;
+ iarg[0] = p->incr; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* sstk */
+ case 70: {
+ struct sstk_args *p = params;
+ iarg[0] = p->incr; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* ovadvise */
+ case 72: {
+ struct ovadvise_args *p = params;
+ iarg[0] = p->anom; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* munmap */
+ case 73: {
+ struct munmap_args *p = params;
+ uarg[0] = (intptr_t) p->addr; /* void * */
+ uarg[1] = p->len; /* size_t */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_mprotect */
+ case 74: {
+ struct freebsd32_mprotect_args *p = params;
+ uarg[0] = (intptr_t) p->addr; /* const void * */
+ uarg[1] = p->len; /* size_t */
+ iarg[2] = p->prot; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* madvise */
+ case 75: {
+ struct madvise_args *p = params;
+ uarg[0] = (intptr_t) p->addr; /* void * */
+ uarg[1] = p->len; /* size_t */
+ iarg[2] = p->behav; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* mincore */
+ case 78: {
+ struct mincore_args *p = params;
+ uarg[0] = (intptr_t) p->addr; /* const void * */
+ uarg[1] = p->len; /* size_t */
+ uarg[2] = (intptr_t) p->vec; /* char * */
+ *n_args = 3;
+ break;
+ }
+ /* getgroups */
+ case 79: {
+ struct getgroups_args *p = params;
+ uarg[0] = p->gidsetsize; /* u_int */
+ uarg[1] = (intptr_t) p->gidset; /* gid_t * */
+ *n_args = 2;
+ break;
+ }
+ /* setgroups */
+ case 80: {
+ struct setgroups_args *p = params;
+ uarg[0] = p->gidsetsize; /* u_int */
+ uarg[1] = (intptr_t) p->gidset; /* gid_t * */
+ *n_args = 2;
+ break;
+ }
+ /* getpgrp */
+ case 81: {
+ *n_args = 0;
+ break;
+ }
+ /* setpgid */
+ case 82: {
+ struct setpgid_args *p = params;
+ iarg[0] = p->pid; /* int */
+ iarg[1] = p->pgid; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_setitimer */
+ case 83: {
+ struct freebsd32_setitimer_args *p = params;
+ uarg[0] = p->which; /* u_int */
+ uarg[1] = (intptr_t) p->itv; /* struct itimerval32 * */
+ uarg[2] = (intptr_t) p->oitv; /* struct itimerval32 * */
+ *n_args = 3;
+ break;
+ }
+ /* swapon */
+ case 85: {
+ struct swapon_args *p = params;
+ uarg[0] = (intptr_t) p->name; /* char * */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_getitimer */
+ case 86: {
+ struct freebsd32_getitimer_args *p = params;
+ uarg[0] = p->which; /* u_int */
+ uarg[1] = (intptr_t) p->itv; /* struct itimerval32 * */
+ *n_args = 2;
+ break;
+ }
+ /* getdtablesize */
+ case 89: {
+ *n_args = 0;
+ break;
+ }
+ /* dup2 */
+ case 90: {
+ struct dup2_args *p = params;
+ uarg[0] = p->from; /* u_int */
+ uarg[1] = p->to; /* u_int */
+ *n_args = 2;
+ break;
+ }
+ /* fcntl */
+ case 92: {
+ struct fcntl_args *p = params;
+ iarg[0] = p->fd; /* int */
+ iarg[1] = p->cmd; /* int */
+ iarg[2] = p->arg; /* long */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_select */
+ case 93: {
+ struct freebsd32_select_args *p = params;
+ iarg[0] = p->nd; /* int */
+ uarg[1] = (intptr_t) p->in; /* fd_set * */
+ uarg[2] = (intptr_t) p->ou; /* fd_set * */
+ uarg[3] = (intptr_t) p->ex; /* fd_set * */
+ uarg[4] = (intptr_t) p->tv; /* struct timeval32 * */
+ *n_args = 5;
+ break;
+ }
+ /* fsync */
+ case 95: {
+ struct fsync_args *p = params;
+ iarg[0] = p->fd; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* setpriority */
+ case 96: {
+ struct setpriority_args *p = params;
+ iarg[0] = p->which; /* int */
+ iarg[1] = p->who; /* int */
+ iarg[2] = p->prio; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* socket */
+ case 97: {
+ struct socket_args *p = params;
+ iarg[0] = p->domain; /* int */
+ iarg[1] = p->type; /* int */
+ iarg[2] = p->protocol; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* connect */
+ case 98: {
+ struct connect_args *p = params;
+ iarg[0] = p->s; /* int */
+ uarg[1] = (intptr_t) p->name; /* caddr_t */
+ iarg[2] = p->namelen; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* getpriority */
+ case 100: {
+ struct getpriority_args *p = params;
+ iarg[0] = p->which; /* int */
+ iarg[1] = p->who; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* bind */
+ case 104: {
+ struct bind_args *p = params;
+ iarg[0] = p->s; /* int */
+ uarg[1] = (intptr_t) p->name; /* caddr_t */
+ iarg[2] = p->namelen; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* setsockopt */
+ case 105: {
+ struct setsockopt_args *p = params;
+ iarg[0] = p->s; /* int */
+ iarg[1] = p->level; /* int */
+ iarg[2] = p->name; /* int */
+ uarg[3] = (intptr_t) p->val; /* caddr_t */
+ iarg[4] = p->valsize; /* int */
+ *n_args = 5;
+ break;
+ }
+ /* listen */
+ case 106: {
+ struct listen_args *p = params;
+ iarg[0] = p->s; /* int */
+ iarg[1] = p->backlog; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_gettimeofday */
+ case 116: {
+ struct freebsd32_gettimeofday_args *p = params;
+ uarg[0] = (intptr_t) p->tp; /* struct timeval32 * */
+ uarg[1] = (intptr_t) p->tzp; /* struct timezone * */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_getrusage */
+ case 117: {
+ struct freebsd32_getrusage_args *p = params;
+ iarg[0] = p->who; /* int */
+ uarg[1] = (intptr_t) p->rusage; /* struct rusage32 * */
+ *n_args = 2;
+ break;
+ }
+ /* getsockopt */
+ case 118: {
+ struct getsockopt_args *p = params;
+ iarg[0] = p->s; /* int */
+ iarg[1] = p->level; /* int */
+ iarg[2] = p->name; /* int */
+ uarg[3] = (intptr_t) p->val; /* caddr_t */
+ uarg[4] = (intptr_t) p->avalsize; /* int * */
+ *n_args = 5;
+ break;
+ }
+ /* freebsd32_readv */
+ case 120: {
+ struct freebsd32_readv_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->iovp; /* struct iovec32 * */
+ uarg[2] = p->iovcnt; /* u_int */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_writev */
+ case 121: {
+ struct freebsd32_writev_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->iovp; /* struct iovec32 * */
+ uarg[2] = p->iovcnt; /* u_int */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_settimeofday */
+ case 122: {
+ struct freebsd32_settimeofday_args *p = params;
+ uarg[0] = (intptr_t) p->tv; /* struct timeval32 * */
+ uarg[1] = (intptr_t) p->tzp; /* struct timezone * */
+ *n_args = 2;
+ break;
+ }
+ /* fchown */
+ case 123: {
+ struct fchown_args *p = params;
+ iarg[0] = p->fd; /* int */
+ iarg[1] = p->uid; /* int */
+ iarg[2] = p->gid; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* fchmod */
+ case 124: {
+ struct fchmod_args *p = params;
+ iarg[0] = p->fd; /* int */
+ iarg[1] = p->mode; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* setreuid */
+ case 126: {
+ struct setreuid_args *p = params;
+ iarg[0] = p->ruid; /* int */
+ iarg[1] = p->euid; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* setregid */
+ case 127: {
+ struct setregid_args *p = params;
+ iarg[0] = p->rgid; /* int */
+ iarg[1] = p->egid; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* rename */
+ case 128: {
+ struct rename_args *p = params;
+ uarg[0] = (intptr_t) p->from; /* char * */
+ uarg[1] = (intptr_t) p->to; /* char * */
+ *n_args = 2;
+ break;
+ }
+ /* flock */
+ case 131: {
+ struct flock_args *p = params;
+ iarg[0] = p->fd; /* int */
+ iarg[1] = p->how; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* mkfifo */
+ case 132: {
+ struct mkfifo_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ iarg[1] = p->mode; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* sendto */
+ case 133: {
+ struct sendto_args *p = params;
+ iarg[0] = p->s; /* int */
+ uarg[1] = (intptr_t) p->buf; /* caddr_t */
+ uarg[2] = p->len; /* size_t */
+ iarg[3] = p->flags; /* int */
+ uarg[4] = (intptr_t) p->to; /* caddr_t */
+ iarg[5] = p->tolen; /* int */
+ *n_args = 6;
+ break;
+ }
+ /* shutdown */
+ case 134: {
+ struct shutdown_args *p = params;
+ iarg[0] = p->s; /* int */
+ iarg[1] = p->how; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* socketpair */
+ case 135: {
+ struct socketpair_args *p = params;
+ iarg[0] = p->domain; /* int */
+ iarg[1] = p->type; /* int */
+ iarg[2] = p->protocol; /* int */
+ uarg[3] = (intptr_t) p->rsv; /* int * */
+ *n_args = 4;
+ break;
+ }
+ /* mkdir */
+ case 136: {
+ struct mkdir_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ iarg[1] = p->mode; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* rmdir */
+ case 137: {
+ struct rmdir_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_utimes */
+ case 138: {
+ struct freebsd32_utimes_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ uarg[1] = (intptr_t) p->tptr; /* struct timeval32 * */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_adjtime */
+ case 140: {
+ struct freebsd32_adjtime_args *p = params;
+ uarg[0] = (intptr_t) p->delta; /* struct timeval32 * */
+ uarg[1] = (intptr_t) p->olddelta; /* struct timeval32 * */
+ *n_args = 2;
+ break;
+ }
+ /* setsid */
+ case 147: {
+ *n_args = 0;
+ break;
+ }
+ /* quotactl */
+ case 148: {
+ struct quotactl_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ iarg[1] = p->cmd; /* int */
+ iarg[2] = p->uid; /* int */
+ uarg[3] = (intptr_t) p->arg; /* caddr_t */
+ *n_args = 4;
+ break;
+ }
+ /* getfh */
+ case 161: {
+ struct getfh_args *p = params;
+ uarg[0] = (intptr_t) p->fname; /* char * */
+ uarg[1] = (intptr_t) p->fhp; /* struct fhandle * */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_sysarch */
+ case 165: {
+ struct freebsd32_sysarch_args *p = params;
+ iarg[0] = p->op; /* int */
+ uarg[1] = (intptr_t) p->parms; /* char * */
+ *n_args = 2;
+ break;
+ }
+ /* rtprio */
+ case 166: {
+ struct rtprio_args *p = params;
+ iarg[0] = p->function; /* int */
+ iarg[1] = p->pid; /* pid_t */
+ uarg[2] = (intptr_t) p->rtp; /* struct rtprio * */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_semsys */
+ case 169: {
+ struct freebsd32_semsys_args *p = params;
+ iarg[0] = p->which; /* int */
+ iarg[1] = p->a2; /* int */
+ iarg[2] = p->a3; /* int */
+ iarg[3] = p->a4; /* int */
+ iarg[4] = p->a5; /* int */
+ *n_args = 5;
+ break;
+ }
+ /* freebsd32_msgsys */
+ case 170: {
+ struct freebsd32_msgsys_args *p = params;
+ iarg[0] = p->which; /* int */
+ iarg[1] = p->a2; /* int */
+ iarg[2] = p->a3; /* int */
+ iarg[3] = p->a4; /* int */
+ iarg[4] = p->a5; /* int */
+ iarg[5] = p->a6; /* int */
+ *n_args = 6;
+ break;
+ }
+ /* freebsd32_shmsys */
+ case 171: {
+ struct freebsd32_shmsys_args *p = params;
+ uarg[0] = p->which; /* uint32_t */
+ uarg[1] = p->a2; /* uint32_t */
+ uarg[2] = p->a3; /* uint32_t */
+ uarg[3] = p->a4; /* uint32_t */
+ *n_args = 4;
+ break;
+ }
+ /* ntp_adjtime */
+ case 176: {
+ struct ntp_adjtime_args *p = params;
+ uarg[0] = (intptr_t) p->tp; /* struct timex * */
+ *n_args = 1;
+ break;
+ }
+ /* setgid */
+ case 181: {
+ struct setgid_args *p = params;
+ iarg[0] = p->gid; /* gid_t */
+ *n_args = 1;
+ break;
+ }
+ /* setegid */
+ case 182: {
+ struct setegid_args *p = params;
+ iarg[0] = p->egid; /* gid_t */
+ *n_args = 1;
+ break;
+ }
+ /* seteuid */
+ case 183: {
+ struct seteuid_args *p = params;
+ uarg[0] = p->euid; /* uid_t */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_stat */
+ case 188: {
+ struct freebsd32_stat_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ uarg[1] = (intptr_t) p->ub; /* struct stat32 * */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_fstat */
+ case 189: {
+ struct freebsd32_fstat_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->ub; /* struct stat32 * */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_lstat */
+ case 190: {
+ struct freebsd32_lstat_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ uarg[1] = (intptr_t) p->ub; /* struct stat32 * */
+ *n_args = 2;
+ break;
+ }
+ /* pathconf */
+ case 191: {
+ struct pathconf_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ iarg[1] = p->name; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* fpathconf */
+ case 192: {
+ struct fpathconf_args *p = params;
+ iarg[0] = p->fd; /* int */
+ iarg[1] = p->name; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* getrlimit */
+ case 194: {
+ struct __getrlimit_args *p = params;
+ uarg[0] = p->which; /* u_int */
+ uarg[1] = (intptr_t) p->rlp; /* struct rlimit * */
+ *n_args = 2;
+ break;
+ }
+ /* setrlimit */
+ case 195: {
+ struct __setrlimit_args *p = params;
+ uarg[0] = p->which; /* u_int */
+ uarg[1] = (intptr_t) p->rlp; /* struct rlimit * */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_getdirentries */
+ case 196: {
+ struct freebsd32_getdirentries_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->buf; /* char * */
+ uarg[2] = p->count; /* u_int */
+ uarg[3] = (intptr_t) p->basep; /* int32_t * */
+ *n_args = 4;
+ break;
+ }
+ /* nosys */
+ case 198: {
+ *n_args = 0;
+ break;
+ }
+ /* freebsd32_sysctl */
+ case 202: {
+ struct freebsd32_sysctl_args *p = params;
+ uarg[0] = (intptr_t) p->name; /* int * */
+ uarg[1] = p->namelen; /* u_int */
+ uarg[2] = (intptr_t) p->old; /* void * */
+ uarg[3] = (intptr_t) p->oldlenp; /* uint32_t * */
+ uarg[4] = (intptr_t) p->new; /* void * */
+ uarg[5] = p->newlen; /* uint32_t */
+ *n_args = 6;
+ break;
+ }
+ /* mlock */
+ case 203: {
+ struct mlock_args *p = params;
+ uarg[0] = (intptr_t) p->addr; /* const void * */
+ uarg[1] = p->len; /* size_t */
+ *n_args = 2;
+ break;
+ }
+ /* munlock */
+ case 204: {
+ struct munlock_args *p = params;
+ uarg[0] = (intptr_t) p->addr; /* const void * */
+ uarg[1] = p->len; /* size_t */
+ *n_args = 2;
+ break;
+ }
+ /* undelete */
+ case 205: {
+ struct undelete_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_futimes */
+ case 206: {
+ struct freebsd32_futimes_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->tptr; /* struct timeval32 * */
+ *n_args = 2;
+ break;
+ }
+ /* getpgid */
+ case 207: {
+ struct getpgid_args *p = params;
+ iarg[0] = p->pid; /* pid_t */
+ *n_args = 1;
+ break;
+ }
+ /* poll */
+ case 209: {
+ struct poll_args *p = params;
+ uarg[0] = (intptr_t) p->fds; /* struct pollfd * */
+ uarg[1] = p->nfds; /* u_int */
+ iarg[2] = p->timeout; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* lkmnosys */
+ case 210: {
+ *n_args = 0;
+ break;
+ }
+ /* lkmnosys */
+ case 211: {
+ *n_args = 0;
+ break;
+ }
+ /* lkmnosys */
+ case 212: {
+ *n_args = 0;
+ break;
+ }
+ /* lkmnosys */
+ case 213: {
+ *n_args = 0;
+ break;
+ }
+ /* lkmnosys */
+ case 214: {
+ *n_args = 0;
+ break;
+ }
+ /* lkmnosys */
+ case 215: {
+ *n_args = 0;
+ break;
+ }
+ /* lkmnosys */
+ case 216: {
+ *n_args = 0;
+ break;
+ }
+ /* lkmnosys */
+ case 217: {
+ *n_args = 0;
+ break;
+ }
+ /* lkmnosys */
+ case 218: {
+ *n_args = 0;
+ break;
+ }
+ /* lkmnosys */
+ case 219: {
+ *n_args = 0;
+ break;
+ }
+ /* semget */
+ case 221: {
+ struct semget_args *p = params;
+ iarg[0] = p->key; /* key_t */
+ iarg[1] = p->nsems; /* int */
+ iarg[2] = p->semflg; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* semop */
+ case 222: {
+ struct semop_args *p = params;
+ iarg[0] = p->semid; /* int */
+ uarg[1] = (intptr_t) p->sops; /* struct sembuf * */
+ uarg[2] = p->nsops; /* u_int */
+ *n_args = 3;
+ break;
+ }
+ /* msgget */
+ case 225: {
+ struct msgget_args *p = params;
+ iarg[0] = p->key; /* key_t */
+ iarg[1] = p->msgflg; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_msgsnd */
+ case 226: {
+ struct freebsd32_msgsnd_args *p = params;
+ iarg[0] = p->msqid; /* int */
+ uarg[1] = (intptr_t) p->msgp; /* void * */
+ uarg[2] = p->msgsz; /* size_t */
+ iarg[3] = p->msgflg; /* int */
+ *n_args = 4;
+ break;
+ }
+ /* freebsd32_msgrcv */
+ case 227: {
+ struct freebsd32_msgrcv_args *p = params;
+ iarg[0] = p->msqid; /* int */
+ uarg[1] = (intptr_t) p->msgp; /* void * */
+ uarg[2] = p->msgsz; /* size_t */
+ iarg[3] = p->msgtyp; /* long */
+ iarg[4] = p->msgflg; /* int */
+ *n_args = 5;
+ break;
+ }
+ /* shmat */
+ case 228: {
+ struct shmat_args *p = params;
+ iarg[0] = p->shmid; /* int */
+ uarg[1] = (intptr_t) p->shmaddr; /* void * */
+ iarg[2] = p->shmflg; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* shmdt */
+ case 230: {
+ struct shmdt_args *p = params;
+ uarg[0] = (intptr_t) p->shmaddr; /* void * */
+ *n_args = 1;
+ break;
+ }
+ /* shmget */
+ case 231: {
+ struct shmget_args *p = params;
+ iarg[0] = p->key; /* key_t */
+ iarg[1] = p->size; /* int */
+ iarg[2] = p->shmflg; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_clock_gettime */
+ case 232: {
+ struct freebsd32_clock_gettime_args *p = params;
+ iarg[0] = p->clock_id; /* clockid_t */
+ uarg[1] = (intptr_t) p->tp; /* struct timespec32 * */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_clock_settime */
+ case 233: {
+ struct freebsd32_clock_settime_args *p = params;
+ iarg[0] = p->clock_id; /* clockid_t */
+ uarg[1] = (intptr_t) p->tp; /* const struct timespec32 * */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_clock_getres */
+ case 234: {
+ struct freebsd32_clock_getres_args *p = params;
+ iarg[0] = p->clock_id; /* clockid_t */
+ uarg[1] = (intptr_t) p->tp; /* struct timespec32 * */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_nanosleep */
+ case 240: {
+ struct freebsd32_nanosleep_args *p = params;
+ uarg[0] = (intptr_t) p->rqtp; /* const struct timespec32 * */
+ uarg[1] = (intptr_t) p->rmtp; /* struct timespec32 * */
+ *n_args = 2;
+ break;
+ }
+ /* ffclock_getcounter */
+ case 241: {
+ struct ffclock_getcounter_args *p = params;
+ uarg[0] = (intptr_t) p->ffcount; /* ffcounter * */
+ *n_args = 1;
+ break;
+ }
+ /* ffclock_setestimate */
+ case 242: {
+ struct ffclock_setestimate_args *p = params;
+ uarg[0] = (intptr_t) p->cest; /* struct ffclock_estimate * */
+ *n_args = 1;
+ break;
+ }
+ /* ffclock_getestimate */
+ case 243: {
+ struct ffclock_getestimate_args *p = params;
+ uarg[0] = (intptr_t) p->cest; /* struct ffclock_estimate * */
+ *n_args = 1;
+ break;
+ }
+ /* clock_getcpuclockid2 */
+ case 247: {
+ struct clock_getcpuclockid2_args *p = params;
+ iarg[0] = p->id; /* id_t */
+ iarg[1] = p->which; /* int */
+ uarg[2] = (intptr_t) p->clock_id; /* clockid_t * */
+ *n_args = 3;
+ break;
+ }
+ /* minherit */
+ case 250: {
+ struct minherit_args *p = params;
+ uarg[0] = (intptr_t) p->addr; /* void * */
+ uarg[1] = p->len; /* size_t */
+ iarg[2] = p->inherit; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* rfork */
+ case 251: {
+ struct rfork_args *p = params;
+ iarg[0] = p->flags; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* openbsd_poll */
+ case 252: {
+ struct openbsd_poll_args *p = params;
+ uarg[0] = (intptr_t) p->fds; /* struct pollfd * */
+ uarg[1] = p->nfds; /* u_int */
+ iarg[2] = p->timeout; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* issetugid */
+ case 253: {
+ *n_args = 0;
+ break;
+ }
+ /* lchown */
+ case 254: {
+ struct lchown_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ iarg[1] = p->uid; /* int */
+ iarg[2] = p->gid; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_aio_read */
+ case 255: {
+ struct freebsd32_aio_read_args *p = params;
+ uarg[0] = (intptr_t) p->aiocbp; /* struct aiocb32 * */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_aio_write */
+ case 256: {
+ struct freebsd32_aio_write_args *p = params;
+ uarg[0] = (intptr_t) p->aiocbp; /* struct aiocb32 * */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_lio_listio */
+ case 257: {
+ struct freebsd32_lio_listio_args *p = params;
+ iarg[0] = p->mode; /* int */
+ uarg[1] = (intptr_t) p->acb_list; /* struct aiocb32 *const * */
+ iarg[2] = p->nent; /* int */
+ uarg[3] = (intptr_t) p->sig; /* struct sigevent * */
+ *n_args = 4;
+ break;
+ }
+ /* getdents */
+ case 272: {
+ struct getdents_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->buf; /* char * */
+ uarg[2] = p->count; /* size_t */
+ *n_args = 3;
+ break;
+ }
+ /* lchmod */
+ case 274: {
+ struct lchmod_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ iarg[1] = p->mode; /* mode_t */
+ *n_args = 2;
+ break;
+ }
+ /* lchown */
+ case 275: {
+ struct lchown_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ uarg[1] = p->uid; /* uid_t */
+ iarg[2] = p->gid; /* gid_t */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_lutimes */
+ case 276: {
+ struct freebsd32_lutimes_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ uarg[1] = (intptr_t) p->tptr; /* struct timeval32 * */
+ *n_args = 2;
+ break;
+ }
+ /* msync */
+ case 277: {
+ struct msync_args *p = params;
+ uarg[0] = (intptr_t) p->addr; /* void * */
+ uarg[1] = p->len; /* size_t */
+ iarg[2] = p->flags; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* nstat */
+ case 278: {
+ struct nstat_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ uarg[1] = (intptr_t) p->ub; /* struct nstat * */
+ *n_args = 2;
+ break;
+ }
+ /* nfstat */
+ case 279: {
+ struct nfstat_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->sb; /* struct nstat * */
+ *n_args = 2;
+ break;
+ }
+ /* nlstat */
+ case 280: {
+ struct nlstat_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ uarg[1] = (intptr_t) p->ub; /* struct nstat * */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_preadv */
+ case 289: {
+ struct freebsd32_preadv_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->iovp; /* struct iovec32 * */
+ uarg[2] = p->iovcnt; /* u_int */
+ uarg[3] = p->offset1; /* uint32_t */
+ uarg[4] = p->offset2; /* uint32_t */
+ *n_args = 5;
+ break;
+ }
+ /* freebsd32_pwritev */
+ case 290: {
+ struct freebsd32_pwritev_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->iovp; /* struct iovec32 * */
+ uarg[2] = p->iovcnt; /* u_int */
+ uarg[3] = p->offset1; /* uint32_t */
+ uarg[4] = p->offset2; /* uint32_t */
+ *n_args = 5;
+ break;
+ }
+ /* fhopen */
+ case 298: {
+ struct fhopen_args *p = params;
+ uarg[0] = (intptr_t) p->u_fhp; /* const struct fhandle * */
+ iarg[1] = p->flags; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* fhstat */
+ case 299: {
+ struct fhstat_args *p = params;
+ uarg[0] = (intptr_t) p->u_fhp; /* const struct fhandle * */
+ uarg[1] = (intptr_t) p->sb; /* struct stat * */
+ *n_args = 2;
+ break;
+ }
+ /* modnext */
+ case 300: {
+ struct modnext_args *p = params;
+ iarg[0] = p->modid; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_modstat */
+ case 301: {
+ struct freebsd32_modstat_args *p = params;
+ iarg[0] = p->modid; /* int */
+ uarg[1] = (intptr_t) p->stat; /* struct module_stat32 * */
+ *n_args = 2;
+ break;
+ }
+ /* modfnext */
+ case 302: {
+ struct modfnext_args *p = params;
+ iarg[0] = p->modid; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* modfind */
+ case 303: {
+ struct modfind_args *p = params;
+ uarg[0] = (intptr_t) p->name; /* const char * */
+ *n_args = 1;
+ break;
+ }
+ /* kldload */
+ case 304: {
+ struct kldload_args *p = params;
+ uarg[0] = (intptr_t) p->file; /* const char * */
+ *n_args = 1;
+ break;
+ }
+ /* kldunload */
+ case 305: {
+ struct kldunload_args *p = params;
+ iarg[0] = p->fileid; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* kldfind */
+ case 306: {
+ struct kldfind_args *p = params;
+ uarg[0] = (intptr_t) p->file; /* const char * */
+ *n_args = 1;
+ break;
+ }
+ /* kldnext */
+ case 307: {
+ struct kldnext_args *p = params;
+ iarg[0] = p->fileid; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_kldstat */
+ case 308: {
+ struct freebsd32_kldstat_args *p = params;
+ iarg[0] = p->fileid; /* int */
+ uarg[1] = (intptr_t) p->stat; /* struct kld32_file_stat * */
+ *n_args = 2;
+ break;
+ }
+ /* kldfirstmod */
+ case 309: {
+ struct kldfirstmod_args *p = params;
+ iarg[0] = p->fileid; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* getsid */
+ case 310: {
+ struct getsid_args *p = params;
+ iarg[0] = p->pid; /* pid_t */
+ *n_args = 1;
+ break;
+ }
+ /* setresuid */
+ case 311: {
+ struct setresuid_args *p = params;
+ uarg[0] = p->ruid; /* uid_t */
+ uarg[1] = p->euid; /* uid_t */
+ uarg[2] = p->suid; /* uid_t */
+ *n_args = 3;
+ break;
+ }
+ /* setresgid */
+ case 312: {
+ struct setresgid_args *p = params;
+ iarg[0] = p->rgid; /* gid_t */
+ iarg[1] = p->egid; /* gid_t */
+ iarg[2] = p->sgid; /* gid_t */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_aio_return */
+ case 314: {
+ struct freebsd32_aio_return_args *p = params;
+ uarg[0] = (intptr_t) p->aiocbp; /* struct aiocb32 * */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_aio_suspend */
+ case 315: {
+ struct freebsd32_aio_suspend_args *p = params;
+ uarg[0] = (intptr_t) p->aiocbp; /* struct aiocb32 *const * */
+ iarg[1] = p->nent; /* int */
+ uarg[2] = (intptr_t) p->timeout; /* const struct timespec32 * */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_aio_cancel */
+ case 316: {
+ struct freebsd32_aio_cancel_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->aiocbp; /* struct aiocb32 * */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_aio_error */
+ case 317: {
+ struct freebsd32_aio_error_args *p = params;
+ uarg[0] = (intptr_t) p->aiocbp; /* struct aiocb32 * */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_oaio_read */
+ case 318: {
+ struct freebsd32_oaio_read_args *p = params;
+ uarg[0] = (intptr_t) p->aiocbp; /* struct oaiocb32 * */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_oaio_write */
+ case 319: {
+ struct freebsd32_oaio_write_args *p = params;
+ uarg[0] = (intptr_t) p->aiocbp; /* struct oaiocb32 * */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_olio_listio */
+ case 320: {
+ struct freebsd32_olio_listio_args *p = params;
+ iarg[0] = p->mode; /* int */
+ uarg[1] = (intptr_t) p->acb_list; /* struct oaiocb32 *const * */
+ iarg[2] = p->nent; /* int */
+ uarg[3] = (intptr_t) p->sig; /* struct osigevent32 * */
+ *n_args = 4;
+ break;
+ }
+ /* yield */
+ case 321: {
+ *n_args = 0;
+ break;
+ }
+ /* mlockall */
+ case 324: {
+ struct mlockall_args *p = params;
+ iarg[0] = p->how; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* munlockall */
+ case 325: {
+ *n_args = 0;
+ break;
+ }
+ /* __getcwd */
+ case 326: {
+ struct __getcwd_args *p = params;
+ uarg[0] = (intptr_t) p->buf; /* u_char * */
+ uarg[1] = p->buflen; /* u_int */
+ *n_args = 2;
+ break;
+ }
+ /* sched_setparam */
+ case 327: {
+ struct sched_setparam_args *p = params;
+ iarg[0] = p->pid; /* pid_t */
+ uarg[1] = (intptr_t) p->param; /* const struct sched_param * */
+ *n_args = 2;
+ break;
+ }
+ /* sched_getparam */
+ case 328: {
+ struct sched_getparam_args *p = params;
+ iarg[0] = p->pid; /* pid_t */
+ uarg[1] = (intptr_t) p->param; /* struct sched_param * */
+ *n_args = 2;
+ break;
+ }
+ /* sched_setscheduler */
+ case 329: {
+ struct sched_setscheduler_args *p = params;
+ iarg[0] = p->pid; /* pid_t */
+ iarg[1] = p->policy; /* int */
+ uarg[2] = (intptr_t) p->param; /* const struct sched_param * */
+ *n_args = 3;
+ break;
+ }
+ /* sched_getscheduler */
+ case 330: {
+ struct sched_getscheduler_args *p = params;
+ iarg[0] = p->pid; /* pid_t */
+ *n_args = 1;
+ break;
+ }
+ /* sched_yield */
+ case 331: {
+ *n_args = 0;
+ break;
+ }
+ /* sched_get_priority_max */
+ case 332: {
+ struct sched_get_priority_max_args *p = params;
+ iarg[0] = p->policy; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* sched_get_priority_min */
+ case 333: {
+ struct sched_get_priority_min_args *p = params;
+ iarg[0] = p->policy; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* sched_rr_get_interval */
+ case 334: {
+ struct sched_rr_get_interval_args *p = params;
+ iarg[0] = p->pid; /* pid_t */
+ uarg[1] = (intptr_t) p->interval; /* struct timespec * */
+ *n_args = 2;
+ break;
+ }
+ /* utrace */
+ case 335: {
+ struct utrace_args *p = params;
+ uarg[0] = (intptr_t) p->addr; /* const void * */
+ uarg[1] = p->len; /* size_t */
+ *n_args = 2;
+ break;
+ }
+ /* kldsym */
+ case 337: {
+ struct kldsym_args *p = params;
+ iarg[0] = p->fileid; /* int */
+ iarg[1] = p->cmd; /* int */
+ uarg[2] = (intptr_t) p->data; /* void * */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_jail */
+ case 338: {
+ struct freebsd32_jail_args *p = params;
+ uarg[0] = (intptr_t) p->jail; /* struct jail32 * */
+ *n_args = 1;
+ break;
+ }
+ /* sigprocmask */
+ case 340: {
+ struct sigprocmask_args *p = params;
+ iarg[0] = p->how; /* int */
+ uarg[1] = (intptr_t) p->set; /* const sigset_t * */
+ uarg[2] = (intptr_t) p->oset; /* sigset_t * */
+ *n_args = 3;
+ break;
+ }
+ /* sigsuspend */
+ case 341: {
+ struct sigsuspend_args *p = params;
+ uarg[0] = (intptr_t) p->sigmask; /* const sigset_t * */
+ *n_args = 1;
+ break;
+ }
+ /* sigpending */
+ case 343: {
+ struct sigpending_args *p = params;
+ uarg[0] = (intptr_t) p->set; /* sigset_t * */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_sigtimedwait */
+ case 345: {
+ struct freebsd32_sigtimedwait_args *p = params;
+ uarg[0] = (intptr_t) p->set; /* const sigset_t * */
+ uarg[1] = (intptr_t) p->info; /* siginfo_t * */
+ uarg[2] = (intptr_t) p->timeout; /* const struct timespec * */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_sigwaitinfo */
+ case 346: {
+ struct freebsd32_sigwaitinfo_args *p = params;
+ uarg[0] = (intptr_t) p->set; /* const sigset_t * */
+ uarg[1] = (intptr_t) p->info; /* siginfo_t * */
+ *n_args = 2;
+ break;
+ }
+ /* __acl_get_file */
+ case 347: {
+ struct __acl_get_file_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ iarg[1] = p->type; /* acl_type_t */
+ uarg[2] = (intptr_t) p->aclp; /* struct acl * */
+ *n_args = 3;
+ break;
+ }
+ /* __acl_set_file */
+ case 348: {
+ struct __acl_set_file_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ iarg[1] = p->type; /* acl_type_t */
+ uarg[2] = (intptr_t) p->aclp; /* struct acl * */
+ *n_args = 3;
+ break;
+ }
+ /* __acl_get_fd */
+ case 349: {
+ struct __acl_get_fd_args *p = params;
+ iarg[0] = p->filedes; /* int */
+ iarg[1] = p->type; /* acl_type_t */
+ uarg[2] = (intptr_t) p->aclp; /* struct acl * */
+ *n_args = 3;
+ break;
+ }
+ /* __acl_set_fd */
+ case 350: {
+ struct __acl_set_fd_args *p = params;
+ iarg[0] = p->filedes; /* int */
+ iarg[1] = p->type; /* acl_type_t */
+ uarg[2] = (intptr_t) p->aclp; /* struct acl * */
+ *n_args = 3;
+ break;
+ }
+ /* __acl_delete_file */
+ case 351: {
+ struct __acl_delete_file_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ iarg[1] = p->type; /* acl_type_t */
+ *n_args = 2;
+ break;
+ }
+ /* __acl_delete_fd */
+ case 352: {
+ struct __acl_delete_fd_args *p = params;
+ iarg[0] = p->filedes; /* int */
+ iarg[1] = p->type; /* acl_type_t */
+ *n_args = 2;
+ break;
+ }
+ /* __acl_aclcheck_file */
+ case 353: {
+ struct __acl_aclcheck_file_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ iarg[1] = p->type; /* acl_type_t */
+ uarg[2] = (intptr_t) p->aclp; /* struct acl * */
+ *n_args = 3;
+ break;
+ }
+ /* __acl_aclcheck_fd */
+ case 354: {
+ struct __acl_aclcheck_fd_args *p = params;
+ iarg[0] = p->filedes; /* int */
+ iarg[1] = p->type; /* acl_type_t */
+ uarg[2] = (intptr_t) p->aclp; /* struct acl * */
+ *n_args = 3;
+ break;
+ }
+ /* extattrctl */
+ case 355: {
+ struct extattrctl_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ iarg[1] = p->cmd; /* int */
+ uarg[2] = (intptr_t) p->filename; /* const char * */
+ iarg[3] = p->attrnamespace; /* int */
+ uarg[4] = (intptr_t) p->attrname; /* const char * */
+ *n_args = 5;
+ break;
+ }
+ /* extattr_set_file */
+ case 356: {
+ struct extattr_set_file_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ iarg[1] = p->attrnamespace; /* int */
+ uarg[2] = (intptr_t) p->attrname; /* const char * */
+ uarg[3] = (intptr_t) p->data; /* void * */
+ uarg[4] = p->nbytes; /* size_t */
+ *n_args = 5;
+ break;
+ }
+ /* extattr_get_file */
+ case 357: {
+ struct extattr_get_file_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ iarg[1] = p->attrnamespace; /* int */
+ uarg[2] = (intptr_t) p->attrname; /* const char * */
+ uarg[3] = (intptr_t) p->data; /* void * */
+ uarg[4] = p->nbytes; /* size_t */
+ *n_args = 5;
+ break;
+ }
+ /* extattr_delete_file */
+ case 358: {
+ struct extattr_delete_file_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ iarg[1] = p->attrnamespace; /* int */
+ uarg[2] = (intptr_t) p->attrname; /* const char * */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_aio_waitcomplete */
+ case 359: {
+ struct freebsd32_aio_waitcomplete_args *p = params;
+ uarg[0] = (intptr_t) p->aiocbp; /* struct aiocb32 ** */
+ uarg[1] = (intptr_t) p->timeout; /* struct timespec32 * */
+ *n_args = 2;
+ break;
+ }
+ /* getresuid */
+ case 360: {
+ struct getresuid_args *p = params;
+ uarg[0] = (intptr_t) p->ruid; /* uid_t * */
+ uarg[1] = (intptr_t) p->euid; /* uid_t * */
+ uarg[2] = (intptr_t) p->suid; /* uid_t * */
+ *n_args = 3;
+ break;
+ }
+ /* getresgid */
+ case 361: {
+ struct getresgid_args *p = params;
+ uarg[0] = (intptr_t) p->rgid; /* gid_t * */
+ uarg[1] = (intptr_t) p->egid; /* gid_t * */
+ uarg[2] = (intptr_t) p->sgid; /* gid_t * */
+ *n_args = 3;
+ break;
+ }
+ /* kqueue */
+ case 362: {
+ *n_args = 0;
+ break;
+ }
+ /* freebsd32_kevent */
+ case 363: {
+ struct freebsd32_kevent_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->changelist; /* const struct kevent32 * */
+ iarg[2] = p->nchanges; /* int */
+ uarg[3] = (intptr_t) p->eventlist; /* struct kevent32 * */
+ iarg[4] = p->nevents; /* int */
+ uarg[5] = (intptr_t) p->timeout; /* const struct timespec32 * */
+ *n_args = 6;
+ break;
+ }
+ /* extattr_set_fd */
+ case 371: {
+ struct extattr_set_fd_args *p = params;
+ iarg[0] = p->fd; /* int */
+ iarg[1] = p->attrnamespace; /* int */
+ uarg[2] = (intptr_t) p->attrname; /* const char * */
+ uarg[3] = (intptr_t) p->data; /* void * */
+ uarg[4] = p->nbytes; /* size_t */
+ *n_args = 5;
+ break;
+ }
+ /* extattr_get_fd */
+ case 372: {
+ struct extattr_get_fd_args *p = params;
+ iarg[0] = p->fd; /* int */
+ iarg[1] = p->attrnamespace; /* int */
+ uarg[2] = (intptr_t) p->attrname; /* const char * */
+ uarg[3] = (intptr_t) p->data; /* void * */
+ uarg[4] = p->nbytes; /* size_t */
+ *n_args = 5;
+ break;
+ }
+ /* extattr_delete_fd */
+ case 373: {
+ struct extattr_delete_fd_args *p = params;
+ iarg[0] = p->fd; /* int */
+ iarg[1] = p->attrnamespace; /* int */
+ uarg[2] = (intptr_t) p->attrname; /* const char * */
+ *n_args = 3;
+ break;
+ }
+ /* __setugid */
+ case 374: {
+ struct __setugid_args *p = params;
+ iarg[0] = p->flag; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* eaccess */
+ case 376: {
+ struct eaccess_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ iarg[1] = p->amode; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_nmount */
+ case 378: {
+ struct freebsd32_nmount_args *p = params;
+ uarg[0] = (intptr_t) p->iovp; /* struct iovec32 * */
+ uarg[1] = p->iovcnt; /* unsigned int */
+ iarg[2] = p->flags; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* kenv */
+ case 390: {
+ struct kenv_args *p = params;
+ iarg[0] = p->what; /* int */
+ uarg[1] = (intptr_t) p->name; /* const char * */
+ uarg[2] = (intptr_t) p->value; /* char * */
+ iarg[3] = p->len; /* int */
+ *n_args = 4;
+ break;
+ }
+ /* lchflags */
+ case 391: {
+ struct lchflags_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ uarg[1] = p->flags; /* u_long */
+ *n_args = 2;
+ break;
+ }
+ /* uuidgen */
+ case 392: {
+ struct uuidgen_args *p = params;
+ uarg[0] = (intptr_t) p->store; /* struct uuid * */
+ iarg[1] = p->count; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_sendfile */
+ case 393: {
+ struct freebsd32_sendfile_args *p = params;
+ iarg[0] = p->fd; /* int */
+ iarg[1] = p->s; /* int */
+ uarg[2] = p->offset1; /* uint32_t */
+ uarg[3] = p->offset2; /* uint32_t */
+ uarg[4] = p->nbytes; /* size_t */
+ uarg[5] = (intptr_t) p->hdtr; /* struct sf_hdtr32 * */
+ uarg[6] = (intptr_t) p->sbytes; /* off_t * */
+ iarg[7] = p->flags; /* int */
+ *n_args = 8;
+ break;
+ }
+ /* getfsstat */
+ case 395: {
+ struct getfsstat_args *p = params;
+ uarg[0] = (intptr_t) p->buf; /* struct statfs * */
+ iarg[1] = p->bufsize; /* long */
+ iarg[2] = p->flags; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* statfs */
+ case 396: {
+ struct statfs_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ uarg[1] = (intptr_t) p->buf; /* struct statfs * */
+ *n_args = 2;
+ break;
+ }
+ /* fstatfs */
+ case 397: {
+ struct fstatfs_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->buf; /* struct statfs * */
+ *n_args = 2;
+ break;
+ }
+ /* fhstatfs */
+ case 398: {
+ struct fhstatfs_args *p = params;
+ uarg[0] = (intptr_t) p->u_fhp; /* const struct fhandle * */
+ uarg[1] = (intptr_t) p->buf; /* struct statfs * */
+ *n_args = 2;
+ break;
+ }
+ /* ksem_close */
+ case 400: {
+ struct ksem_close_args *p = params;
+ iarg[0] = p->id; /* semid_t */
+ *n_args = 1;
+ break;
+ }
+ /* ksem_post */
+ case 401: {
+ struct ksem_post_args *p = params;
+ iarg[0] = p->id; /* semid_t */
+ *n_args = 1;
+ break;
+ }
+ /* ksem_wait */
+ case 402: {
+ struct ksem_wait_args *p = params;
+ iarg[0] = p->id; /* semid_t */
+ *n_args = 1;
+ break;
+ }
+ /* ksem_trywait */
+ case 403: {
+ struct ksem_trywait_args *p = params;
+ iarg[0] = p->id; /* semid_t */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_ksem_init */
+ case 404: {
+ struct freebsd32_ksem_init_args *p = params;
+ uarg[0] = (intptr_t) p->idp; /* semid_t * */
+ uarg[1] = p->value; /* unsigned int */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_ksem_open */
+ case 405: {
+ struct freebsd32_ksem_open_args *p = params;
+ uarg[0] = (intptr_t) p->idp; /* semid_t * */
+ uarg[1] = (intptr_t) p->name; /* const char * */
+ iarg[2] = p->oflag; /* int */
+ iarg[3] = p->mode; /* mode_t */
+ uarg[4] = p->value; /* unsigned int */
+ *n_args = 5;
+ break;
+ }
+ /* ksem_unlink */
+ case 406: {
+ struct ksem_unlink_args *p = params;
+ uarg[0] = (intptr_t) p->name; /* const char * */
+ *n_args = 1;
+ break;
+ }
+ /* ksem_getvalue */
+ case 407: {
+ struct ksem_getvalue_args *p = params;
+ iarg[0] = p->id; /* semid_t */
+ uarg[1] = (intptr_t) p->val; /* int * */
+ *n_args = 2;
+ break;
+ }
+ /* ksem_destroy */
+ case 408: {
+ struct ksem_destroy_args *p = params;
+ iarg[0] = p->id; /* semid_t */
+ *n_args = 1;
+ break;
+ }
+ /* extattr_set_link */
+ case 412: {
+ struct extattr_set_link_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ iarg[1] = p->attrnamespace; /* int */
+ uarg[2] = (intptr_t) p->attrname; /* const char * */
+ uarg[3] = (intptr_t) p->data; /* void * */
+ uarg[4] = p->nbytes; /* size_t */
+ *n_args = 5;
+ break;
+ }
+ /* extattr_get_link */
+ case 413: {
+ struct extattr_get_link_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ iarg[1] = p->attrnamespace; /* int */
+ uarg[2] = (intptr_t) p->attrname; /* const char * */
+ uarg[3] = (intptr_t) p->data; /* void * */
+ uarg[4] = p->nbytes; /* size_t */
+ *n_args = 5;
+ break;
+ }
+ /* extattr_delete_link */
+ case 414: {
+ struct extattr_delete_link_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ iarg[1] = p->attrnamespace; /* int */
+ uarg[2] = (intptr_t) p->attrname; /* const char * */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_sigaction */
+ case 416: {
+ struct freebsd32_sigaction_args *p = params;
+ iarg[0] = p->sig; /* int */
+ uarg[1] = (intptr_t) p->act; /* struct sigaction32 * */
+ uarg[2] = (intptr_t) p->oact; /* struct sigaction32 * */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_sigreturn */
+ case 417: {
+ struct freebsd32_sigreturn_args *p = params;
+ uarg[0] = (intptr_t) p->sigcntxp; /* const struct freebsd32_ucontext * */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_getcontext */
+ case 421: {
+ struct freebsd32_getcontext_args *p = params;
+ uarg[0] = (intptr_t) p->ucp; /* struct freebsd32_ucontext * */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_setcontext */
+ case 422: {
+ struct freebsd32_setcontext_args *p = params;
+ uarg[0] = (intptr_t) p->ucp; /* const struct freebsd32_ucontext * */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_swapcontext */
+ case 423: {
+ struct freebsd32_swapcontext_args *p = params;
+ uarg[0] = (intptr_t) p->oucp; /* struct freebsd32_ucontext * */
+ uarg[1] = (intptr_t) p->ucp; /* const struct freebsd32_ucontext * */
+ *n_args = 2;
+ break;
+ }
+ /* __acl_get_link */
+ case 425: {
+ struct __acl_get_link_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ iarg[1] = p->type; /* acl_type_t */
+ uarg[2] = (intptr_t) p->aclp; /* struct acl * */
+ *n_args = 3;
+ break;
+ }
+ /* __acl_set_link */
+ case 426: {
+ struct __acl_set_link_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ iarg[1] = p->type; /* acl_type_t */
+ uarg[2] = (intptr_t) p->aclp; /* struct acl * */
+ *n_args = 3;
+ break;
+ }
+ /* __acl_delete_link */
+ case 427: {
+ struct __acl_delete_link_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ iarg[1] = p->type; /* acl_type_t */
+ *n_args = 2;
+ break;
+ }
+ /* __acl_aclcheck_link */
+ case 428: {
+ struct __acl_aclcheck_link_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ iarg[1] = p->type; /* acl_type_t */
+ uarg[2] = (intptr_t) p->aclp; /* struct acl * */
+ *n_args = 3;
+ break;
+ }
+ /* sigwait */
+ case 429: {
+ struct sigwait_args *p = params;
+ uarg[0] = (intptr_t) p->set; /* const sigset_t * */
+ uarg[1] = (intptr_t) p->sig; /* int * */
+ *n_args = 2;
+ break;
+ }
+ /* thr_exit */
+ case 431: {
+ struct thr_exit_args *p = params;
+ uarg[0] = (intptr_t) p->state; /* long * */
+ *n_args = 1;
+ break;
+ }
+ /* thr_self */
+ case 432: {
+ struct thr_self_args *p = params;
+ uarg[0] = (intptr_t) p->id; /* long * */
+ *n_args = 1;
+ break;
+ }
+ /* thr_kill */
+ case 433: {
+ struct thr_kill_args *p = params;
+ iarg[0] = p->id; /* long */
+ iarg[1] = p->sig; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_umtx_lock */
+ case 434: {
+ struct freebsd32_umtx_lock_args *p = params;
+ uarg[0] = (intptr_t) p->umtx; /* struct umtx * */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_umtx_unlock */
+ case 435: {
+ struct freebsd32_umtx_unlock_args *p = params;
+ uarg[0] = (intptr_t) p->umtx; /* struct umtx * */
+ *n_args = 1;
+ break;
+ }
+ /* jail_attach */
+ case 436: {
+ struct jail_attach_args *p = params;
+ iarg[0] = p->jid; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* extattr_list_fd */
+ case 437: {
+ struct extattr_list_fd_args *p = params;
+ iarg[0] = p->fd; /* int */
+ iarg[1] = p->attrnamespace; /* int */
+ uarg[2] = (intptr_t) p->data; /* void * */
+ uarg[3] = p->nbytes; /* size_t */
+ *n_args = 4;
+ break;
+ }
+ /* extattr_list_file */
+ case 438: {
+ struct extattr_list_file_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ iarg[1] = p->attrnamespace; /* int */
+ uarg[2] = (intptr_t) p->data; /* void * */
+ uarg[3] = p->nbytes; /* size_t */
+ *n_args = 4;
+ break;
+ }
+ /* extattr_list_link */
+ case 439: {
+ struct extattr_list_link_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ iarg[1] = p->attrnamespace; /* int */
+ uarg[2] = (intptr_t) p->data; /* void * */
+ uarg[3] = p->nbytes; /* size_t */
+ *n_args = 4;
+ break;
+ }
+ /* freebsd32_ksem_timedwait */
+ case 441: {
+ struct freebsd32_ksem_timedwait_args *p = params;
+ iarg[0] = p->id; /* semid_t */
+ uarg[1] = (intptr_t) p->abstime; /* const struct timespec32 * */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_thr_suspend */
+ case 442: {
+ struct freebsd32_thr_suspend_args *p = params;
+ uarg[0] = (intptr_t) p->timeout; /* const struct timespec32 * */
+ *n_args = 1;
+ break;
+ }
+ /* thr_wake */
+ case 443: {
+ struct thr_wake_args *p = params;
+ iarg[0] = p->id; /* long */
+ *n_args = 1;
+ break;
+ }
+ /* kldunloadf */
+ case 444: {
+ struct kldunloadf_args *p = params;
+ iarg[0] = p->fileid; /* int */
+ iarg[1] = p->flags; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* audit */
+ case 445: {
+ struct audit_args *p = params;
+ uarg[0] = (intptr_t) p->record; /* const void * */
+ uarg[1] = p->length; /* u_int */
+ *n_args = 2;
+ break;
+ }
+ /* auditon */
+ case 446: {
+ struct auditon_args *p = params;
+ iarg[0] = p->cmd; /* int */
+ uarg[1] = (intptr_t) p->data; /* void * */
+ uarg[2] = p->length; /* u_int */
+ *n_args = 3;
+ break;
+ }
+ /* getauid */
+ case 447: {
+ struct getauid_args *p = params;
+ uarg[0] = (intptr_t) p->auid; /* uid_t * */
+ *n_args = 1;
+ break;
+ }
+ /* setauid */
+ case 448: {
+ struct setauid_args *p = params;
+ uarg[0] = (intptr_t) p->auid; /* uid_t * */
+ *n_args = 1;
+ break;
+ }
+ /* getaudit */
+ case 449: {
+ struct getaudit_args *p = params;
+ uarg[0] = (intptr_t) p->auditinfo; /* struct auditinfo * */
+ *n_args = 1;
+ break;
+ }
+ /* setaudit */
+ case 450: {
+ struct setaudit_args *p = params;
+ uarg[0] = (intptr_t) p->auditinfo; /* struct auditinfo * */
+ *n_args = 1;
+ break;
+ }
+ /* getaudit_addr */
+ case 451: {
+ struct getaudit_addr_args *p = params;
+ uarg[0] = (intptr_t) p->auditinfo_addr; /* struct auditinfo_addr * */
+ uarg[1] = p->length; /* u_int */
+ *n_args = 2;
+ break;
+ }
+ /* setaudit_addr */
+ case 452: {
+ struct setaudit_addr_args *p = params;
+ uarg[0] = (intptr_t) p->auditinfo_addr; /* struct auditinfo_addr * */
+ uarg[1] = p->length; /* u_int */
+ *n_args = 2;
+ break;
+ }
+ /* auditctl */
+ case 453: {
+ struct auditctl_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_umtx_op */
+ case 454: {
+ struct freebsd32_umtx_op_args *p = params;
+ uarg[0] = (intptr_t) p->obj; /* void * */
+ iarg[1] = p->op; /* int */
+ uarg[2] = p->val; /* u_long */
+ uarg[3] = (intptr_t) p->uaddr; /* void * */
+ uarg[4] = (intptr_t) p->uaddr2; /* void * */
+ *n_args = 5;
+ break;
+ }
+ /* freebsd32_thr_new */
+ case 455: {
+ struct freebsd32_thr_new_args *p = params;
+ uarg[0] = (intptr_t) p->param; /* struct thr_param32 * */
+ iarg[1] = p->param_size; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* sigqueue */
+ case 456: {
+ struct sigqueue_args *p = params;
+ iarg[0] = p->pid; /* pid_t */
+ iarg[1] = p->signum; /* int */
+ uarg[2] = (intptr_t) p->value; /* void * */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_kmq_open */
+ case 457: {
+ struct freebsd32_kmq_open_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ iarg[1] = p->flags; /* int */
+ iarg[2] = p->mode; /* mode_t */
+ uarg[3] = (intptr_t) p->attr; /* const struct mq_attr32 * */
+ *n_args = 4;
+ break;
+ }
+ /* freebsd32_kmq_setattr */
+ case 458: {
+ struct freebsd32_kmq_setattr_args *p = params;
+ iarg[0] = p->mqd; /* int */
+ uarg[1] = (intptr_t) p->attr; /* const struct mq_attr32 * */
+ uarg[2] = (intptr_t) p->oattr; /* struct mq_attr32 * */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_kmq_timedreceive */
+ case 459: {
+ struct freebsd32_kmq_timedreceive_args *p = params;
+ iarg[0] = p->mqd; /* int */
+ uarg[1] = (intptr_t) p->msg_ptr; /* char * */
+ uarg[2] = p->msg_len; /* size_t */
+ uarg[3] = (intptr_t) p->msg_prio; /* unsigned * */
+ uarg[4] = (intptr_t) p->abs_timeout; /* const struct timespec32 * */
+ *n_args = 5;
+ break;
+ }
+ /* freebsd32_kmq_timedsend */
+ case 460: {
+ struct freebsd32_kmq_timedsend_args *p = params;
+ iarg[0] = p->mqd; /* int */
+ uarg[1] = (intptr_t) p->msg_ptr; /* const char * */
+ uarg[2] = p->msg_len; /* size_t */
+ uarg[3] = p->msg_prio; /* unsigned */
+ uarg[4] = (intptr_t) p->abs_timeout; /* const struct timespec32 * */
+ *n_args = 5;
+ break;
+ }
+ /* kmq_notify */
+ case 461: {
+ struct kmq_notify_args *p = params;
+ iarg[0] = p->mqd; /* int */
+ uarg[1] = (intptr_t) p->sigev; /* const struct sigevent * */
+ *n_args = 2;
+ break;
+ }
+ /* kmq_unlink */
+ case 462: {
+ struct kmq_unlink_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ *n_args = 1;
+ break;
+ }
+ /* abort2 */
+ case 463: {
+ struct abort2_args *p = params;
+ uarg[0] = (intptr_t) p->why; /* const char * */
+ iarg[1] = p->nargs; /* int */
+ uarg[2] = (intptr_t) p->args; /* void ** */
+ *n_args = 3;
+ break;
+ }
+ /* thr_set_name */
+ case 464: {
+ struct thr_set_name_args *p = params;
+ iarg[0] = p->id; /* long */
+ uarg[1] = (intptr_t) p->name; /* const char * */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_aio_fsync */
+ case 465: {
+ struct freebsd32_aio_fsync_args *p = params;
+ iarg[0] = p->op; /* int */
+ uarg[1] = (intptr_t) p->aiocbp; /* struct aiocb32 * */
+ *n_args = 2;
+ break;
+ }
+ /* rtprio_thread */
+ case 466: {
+ struct rtprio_thread_args *p = params;
+ iarg[0] = p->function; /* int */
+ iarg[1] = p->lwpid; /* lwpid_t */
+ uarg[2] = (intptr_t) p->rtp; /* struct rtprio * */
+ *n_args = 3;
+ break;
+ }
+ /* sctp_peeloff */
+ case 471: {
+ struct sctp_peeloff_args *p = params;
+ iarg[0] = p->sd; /* int */
+ uarg[1] = p->name; /* uint32_t */
+ *n_args = 2;
+ break;
+ }
+ /* sctp_generic_sendmsg */
+ case 472: {
+ struct sctp_generic_sendmsg_args *p = params;
+ iarg[0] = p->sd; /* int */
+ uarg[1] = (intptr_t) p->msg; /* caddr_t */
+ iarg[2] = p->mlen; /* int */
+ uarg[3] = (intptr_t) p->to; /* caddr_t */
+ iarg[4] = p->tolen; /* __socklen_t */
+ uarg[5] = (intptr_t) p->sinfo; /* struct sctp_sndrcvinfo * */
+ iarg[6] = p->flags; /* int */
+ *n_args = 7;
+ break;
+ }
+ /* sctp_generic_sendmsg_iov */
+ case 473: {
+ struct sctp_generic_sendmsg_iov_args *p = params;
+ iarg[0] = p->sd; /* int */
+ uarg[1] = (intptr_t) p->iov; /* struct iovec * */
+ iarg[2] = p->iovlen; /* int */
+ uarg[3] = (intptr_t) p->to; /* caddr_t */
+ iarg[4] = p->tolen; /* __socklen_t */
+ uarg[5] = (intptr_t) p->sinfo; /* struct sctp_sndrcvinfo * */
+ iarg[6] = p->flags; /* int */
+ *n_args = 7;
+ break;
+ }
+ /* sctp_generic_recvmsg */
+ case 474: {
+ struct sctp_generic_recvmsg_args *p = params;
+ iarg[0] = p->sd; /* int */
+ uarg[1] = (intptr_t) p->iov; /* struct iovec * */
+ iarg[2] = p->iovlen; /* int */
+ uarg[3] = (intptr_t) p->from; /* struct sockaddr * */
+ uarg[4] = (intptr_t) p->fromlenaddr; /* __socklen_t * */
+ uarg[5] = (intptr_t) p->sinfo; /* struct sctp_sndrcvinfo * */
+ uarg[6] = (intptr_t) p->msg_flags; /* int * */
+ *n_args = 7;
+ break;
+ }
+#ifdef PAD64_REQUIRED
+ /* freebsd32_pread */
+ case 475: {
+ struct freebsd32_pread_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->buf; /* void * */
+ uarg[2] = p->nbyte; /* size_t */
+ iarg[3] = p->pad; /* int */
+ uarg[4] = p->offset1; /* uint32_t */
+ uarg[5] = p->offset2; /* uint32_t */
+ *n_args = 6;
+ break;
+ }
+ /* freebsd32_pwrite */
+ case 476: {
+ struct freebsd32_pwrite_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->buf; /* const void * */
+ uarg[2] = p->nbyte; /* size_t */
+ iarg[3] = p->pad; /* int */
+ uarg[4] = p->offset1; /* uint32_t */
+ uarg[5] = p->offset2; /* uint32_t */
+ *n_args = 6;
+ break;
+ }
+ /* freebsd32_mmap */
+ case 477: {
+ struct freebsd32_mmap_args *p = params;
+ uarg[0] = (intptr_t) p->addr; /* caddr_t */
+ uarg[1] = p->len; /* size_t */
+ iarg[2] = p->prot; /* int */
+ iarg[3] = p->flags; /* int */
+ iarg[4] = p->fd; /* int */
+ iarg[5] = p->pad; /* int */
+ uarg[6] = p->pos1; /* uint32_t */
+ uarg[7] = p->pos2; /* uint32_t */
+ *n_args = 8;
+ break;
+ }
+ /* freebsd32_lseek */
+ case 478: {
+ struct freebsd32_lseek_args *p = params;
+ iarg[0] = p->fd; /* int */
+ iarg[1] = p->pad; /* int */
+ uarg[2] = p->offset1; /* uint32_t */
+ uarg[3] = p->offset2; /* uint32_t */
+ iarg[4] = p->whence; /* int */
+ *n_args = 5;
+ break;
+ }
+ /* freebsd32_truncate */
+ case 479: {
+ struct freebsd32_truncate_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ iarg[1] = p->pad; /* int */
+ uarg[2] = p->length1; /* uint32_t */
+ uarg[3] = p->length2; /* uint32_t */
+ *n_args = 4;
+ break;
+ }
+ /* freebsd32_ftruncate */
+ case 480: {
+ struct freebsd32_ftruncate_args *p = params;
+ iarg[0] = p->fd; /* int */
+ iarg[1] = p->pad; /* int */
+ uarg[2] = p->length1; /* uint32_t */
+ uarg[3] = p->length2; /* uint32_t */
+ *n_args = 4;
+ break;
+ }
+#else
+ /* freebsd32_pread */
+ case 475: {
+ struct freebsd32_pread_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->buf; /* void * */
+ uarg[2] = p->nbyte; /* size_t */
+ uarg[3] = p->offset1; /* uint32_t */
+ uarg[4] = p->offset2; /* uint32_t */
+ *n_args = 5;
+ break;
+ }
+ /* freebsd32_pwrite */
+ case 476: {
+ struct freebsd32_pwrite_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->buf; /* const void * */
+ uarg[2] = p->nbyte; /* size_t */
+ uarg[3] = p->offset1; /* uint32_t */
+ uarg[4] = p->offset2; /* uint32_t */
+ *n_args = 5;
+ break;
+ }
+ /* freebsd32_mmap */
+ case 477: {
+ struct freebsd32_mmap_args *p = params;
+ uarg[0] = (intptr_t) p->addr; /* caddr_t */
+ uarg[1] = p->len; /* size_t */
+ iarg[2] = p->prot; /* int */
+ iarg[3] = p->flags; /* int */
+ iarg[4] = p->fd; /* int */
+ uarg[5] = p->pos1; /* uint32_t */
+ uarg[6] = p->pos2; /* uint32_t */
+ *n_args = 7;
+ break;
+ }
+ /* freebsd32_lseek */
+ case 478: {
+ struct freebsd32_lseek_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = p->offset1; /* uint32_t */
+ uarg[2] = p->offset2; /* uint32_t */
+ iarg[3] = p->whence; /* int */
+ *n_args = 4;
+ break;
+ }
+ /* freebsd32_truncate */
+ case 479: {
+ struct freebsd32_truncate_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ uarg[1] = p->length1; /* uint32_t */
+ uarg[2] = p->length2; /* uint32_t */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_ftruncate */
+ case 480: {
+ struct freebsd32_ftruncate_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = p->length1; /* uint32_t */
+ uarg[2] = p->length2; /* uint32_t */
+ *n_args = 3;
+ break;
+ }
+#endif
+ /* thr_kill2 */
+ case 481: {
+ struct thr_kill2_args *p = params;
+ iarg[0] = p->pid; /* pid_t */
+ iarg[1] = p->id; /* long */
+ iarg[2] = p->sig; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* shm_open */
+ case 482: {
+ struct shm_open_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ iarg[1] = p->flags; /* int */
+ iarg[2] = p->mode; /* mode_t */
+ *n_args = 3;
+ break;
+ }
+ /* shm_unlink */
+ case 483: {
+ struct shm_unlink_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* const char * */
+ *n_args = 1;
+ break;
+ }
+ /* cpuset */
+ case 484: {
+ struct cpuset_args *p = params;
+ uarg[0] = (intptr_t) p->setid; /* cpusetid_t * */
+ *n_args = 1;
+ break;
+ }
+#ifdef PAD64_REQUIRED
+ /* freebsd32_cpuset_setid */
+ case 485: {
+ struct freebsd32_cpuset_setid_args *p = params;
+ iarg[0] = p->which; /* cpuwhich_t */
+ iarg[1] = p->pad; /* int */
+ uarg[2] = p->id1; /* uint32_t */
+ uarg[3] = p->id2; /* uint32_t */
+ iarg[4] = p->setid; /* cpusetid_t */
+ *n_args = 5;
+ break;
+ }
+#else
+ /* freebsd32_cpuset_setid */
+ case 485: {
+ struct freebsd32_cpuset_setid_args *p = params;
+ iarg[0] = p->which; /* cpuwhich_t */
+ uarg[1] = p->id1; /* uint32_t */
+ uarg[2] = p->id2; /* uint32_t */
+ iarg[3] = p->setid; /* cpusetid_t */
+ *n_args = 4;
+ break;
+ }
+#endif
+ /* freebsd32_cpuset_getid */
+ case 486: {
+ struct freebsd32_cpuset_getid_args *p = params;
+ iarg[0] = p->level; /* cpulevel_t */
+ iarg[1] = p->which; /* cpuwhich_t */
+ uarg[2] = p->id1; /* uint32_t */
+ uarg[3] = p->id2; /* uint32_t */
+ uarg[4] = (intptr_t) p->setid; /* cpusetid_t * */
+ *n_args = 5;
+ break;
+ }
+ /* freebsd32_cpuset_getaffinity */
+ case 487: {
+ struct freebsd32_cpuset_getaffinity_args *p = params;
+ iarg[0] = p->level; /* cpulevel_t */
+ iarg[1] = p->which; /* cpuwhich_t */
+ uarg[2] = p->id1; /* uint32_t */
+ uarg[3] = p->id2; /* uint32_t */
+ uarg[4] = p->cpusetsize; /* size_t */
+ uarg[5] = (intptr_t) p->mask; /* cpuset_t * */
+ *n_args = 6;
+ break;
+ }
+ /* freebsd32_cpuset_setaffinity */
+ case 488: {
+ struct freebsd32_cpuset_setaffinity_args *p = params;
+ iarg[0] = p->level; /* cpulevel_t */
+ iarg[1] = p->which; /* cpuwhich_t */
+ uarg[2] = p->id1; /* uint32_t */
+ uarg[3] = p->id2; /* uint32_t */
+ uarg[4] = p->cpusetsize; /* size_t */
+ uarg[5] = (intptr_t) p->mask; /* const cpuset_t * */
+ *n_args = 6;
+ break;
+ }
+ /* faccessat */
+ case 489: {
+ struct faccessat_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->path; /* char * */
+ iarg[2] = p->amode; /* int */
+ iarg[3] = p->flag; /* int */
+ *n_args = 4;
+ break;
+ }
+ /* fchmodat */
+ case 490: {
+ struct fchmodat_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->path; /* const char * */
+ iarg[2] = p->mode; /* mode_t */
+ iarg[3] = p->flag; /* int */
+ *n_args = 4;
+ break;
+ }
+ /* fchownat */
+ case 491: {
+ struct fchownat_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->path; /* char * */
+ uarg[2] = p->uid; /* uid_t */
+ iarg[3] = p->gid; /* gid_t */
+ iarg[4] = p->flag; /* int */
+ *n_args = 5;
+ break;
+ }
+ /* freebsd32_fexecve */
+ case 492: {
+ struct freebsd32_fexecve_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->argv; /* uint32_t * */
+ uarg[2] = (intptr_t) p->envv; /* uint32_t * */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_fstatat */
+ case 493: {
+ struct freebsd32_fstatat_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->path; /* char * */
+ uarg[2] = (intptr_t) p->buf; /* struct stat * */
+ iarg[3] = p->flag; /* int */
+ *n_args = 4;
+ break;
+ }
+ /* freebsd32_futimesat */
+ case 494: {
+ struct freebsd32_futimesat_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->path; /* char * */
+ uarg[2] = (intptr_t) p->times; /* struct timeval * */
+ *n_args = 3;
+ break;
+ }
+ /* linkat */
+ case 495: {
+ struct linkat_args *p = params;
+ iarg[0] = p->fd1; /* int */
+ uarg[1] = (intptr_t) p->path1; /* char * */
+ iarg[2] = p->fd2; /* int */
+ uarg[3] = (intptr_t) p->path2; /* char * */
+ iarg[4] = p->flag; /* int */
+ *n_args = 5;
+ break;
+ }
+ /* mkdirat */
+ case 496: {
+ struct mkdirat_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->path; /* char * */
+ iarg[2] = p->mode; /* mode_t */
+ *n_args = 3;
+ break;
+ }
+ /* mkfifoat */
+ case 497: {
+ struct mkfifoat_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->path; /* char * */
+ iarg[2] = p->mode; /* mode_t */
+ *n_args = 3;
+ break;
+ }
+ /* mknodat */
+ case 498: {
+ struct mknodat_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->path; /* char * */
+ iarg[2] = p->mode; /* mode_t */
+ iarg[3] = p->dev; /* dev_t */
+ *n_args = 4;
+ break;
+ }
+ /* openat */
+ case 499: {
+ struct openat_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->path; /* char * */
+ iarg[2] = p->flag; /* int */
+ iarg[3] = p->mode; /* mode_t */
+ *n_args = 4;
+ break;
+ }
+ /* readlinkat */
+ case 500: {
+ struct readlinkat_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->path; /* char * */
+ uarg[2] = (intptr_t) p->buf; /* char * */
+ uarg[3] = p->bufsize; /* size_t */
+ *n_args = 4;
+ break;
+ }
+ /* renameat */
+ case 501: {
+ struct renameat_args *p = params;
+ iarg[0] = p->oldfd; /* int */
+ uarg[1] = (intptr_t) p->old; /* char * */
+ iarg[2] = p->newfd; /* int */
+ uarg[3] = (intptr_t) p->new; /* const char * */
+ *n_args = 4;
+ break;
+ }
+ /* symlinkat */
+ case 502: {
+ struct symlinkat_args *p = params;
+ uarg[0] = (intptr_t) p->path1; /* char * */
+ iarg[1] = p->fd; /* int */
+ uarg[2] = (intptr_t) p->path2; /* char * */
+ *n_args = 3;
+ break;
+ }
+ /* unlinkat */
+ case 503: {
+ struct unlinkat_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->path; /* char * */
+ iarg[2] = p->flag; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* posix_openpt */
+ case 504: {
+ struct posix_openpt_args *p = params;
+ iarg[0] = p->flags; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_jail_get */
+ case 506: {
+ struct freebsd32_jail_get_args *p = params;
+ uarg[0] = (intptr_t) p->iovp; /* struct iovec32 * */
+ uarg[1] = p->iovcnt; /* unsigned int */
+ iarg[2] = p->flags; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_jail_set */
+ case 507: {
+ struct freebsd32_jail_set_args *p = params;
+ uarg[0] = (intptr_t) p->iovp; /* struct iovec32 * */
+ uarg[1] = p->iovcnt; /* unsigned int */
+ iarg[2] = p->flags; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* jail_remove */
+ case 508: {
+ struct jail_remove_args *p = params;
+ iarg[0] = p->jid; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* closefrom */
+ case 509: {
+ struct closefrom_args *p = params;
+ iarg[0] = p->lowfd; /* int */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_semctl */
+ case 510: {
+ struct freebsd32_semctl_args *p = params;
+ iarg[0] = p->semid; /* int */
+ iarg[1] = p->semnum; /* int */
+ iarg[2] = p->cmd; /* int */
+ uarg[3] = (intptr_t) p->arg; /* union semun32 * */
+ *n_args = 4;
+ break;
+ }
+ /* freebsd32_msgctl */
+ case 511: {
+ struct freebsd32_msgctl_args *p = params;
+ iarg[0] = p->msqid; /* int */
+ iarg[1] = p->cmd; /* int */
+ uarg[2] = (intptr_t) p->buf; /* struct msqid_ds32 * */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_shmctl */
+ case 512: {
+ struct freebsd32_shmctl_args *p = params;
+ iarg[0] = p->shmid; /* int */
+ iarg[1] = p->cmd; /* int */
+ uarg[2] = (intptr_t) p->buf; /* struct shmid_ds32 * */
+ *n_args = 3;
+ break;
+ }
+ /* lpathconf */
+ case 513: {
+ struct lpathconf_args *p = params;
+ uarg[0] = (intptr_t) p->path; /* char * */
+ iarg[1] = p->name; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* cap_new */
+ case 514: {
+ struct cap_new_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = p->rights; /* uint64_t */
+ *n_args = 2;
+ break;
+ }
+ /* cap_rights_get */
+ case 515: {
+ struct cap_rights_get_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->rightsp; /* uint64_t * */
+ *n_args = 2;
+ break;
+ }
+ /* cap_enter */
+ case 516: {
+ *n_args = 0;
+ break;
+ }
+ /* cap_getmode */
+ case 517: {
+ struct cap_getmode_args *p = params;
+ uarg[0] = (intptr_t) p->modep; /* u_int * */
+ *n_args = 1;
+ break;
+ }
+ /* freebsd32_pselect */
+ case 522: {
+ struct freebsd32_pselect_args *p = params;
+ iarg[0] = p->nd; /* int */
+ uarg[1] = (intptr_t) p->in; /* fd_set * */
+ uarg[2] = (intptr_t) p->ou; /* fd_set * */
+ uarg[3] = (intptr_t) p->ex; /* fd_set * */
+ uarg[4] = (intptr_t) p->ts; /* const struct timespec32 * */
+ uarg[5] = (intptr_t) p->sm; /* const sigset_t * */
+ *n_args = 6;
+ break;
+ }
+ /* getloginclass */
+ case 523: {
+ struct getloginclass_args *p = params;
+ uarg[0] = (intptr_t) p->namebuf; /* char * */
+ uarg[1] = p->namelen; /* size_t */
+ *n_args = 2;
+ break;
+ }
+ /* setloginclass */
+ case 524: {
+ struct setloginclass_args *p = params;
+ uarg[0] = (intptr_t) p->namebuf; /* const char * */
+ *n_args = 1;
+ break;
+ }
+ /* rctl_get_racct */
+ case 525: {
+ struct rctl_get_racct_args *p = params;
+ uarg[0] = (intptr_t) p->inbufp; /* const void * */
+ uarg[1] = p->inbuflen; /* size_t */
+ uarg[2] = (intptr_t) p->outbufp; /* void * */
+ uarg[3] = p->outbuflen; /* size_t */
+ *n_args = 4;
+ break;
+ }
+ /* rctl_get_rules */
+ case 526: {
+ struct rctl_get_rules_args *p = params;
+ uarg[0] = (intptr_t) p->inbufp; /* const void * */
+ uarg[1] = p->inbuflen; /* size_t */
+ uarg[2] = (intptr_t) p->outbufp; /* void * */
+ uarg[3] = p->outbuflen; /* size_t */
+ *n_args = 4;
+ break;
+ }
+ /* rctl_get_limits */
+ case 527: {
+ struct rctl_get_limits_args *p = params;
+ uarg[0] = (intptr_t) p->inbufp; /* const void * */
+ uarg[1] = p->inbuflen; /* size_t */
+ uarg[2] = (intptr_t) p->outbufp; /* void * */
+ uarg[3] = p->outbuflen; /* size_t */
+ *n_args = 4;
+ break;
+ }
+ /* rctl_add_rule */
+ case 528: {
+ struct rctl_add_rule_args *p = params;
+ uarg[0] = (intptr_t) p->inbufp; /* const void * */
+ uarg[1] = p->inbuflen; /* size_t */
+ uarg[2] = (intptr_t) p->outbufp; /* void * */
+ uarg[3] = p->outbuflen; /* size_t */
+ *n_args = 4;
+ break;
+ }
+ /* rctl_remove_rule */
+ case 529: {
+ struct rctl_remove_rule_args *p = params;
+ uarg[0] = (intptr_t) p->inbufp; /* const void * */
+ uarg[1] = p->inbuflen; /* size_t */
+ uarg[2] = (intptr_t) p->outbufp; /* void * */
+ uarg[3] = p->outbuflen; /* size_t */
+ *n_args = 4;
+ break;
+ }
+#ifdef PAD64_REQUIRED
+ /* freebsd32_posix_fallocate */
+ case 530: {
+ struct freebsd32_posix_fallocate_args *p = params;
+ iarg[0] = p->fd; /* int */
+ iarg[1] = p->pad; /* int */
+ uarg[2] = p->offset1; /* uint32_t */
+ uarg[3] = p->offset2; /* uint32_t */
+ uarg[4] = p->len1; /* uint32_t */
+ uarg[5] = p->len2; /* uint32_t */
+ *n_args = 6;
+ break;
+ }
+ /* freebsd32_posix_fadvise */
+ case 531: {
+ struct freebsd32_posix_fadvise_args *p = params;
+ iarg[0] = p->fd; /* int */
+ iarg[1] = p->pad; /* int */
+ uarg[2] = p->offset1; /* uint32_t */
+ uarg[3] = p->offset2; /* uint32_t */
+ uarg[4] = p->len1; /* uint32_t */
+ uarg[5] = p->len2; /* uint32_t */
+ iarg[6] = p->advice; /* int */
+ *n_args = 7;
+ break;
+ }
+ /* freebsd32_wait6 */
+ case 532: {
+ struct freebsd32_wait6_args *p = params;
+ iarg[0] = p->idtype; /* int */
+ iarg[1] = p->pad; /* int */
+ uarg[2] = p->id1; /* uint32_t */
+ uarg[3] = p->id2; /* uint32_t */
+ uarg[4] = (intptr_t) p->status; /* int * */
+ iarg[5] = p->options; /* int */
+ uarg[6] = (intptr_t) p->wrusage; /* struct wrusage32 * */
+ uarg[7] = (intptr_t) p->info; /* siginfo_t * */
+ *n_args = 8;
+ break;
+ }
+#else
+ /* freebsd32_posix_fallocate */
+ case 530: {
+ struct freebsd32_posix_fallocate_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = p->offset1; /* uint32_t */
+ uarg[2] = p->offset2; /* uint32_t */
+ uarg[3] = p->len1; /* uint32_t */
+ uarg[4] = p->len2; /* uint32_t */
+ *n_args = 5;
+ break;
+ }
+ /* freebsd32_posix_fadvise */
+ case 531: {
+ struct freebsd32_posix_fadvise_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = p->offset1; /* uint32_t */
+ uarg[2] = p->offset2; /* uint32_t */
+ uarg[3] = p->len1; /* uint32_t */
+ uarg[4] = p->len2; /* uint32_t */
+ iarg[5] = p->advice; /* int */
+ *n_args = 6;
+ break;
+ }
+ /* freebsd32_wait6 */
+ case 532: {
+ struct freebsd32_wait6_args *p = params;
+ iarg[0] = p->idtype; /* int */
+ uarg[1] = p->id1; /* uint32_t */
+ uarg[2] = p->id2; /* uint32_t */
+ uarg[3] = (intptr_t) p->status; /* int * */
+ iarg[4] = p->options; /* int */
+ uarg[5] = (intptr_t) p->wrusage; /* struct wrusage32 * */
+ uarg[6] = (intptr_t) p->info; /* siginfo_t * */
+ *n_args = 7;
+ break;
+ }
+#endif
+ /* cap_rights_limit */
+ case 533: {
+ struct cap_rights_limit_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = p->rights; /* uint64_t */
+ *n_args = 2;
+ break;
+ }
+ /* cap_ioctls_limit */
+ case 534: {
+ struct cap_ioctls_limit_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->cmds; /* const u_long * */
+ uarg[2] = p->ncmds; /* size_t */
+ *n_args = 3;
+ break;
+ }
+ /* cap_ioctls_get */
+ case 535: {
+ struct cap_ioctls_get_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->cmds; /* u_long * */
+ uarg[2] = p->maxcmds; /* size_t */
+ *n_args = 3;
+ break;
+ }
+ /* cap_fcntls_limit */
+ case 536: {
+ struct cap_fcntls_limit_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = p->fcntlrights; /* uint32_t */
+ *n_args = 2;
+ break;
+ }
+ /* cap_fcntls_get */
+ case 537: {
+ struct cap_fcntls_get_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->fcntlrightsp; /* uint32_t * */
+ *n_args = 2;
+ break;
+ }
+ /* bindat */
+ case 538: {
+ struct bindat_args *p = params;
+ iarg[0] = p->fd; /* int */
+ iarg[1] = p->s; /* int */
+ uarg[2] = (intptr_t) p->name; /* caddr_t */
+ iarg[3] = p->namelen; /* int */
+ *n_args = 4;
+ break;
+ }
+ /* connectat */
+ case 539: {
+ struct connectat_args *p = params;
+ iarg[0] = p->fd; /* int */
+ iarg[1] = p->s; /* int */
+ uarg[2] = (intptr_t) p->name; /* caddr_t */
+ iarg[3] = p->namelen; /* int */
+ *n_args = 4;
+ break;
+ }
+ /* chflagsat */
+ case 540: {
+ struct chflagsat_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->path; /* const char * */
+ uarg[2] = p->flags; /* u_long */
+ iarg[3] = p->atflag; /* int */
+ *n_args = 4;
+ break;
+ }
+ /* accept4 */
+ case 541: {
+ struct accept4_args *p = params;
+ iarg[0] = p->s; /* int */
+ uarg[1] = (intptr_t) p->name; /* struct sockaddr *__restrict */
+ uarg[2] = (intptr_t) p->anamelen; /* __socklen_t *__restrict */
+ iarg[3] = p->flags; /* int */
+ *n_args = 4;
+ break;
+ }
+ /* pipe2 */
+ case 542: {
+ struct pipe2_args *p = params;
+ uarg[0] = (intptr_t) p->fildes; /* int * */
+ iarg[1] = p->flags; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* freebsd32_aio_mlock */
+ case 543: {
+ struct freebsd32_aio_mlock_args *p = params;
+ uarg[0] = (intptr_t) p->aiocbp; /* struct aiocb32 * */
+ *n_args = 1;
+ break;
+ }
+ default:
+ *n_args = 0;
+ break;
+ };
+}
+static void
+systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
+{
+ const char *p = NULL;
+ switch (sysnum) {
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
+#define PAD64_REQUIRED
+#endif
+ /* nosys */
+ case 0:
+ break;
+ /* sys_exit */
+ case 1:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* fork */
+ case 2:
+ break;
+ /* read */
+ case 3:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "void *";
+ break;
+ case 2:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* write */
+ case 4:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "const void *";
+ break;
+ case 2:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* open */
+ case 5:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* close */
+ case 6:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_wait4 */
+ case 7:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "struct rusage32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* link */
+ case 9:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* unlink */
+ case 10:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* chdir */
+ case 12:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* fchdir */
+ case 13:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* mknod */
+ case 14:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* chmod */
+ case 15:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* chown */
+ case 16:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* obreak */
+ case 17:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getpid */
+ case 20:
+ break;
+ /* mount */
+ case 21:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "char *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "caddr_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* unmount */
+ case 22:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* setuid */
+ case 23:
+ switch(ndx) {
+ case 0:
+ p = "uid_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getuid */
+ case 24:
+ break;
+ /* geteuid */
+ case 25:
+ break;
+ /* ptrace */
+ case 26:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "pid_t";
+ break;
+ case 2:
+ p = "caddr_t";
+ break;
+ case 3:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_recvmsg */
+ case 27:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct msghdr32 *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_sendmsg */
+ case 28:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct msghdr32 *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_recvfrom */
+ case 29:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "uint32_t";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ case 3:
+ p = "int";
+ break;
+ case 4:
+ p = "uint32_t";
+ break;
+ case 5:
+ p = "uint32_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* accept */
+ case 30:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "caddr_t";
+ break;
+ case 2:
+ p = "int *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getpeername */
+ case 31:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "caddr_t";
+ break;
+ case 2:
+ p = "int *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getsockname */
+ case 32:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "caddr_t";
+ break;
+ case 2:
+ p = "int *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* access */
+ case 33:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* chflags */
+ case 34:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "u_long";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* fchflags */
+ case 35:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "u_long";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sync */
+ case 36:
+ break;
+ /* kill */
+ case 37:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getppid */
+ case 39:
+ break;
+ /* dup */
+ case 41:
+ switch(ndx) {
+ case 0:
+ p = "u_int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* pipe */
+ case 42:
+ break;
+ /* getegid */
+ case 43:
+ break;
+ /* profil */
+ case 44:
+ switch(ndx) {
+ case 0:
+ p = "caddr_t";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ case 2:
+ p = "size_t";
+ break;
+ case 3:
+ p = "u_int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* ktrace */
+ case 45:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getgid */
+ case 47:
+ break;
+ /* getlogin */
+ case 49:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "u_int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* setlogin */
+ case 50:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* acct */
+ case 51:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_sigaltstack */
+ case 53:
+ switch(ndx) {
+ case 0:
+ p = "struct sigaltstack32 *";
+ break;
+ case 1:
+ p = "struct sigaltstack32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_ioctl */
+ case 54:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "uint32_t";
+ break;
+ case 2:
+ p = "struct md_ioctl32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* reboot */
+ case 55:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* revoke */
+ case 56:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* symlink */
+ case 57:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* readlink */
+ case 58:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "char *";
+ break;
+ case 2:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_execve */
+ case 59:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "uint32_t *";
+ break;
+ case 2:
+ p = "uint32_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* umask */
+ case 60:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* chroot */
+ case 61:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* msync */
+ case 65:
+ switch(ndx) {
+ case 0:
+ p = "void *";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* vfork */
+ case 66:
+ break;
+ /* sbrk */
+ case 69:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sstk */
+ case 70:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* ovadvise */
+ case 72:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* munmap */
+ case 73:
+ switch(ndx) {
+ case 0:
+ p = "void *";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_mprotect */
+ case 74:
+ switch(ndx) {
+ case 0:
+ p = "const void *";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* madvise */
+ case 75:
+ switch(ndx) {
+ case 0:
+ p = "void *";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* mincore */
+ case 78:
+ switch(ndx) {
+ case 0:
+ p = "const void *";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ case 2:
+ p = "char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getgroups */
+ case 79:
+ switch(ndx) {
+ case 0:
+ p = "u_int";
+ break;
+ case 1:
+ p = "gid_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* setgroups */
+ case 80:
+ switch(ndx) {
+ case 0:
+ p = "u_int";
+ break;
+ case 1:
+ p = "gid_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getpgrp */
+ case 81:
+ break;
+ /* setpgid */
+ case 82:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_setitimer */
+ case 83:
+ switch(ndx) {
+ case 0:
+ p = "u_int";
+ break;
+ case 1:
+ p = "struct itimerval32 *";
+ break;
+ case 2:
+ p = "struct itimerval32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* swapon */
+ case 85:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_getitimer */
+ case 86:
+ switch(ndx) {
+ case 0:
+ p = "u_int";
+ break;
+ case 1:
+ p = "struct itimerval32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getdtablesize */
+ case 89:
+ break;
+ /* dup2 */
+ case 90:
+ switch(ndx) {
+ case 0:
+ p = "u_int";
+ break;
+ case 1:
+ p = "u_int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* fcntl */
+ case 92:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "long";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_select */
+ case 93:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "fd_set *";
+ break;
+ case 2:
+ p = "fd_set *";
+ break;
+ case 3:
+ p = "fd_set *";
+ break;
+ case 4:
+ p = "struct timeval32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* fsync */
+ case 95:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* setpriority */
+ case 96:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* socket */
+ case 97:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* connect */
+ case 98:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "caddr_t";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getpriority */
+ case 100:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* bind */
+ case 104:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "caddr_t";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* setsockopt */
+ case 105:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "caddr_t";
+ break;
+ case 4:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* listen */
+ case 106:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_gettimeofday */
+ case 116:
+ switch(ndx) {
+ case 0:
+ p = "struct timeval32 *";
+ break;
+ case 1:
+ p = "struct timezone *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_getrusage */
+ case 117:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct rusage32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getsockopt */
+ case 118:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "caddr_t";
+ break;
+ case 4:
+ p = "int *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_readv */
+ case 120:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct iovec32 *";
+ break;
+ case 2:
+ p = "u_int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_writev */
+ case 121:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct iovec32 *";
+ break;
+ case 2:
+ p = "u_int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_settimeofday */
+ case 122:
+ switch(ndx) {
+ case 0:
+ p = "struct timeval32 *";
+ break;
+ case 1:
+ p = "struct timezone *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* fchown */
+ case 123:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* fchmod */
+ case 124:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* setreuid */
+ case 126:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* setregid */
+ case 127:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* rename */
+ case 128:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* flock */
+ case 131:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* mkfifo */
+ case 132:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sendto */
+ case 133:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "caddr_t";
+ break;
+ case 2:
+ p = "size_t";
+ break;
+ case 3:
+ p = "int";
+ break;
+ case 4:
+ p = "caddr_t";
+ break;
+ case 5:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* shutdown */
+ case 134:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* socketpair */
+ case 135:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "int *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* mkdir */
+ case 136:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* rmdir */
+ case 137:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_utimes */
+ case 138:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "struct timeval32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_adjtime */
+ case 140:
+ switch(ndx) {
+ case 0:
+ p = "struct timeval32 *";
+ break;
+ case 1:
+ p = "struct timeval32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* setsid */
+ case 147:
+ break;
+ /* quotactl */
+ case 148:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "caddr_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getfh */
+ case 161:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "struct fhandle *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_sysarch */
+ case 165:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* rtprio */
+ case 166:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "pid_t";
+ break;
+ case 2:
+ p = "struct rtprio *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_semsys */
+ case 169:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "int";
+ break;
+ case 4:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_msgsys */
+ case 170:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "int";
+ break;
+ case 4:
+ p = "int";
+ break;
+ case 5:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_shmsys */
+ case 171:
+ switch(ndx) {
+ case 0:
+ p = "uint32_t";
+ break;
+ case 1:
+ p = "uint32_t";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ case 3:
+ p = "uint32_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* ntp_adjtime */
+ case 176:
+ switch(ndx) {
+ case 0:
+ p = "struct timex *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* setgid */
+ case 181:
+ switch(ndx) {
+ case 0:
+ p = "gid_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* setegid */
+ case 182:
+ switch(ndx) {
+ case 0:
+ p = "gid_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* seteuid */
+ case 183:
+ switch(ndx) {
+ case 0:
+ p = "uid_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_stat */
+ case 188:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "struct stat32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_fstat */
+ case 189:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct stat32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_lstat */
+ case 190:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "struct stat32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* pathconf */
+ case 191:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* fpathconf */
+ case 192:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getrlimit */
+ case 194:
+ switch(ndx) {
+ case 0:
+ p = "u_int";
+ break;
+ case 1:
+ p = "struct rlimit *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* setrlimit */
+ case 195:
+ switch(ndx) {
+ case 0:
+ p = "u_int";
+ break;
+ case 1:
+ p = "struct rlimit *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_getdirentries */
+ case 196:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "char *";
+ break;
+ case 2:
+ p = "u_int";
+ break;
+ case 3:
+ p = "int32_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* nosys */
+ case 198:
+ break;
+ /* freebsd32_sysctl */
+ case 202:
+ switch(ndx) {
+ case 0:
+ p = "int *";
+ break;
+ case 1:
+ p = "u_int";
+ break;
+ case 2:
+ p = "void *";
+ break;
+ case 3:
+ p = "uint32_t *";
+ break;
+ case 4:
+ p = "void *";
+ break;
+ case 5:
+ p = "uint32_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* mlock */
+ case 203:
+ switch(ndx) {
+ case 0:
+ p = "const void *";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* munlock */
+ case 204:
+ switch(ndx) {
+ case 0:
+ p = "const void *";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* undelete */
+ case 205:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_futimes */
+ case 206:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct timeval32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getpgid */
+ case 207:
+ switch(ndx) {
+ case 0:
+ p = "pid_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* poll */
+ case 209:
+ switch(ndx) {
+ case 0:
+ p = "struct pollfd *";
+ break;
+ case 1:
+ p = "u_int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* lkmnosys */
+ case 210:
+ break;
+ /* lkmnosys */
+ case 211:
+ break;
+ /* lkmnosys */
+ case 212:
+ break;
+ /* lkmnosys */
+ case 213:
+ break;
+ /* lkmnosys */
+ case 214:
+ break;
+ /* lkmnosys */
+ case 215:
+ break;
+ /* lkmnosys */
+ case 216:
+ break;
+ /* lkmnosys */
+ case 217:
+ break;
+ /* lkmnosys */
+ case 218:
+ break;
+ /* lkmnosys */
+ case 219:
+ break;
+ /* semget */
+ case 221:
+ switch(ndx) {
+ case 0:
+ p = "key_t";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* semop */
+ case 222:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct sembuf *";
+ break;
+ case 2:
+ p = "u_int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* msgget */
+ case 225:
+ switch(ndx) {
+ case 0:
+ p = "key_t";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_msgsnd */
+ case 226:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "void *";
+ break;
+ case 2:
+ p = "size_t";
+ break;
+ case 3:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_msgrcv */
+ case 227:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "void *";
+ break;
+ case 2:
+ p = "size_t";
+ break;
+ case 3:
+ p = "long";
+ break;
+ case 4:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* shmat */
+ case 228:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "void *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* shmdt */
+ case 230:
+ switch(ndx) {
+ case 0:
+ p = "void *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* shmget */
+ case 231:
+ switch(ndx) {
+ case 0:
+ p = "key_t";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_clock_gettime */
+ case 232:
+ switch(ndx) {
+ case 0:
+ p = "clockid_t";
+ break;
+ case 1:
+ p = "struct timespec32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_clock_settime */
+ case 233:
+ switch(ndx) {
+ case 0:
+ p = "clockid_t";
+ break;
+ case 1:
+ p = "const struct timespec32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_clock_getres */
+ case 234:
+ switch(ndx) {
+ case 0:
+ p = "clockid_t";
+ break;
+ case 1:
+ p = "struct timespec32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_nanosleep */
+ case 240:
+ switch(ndx) {
+ case 0:
+ p = "const struct timespec32 *";
+ break;
+ case 1:
+ p = "struct timespec32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* ffclock_getcounter */
+ case 241:
+ switch(ndx) {
+ case 0:
+ p = "ffcounter *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* ffclock_setestimate */
+ case 242:
+ switch(ndx) {
+ case 0:
+ p = "struct ffclock_estimate *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* ffclock_getestimate */
+ case 243:
+ switch(ndx) {
+ case 0:
+ p = "struct ffclock_estimate *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* clock_getcpuclockid2 */
+ case 247:
+ switch(ndx) {
+ case 0:
+ p = "id_t";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "clockid_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* minherit */
+ case 250:
+ switch(ndx) {
+ case 0:
+ p = "void *";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* rfork */
+ case 251:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* openbsd_poll */
+ case 252:
+ switch(ndx) {
+ case 0:
+ p = "struct pollfd *";
+ break;
+ case 1:
+ p = "u_int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* issetugid */
+ case 253:
+ break;
+ /* lchown */
+ case 254:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_aio_read */
+ case 255:
+ switch(ndx) {
+ case 0:
+ p = "struct aiocb32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_aio_write */
+ case 256:
+ switch(ndx) {
+ case 0:
+ p = "struct aiocb32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_lio_listio */
+ case 257:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct aiocb32 *const *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "struct sigevent *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getdents */
+ case 272:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "char *";
+ break;
+ case 2:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* lchmod */
+ case 274:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "mode_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* lchown */
+ case 275:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "uid_t";
+ break;
+ case 2:
+ p = "gid_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_lutimes */
+ case 276:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "struct timeval32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* msync */
+ case 277:
+ switch(ndx) {
+ case 0:
+ p = "void *";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* nstat */
+ case 278:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "struct nstat *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* nfstat */
+ case 279:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct nstat *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* nlstat */
+ case 280:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "struct nstat *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_preadv */
+ case 289:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct iovec32 *";
+ break;
+ case 2:
+ p = "u_int";
+ break;
+ case 3:
+ p = "uint32_t";
+ break;
+ case 4:
+ p = "uint32_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_pwritev */
+ case 290:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct iovec32 *";
+ break;
+ case 2:
+ p = "u_int";
+ break;
+ case 3:
+ p = "uint32_t";
+ break;
+ case 4:
+ p = "uint32_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* fhopen */
+ case 298:
+ switch(ndx) {
+ case 0:
+ p = "const struct fhandle *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* fhstat */
+ case 299:
+ switch(ndx) {
+ case 0:
+ p = "const struct fhandle *";
+ break;
+ case 1:
+ p = "struct stat *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* modnext */
+ case 300:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_modstat */
+ case 301:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct module_stat32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* modfnext */
+ case 302:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* modfind */
+ case 303:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* kldload */
+ case 304:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* kldunload */
+ case 305:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* kldfind */
+ case 306:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* kldnext */
+ case 307:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_kldstat */
+ case 308:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct kld32_file_stat *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* kldfirstmod */
+ case 309:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getsid */
+ case 310:
+ switch(ndx) {
+ case 0:
+ p = "pid_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* setresuid */
+ case 311:
+ switch(ndx) {
+ case 0:
+ p = "uid_t";
+ break;
+ case 1:
+ p = "uid_t";
+ break;
+ case 2:
+ p = "uid_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* setresgid */
+ case 312:
+ switch(ndx) {
+ case 0:
+ p = "gid_t";
+ break;
+ case 1:
+ p = "gid_t";
+ break;
+ case 2:
+ p = "gid_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_aio_return */
+ case 314:
+ switch(ndx) {
+ case 0:
+ p = "struct aiocb32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_aio_suspend */
+ case 315:
+ switch(ndx) {
+ case 0:
+ p = "struct aiocb32 *const *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "const struct timespec32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_aio_cancel */
+ case 316:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct aiocb32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_aio_error */
+ case 317:
+ switch(ndx) {
+ case 0:
+ p = "struct aiocb32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_oaio_read */
+ case 318:
+ switch(ndx) {
+ case 0:
+ p = "struct oaiocb32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_oaio_write */
+ case 319:
+ switch(ndx) {
+ case 0:
+ p = "struct oaiocb32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_olio_listio */
+ case 320:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct oaiocb32 *const *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "struct osigevent32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* yield */
+ case 321:
+ break;
+ /* mlockall */
+ case 324:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* munlockall */
+ case 325:
+ break;
+ /* __getcwd */
+ case 326:
+ switch(ndx) {
+ case 0:
+ p = "u_char *";
+ break;
+ case 1:
+ p = "u_int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sched_setparam */
+ case 327:
+ switch(ndx) {
+ case 0:
+ p = "pid_t";
+ break;
+ case 1:
+ p = "const struct sched_param *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sched_getparam */
+ case 328:
+ switch(ndx) {
+ case 0:
+ p = "pid_t";
+ break;
+ case 1:
+ p = "struct sched_param *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sched_setscheduler */
+ case 329:
+ switch(ndx) {
+ case 0:
+ p = "pid_t";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "const struct sched_param *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sched_getscheduler */
+ case 330:
+ switch(ndx) {
+ case 0:
+ p = "pid_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sched_yield */
+ case 331:
+ break;
+ /* sched_get_priority_max */
+ case 332:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sched_get_priority_min */
+ case 333:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sched_rr_get_interval */
+ case 334:
+ switch(ndx) {
+ case 0:
+ p = "pid_t";
+ break;
+ case 1:
+ p = "struct timespec *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* utrace */
+ case 335:
+ switch(ndx) {
+ case 0:
+ p = "const void *";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* kldsym */
+ case 337:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "void *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_jail */
+ case 338:
+ switch(ndx) {
+ case 0:
+ p = "struct jail32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sigprocmask */
+ case 340:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "const sigset_t *";
+ break;
+ case 2:
+ p = "sigset_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sigsuspend */
+ case 341:
+ switch(ndx) {
+ case 0:
+ p = "const sigset_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sigpending */
+ case 343:
+ switch(ndx) {
+ case 0:
+ p = "sigset_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_sigtimedwait */
+ case 345:
+ switch(ndx) {
+ case 0:
+ p = "const sigset_t *";
+ break;
+ case 1:
+ p = "siginfo_t *";
+ break;
+ case 2:
+ p = "const struct timespec *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_sigwaitinfo */
+ case 346:
+ switch(ndx) {
+ case 0:
+ p = "const sigset_t *";
+ break;
+ case 1:
+ p = "siginfo_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* __acl_get_file */
+ case 347:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "struct acl *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* __acl_set_file */
+ case 348:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "struct acl *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* __acl_get_fd */
+ case 349:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "struct acl *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* __acl_set_fd */
+ case 350:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "struct acl *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* __acl_delete_file */
+ case 351:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* __acl_delete_fd */
+ case 352:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* __acl_aclcheck_file */
+ case 353:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "struct acl *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* __acl_aclcheck_fd */
+ case 354:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "struct acl *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* extattrctl */
+ case 355:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "const char *";
+ break;
+ case 3:
+ p = "int";
+ break;
+ case 4:
+ p = "const char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* extattr_set_file */
+ case 356:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "const char *";
+ break;
+ case 3:
+ p = "void *";
+ break;
+ case 4:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* extattr_get_file */
+ case 357:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "const char *";
+ break;
+ case 3:
+ p = "void *";
+ break;
+ case 4:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* extattr_delete_file */
+ case 358:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "const char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_aio_waitcomplete */
+ case 359:
+ switch(ndx) {
+ case 0:
+ p = "struct aiocb32 **";
+ break;
+ case 1:
+ p = "struct timespec32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getresuid */
+ case 360:
+ switch(ndx) {
+ case 0:
+ p = "uid_t *";
+ break;
+ case 1:
+ p = "uid_t *";
+ break;
+ case 2:
+ p = "uid_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getresgid */
+ case 361:
+ switch(ndx) {
+ case 0:
+ p = "gid_t *";
+ break;
+ case 1:
+ p = "gid_t *";
+ break;
+ case 2:
+ p = "gid_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* kqueue */
+ case 362:
+ break;
+ /* freebsd32_kevent */
+ case 363:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "const struct kevent32 *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "struct kevent32 *";
+ break;
+ case 4:
+ p = "int";
+ break;
+ case 5:
+ p = "const struct timespec32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* extattr_set_fd */
+ case 371:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "const char *";
+ break;
+ case 3:
+ p = "void *";
+ break;
+ case 4:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* extattr_get_fd */
+ case 372:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "const char *";
+ break;
+ case 3:
+ p = "void *";
+ break;
+ case 4:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* extattr_delete_fd */
+ case 373:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "const char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* __setugid */
+ case 374:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* eaccess */
+ case 376:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_nmount */
+ case 378:
+ switch(ndx) {
+ case 0:
+ p = "struct iovec32 *";
+ break;
+ case 1:
+ p = "unsigned int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* kenv */
+ case 390:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "const char *";
+ break;
+ case 2:
+ p = "char *";
+ break;
+ case 3:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* lchflags */
+ case 391:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "u_long";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* uuidgen */
+ case 392:
+ switch(ndx) {
+ case 0:
+ p = "struct uuid *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_sendfile */
+ case 393:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ case 3:
+ p = "uint32_t";
+ break;
+ case 4:
+ p = "size_t";
+ break;
+ case 5:
+ p = "struct sf_hdtr32 *";
+ break;
+ case 6:
+ p = "off_t *";
+ break;
+ case 7:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getfsstat */
+ case 395:
+ switch(ndx) {
+ case 0:
+ p = "struct statfs *";
+ break;
+ case 1:
+ p = "long";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* statfs */
+ case 396:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "struct statfs *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* fstatfs */
+ case 397:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct statfs *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* fhstatfs */
+ case 398:
+ switch(ndx) {
+ case 0:
+ p = "const struct fhandle *";
+ break;
+ case 1:
+ p = "struct statfs *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* ksem_close */
+ case 400:
+ switch(ndx) {
+ case 0:
+ p = "semid_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* ksem_post */
+ case 401:
+ switch(ndx) {
+ case 0:
+ p = "semid_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* ksem_wait */
+ case 402:
+ switch(ndx) {
+ case 0:
+ p = "semid_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* ksem_trywait */
+ case 403:
+ switch(ndx) {
+ case 0:
+ p = "semid_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_ksem_init */
+ case 404:
+ switch(ndx) {
+ case 0:
+ p = "semid_t *";
+ break;
+ case 1:
+ p = "unsigned int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_ksem_open */
+ case 405:
+ switch(ndx) {
+ case 0:
+ p = "semid_t *";
+ break;
+ case 1:
+ p = "const char *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "mode_t";
+ break;
+ case 4:
+ p = "unsigned int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* ksem_unlink */
+ case 406:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* ksem_getvalue */
+ case 407:
+ switch(ndx) {
+ case 0:
+ p = "semid_t";
+ break;
+ case 1:
+ p = "int *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* ksem_destroy */
+ case 408:
+ switch(ndx) {
+ case 0:
+ p = "semid_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* extattr_set_link */
+ case 412:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "const char *";
+ break;
+ case 3:
+ p = "void *";
+ break;
+ case 4:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* extattr_get_link */
+ case 413:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "const char *";
+ break;
+ case 3:
+ p = "void *";
+ break;
+ case 4:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* extattr_delete_link */
+ case 414:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "const char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_sigaction */
+ case 416:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct sigaction32 *";
+ break;
+ case 2:
+ p = "struct sigaction32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_sigreturn */
+ case 417:
+ switch(ndx) {
+ case 0:
+ p = "const struct freebsd32_ucontext *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_getcontext */
+ case 421:
+ switch(ndx) {
+ case 0:
+ p = "struct freebsd32_ucontext *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_setcontext */
+ case 422:
+ switch(ndx) {
+ case 0:
+ p = "const struct freebsd32_ucontext *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_swapcontext */
+ case 423:
+ switch(ndx) {
+ case 0:
+ p = "struct freebsd32_ucontext *";
+ break;
+ case 1:
+ p = "const struct freebsd32_ucontext *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* __acl_get_link */
+ case 425:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "struct acl *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* __acl_set_link */
+ case 426:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "struct acl *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* __acl_delete_link */
+ case 427:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* __acl_aclcheck_link */
+ case 428:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "acl_type_t";
+ break;
+ case 2:
+ p = "struct acl *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sigwait */
+ case 429:
+ switch(ndx) {
+ case 0:
+ p = "const sigset_t *";
+ break;
+ case 1:
+ p = "int *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* thr_exit */
+ case 431:
+ switch(ndx) {
+ case 0:
+ p = "long *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* thr_self */
+ case 432:
+ switch(ndx) {
+ case 0:
+ p = "long *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* thr_kill */
+ case 433:
+ switch(ndx) {
+ case 0:
+ p = "long";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_umtx_lock */
+ case 434:
+ switch(ndx) {
+ case 0:
+ p = "struct umtx *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_umtx_unlock */
+ case 435:
+ switch(ndx) {
+ case 0:
+ p = "struct umtx *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* jail_attach */
+ case 436:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* extattr_list_fd */
+ case 437:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "void *";
+ break;
+ case 3:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* extattr_list_file */
+ case 438:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "void *";
+ break;
+ case 3:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* extattr_list_link */
+ case 439:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "void *";
+ break;
+ case 3:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_ksem_timedwait */
+ case 441:
+ switch(ndx) {
+ case 0:
+ p = "semid_t";
+ break;
+ case 1:
+ p = "const struct timespec32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_thr_suspend */
+ case 442:
+ switch(ndx) {
+ case 0:
+ p = "const struct timespec32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* thr_wake */
+ case 443:
+ switch(ndx) {
+ case 0:
+ p = "long";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* kldunloadf */
+ case 444:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* audit */
+ case 445:
+ switch(ndx) {
+ case 0:
+ p = "const void *";
+ break;
+ case 1:
+ p = "u_int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* auditon */
+ case 446:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "void *";
+ break;
+ case 2:
+ p = "u_int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getauid */
+ case 447:
+ switch(ndx) {
+ case 0:
+ p = "uid_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* setauid */
+ case 448:
+ switch(ndx) {
+ case 0:
+ p = "uid_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getaudit */
+ case 449:
+ switch(ndx) {
+ case 0:
+ p = "struct auditinfo *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* setaudit */
+ case 450:
+ switch(ndx) {
+ case 0:
+ p = "struct auditinfo *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getaudit_addr */
+ case 451:
+ switch(ndx) {
+ case 0:
+ p = "struct auditinfo_addr *";
+ break;
+ case 1:
+ p = "u_int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* setaudit_addr */
+ case 452:
+ switch(ndx) {
+ case 0:
+ p = "struct auditinfo_addr *";
+ break;
+ case 1:
+ p = "u_int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* auditctl */
+ case 453:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_umtx_op */
+ case 454:
+ switch(ndx) {
+ case 0:
+ p = "void *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "u_long";
+ break;
+ case 3:
+ p = "void *";
+ break;
+ case 4:
+ p = "void *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_thr_new */
+ case 455:
+ switch(ndx) {
+ case 0:
+ p = "struct thr_param32 *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sigqueue */
+ case 456:
+ switch(ndx) {
+ case 0:
+ p = "pid_t";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "void *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_kmq_open */
+ case 457:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "mode_t";
+ break;
+ case 3:
+ p = "const struct mq_attr32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_kmq_setattr */
+ case 458:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "const struct mq_attr32 *";
+ break;
+ case 2:
+ p = "struct mq_attr32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_kmq_timedreceive */
+ case 459:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "char *";
+ break;
+ case 2:
+ p = "size_t";
+ break;
+ case 3:
+ p = "unsigned *";
+ break;
+ case 4:
+ p = "const struct timespec32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_kmq_timedsend */
+ case 460:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "const char *";
+ break;
+ case 2:
+ p = "size_t";
+ break;
+ case 3:
+ p = "unsigned";
+ break;
+ case 4:
+ p = "const struct timespec32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* kmq_notify */
+ case 461:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "const struct sigevent *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* kmq_unlink */
+ case 462:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* abort2 */
+ case 463:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "void **";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* thr_set_name */
+ case 464:
+ switch(ndx) {
+ case 0:
+ p = "long";
+ break;
+ case 1:
+ p = "const char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_aio_fsync */
+ case 465:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct aiocb32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* rtprio_thread */
+ case 466:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "lwpid_t";
+ break;
+ case 2:
+ p = "struct rtprio *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sctp_peeloff */
+ case 471:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "uint32_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sctp_generic_sendmsg */
+ case 472:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "caddr_t";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "caddr_t";
+ break;
+ case 4:
+ p = "__socklen_t";
+ break;
+ case 5:
+ p = "struct sctp_sndrcvinfo *";
+ break;
+ case 6:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sctp_generic_sendmsg_iov */
+ case 473:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct iovec *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "caddr_t";
+ break;
+ case 4:
+ p = "__socklen_t";
+ break;
+ case 5:
+ p = "struct sctp_sndrcvinfo *";
+ break;
+ case 6:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* sctp_generic_recvmsg */
+ case 474:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct iovec *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "struct sockaddr *";
+ break;
+ case 4:
+ p = "__socklen_t *";
+ break;
+ case 5:
+ p = "struct sctp_sndrcvinfo *";
+ break;
+ case 6:
+ p = "int *";
+ break;
+ default:
+ break;
+ };
+ break;
+#ifdef PAD64_REQUIRED
+ /* freebsd32_pread */
+ case 475:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "void *";
+ break;
+ case 2:
+ p = "size_t";
+ break;
+ case 3:
+ p = "int";
+ break;
+ case 4:
+ p = "uint32_t";
+ break;
+ case 5:
+ p = "uint32_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_pwrite */
+ case 476:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "const void *";
+ break;
+ case 2:
+ p = "size_t";
+ break;
+ case 3:
+ p = "int";
+ break;
+ case 4:
+ p = "uint32_t";
+ break;
+ case 5:
+ p = "uint32_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_mmap */
+ case 477:
+ switch(ndx) {
+ case 0:
+ p = "caddr_t";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "int";
+ break;
+ case 4:
+ p = "int";
+ break;
+ case 5:
+ p = "int";
+ break;
+ case 6:
+ p = "uint32_t";
+ break;
+ case 7:
+ p = "uint32_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_lseek */
+ case 478:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ case 3:
+ p = "uint32_t";
+ break;
+ case 4:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_truncate */
+ case 479:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ case 3:
+ p = "uint32_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_ftruncate */
+ case 480:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ case 3:
+ p = "uint32_t";
+ break;
+ default:
+ break;
+ };
+ break;
+#else
+ /* freebsd32_pread */
+ case 475:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "void *";
+ break;
+ case 2:
+ p = "size_t";
+ break;
+ case 3:
+ p = "uint32_t";
+ break;
+ case 4:
+ p = "uint32_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_pwrite */
+ case 476:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "const void *";
+ break;
+ case 2:
+ p = "size_t";
+ break;
+ case 3:
+ p = "uint32_t";
+ break;
+ case 4:
+ p = "uint32_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_mmap */
+ case 477:
+ switch(ndx) {
+ case 0:
+ p = "caddr_t";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "int";
+ break;
+ case 4:
+ p = "int";
+ break;
+ case 5:
+ p = "uint32_t";
+ break;
+ case 6:
+ p = "uint32_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_lseek */
+ case 478:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "uint32_t";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ case 3:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_truncate */
+ case 479:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "uint32_t";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_ftruncate */
+ case 480:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "uint32_t";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ default:
+ break;
+ };
+ break;
+#endif
+ /* thr_kill2 */
+ case 481:
+ switch(ndx) {
+ case 0:
+ p = "pid_t";
+ break;
+ case 1:
+ p = "long";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* shm_open */
+ case 482:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "mode_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* shm_unlink */
+ case 483:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* cpuset */
+ case 484:
+ switch(ndx) {
+ case 0:
+ p = "cpusetid_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+#ifdef PAD64_REQUIRED
+ /* freebsd32_cpuset_setid */
+ case 485:
+ switch(ndx) {
+ case 0:
+ p = "cpuwhich_t";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ case 3:
+ p = "uint32_t";
+ break;
+ case 4:
+ p = "cpusetid_t";
+ break;
+ default:
+ break;
+ };
+ break;
+#else
+ /* freebsd32_cpuset_setid */
+ case 485:
+ switch(ndx) {
+ case 0:
+ p = "cpuwhich_t";
+ break;
+ case 1:
+ p = "uint32_t";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ case 3:
+ p = "cpusetid_t";
+ break;
+ default:
+ break;
+ };
+ break;
+#endif
+ /* freebsd32_cpuset_getid */
+ case 486:
+ switch(ndx) {
+ case 0:
+ p = "cpulevel_t";
+ break;
+ case 1:
+ p = "cpuwhich_t";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ case 3:
+ p = "uint32_t";
+ break;
+ case 4:
+ p = "cpusetid_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_cpuset_getaffinity */
+ case 487:
+ switch(ndx) {
+ case 0:
+ p = "cpulevel_t";
+ break;
+ case 1:
+ p = "cpuwhich_t";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ case 3:
+ p = "uint32_t";
+ break;
+ case 4:
+ p = "size_t";
+ break;
+ case 5:
+ p = "cpuset_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_cpuset_setaffinity */
+ case 488:
+ switch(ndx) {
+ case 0:
+ p = "cpulevel_t";
+ break;
+ case 1:
+ p = "cpuwhich_t";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ case 3:
+ p = "uint32_t";
+ break;
+ case 4:
+ p = "size_t";
+ break;
+ case 5:
+ p = "const cpuset_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* faccessat */
+ case 489:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "char *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* fchmodat */
+ case 490:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "const char *";
+ break;
+ case 2:
+ p = "mode_t";
+ break;
+ case 3:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* fchownat */
+ case 491:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "char *";
+ break;
+ case 2:
+ p = "uid_t";
+ break;
+ case 3:
+ p = "gid_t";
+ break;
+ case 4:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_fexecve */
+ case 492:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "uint32_t *";
+ break;
+ case 2:
+ p = "uint32_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_fstatat */
+ case 493:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "char *";
+ break;
+ case 2:
+ p = "struct stat *";
+ break;
+ case 3:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_futimesat */
+ case 494:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "char *";
+ break;
+ case 2:
+ p = "struct timeval *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* linkat */
+ case 495:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "char *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "char *";
+ break;
+ case 4:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* mkdirat */
+ case 496:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "char *";
+ break;
+ case 2:
+ p = "mode_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* mkfifoat */
+ case 497:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "char *";
+ break;
+ case 2:
+ p = "mode_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* mknodat */
+ case 498:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "char *";
+ break;
+ case 2:
+ p = "mode_t";
+ break;
+ case 3:
+ p = "dev_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* openat */
+ case 499:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "char *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "mode_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* readlinkat */
+ case 500:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "char *";
+ break;
+ case 2:
+ p = "char *";
+ break;
+ case 3:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* renameat */
+ case 501:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "char *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "const char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* symlinkat */
+ case 502:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* unlinkat */
+ case 503:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "char *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* posix_openpt */
+ case 504:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_jail_get */
+ case 506:
+ switch(ndx) {
+ case 0:
+ p = "struct iovec32 *";
+ break;
+ case 1:
+ p = "unsigned int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_jail_set */
+ case 507:
+ switch(ndx) {
+ case 0:
+ p = "struct iovec32 *";
+ break;
+ case 1:
+ p = "unsigned int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* jail_remove */
+ case 508:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* closefrom */
+ case 509:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_semctl */
+ case 510:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "union semun32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_msgctl */
+ case 511:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "struct msqid_ds32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_shmctl */
+ case 512:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "struct shmid_ds32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* lpathconf */
+ case 513:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* cap_new */
+ case 514:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "uint64_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* cap_rights_get */
+ case 515:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "uint64_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* cap_enter */
+ case 516:
+ break;
+ /* cap_getmode */
+ case 517:
+ switch(ndx) {
+ case 0:
+ p = "u_int *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_pselect */
+ case 522:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "fd_set *";
+ break;
+ case 2:
+ p = "fd_set *";
+ break;
+ case 3:
+ p = "fd_set *";
+ break;
+ case 4:
+ p = "const struct timespec32 *";
+ break;
+ case 5:
+ p = "const sigset_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* getloginclass */
+ case 523:
+ switch(ndx) {
+ case 0:
+ p = "char *";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* setloginclass */
+ case 524:
+ switch(ndx) {
+ case 0:
+ p = "const char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* rctl_get_racct */
+ case 525:
+ switch(ndx) {
+ case 0:
+ p = "const void *";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ case 2:
+ p = "void *";
+ break;
+ case 3:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* rctl_get_rules */
+ case 526:
+ switch(ndx) {
+ case 0:
+ p = "const void *";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ case 2:
+ p = "void *";
+ break;
+ case 3:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* rctl_get_limits */
+ case 527:
+ switch(ndx) {
+ case 0:
+ p = "const void *";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ case 2:
+ p = "void *";
+ break;
+ case 3:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* rctl_add_rule */
+ case 528:
+ switch(ndx) {
+ case 0:
+ p = "const void *";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ case 2:
+ p = "void *";
+ break;
+ case 3:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* rctl_remove_rule */
+ case 529:
+ switch(ndx) {
+ case 0:
+ p = "const void *";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ case 2:
+ p = "void *";
+ break;
+ case 3:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+#ifdef PAD64_REQUIRED
+ /* freebsd32_posix_fallocate */
+ case 530:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ case 3:
+ p = "uint32_t";
+ break;
+ case 4:
+ p = "uint32_t";
+ break;
+ case 5:
+ p = "uint32_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_posix_fadvise */
+ case 531:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ case 3:
+ p = "uint32_t";
+ break;
+ case 4:
+ p = "uint32_t";
+ break;
+ case 5:
+ p = "uint32_t";
+ break;
+ case 6:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_wait6 */
+ case 532:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ case 3:
+ p = "uint32_t";
+ break;
+ case 4:
+ p = "int *";
+ break;
+ case 5:
+ p = "int";
+ break;
+ case 6:
+ p = "struct wrusage32 *";
+ break;
+ case 7:
+ p = "siginfo_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+#else
+ /* freebsd32_posix_fallocate */
+ case 530:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "uint32_t";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ case 3:
+ p = "uint32_t";
+ break;
+ case 4:
+ p = "uint32_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_posix_fadvise */
+ case 531:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "uint32_t";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ case 3:
+ p = "uint32_t";
+ break;
+ case 4:
+ p = "uint32_t";
+ break;
+ case 5:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_wait6 */
+ case 532:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "uint32_t";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ case 3:
+ p = "int *";
+ break;
+ case 4:
+ p = "int";
+ break;
+ case 5:
+ p = "struct wrusage32 *";
+ break;
+ case 6:
+ p = "siginfo_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+#endif
+ /* cap_rights_limit */
+ case 533:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "uint64_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* cap_ioctls_limit */
+ case 534:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "const u_long *";
+ break;
+ case 2:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* cap_ioctls_get */
+ case 535:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "u_long *";
+ break;
+ case 2:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* cap_fcntls_limit */
+ case 536:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "uint32_t";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* cap_fcntls_get */
+ case 537:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "uint32_t *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* bindat */
+ case 538:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "caddr_t";
+ break;
+ case 3:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* connectat */
+ case 539:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "caddr_t";
+ break;
+ case 3:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* chflagsat */
+ case 540:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "const char *";
+ break;
+ case 2:
+ p = "u_long";
+ break;
+ case 3:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* accept4 */
+ case 541:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "struct sockaddr *__restrict";
+ break;
+ case 2:
+ p = "__socklen_t *__restrict";
+ break;
+ case 3:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* pipe2 */
+ case 542:
+ switch(ndx) {
+ case 0:
+ p = "int *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_aio_mlock */
+ case 543:
+ switch(ndx) {
+ case 0:
+ p = "struct aiocb32 *";
+ break;
+ default:
+ break;
+ };
+ break;
+ default:
+ break;
+ };
+ if (p != NULL)
+ strlcpy(desc, p, descsz);
+}
+static void
+systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
+{
+ const char *p = NULL;
+ switch (sysnum) {
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
+#define PAD64_REQUIRED
+#endif
+ /* nosys */
+ case 0:
+ /* sys_exit */
+ case 1:
+ if (ndx == 0 || ndx == 1)
+ p = "void";
+ break;
+ /* fork */
+ case 2:
+ /* read */
+ case 3:
+ if (ndx == 0 || ndx == 1)
+ p = "ssize_t";
+ break;
+ /* write */
+ case 4:
+ if (ndx == 0 || ndx == 1)
+ p = "ssize_t";
+ break;
+ /* open */
+ case 5:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* close */
+ case 6:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_wait4 */
+ case 7:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* link */
+ case 9:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* unlink */
+ case 10:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* chdir */
+ case 12:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* fchdir */
+ case 13:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* mknod */
+ case 14:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* chmod */
+ case 15:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* chown */
+ case 16:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* obreak */
+ case 17:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getpid */
+ case 20:
+ /* mount */
+ case 21:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* unmount */
+ case 22:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* setuid */
+ case 23:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getuid */
+ case 24:
+ /* geteuid */
+ case 25:
+ /* ptrace */
+ case 26:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_recvmsg */
+ case 27:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_sendmsg */
+ case 28:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_recvfrom */
+ case 29:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* accept */
+ case 30:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getpeername */
+ case 31:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getsockname */
+ case 32:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* access */
+ case 33:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* chflags */
+ case 34:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* fchflags */
+ case 35:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sync */
+ case 36:
+ /* kill */
+ case 37:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getppid */
+ case 39:
+ /* dup */
+ case 41:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* pipe */
+ case 42:
+ /* getegid */
+ case 43:
+ /* profil */
+ case 44:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* ktrace */
+ case 45:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getgid */
+ case 47:
+ /* getlogin */
+ case 49:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* setlogin */
+ case 50:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* acct */
+ case 51:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_sigaltstack */
+ case 53:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_ioctl */
+ case 54:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* reboot */
+ case 55:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* revoke */
+ case 56:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* symlink */
+ case 57:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* readlink */
+ case 58:
+ if (ndx == 0 || ndx == 1)
+ p = "ssize_t";
+ break;
+ /* freebsd32_execve */
+ case 59:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* umask */
+ case 60:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* chroot */
+ case 61:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* msync */
+ case 65:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* vfork */
+ case 66:
+ /* sbrk */
+ case 69:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sstk */
+ case 70:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* ovadvise */
+ case 72:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* munmap */
+ case 73:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_mprotect */
+ case 74:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* madvise */
+ case 75:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* mincore */
+ case 78:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getgroups */
+ case 79:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* setgroups */
+ case 80:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getpgrp */
+ case 81:
+ /* setpgid */
+ case 82:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_setitimer */
+ case 83:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* swapon */
+ case 85:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_getitimer */
+ case 86:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getdtablesize */
+ case 89:
+ /* dup2 */
+ case 90:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* fcntl */
+ case 92:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_select */
+ case 93:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* fsync */
+ case 95:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* setpriority */
+ case 96:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* socket */
+ case 97:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* connect */
+ case 98:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getpriority */
+ case 100:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* bind */
+ case 104:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* setsockopt */
+ case 105:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* listen */
+ case 106:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_gettimeofday */
+ case 116:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_getrusage */
+ case 117:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getsockopt */
+ case 118:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_readv */
+ case 120:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_writev */
+ case 121:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_settimeofday */
+ case 122:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* fchown */
+ case 123:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* fchmod */
+ case 124:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* setreuid */
+ case 126:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* setregid */
+ case 127:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* rename */
+ case 128:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* flock */
+ case 131:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* mkfifo */
+ case 132:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sendto */
+ case 133:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* shutdown */
+ case 134:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* socketpair */
+ case 135:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* mkdir */
+ case 136:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* rmdir */
+ case 137:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_utimes */
+ case 138:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_adjtime */
+ case 140:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* setsid */
+ case 147:
+ /* quotactl */
+ case 148:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getfh */
+ case 161:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_sysarch */
+ case 165:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* rtprio */
+ case 166:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_semsys */
+ case 169:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_msgsys */
+ case 170:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_shmsys */
+ case 171:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* ntp_adjtime */
+ case 176:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* setgid */
+ case 181:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* setegid */
+ case 182:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* seteuid */
+ case 183:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_stat */
+ case 188:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_fstat */
+ case 189:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_lstat */
+ case 190:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* pathconf */
+ case 191:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* fpathconf */
+ case 192:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getrlimit */
+ case 194:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* setrlimit */
+ case 195:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_getdirentries */
+ case 196:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* nosys */
+ case 198:
+ /* freebsd32_sysctl */
+ case 202:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* mlock */
+ case 203:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* munlock */
+ case 204:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* undelete */
+ case 205:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_futimes */
+ case 206:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getpgid */
+ case 207:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* poll */
+ case 209:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* lkmnosys */
+ case 210:
+ /* lkmnosys */
+ case 211:
+ /* lkmnosys */
+ case 212:
+ /* lkmnosys */
+ case 213:
+ /* lkmnosys */
+ case 214:
+ /* lkmnosys */
+ case 215:
+ /* lkmnosys */
+ case 216:
+ /* lkmnosys */
+ case 217:
+ /* lkmnosys */
+ case 218:
+ /* lkmnosys */
+ case 219:
+ /* semget */
+ case 221:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* semop */
+ case 222:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* msgget */
+ case 225:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_msgsnd */
+ case 226:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_msgrcv */
+ case 227:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* shmat */
+ case 228:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* shmdt */
+ case 230:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* shmget */
+ case 231:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_clock_gettime */
+ case 232:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_clock_settime */
+ case 233:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_clock_getres */
+ case 234:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_nanosleep */
+ case 240:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* ffclock_getcounter */
+ case 241:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* ffclock_setestimate */
+ case 242:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* ffclock_getestimate */
+ case 243:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* clock_getcpuclockid2 */
+ case 247:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* minherit */
+ case 250:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* rfork */
+ case 251:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* openbsd_poll */
+ case 252:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* issetugid */
+ case 253:
+ /* lchown */
+ case 254:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_aio_read */
+ case 255:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_aio_write */
+ case 256:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_lio_listio */
+ case 257:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getdents */
+ case 272:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* lchmod */
+ case 274:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* lchown */
+ case 275:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_lutimes */
+ case 276:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* msync */
+ case 277:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* nstat */
+ case 278:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* nfstat */
+ case 279:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* nlstat */
+ case 280:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_preadv */
+ case 289:
+ if (ndx == 0 || ndx == 1)
+ p = "ssize_t";
+ break;
+ /* freebsd32_pwritev */
+ case 290:
+ if (ndx == 0 || ndx == 1)
+ p = "ssize_t";
+ break;
+ /* fhopen */
+ case 298:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* fhstat */
+ case 299:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* modnext */
+ case 300:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_modstat */
+ case 301:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* modfnext */
+ case 302:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* modfind */
+ case 303:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* kldload */
+ case 304:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* kldunload */
+ case 305:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* kldfind */
+ case 306:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* kldnext */
+ case 307:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_kldstat */
+ case 308:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* kldfirstmod */
+ case 309:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getsid */
+ case 310:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* setresuid */
+ case 311:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* setresgid */
+ case 312:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_aio_return */
+ case 314:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_aio_suspend */
+ case 315:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_aio_cancel */
+ case 316:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_aio_error */
+ case 317:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_oaio_read */
+ case 318:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_oaio_write */
+ case 319:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_olio_listio */
+ case 320:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* yield */
+ case 321:
+ /* mlockall */
+ case 324:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* munlockall */
+ case 325:
+ /* __getcwd */
+ case 326:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sched_setparam */
+ case 327:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sched_getparam */
+ case 328:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sched_setscheduler */
+ case 329:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sched_getscheduler */
+ case 330:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sched_yield */
+ case 331:
+ /* sched_get_priority_max */
+ case 332:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sched_get_priority_min */
+ case 333:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sched_rr_get_interval */
+ case 334:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* utrace */
+ case 335:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* kldsym */
+ case 337:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_jail */
+ case 338:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sigprocmask */
+ case 340:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sigsuspend */
+ case 341:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sigpending */
+ case 343:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_sigtimedwait */
+ case 345:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_sigwaitinfo */
+ case 346:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* __acl_get_file */
+ case 347:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* __acl_set_file */
+ case 348:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* __acl_get_fd */
+ case 349:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* __acl_set_fd */
+ case 350:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* __acl_delete_file */
+ case 351:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* __acl_delete_fd */
+ case 352:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* __acl_aclcheck_file */
+ case 353:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* __acl_aclcheck_fd */
+ case 354:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* extattrctl */
+ case 355:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* extattr_set_file */
+ case 356:
+ if (ndx == 0 || ndx == 1)
+ p = "ssize_t";
+ break;
+ /* extattr_get_file */
+ case 357:
+ if (ndx == 0 || ndx == 1)
+ p = "ssize_t";
+ break;
+ /* extattr_delete_file */
+ case 358:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_aio_waitcomplete */
+ case 359:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getresuid */
+ case 360:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getresgid */
+ case 361:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* kqueue */
+ case 362:
+ /* freebsd32_kevent */
+ case 363:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* extattr_set_fd */
+ case 371:
+ if (ndx == 0 || ndx == 1)
+ p = "ssize_t";
+ break;
+ /* extattr_get_fd */
+ case 372:
+ if (ndx == 0 || ndx == 1)
+ p = "ssize_t";
+ break;
+ /* extattr_delete_fd */
+ case 373:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* __setugid */
+ case 374:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* eaccess */
+ case 376:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_nmount */
+ case 378:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* kenv */
+ case 390:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* lchflags */
+ case 391:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* uuidgen */
+ case 392:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_sendfile */
+ case 393:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getfsstat */
+ case 395:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* statfs */
+ case 396:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* fstatfs */
+ case 397:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* fhstatfs */
+ case 398:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* ksem_close */
+ case 400:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* ksem_post */
+ case 401:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* ksem_wait */
+ case 402:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* ksem_trywait */
+ case 403:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_ksem_init */
+ case 404:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_ksem_open */
+ case 405:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* ksem_unlink */
+ case 406:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* ksem_getvalue */
+ case 407:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* ksem_destroy */
+ case 408:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* extattr_set_link */
+ case 412:
+ if (ndx == 0 || ndx == 1)
+ p = "ssize_t";
+ break;
+ /* extattr_get_link */
+ case 413:
+ if (ndx == 0 || ndx == 1)
+ p = "ssize_t";
+ break;
+ /* extattr_delete_link */
+ case 414:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_sigaction */
+ case 416:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_sigreturn */
+ case 417:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_getcontext */
+ case 421:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_setcontext */
+ case 422:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_swapcontext */
+ case 423:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* __acl_get_link */
+ case 425:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* __acl_set_link */
+ case 426:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* __acl_delete_link */
+ case 427:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* __acl_aclcheck_link */
+ case 428:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sigwait */
+ case 429:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* thr_exit */
+ case 431:
+ if (ndx == 0 || ndx == 1)
+ p = "void";
+ break;
+ /* thr_self */
+ case 432:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* thr_kill */
+ case 433:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_umtx_lock */
+ case 434:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_umtx_unlock */
+ case 435:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* jail_attach */
+ case 436:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* extattr_list_fd */
+ case 437:
+ if (ndx == 0 || ndx == 1)
+ p = "ssize_t";
+ break;
+ /* extattr_list_file */
+ case 438:
+ if (ndx == 0 || ndx == 1)
+ p = "ssize_t";
+ break;
+ /* extattr_list_link */
+ case 439:
+ if (ndx == 0 || ndx == 1)
+ p = "ssize_t";
+ break;
+ /* freebsd32_ksem_timedwait */
+ case 441:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_thr_suspend */
+ case 442:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* thr_wake */
+ case 443:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* kldunloadf */
+ case 444:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* audit */
+ case 445:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* auditon */
+ case 446:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getauid */
+ case 447:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* setauid */
+ case 448:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getaudit */
+ case 449:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* setaudit */
+ case 450:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getaudit_addr */
+ case 451:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* setaudit_addr */
+ case 452:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* auditctl */
+ case 453:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_umtx_op */
+ case 454:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_thr_new */
+ case 455:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sigqueue */
+ case 456:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_kmq_open */
+ case 457:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_kmq_setattr */
+ case 458:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_kmq_timedreceive */
+ case 459:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_kmq_timedsend */
+ case 460:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* kmq_notify */
+ case 461:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* kmq_unlink */
+ case 462:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* abort2 */
+ case 463:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* thr_set_name */
+ case 464:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_aio_fsync */
+ case 465:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* rtprio_thread */
+ case 466:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sctp_peeloff */
+ case 471:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sctp_generic_sendmsg */
+ case 472:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sctp_generic_sendmsg_iov */
+ case 473:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* sctp_generic_recvmsg */
+ case 474:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+#ifdef PAD64_REQUIRED
+ /* freebsd32_pread */
+ case 475:
+ if (ndx == 0 || ndx == 1)
+ p = "ssize_t";
+ break;
+ /* freebsd32_pwrite */
+ case 476:
+ if (ndx == 0 || ndx == 1)
+ p = "ssize_t";
+ break;
+ /* freebsd32_mmap */
+ case 477:
+ if (ndx == 0 || ndx == 1)
+ p = "caddr_t";
+ break;
+ /* freebsd32_lseek */
+ case 478:
+ if (ndx == 0 || ndx == 1)
+ p = "off_t";
+ break;
+ /* freebsd32_truncate */
+ case 479:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_ftruncate */
+ case 480:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+#else
+ /* freebsd32_pread */
+ case 475:
+ if (ndx == 0 || ndx == 1)
+ p = "ssize_t";
+ break;
+ /* freebsd32_pwrite */
+ case 476:
+ if (ndx == 0 || ndx == 1)
+ p = "ssize_t";
+ break;
+ /* freebsd32_mmap */
+ case 477:
+ if (ndx == 0 || ndx == 1)
+ p = "caddr_t";
+ break;
+ /* freebsd32_lseek */
+ case 478:
+ if (ndx == 0 || ndx == 1)
+ p = "off_t";
+ break;
+ /* freebsd32_truncate */
+ case 479:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_ftruncate */
+ case 480:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+#endif
+ /* thr_kill2 */
+ case 481:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* shm_open */
+ case 482:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* shm_unlink */
+ case 483:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* cpuset */
+ case 484:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+#ifdef PAD64_REQUIRED
+ /* freebsd32_cpuset_setid */
+ case 485:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+#else
+ /* freebsd32_cpuset_setid */
+ case 485:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+#endif
+ /* freebsd32_cpuset_getid */
+ case 486:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_cpuset_getaffinity */
+ case 487:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_cpuset_setaffinity */
+ case 488:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* faccessat */
+ case 489:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* fchmodat */
+ case 490:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* fchownat */
+ case 491:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_fexecve */
+ case 492:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_fstatat */
+ case 493:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_futimesat */
+ case 494:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* linkat */
+ case 495:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* mkdirat */
+ case 496:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* mkfifoat */
+ case 497:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* mknodat */
+ case 498:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* openat */
+ case 499:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* readlinkat */
+ case 500:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* renameat */
+ case 501:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* symlinkat */
+ case 502:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* unlinkat */
+ case 503:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* posix_openpt */
+ case 504:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_jail_get */
+ case 506:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_jail_set */
+ case 507:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* jail_remove */
+ case 508:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* closefrom */
+ case 509:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_semctl */
+ case 510:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_msgctl */
+ case 511:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_shmctl */
+ case 512:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* lpathconf */
+ case 513:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* cap_new */
+ case 514:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* cap_rights_get */
+ case 515:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* cap_enter */
+ case 516:
+ /* cap_getmode */
+ case 517:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_pselect */
+ case 522:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* getloginclass */
+ case 523:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* setloginclass */
+ case 524:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* rctl_get_racct */
+ case 525:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* rctl_get_rules */
+ case 526:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* rctl_get_limits */
+ case 527:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* rctl_add_rule */
+ case 528:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* rctl_remove_rule */
+ case 529:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+#ifdef PAD64_REQUIRED
+ /* freebsd32_posix_fallocate */
+ case 530:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_posix_fadvise */
+ case 531:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_wait6 */
+ case 532:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+#else
+ /* freebsd32_posix_fallocate */
+ case 530:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_posix_fadvise */
+ case 531:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_wait6 */
+ case 532:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+#endif
+ /* cap_rights_limit */
+ case 533:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* cap_ioctls_limit */
+ case 534:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* cap_ioctls_get */
+ case 535:
+ if (ndx == 0 || ndx == 1)
+ p = "ssize_t";
+ break;
+ /* cap_fcntls_limit */
+ case 536:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* cap_fcntls_get */
+ case 537:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* bindat */
+ case 538:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* connectat */
+ case 539:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* chflagsat */
+ case 540:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* accept4 */
+ case 541:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* pipe2 */
+ case 542:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_aio_mlock */
+ case 543:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ if (p != NULL)
+ strlcpy(desc, p, descsz);
+}
diff --git a/sys/compat/freebsd32/freebsd32_util.h b/sys/compat/freebsd32/freebsd32_util.h
new file mode 100644
index 0000000..9282275
--- /dev/null
+++ b/sys/compat/freebsd32/freebsd32_util.h
@@ -0,0 +1,118 @@
+/*-
+ * Copyright (c) 1998-1999 Andrew Gallatin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _COMPAT_FREEBSD32_FREEBSD32_UTIL_H_
+#define _COMPAT_FREEBSD32_FREEBSD32_UTIL_H_
+
+#include <sys/cdefs.h>
+#include <sys/exec.h>
+#include <sys/sysent.h>
+#include <sys/uio.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
+struct freebsd32_ps_strings {
+ u_int32_t ps_argvstr; /* first of 0 or more argument strings */
+ int ps_nargvstr; /* the number of argument strings */
+ u_int32_t ps_envstr; /* first of 0 or more environment strings */
+ int ps_nenvstr; /* the number of environment strings */
+};
+
+#if defined(__amd64__) || defined(__ia64__)
+#include <compat/ia32/ia32_util.h>
+#endif
+
+#define FREEBSD32_PS_STRINGS \
+ (FREEBSD32_USRSTACK - sizeof(struct freebsd32_ps_strings))
+
+extern struct sysent freebsd32_sysent[];
+
+#define SYSCALL32_MODULE(name, offset, new_sysent, evh, arg) \
+static struct syscall_module_data name##_syscall32_mod = { \
+ evh, arg, offset, new_sysent, { 0, NULL } \
+}; \
+ \
+static moduledata_t name##32_mod = { \
+ "sys32/" #name, \
+ syscall32_module_handler, \
+ &name##_syscall32_mod \
+}; \
+DECLARE_MODULE(name##32, name##32_mod, SI_SUB_SYSCALLS, SI_ORDER_MIDDLE)
+
+#define SYSCALL32_MODULE_HELPER(syscallname) \
+static int syscallname##_syscall32 = FREEBSD32_SYS_##syscallname; \
+static struct sysent syscallname##_sysent32 = { \
+ (sizeof(struct syscallname ## _args ) \
+ / sizeof(register_t)), \
+ (sy_call_t *)& syscallname \
+}; \
+SYSCALL32_MODULE(syscallname, \
+ & syscallname##_syscall32, & syscallname##_sysent32,\
+ NULL, NULL);
+
+#define SYSCALL32_INIT_HELPER(syscallname) { \
+ .new_sysent = { \
+ .sy_narg = (sizeof(struct syscallname ## _args ) \
+ / sizeof(register_t)), \
+ .sy_call = (sy_call_t *)& syscallname, \
+ }, \
+ .syscall_no = FREEBSD32_SYS_##syscallname \
+}
+
+#define SYSCALL32_INIT_HELPER_COMPAT(syscallname) { \
+ .new_sysent = { \
+ .sy_narg = (sizeof(struct syscallname ## _args ) \
+ / sizeof(register_t)), \
+ .sy_call = (sy_call_t *)& sys_ ## syscallname, \
+ }, \
+ .syscall_no = FREEBSD32_SYS_##syscallname \
+}
+
+int syscall32_register(int *offset, struct sysent *new_sysent,
+ struct sysent *old_sysent);
+int syscall32_deregister(int *offset, struct sysent *old_sysent);
+int syscall32_module_handler(struct module *mod, int what, void *arg);
+int syscall32_helper_register(struct syscall_helper_data *sd);
+int syscall32_helper_unregister(struct syscall_helper_data *sd);
+
+struct iovec32;
+struct rusage32;
+register_t *freebsd32_copyout_strings(struct image_params *imgp);
+int freebsd32_copyiniov(struct iovec32 *iovp, u_int iovcnt,
+ struct iovec **iov, int error);
+void freebsd32_rusage_out(const struct rusage *s, struct rusage32 *s32);
+
+struct image_args;
+int freebsd32_exec_copyin_args(struct image_args *args, char *fname,
+ enum uio_seg segflg, u_int32_t *argv, u_int32_t *envv);
+
+#endif /* !_COMPAT_FREEBSD32_FREEBSD32_UTIL_H_ */
diff --git a/sys/compat/freebsd32/syscalls.conf b/sys/compat/freebsd32/syscalls.conf
new file mode 100644
index 0000000..3715400
--- /dev/null
+++ b/sys/compat/freebsd32/syscalls.conf
@@ -0,0 +1,11 @@
+# $FreeBSD$
+sysnames="freebsd32_syscalls.c"
+sysproto="freebsd32_proto.h"
+sysproto_h=_FREEBSD32_SYSPROTO_H_
+syshdr="freebsd32_syscall.h"
+syssw="freebsd32_sysent.c"
+sysmk="/dev/null"
+syscallprefix="FREEBSD32_SYS_"
+switchname="freebsd32_sysent"
+namesname="freebsd32_syscallnames"
+systrace="freebsd32_systrace_args.c"
diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master
new file mode 100644
index 0000000..bcca754
--- /dev/null
+++ b/sys/compat/freebsd32/syscalls.master
@@ -0,0 +1,1048 @@
+ $FreeBSD$
+; from: @(#)syscalls.master 8.2 (Berkeley) 1/13/94
+; from: src/sys/kern/syscalls.master 1.107
+;
+; System call name/number master file.
+; Processed to created init_sysent.c, syscalls.c and syscall.h.
+
+; Columns: number audit type name alt{name,tag,rtyp}/comments
+; number system call number, must be in order
+; audit the audit event associated with the system call
+; A value of AUE_NULL means no auditing, but it also means that
+; there is no audit event for the call at this time. For the
+; case where the event exists, but we don't want auditing, the
+; event should be #defined to AUE_NULL in audit_kevents.h.
+; type one of STD, OBSOL, UNIMPL, COMPAT, COMPAT4, COMPAT6,
+; COMPAT7, NODEF, NOARGS, NOPROTO, NOSTD
+; The COMPAT* options may be combined with one or more NO*
+; options separated by '|' with no spaces (e.g. COMPAT|NOARGS)
+; name psuedo-prototype of syscall routine
+; If one of the following alts is different, then all appear:
+; altname name of system call if different
+; alttag name of args struct tag if different from [o]`name'"_args"
+; altrtyp return type if not int (bogus - syscalls always return int)
+; for UNIMPL/OBSOL, name continues with comments
+
+; types:
+; STD always included
+; COMPAT included on COMPAT #ifdef
+; COMPAT4 included on COMPAT4 #ifdef (FreeBSD 4 compat)
+; COMPAT6 included on COMPAT6 #ifdef (FreeBSD 6 compat)
+; COMPAT7 included on COMPAT7 #ifdef (FreeBSD 7 compat)
+; OBSOL obsolete, not included in system, only specifies name
+; UNIMPL not implemented, placeholder only
+; NOSTD implemented but as a lkm that can be statically
+; compiled in; sysent entry will be filled with lkmressys
+; so the SYSCALL_MODULE macro works
+; NOARGS same as STD except do not create structure in sys/sysproto.h
+; NODEF same as STD except only have the entry in the syscall table
+; added. Meaning - do not create structure or function
+; prototype in sys/sysproto.h
+; NOPROTO same as STD except do not create structure or
+; function prototype in sys/sysproto.h. Does add a
+; definition to syscall.h besides adding a sysent.
+
+; #ifdef's, etc. may be included, and are copied to the output files.
+
+#include <sys/param.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <sys/mount.h>
+#include <sys/socket.h>
+#include <compat/freebsd32/freebsd32.h>
+#include <compat/freebsd32/freebsd32_proto.h>
+
+#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
+#define PAD64_REQUIRED
+#endif
+
+; Reserved/unimplemented system calls in the range 0-150 inclusive
+; are reserved for use in future Berkeley releases.
+; Additional system calls implemented in vendor and other
+; redistributions should be placed in the reserved range at the end
+; of the current calls.
+
+0 AUE_NULL NOPROTO { int nosys(void); } syscall nosys_args int
+1 AUE_EXIT NOPROTO { void sys_exit(int rval); } exit \
+ sys_exit_args void
+2 AUE_FORK NOPROTO { int fork(void); }
+3 AUE_READ NOPROTO { ssize_t read(int fd, void *buf, \
+ size_t nbyte); }
+4 AUE_WRITE NOPROTO { ssize_t write(int fd, const void *buf, \
+ size_t nbyte); }
+5 AUE_OPEN_RWTC NOPROTO { int open(char *path, int flags, \
+ int mode); }
+6 AUE_CLOSE NOPROTO { int close(int fd); }
+7 AUE_WAIT4 STD { int freebsd32_wait4(int pid, int *status, \
+ int options, struct rusage32 *rusage); }
+8 AUE_CREAT OBSOL old creat
+9 AUE_LINK NOPROTO { int link(char *path, char *link); }
+10 AUE_UNLINK NOPROTO { int unlink(char *path); }
+11 AUE_NULL OBSOL execv
+12 AUE_CHDIR NOPROTO { int chdir(char *path); }
+13 AUE_FCHDIR NOPROTO { int fchdir(int fd); }
+14 AUE_MKNOD NOPROTO { int mknod(char *path, int mode, int dev); }
+15 AUE_CHMOD NOPROTO { int chmod(char *path, int mode); }
+16 AUE_CHOWN NOPROTO { int chown(char *path, int uid, int gid); }
+17 AUE_NULL NOPROTO { int obreak(char *nsize); } break \
+ obreak_args int
+18 AUE_GETFSSTAT COMPAT4 { int freebsd32_getfsstat( \
+ struct statfs32 *buf, long bufsize, \
+ int flags); }
+19 AUE_LSEEK COMPAT { int freebsd32_lseek(int fd, int offset, \
+ int whence); }
+20 AUE_GETPID NOPROTO { pid_t getpid(void); }
+21 AUE_MOUNT NOPROTO { int mount(char *type, char *path, \
+ int flags, caddr_t data); }
+22 AUE_UMOUNT NOPROTO { int unmount(char *path, int flags); }
+23 AUE_SETUID NOPROTO { int setuid(uid_t uid); }
+24 AUE_GETUID NOPROTO { uid_t getuid(void); }
+25 AUE_GETEUID NOPROTO { uid_t geteuid(void); }
+26 AUE_PTRACE NOPROTO { int ptrace(int req, pid_t pid, \
+ caddr_t addr, int data); }
+27 AUE_RECVMSG STD { int freebsd32_recvmsg(int s, struct msghdr32 *msg, \
+ int flags); }
+28 AUE_SENDMSG STD { int freebsd32_sendmsg(int s, struct msghdr32 *msg, \
+ int flags); }
+29 AUE_RECVFROM STD { int freebsd32_recvfrom(int s, uint32_t buf, \
+ uint32_t len, int flags, uint32_t from, \
+ uint32_t fromlenaddr); }
+30 AUE_ACCEPT NOPROTO { int accept(int s, caddr_t name, \
+ int *anamelen); }
+31 AUE_GETPEERNAME NOPROTO { int getpeername(int fdes, caddr_t asa, \
+ int *alen); }
+32 AUE_GETSOCKNAME NOPROTO { int getsockname(int fdes, caddr_t asa, \
+ int *alen); }
+33 AUE_ACCESS NOPROTO { int access(char *path, int amode); }
+34 AUE_CHFLAGS NOPROTO { int chflags(const char *path, u_long flags); }
+35 AUE_FCHFLAGS NOPROTO { int fchflags(int fd, u_long flags); }
+36 AUE_SYNC NOPROTO { int sync(void); }
+37 AUE_KILL NOPROTO { int kill(int pid, int signum); }
+38 AUE_STAT COMPAT { int freebsd32_stat(char *path, \
+ struct ostat32 *ub); }
+39 AUE_GETPPID NOPROTO { pid_t getppid(void); }
+40 AUE_LSTAT COMPAT { int freebsd32_lstat(char *path, \
+ struct ostat *ub); }
+41 AUE_DUP NOPROTO { int dup(u_int fd); }
+42 AUE_PIPE NOPROTO { int pipe(void); }
+43 AUE_GETEGID NOPROTO { gid_t getegid(void); }
+44 AUE_PROFILE NOPROTO { int profil(caddr_t samples, size_t size, \
+ size_t offset, u_int scale); }
+45 AUE_KTRACE NOPROTO { int ktrace(const char *fname, int ops, \
+ int facs, int pid); }
+46 AUE_SIGACTION COMPAT { int freebsd32_sigaction( int signum, \
+ struct osigaction32 *nsa, \
+ struct osigaction32 *osa); }
+47 AUE_GETGID NOPROTO { gid_t getgid(void); }
+48 AUE_SIGPROCMASK COMPAT { int freebsd32_sigprocmask(int how, \
+ osigset_t mask); }
+49 AUE_GETLOGIN NOPROTO { int getlogin(char *namebuf, \
+ u_int namelen); }
+50 AUE_SETLOGIN NOPROTO { int setlogin(char *namebuf); }
+51 AUE_ACCT NOPROTO { int acct(char *path); }
+52 AUE_SIGPENDING COMPAT { int freebsd32_sigpending(void); }
+53 AUE_SIGALTSTACK STD { int freebsd32_sigaltstack( \
+ struct sigaltstack32 *ss, \
+ struct sigaltstack32 *oss); }
+54 AUE_NULL STD { int freebsd32_ioctl(int fd, uint32_t com, \
+ struct md_ioctl32 *data); }
+55 AUE_REBOOT NOPROTO { int reboot(int opt); }
+56 AUE_REVOKE NOPROTO { int revoke(char *path); }
+57 AUE_SYMLINK NOPROTO { int symlink(char *path, char *link); }
+58 AUE_READLINK NOPROTO { ssize_t readlink(char *path, char *buf, \
+ size_t count); }
+59 AUE_EXECVE STD { int freebsd32_execve(char *fname, \
+ uint32_t *argv, uint32_t *envv); }
+60 AUE_UMASK NOPROTO { int umask(int newmask); } umask \
+ umask_args int
+61 AUE_CHROOT NOPROTO { int chroot(char *path); }
+62 AUE_FSTAT COMPAT { int freebsd32_fstat(int fd, \
+ struct ostat32 *ub); }
+63 AUE_NULL OBSOL ogetkerninfo
+64 AUE_NULL COMPAT { int freebsd32_getpagesize( \
+ int32_t dummy); }
+65 AUE_MSYNC NOPROTO { int msync(void *addr, size_t len, \
+ int flags); }
+66 AUE_VFORK NOPROTO { int vfork(void); }
+67 AUE_NULL OBSOL vread
+68 AUE_NULL OBSOL vwrite
+69 AUE_SBRK NOPROTO { int sbrk(int incr); }
+70 AUE_SSTK NOPROTO { int sstk(int incr); }
+71 AUE_MMAP COMPAT|NOPROTO { int mmap(void *addr, int len, \
+ int prot, int flags, int fd, int pos); }
+72 AUE_O_VADVISE NOPROTO { int ovadvise(int anom); } vadvise \
+ ovadvise_args int
+73 AUE_MUNMAP NOPROTO { int munmap(void *addr, size_t len); }
+74 AUE_MPROTECT STD { int freebsd32_mprotect(const void *addr, \
+ size_t len, int prot); }
+75 AUE_MADVISE NOPROTO { int madvise(void *addr, size_t len, \
+ int behav); }
+76 AUE_NULL OBSOL vhangup
+77 AUE_NULL OBSOL vlimit
+78 AUE_MINCORE NOPROTO { int mincore(const void *addr, size_t len, \
+ char *vec); }
+79 AUE_GETGROUPS NOPROTO { int getgroups(u_int gidsetsize, \
+ gid_t *gidset); }
+80 AUE_SETGROUPS NOPROTO { int setgroups(u_int gidsetsize, \
+ gid_t *gidset); }
+81 AUE_GETPGRP NOPROTO { int getpgrp(void); }
+82 AUE_SETPGRP NOPROTO { int setpgid(int pid, int pgid); }
+83 AUE_SETITIMER STD { int freebsd32_setitimer(u_int which, \
+ struct itimerval32 *itv, \
+ struct itimerval32 *oitv); }
+84 AUE_NULL OBSOL owait
+; XXX implement
+85 AUE_SWAPON NOPROTO { int swapon(char *name); }
+86 AUE_GETITIMER STD { int freebsd32_getitimer(u_int which, \
+ struct itimerval32 *itv); }
+87 AUE_O_GETHOSTNAME OBSOL ogethostname
+88 AUE_O_SETHOSTNAME OBSOL osethostname
+89 AUE_GETDTABLESIZE NOPROTO { int getdtablesize(void); }
+90 AUE_DUP2 NOPROTO { int dup2(u_int from, u_int to); }
+91 AUE_NULL UNIMPL getdopt
+92 AUE_FCNTL NOPROTO { int fcntl(int fd, int cmd, long arg); }
+93 AUE_SELECT STD { int freebsd32_select(int nd, fd_set *in, \
+ fd_set *ou, fd_set *ex, \
+ struct timeval32 *tv); }
+94 AUE_NULL UNIMPL setdopt
+95 AUE_FSYNC NOPROTO { int fsync(int fd); }
+96 AUE_SETPRIORITY NOPROTO { int setpriority(int which, int who, \
+ int prio); }
+97 AUE_SOCKET NOPROTO { int socket(int domain, int type, \
+ int protocol); }
+98 AUE_CONNECT NOPROTO { int connect(int s, caddr_t name, \
+ int namelen); }
+99 AUE_NULL OBSOL oaccept
+100 AUE_GETPRIORITY NOPROTO { int getpriority(int which, int who); }
+101 AUE_NULL OBSOL osend
+102 AUE_NULL OBSOL orecv
+103 AUE_NULL COMPAT { int freebsd32_sigreturn( \
+ struct ia32_sigcontext3 *sigcntxp); }
+104 AUE_BIND NOPROTO { int bind(int s, caddr_t name, \
+ int namelen); }
+105 AUE_SETSOCKOPT NOPROTO { int setsockopt(int s, int level, \
+ int name, caddr_t val, int valsize); }
+106 AUE_LISTEN NOPROTO { int listen(int s, int backlog); }
+107 AUE_NULL OBSOL vtimes
+108 AUE_O_SIGVEC COMPAT { int freebsd32_sigvec(int signum, \
+ struct sigvec32 *nsv, \
+ struct sigvec32 *osv); }
+109 AUE_O_SIGBLOCK COMPAT { int freebsd32_sigblock(int mask); }
+110 AUE_O_SIGSETMASK COMPAT { int freebsd32_sigsetmask( int mask); }
+111 AUE_SIGSUSPEND COMPAT { int freebsd32_sigsuspend( int mask); }
+112 AUE_O_SIGSTACK COMPAT { int freebsd32_sigstack( \
+ struct sigstack32 *nss, \
+ struct sigstack32 *oss); }
+113 AUE_NULL OBSOL orecvmsg
+114 AUE_NULL OBSOL osendmsg
+115 AUE_NULL OBSOL vtrace
+116 AUE_GETTIMEOFDAY STD { int freebsd32_gettimeofday( \
+ struct timeval32 *tp, \
+ struct timezone *tzp); }
+117 AUE_GETRUSAGE STD { int freebsd32_getrusage(int who, \
+ struct rusage32 *rusage); }
+118 AUE_GETSOCKOPT NOPROTO { int getsockopt(int s, int level, \
+ int name, caddr_t val, int *avalsize); }
+119 AUE_NULL UNIMPL resuba (BSD/OS 2.x)
+120 AUE_READV STD { int freebsd32_readv(int fd, \
+ struct iovec32 *iovp, u_int iovcnt); }
+121 AUE_WRITEV STD { int freebsd32_writev(int fd, \
+ struct iovec32 *iovp, u_int iovcnt); }
+122 AUE_SETTIMEOFDAY STD { int freebsd32_settimeofday( \
+ struct timeval32 *tv, \
+ struct timezone *tzp); }
+123 AUE_FCHOWN NOPROTO { int fchown(int fd, int uid, int gid); }
+124 AUE_FCHMOD NOPROTO { int fchmod(int fd, int mode); }
+125 AUE_RECVFROM OBSOL orecvfrom
+126 AUE_SETREUID NOPROTO { int setreuid(int ruid, int euid); }
+127 AUE_SETREGID NOPROTO { int setregid(int rgid, int egid); }
+128 AUE_RENAME NOPROTO { int rename(char *from, char *to); }
+129 AUE_TRUNCATE COMPAT|NOPROTO { int truncate(char *path, \
+ int length); }
+130 AUE_FTRUNCATE COMPAT|NOPROTO { int ftruncate(int fd, int length); }
+131 AUE_FLOCK NOPROTO { int flock(int fd, int how); }
+132 AUE_MKFIFO NOPROTO { int mkfifo(char *path, int mode); }
+133 AUE_SENDTO NOPROTO { int sendto(int s, caddr_t buf, \
+ size_t len, int flags, caddr_t to, \
+ int tolen); }
+134 AUE_SHUTDOWN NOPROTO { int shutdown(int s, int how); }
+135 AUE_SOCKETPAIR NOPROTO { int socketpair(int domain, int type, \
+ int protocol, int *rsv); }
+136 AUE_MKDIR NOPROTO { int mkdir(char *path, int mode); }
+137 AUE_RMDIR NOPROTO { int rmdir(char *path); }
+138 AUE_UTIMES STD { int freebsd32_utimes(char *path, \
+ struct timeval32 *tptr); }
+139 AUE_NULL OBSOL 4.2 sigreturn
+140 AUE_ADJTIME STD { int freebsd32_adjtime( \
+ struct timeval32 *delta, \
+ struct timeval32 *olddelta); }
+141 AUE_GETPEERNAME OBSOL ogetpeername
+142 AUE_SYSCTL OBSOL ogethostid
+143 AUE_SYSCTL OBSOL sethostid
+144 AUE_GETRLIMIT OBSOL getrlimit
+145 AUE_SETRLIMIT OBSOL setrlimit
+146 AUE_KILLPG OBSOL killpg
+147 AUE_SETSID NOPROTO { int setsid(void); }
+148 AUE_QUOTACTL NOPROTO { int quotactl(char *path, int cmd, int uid, \
+ caddr_t arg); }
+149 AUE_O_QUOTA OBSOL oquota
+150 AUE_GETSOCKNAME OBSOL ogetsockname
+
+; Syscalls 151-180 inclusive are reserved for vendor-specific
+; system calls. (This includes various calls added for compatibity
+; with other Unix variants.)
+; Some of these calls are now supported by BSD...
+151 AUE_NULL UNIMPL sem_lock (BSD/OS 2.x)
+152 AUE_NULL UNIMPL sem_wakeup (BSD/OS 2.x)
+153 AUE_NULL UNIMPL asyncdaemon (BSD/OS 2.x)
+; 154 is initialised by the NLM code, if present.
+154 AUE_NULL UNIMPL nlm_syscall
+; 155 is initialized by the NFS code, if present.
+; XXX this is a problem!!!
+155 AUE_NFS_SVC UNIMPL nfssvc
+156 AUE_GETDIRENTRIES COMPAT { int freebsd32_getdirentries(int fd, \
+ char *buf, u_int count, uint32_t *basep); }
+157 AUE_STATFS COMPAT4 { int freebsd32_statfs(char *path, \
+ struct statfs32 *buf); }
+158 AUE_FSTATFS COMPAT4 { int freebsd32_fstatfs(int fd, \
+ struct statfs32 *buf); }
+159 AUE_NULL UNIMPL nosys
+160 AUE_LGETFH UNIMPL lgetfh
+161 AUE_NFS_GETFH NOPROTO { int getfh(char *fname, \
+ struct fhandle *fhp); }
+162 AUE_NULL OBSOL getdomainname
+163 AUE_NULL OBSOL setdomainname
+164 AUE_NULL OBSOL uname
+165 AUE_SYSARCH STD { int freebsd32_sysarch(int op, char *parms); }
+166 AUE_RTPRIO NOPROTO { int rtprio(int function, pid_t pid, \
+ struct rtprio *rtp); }
+167 AUE_NULL UNIMPL nosys
+168 AUE_NULL UNIMPL nosys
+169 AUE_SEMSYS NOSTD { int freebsd32_semsys(int which, int a2, \
+ int a3, int a4, int a5); }
+170 AUE_MSGSYS NOSTD { int freebsd32_msgsys(int which, int a2, \
+ int a3, int a4, int a5, int a6); }
+171 AUE_SHMSYS NOSTD { int freebsd32_shmsys(uint32_t which, uint32_t a2, \
+ uint32_t a3, uint32_t a4); }
+172 AUE_NULL UNIMPL nosys
+173 AUE_PREAD COMPAT6 { ssize_t freebsd32_pread(int fd, void *buf, \
+ size_t nbyte, int pad, \
+ uint32_t offset1, uint32_t offset2); }
+174 AUE_PWRITE COMPAT6 { ssize_t freebsd32_pwrite(int fd, \
+ const void *buf, size_t nbyte, int pad, \
+ uint32_t offset1, uint32_t offset2); }
+175 AUE_NULL UNIMPL nosys
+176 AUE_NTP_ADJTIME NOPROTO { int ntp_adjtime(struct timex *tp); }
+177 AUE_NULL UNIMPL sfork (BSD/OS 2.x)
+178 AUE_NULL UNIMPL getdescriptor (BSD/OS 2.x)
+179 AUE_NULL UNIMPL setdescriptor (BSD/OS 2.x)
+180 AUE_NULL UNIMPL nosys
+
+; Syscalls 181-199 are used by/reserved for BSD
+181 AUE_SETGID NOPROTO { int setgid(gid_t gid); }
+182 AUE_SETEGID NOPROTO { int setegid(gid_t egid); }
+183 AUE_SETEUID NOPROTO { int seteuid(uid_t euid); }
+184 AUE_NULL UNIMPL lfs_bmapv
+185 AUE_NULL UNIMPL lfs_markv
+186 AUE_NULL UNIMPL lfs_segclean
+187 AUE_NULL UNIMPL lfs_segwait
+188 AUE_STAT STD { int freebsd32_stat(char *path, \
+ struct stat32 *ub); }
+189 AUE_FSTAT STD { int freebsd32_fstat(int fd, \
+ struct stat32 *ub); }
+190 AUE_LSTAT STD { int freebsd32_lstat(char *path, \
+ struct stat32 *ub); }
+191 AUE_PATHCONF NOPROTO { int pathconf(char *path, int name); }
+192 AUE_FPATHCONF NOPROTO { int fpathconf(int fd, int name); }
+193 AUE_NULL UNIMPL nosys
+194 AUE_GETRLIMIT NOPROTO { int getrlimit(u_int which, \
+ struct rlimit *rlp); } getrlimit \
+ __getrlimit_args int
+195 AUE_SETRLIMIT NOPROTO { int setrlimit(u_int which, \
+ struct rlimit *rlp); } setrlimit \
+ __setrlimit_args int
+196 AUE_GETDIRENTRIES STD { int freebsd32_getdirentries(int fd, \
+ char *buf, u_int count, int32_t *basep); }
+197 AUE_MMAP COMPAT6 { caddr_t freebsd32_mmap(caddr_t addr, \
+ size_t len, int prot, int flags, int fd, \
+ int pad, uint32_t pos1, uint32_t pos2); }
+198 AUE_NULL NOPROTO { int nosys(void); } __syscall \
+ __syscall_args int
+199 AUE_LSEEK COMPAT6 { off_t freebsd32_lseek(int fd, int pad, \
+ uint32_t offset1, uint32_t offset2, \
+ int whence); }
+200 AUE_TRUNCATE COMPAT6 { int freebsd32_truncate(char *path, \
+ int pad, uint32_t length1, \
+ uint32_t length2); }
+201 AUE_FTRUNCATE COMPAT6 { int freebsd32_ftruncate(int fd, int pad, \
+ uint32_t length1, uint32_t length2); }
+202 AUE_SYSCTL STD { int freebsd32_sysctl(int *name, \
+ u_int namelen, void *old, \
+ uint32_t *oldlenp, void *new, \
+ uint32_t newlen); }
+203 AUE_MLOCK NOPROTO { int mlock(const void *addr, \
+ size_t len); }
+204 AUE_MUNLOCK NOPROTO { int munlock(const void *addr, \
+ size_t len); }
+205 AUE_UNDELETE NOPROTO { int undelete(char *path); }
+206 AUE_FUTIMES STD { int freebsd32_futimes(int fd, \
+ struct timeval32 *tptr); }
+207 AUE_GETPGID NOPROTO { int getpgid(pid_t pid); }
+208 AUE_NULL UNIMPL newreboot (NetBSD)
+209 AUE_POLL NOPROTO { int poll(struct pollfd *fds, u_int nfds, \
+ int timeout); }
+
+;
+; The following are reserved for loadable syscalls
+;
+210 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int
+211 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int
+212 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int
+213 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int
+214 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int
+215 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int
+216 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int
+217 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int
+218 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int
+219 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int
+
+;
+; The following were introduced with NetBSD/4.4Lite-2
+; They are initialized by their respective modules/sysinits
+; XXX PROBLEM!!
+220 AUE_SEMCTL COMPAT7|NOSTD { int freebsd32_semctl( \
+ int semid, int semnum, \
+ int cmd, union semun32 *arg); }
+221 AUE_SEMGET NOSTD|NOPROTO { int semget(key_t key, int nsems, \
+ int semflg); }
+222 AUE_SEMOP NOSTD|NOPROTO { int semop(int semid, \
+ struct sembuf *sops, u_int nsops); }
+223 AUE_NULL UNIMPL semconfig
+224 AUE_MSGCTL COMPAT7|NOSTD { int freebsd32_msgctl( \
+ int msqid, int cmd, \
+ struct msqid_ds32_old *buf); }
+225 AUE_MSGGET NOSTD|NOPROTO { int msgget(key_t key, int msgflg); }
+226 AUE_MSGSND NOSTD { int freebsd32_msgsnd(int msqid, void *msgp, \
+ size_t msgsz, int msgflg); }
+227 AUE_MSGRCV NOSTD { int freebsd32_msgrcv(int msqid, void *msgp, \
+ size_t msgsz, long msgtyp, int msgflg); }
+228 AUE_SHMAT NOSTD|NOPROTO { int shmat(int shmid, void *shmaddr, \
+ int shmflg); }
+229 AUE_SHMCTL COMPAT7|NOSTD { int freebsd32_shmctl( \
+ int shmid, int cmd, \
+ struct shmid_ds32_old *buf); }
+230 AUE_SHMDT NOSTD|NOPROTO { int shmdt(void *shmaddr); }
+231 AUE_SHMGET NOSTD|NOPROTO { int shmget(key_t key, int size, \
+ int shmflg); }
+;
+232 AUE_NULL STD { int freebsd32_clock_gettime(clockid_t clock_id, \
+ struct timespec32 *tp); }
+233 AUE_CLOCK_SETTIME STD { int freebsd32_clock_settime(clockid_t clock_id, \
+ const struct timespec32 *tp); }
+234 AUE_NULL STD { int freebsd32_clock_getres(clockid_t clock_id, \
+ struct timespec32 *tp); }
+235 AUE_NULL UNIMPL timer_create
+236 AUE_NULL UNIMPL timer_delete
+237 AUE_NULL UNIMPL timer_settime
+238 AUE_NULL UNIMPL timer_gettime
+239 AUE_NULL UNIMPL timer_getoverrun
+240 AUE_NULL STD { int freebsd32_nanosleep( \
+ const struct timespec32 *rqtp, \
+ struct timespec32 *rmtp); }
+241 AUE_NULL NOPROTO { int ffclock_getcounter(ffcounter *ffcount); }
+242 AUE_NULL NOPROTO { int ffclock_setestimate( \
+ struct ffclock_estimate *cest); }
+243 AUE_NULL NOPROTO { int ffclock_getestimate( \
+ struct ffclock_estimate *cest); }
+244 AUE_NULL UNIMPL nosys
+245 AUE_NULL UNIMPL nosys
+246 AUE_NULL UNIMPL nosys
+247 AUE_NULL NOPROTO { int clock_getcpuclockid2(id_t id,\
+ int which, clockid_t *clock_id); }
+248 AUE_NULL UNIMPL ntp_gettime
+249 AUE_NULL UNIMPL nosys
+; syscall numbers initially used in OpenBSD
+250 AUE_MINHERIT NOPROTO { int minherit(void *addr, size_t len, \
+ int inherit); }
+251 AUE_RFORK NOPROTO { int rfork(int flags); }
+252 AUE_POLL NOPROTO { int openbsd_poll(struct pollfd *fds, \
+ u_int nfds, int timeout); }
+253 AUE_ISSETUGID NOPROTO { int issetugid(void); }
+254 AUE_LCHOWN NOPROTO { int lchown(char *path, int uid, int gid); }
+255 AUE_NULL NOSTD { int freebsd32_aio_read( \
+ struct aiocb32 *aiocbp); }
+256 AUE_NULL NOSTD { int freebsd32_aio_write( \
+ struct aiocb32 *aiocbp); }
+257 AUE_NULL NOSTD { int freebsd32_lio_listio(int mode, \
+ struct aiocb32 * const *acb_list, \
+ int nent, struct sigevent *sig); }
+258 AUE_NULL UNIMPL nosys
+259 AUE_NULL UNIMPL nosys
+260 AUE_NULL UNIMPL nosys
+261 AUE_NULL UNIMPL nosys
+262 AUE_NULL UNIMPL nosys
+263 AUE_NULL UNIMPL nosys
+264 AUE_NULL UNIMPL nosys
+265 AUE_NULL UNIMPL nosys
+266 AUE_NULL UNIMPL nosys
+267 AUE_NULL UNIMPL nosys
+268 AUE_NULL UNIMPL nosys
+269 AUE_NULL UNIMPL nosys
+270 AUE_NULL UNIMPL nosys
+271 AUE_NULL UNIMPL nosys
+272 AUE_O_GETDENTS NOPROTO { int getdents(int fd, char *buf, \
+ size_t count); }
+273 AUE_NULL UNIMPL nosys
+274 AUE_LCHMOD NOPROTO { int lchmod(char *path, mode_t mode); }
+275 AUE_LCHOWN NOPROTO { int lchown(char *path, uid_t uid, \
+ gid_t gid); } netbsd_lchown \
+ lchown_args int
+276 AUE_LUTIMES STD { int freebsd32_lutimes(char *path, \
+ struct timeval32 *tptr); }
+277 AUE_MSYNC NOPROTO { int msync(void *addr, size_t len, \
+ int flags); } netbsd_msync msync_args int
+278 AUE_STAT NOPROTO { int nstat(char *path, struct nstat *ub); }
+279 AUE_FSTAT NOPROTO { int nfstat(int fd, struct nstat *sb); }
+280 AUE_LSTAT NOPROTO { int nlstat(char *path, struct nstat *ub); }
+281 AUE_NULL UNIMPL nosys
+282 AUE_NULL UNIMPL nosys
+283 AUE_NULL UNIMPL nosys
+284 AUE_NULL UNIMPL nosys
+285 AUE_NULL UNIMPL nosys
+286 AUE_NULL UNIMPL nosys
+287 AUE_NULL UNIMPL nosys
+288 AUE_NULL UNIMPL nosys
+; 289 and 290 from NetBSD (OpenBSD: 267 and 268)
+289 AUE_PREADV STD { ssize_t freebsd32_preadv(int fd, \
+ struct iovec32 *iovp, \
+ u_int iovcnt, \
+ uint32_t offset1, uint32_t offset2); }
+290 AUE_PWRITEV STD { ssize_t freebsd32_pwritev(int fd, \
+ struct iovec32 *iovp, \
+ u_int iovcnt, \
+ uint32_t offset1, uint32_t offset2); }
+291 AUE_NULL UNIMPL nosys
+292 AUE_NULL UNIMPL nosys
+293 AUE_NULL UNIMPL nosys
+294 AUE_NULL UNIMPL nosys
+295 AUE_NULL UNIMPL nosys
+296 AUE_NULL UNIMPL nosys
+; XXX 297 is 300 in NetBSD
+297 AUE_FHSTATFS COMPAT4 { int freebsd32_fhstatfs( \
+ const struct fhandle *u_fhp, \
+ struct statfs32 *buf); }
+298 AUE_FHOPEN NOPROTO { int fhopen(const struct fhandle *u_fhp, \
+ int flags); }
+299 AUE_FHSTAT NOPROTO { int fhstat(const struct fhandle *u_fhp, \
+ struct stat *sb); }
+; syscall numbers for FreeBSD
+300 AUE_NULL NOPROTO { int modnext(int modid); }
+301 AUE_NULL STD { int freebsd32_modstat(int modid, \
+ struct module_stat32* stat); }
+302 AUE_NULL NOPROTO { int modfnext(int modid); }
+303 AUE_NULL NOPROTO { int modfind(const char *name); }
+304 AUE_MODLOAD NOPROTO { int kldload(const char *file); }
+305 AUE_MODUNLOAD NOPROTO { int kldunload(int fileid); }
+306 AUE_NULL NOPROTO { int kldfind(const char *file); }
+307 AUE_NULL NOPROTO { int kldnext(int fileid); }
+308 AUE_NULL STD { int freebsd32_kldstat(int fileid, \
+ struct kld32_file_stat* stat); }
+309 AUE_NULL NOPROTO { int kldfirstmod(int fileid); }
+310 AUE_GETSID NOPROTO { int getsid(pid_t pid); }
+311 AUE_SETRESUID NOPROTO { int setresuid(uid_t ruid, uid_t euid, \
+ uid_t suid); }
+312 AUE_SETRESGID NOPROTO { int setresgid(gid_t rgid, gid_t egid, \
+ gid_t sgid); }
+313 AUE_NULL OBSOL signanosleep
+314 AUE_NULL NOSTD { int freebsd32_aio_return( \
+ struct aiocb32 *aiocbp); }
+315 AUE_NULL NOSTD { int freebsd32_aio_suspend( \
+ struct aiocb32 * const * aiocbp, int nent, \
+ const struct timespec32 *timeout); }
+316 AUE_NULL NOSTD { int freebsd32_aio_cancel(int fd, \
+ struct aiocb32 *aiocbp); }
+317 AUE_NULL NOSTD { int freebsd32_aio_error( \
+ struct aiocb32 *aiocbp); }
+318 AUE_NULL NOSTD { int freebsd32_oaio_read( \
+ struct oaiocb32 *aiocbp); }
+319 AUE_NULL NOSTD { int freebsd32_oaio_write( \
+ struct oaiocb32 *aiocbp); }
+320 AUE_NULL NOSTD { int freebsd32_olio_listio(int mode, \
+ struct oaiocb32 * const *acb_list, \
+ int nent, struct osigevent32 *sig); }
+321 AUE_NULL NOPROTO { int yield(void); }
+322 AUE_NULL OBSOL thr_sleep
+323 AUE_NULL OBSOL thr_wakeup
+324 AUE_MLOCKALL NOPROTO { int mlockall(int how); }
+325 AUE_MUNLOCKALL NOPROTO { int munlockall(void); }
+326 AUE_GETCWD NOPROTO { int __getcwd(u_char *buf, u_int buflen); }
+
+327 AUE_NULL NOPROTO { int sched_setparam (pid_t pid, \
+ const struct sched_param *param); }
+328 AUE_NULL NOPROTO { int sched_getparam (pid_t pid, \
+ struct sched_param *param); }
+
+329 AUE_NULL NOPROTO { int sched_setscheduler (pid_t pid, \
+ int policy, \
+ const struct sched_param *param); }
+330 AUE_NULL NOPROTO { int sched_getscheduler (pid_t pid); }
+
+331 AUE_NULL NOPROTO { int sched_yield (void); }
+332 AUE_NULL NOPROTO { int sched_get_priority_max (int policy); }
+333 AUE_NULL NOPROTO { int sched_get_priority_min (int policy); }
+334 AUE_NULL NOPROTO { int sched_rr_get_interval (pid_t pid, \
+ struct timespec *interval); }
+335 AUE_NULL NOPROTO { int utrace(const void *addr, size_t len); }
+336 AUE_SENDFILE COMPAT4 { int freebsd32_sendfile(int fd, int s, \
+ uint32_t offset1, uint32_t offset2, \
+ size_t nbytes, struct sf_hdtr32 *hdtr, \
+ off_t *sbytes, int flags); }
+337 AUE_NULL NOPROTO { int kldsym(int fileid, int cmd, \
+ void *data); }
+338 AUE_JAIL STD { int freebsd32_jail(struct jail32 *jail); }
+339 AUE_NULL UNIMPL pioctl
+340 AUE_SIGPROCMASK NOPROTO { int sigprocmask(int how, \
+ const sigset_t *set, sigset_t *oset); }
+341 AUE_SIGSUSPEND NOPROTO { int sigsuspend(const sigset_t *sigmask); }
+342 AUE_SIGACTION COMPAT4 { int freebsd32_sigaction(int sig, \
+ struct sigaction32 *act, \
+ struct sigaction32 *oact); }
+343 AUE_SIGPENDING NOPROTO { int sigpending(sigset_t *set); }
+344 AUE_SIGRETURN COMPAT4 { int freebsd32_sigreturn( \
+ const struct freebsd4_freebsd32_ucontext *sigcntxp); }
+345 AUE_SIGWAIT STD { int freebsd32_sigtimedwait(const sigset_t *set, \
+ siginfo_t *info, \
+ const struct timespec *timeout); }
+346 AUE_NULL STD { int freebsd32_sigwaitinfo(const sigset_t *set, \
+ siginfo_t *info); }
+347 AUE_NULL NOPROTO { int __acl_get_file(const char *path, \
+ acl_type_t type, struct acl *aclp); }
+348 AUE_NULL NOPROTO { int __acl_set_file(const char *path, \
+ acl_type_t type, struct acl *aclp); }
+349 AUE_NULL NOPROTO { int __acl_get_fd(int filedes, \
+ acl_type_t type, struct acl *aclp); }
+350 AUE_NULL NOPROTO { int __acl_set_fd(int filedes, \
+ acl_type_t type, struct acl *aclp); }
+351 AUE_NULL NOPROTO { int __acl_delete_file(const char *path, \
+ acl_type_t type); }
+352 AUE_NULL NOPROTO { int __acl_delete_fd(int filedes, \
+ acl_type_t type); }
+353 AUE_NULL NOPROTO { int __acl_aclcheck_file(const char *path, \
+ acl_type_t type, struct acl *aclp); }
+354 AUE_NULL NOPROTO { int __acl_aclcheck_fd(int filedes, \
+ acl_type_t type, struct acl *aclp); }
+355 AUE_EXTATTRCTL NOPROTO { int extattrctl(const char *path, int cmd, \
+ const char *filename, int attrnamespace, \
+ const char *attrname); }
+356 AUE_EXTATTR_SET_FILE NOPROTO { ssize_t extattr_set_file( \
+ const char *path, int attrnamespace, \
+ const char *attrname, void *data, \
+ size_t nbytes); }
+357 AUE_EXTATTR_GET_FILE NOPROTO { ssize_t extattr_get_file( \
+ const char *path, int attrnamespace, \
+ const char *attrname, void *data, \
+ size_t nbytes); }
+358 AUE_EXTATTR_DELETE_FILE NOPROTO { int extattr_delete_file( \
+ const char *path, int attrnamespace, \
+ const char *attrname); }
+359 AUE_NULL NOSTD { int freebsd32_aio_waitcomplete( \
+ struct aiocb32 **aiocbp, \
+ struct timespec32 *timeout); }
+360 AUE_GETRESUID NOPROTO { int getresuid(uid_t *ruid, uid_t *euid, \
+ uid_t *suid); }
+361 AUE_GETRESGID NOPROTO { int getresgid(gid_t *rgid, gid_t *egid, \
+ gid_t *sgid); }
+362 AUE_KQUEUE NOPROTO { int kqueue(void); }
+363 AUE_NULL STD { int freebsd32_kevent(int fd, \
+ const struct kevent32 *changelist, \
+ int nchanges, \
+ struct kevent32 *eventlist, int nevents, \
+ const struct timespec32 *timeout); }
+364 AUE_NULL UNIMPL __cap_get_proc
+365 AUE_NULL UNIMPL __cap_set_proc
+366 AUE_NULL UNIMPL __cap_get_fd
+367 AUE_NULL UNIMPL __cap_get_file
+368 AUE_NULL UNIMPL __cap_set_fd
+369 AUE_NULL UNIMPL __cap_set_file
+370 AUE_NULL UNIMPL nosys
+371 AUE_EXTATTR_SET_FD NOPROTO { ssize_t extattr_set_fd(int fd, \
+ int attrnamespace, const char *attrname, \
+ void *data, size_t nbytes); }
+372 AUE_EXTATTR_GET_FD NOPROTO { ssize_t extattr_get_fd(int fd, \
+ int attrnamespace, const char *attrname, \
+ void *data, size_t nbytes); }
+373 AUE_EXTATTR_DELETE_FD NOPROTO { int extattr_delete_fd(int fd, \
+ int attrnamespace, \
+ const char *attrname); }
+374 AUE_NULL NOPROTO { int __setugid(int flag); }
+375 AUE_NULL UNIMPL nfsclnt
+376 AUE_EACCESS NOPROTO { int eaccess(char *path, int amode); }
+377 AUE_NULL UNIMPL afs_syscall
+378 AUE_NMOUNT STD { int freebsd32_nmount(struct iovec32 *iovp, \
+ unsigned int iovcnt, int flags); }
+379 AUE_NULL UNIMPL kse_exit
+380 AUE_NULL UNIMPL kse_wakeup
+381 AUE_NULL UNIMPL kse_create
+382 AUE_NULL UNIMPL kse_thr_interrupt
+383 AUE_NULL UNIMPL kse_release
+384 AUE_NULL UNIMPL __mac_get_proc
+385 AUE_NULL UNIMPL __mac_set_proc
+386 AUE_NULL UNIMPL __mac_get_fd
+387 AUE_NULL UNIMPL __mac_get_file
+388 AUE_NULL UNIMPL __mac_set_fd
+389 AUE_NULL UNIMPL __mac_set_file
+390 AUE_NULL NOPROTO { int kenv(int what, const char *name, \
+ char *value, int len); }
+391 AUE_LCHFLAGS NOPROTO { int lchflags(const char *path, \
+ u_long flags); }
+392 AUE_NULL NOPROTO { int uuidgen(struct uuid *store, \
+ int count); }
+393 AUE_SENDFILE STD { int freebsd32_sendfile(int fd, int s, \
+ uint32_t offset1, uint32_t offset2, \
+ size_t nbytes, struct sf_hdtr32 *hdtr, \
+ off_t *sbytes, int flags); }
+394 AUE_NULL UNIMPL mac_syscall
+395 AUE_GETFSSTAT NOPROTO { int getfsstat(struct statfs *buf, \
+ long bufsize, int flags); }
+396 AUE_STATFS NOPROTO { int statfs(char *path, \
+ struct statfs *buf); }
+397 AUE_FSTATFS NOPROTO { int fstatfs(int fd, struct statfs *buf); }
+398 AUE_FHSTATFS NOPROTO { int fhstatfs(const struct fhandle *u_fhp, \
+ struct statfs *buf); }
+399 AUE_NULL UNIMPL nosys
+400 AUE_NULL NOSTD|NOPROTO { int ksem_close(semid_t id); }
+401 AUE_NULL NOSTD|NOPROTO { int ksem_post(semid_t id); }
+402 AUE_NULL NOSTD|NOPROTO { int ksem_wait(semid_t id); }
+403 AUE_NULL NOSTD|NOPROTO { int ksem_trywait(semid_t id); }
+404 AUE_NULL NOSTD { int freebsd32_ksem_init(semid_t *idp, \
+ unsigned int value); }
+405 AUE_NULL NOSTD { int freebsd32_ksem_open(semid_t *idp, \
+ const char *name, int oflag, \
+ mode_t mode, unsigned int value); }
+406 AUE_NULL NOSTD|NOPROTO { int ksem_unlink(const char *name); }
+407 AUE_NULL NOSTD|NOPROTO { int ksem_getvalue(semid_t id, \
+ int *val); }
+408 AUE_NULL NOSTD|NOPROTO { int ksem_destroy(semid_t id); }
+409 AUE_NULL UNIMPL __mac_get_pid
+410 AUE_NULL UNIMPL __mac_get_link
+411 AUE_NULL UNIMPL __mac_set_link
+412 AUE_EXTATTR_SET_LINK NOPROTO { ssize_t extattr_set_link( \
+ const char *path, int attrnamespace, \
+ const char *attrname, void *data, \
+ size_t nbytes); }
+413 AUE_EXTATTR_GET_LINK NOPROTO { ssize_t extattr_get_link( \
+ const char *path, int attrnamespace, \
+ const char *attrname, void *data, \
+ size_t nbytes); }
+414 AUE_EXTATTR_DELETE_LINK NOPROTO { int extattr_delete_link( \
+ const char *path, int attrnamespace, \
+ const char *attrname); }
+415 AUE_NULL UNIMPL __mac_execve
+416 AUE_SIGACTION STD { int freebsd32_sigaction(int sig, \
+ struct sigaction32 *act, \
+ struct sigaction32 *oact); }
+417 AUE_SIGRETURN STD { int freebsd32_sigreturn( \
+ const struct freebsd32_ucontext *sigcntxp); }
+418 AUE_NULL UNIMPL __xstat
+419 AUE_NULL UNIMPL __xfstat
+420 AUE_NULL UNIMPL __xlstat
+421 AUE_NULL STD { int freebsd32_getcontext( \
+ struct freebsd32_ucontext *ucp); }
+422 AUE_NULL STD { int freebsd32_setcontext( \
+ const struct freebsd32_ucontext *ucp); }
+423 AUE_NULL STD { int freebsd32_swapcontext( \
+ struct freebsd32_ucontext *oucp, \
+ const struct freebsd32_ucontext *ucp); }
+424 AUE_SWAPOFF UNIMPL swapoff
+425 AUE_NULL NOPROTO { int __acl_get_link(const char *path, \
+ acl_type_t type, struct acl *aclp); }
+426 AUE_NULL NOPROTO { int __acl_set_link(const char *path, \
+ acl_type_t type, struct acl *aclp); }
+427 AUE_NULL NOPROTO { int __acl_delete_link(const char *path, \
+ acl_type_t type); }
+428 AUE_NULL NOPROTO { int __acl_aclcheck_link(const char *path, \
+ acl_type_t type, struct acl *aclp); }
+429 AUE_SIGWAIT NOPROTO { int sigwait(const sigset_t *set, \
+ int *sig); }
+430 AUE_NULL UNIMPL thr_create;
+431 AUE_NULL NOPROTO { void thr_exit(long *state); }
+432 AUE_NULL NOPROTO { int thr_self(long *id); }
+433 AUE_NULL NOPROTO { int thr_kill(long id, int sig); }
+434 AUE_NULL STD { int freebsd32_umtx_lock(struct umtx *umtx); }
+435 AUE_NULL STD { int freebsd32_umtx_unlock(struct umtx *umtx); }
+436 AUE_NULL NOPROTO { int jail_attach(int jid); }
+437 AUE_EXTATTR_LIST_FD NOPROTO { ssize_t extattr_list_fd(int fd, \
+ int attrnamespace, void *data, \
+ size_t nbytes); }
+438 AUE_EXTATTR_LIST_FILE NOPROTO { ssize_t extattr_list_file( \
+ const char *path, int attrnamespace, \
+ void *data, size_t nbytes); }
+439 AUE_EXTATTR_LIST_LINK NOPROTO { ssize_t extattr_list_link( \
+ const char *path, int attrnamespace, \
+ void *data, size_t nbytes); }
+440 AUE_NULL UNIMPL kse_switchin
+441 AUE_NULL NOSTD { int freebsd32_ksem_timedwait(semid_t id, \
+ const struct timespec32 *abstime); }
+442 AUE_NULL STD { int freebsd32_thr_suspend( \
+ const struct timespec32 *timeout); }
+443 AUE_NULL NOPROTO { int thr_wake(long id); }
+444 AUE_MODUNLOAD NOPROTO { int kldunloadf(int fileid, int flags); }
+445 AUE_AUDIT NOPROTO { int audit(const void *record, \
+ u_int length); }
+446 AUE_AUDITON NOPROTO { int auditon(int cmd, void *data, \
+ u_int length); }
+447 AUE_GETAUID NOPROTO { int getauid(uid_t *auid); }
+448 AUE_SETAUID NOPROTO { int setauid(uid_t *auid); }
+449 AUE_GETAUDIT NOPROTO { int getaudit(struct auditinfo *auditinfo); }
+450 AUE_SETAUDIT NOPROTO { int setaudit(struct auditinfo *auditinfo); }
+451 AUE_GETAUDIT_ADDR NOPROTO { int getaudit_addr( \
+ struct auditinfo_addr *auditinfo_addr, \
+ u_int length); }
+452 AUE_SETAUDIT_ADDR NOPROTO { int setaudit_addr( \
+ struct auditinfo_addr *auditinfo_addr, \
+ u_int length); }
+453 AUE_AUDITCTL NOPROTO { int auditctl(char *path); }
+454 AUE_NULL STD { int freebsd32_umtx_op(void *obj, int op,\
+ u_long val, void *uaddr, \
+ void *uaddr2); }
+455 AUE_NULL STD { int freebsd32_thr_new( \
+ struct thr_param32 *param, \
+ int param_size); }
+456 AUE_NULL NOPROTO { int sigqueue(pid_t pid, int signum, \
+ void *value); }
+457 AUE_NULL NOSTD { int freebsd32_kmq_open( \
+ const char *path, int flags, mode_t mode, \
+ const struct mq_attr32 *attr); }
+458 AUE_NULL NOSTD { int freebsd32_kmq_setattr(int mqd, \
+ const struct mq_attr32 *attr, \
+ struct mq_attr32 *oattr); }
+459 AUE_NULL NOSTD { int freebsd32_kmq_timedreceive(int mqd, \
+ char *msg_ptr, size_t msg_len, \
+ unsigned *msg_prio, \
+ const struct timespec32 *abs_timeout); }
+460 AUE_NULL NOSTD { int freebsd32_kmq_timedsend(int mqd, \
+ const char *msg_ptr, size_t msg_len,\
+ unsigned msg_prio, \
+ const struct timespec32 *abs_timeout);}
+461 AUE_NULL NOPROTO|NOSTD { int kmq_notify(int mqd, \
+ const struct sigevent *sigev); }
+462 AUE_NULL NOPROTO|NOSTD { int kmq_unlink(const char *path); }
+463 AUE_NULL NOPROTO { int abort2(const char *why, int nargs, void **args); }
+464 AUE_NULL NOPROTO { int thr_set_name(long id, const char *name); }
+465 AUE_NULL NOSTD { int freebsd32_aio_fsync(int op, \
+ struct aiocb32 *aiocbp); }
+466 AUE_RTPRIO NOPROTO { int rtprio_thread(int function, \
+ lwpid_t lwpid, struct rtprio *rtp); }
+467 AUE_NULL UNIMPL nosys
+468 AUE_NULL UNIMPL nosys
+469 AUE_NULL UNIMPL __getpath_fromfd
+470 AUE_NULL UNIMPL __getpath_fromaddr
+471 AUE_NULL NOPROTO { int sctp_peeloff(int sd, uint32_t name); }
+472 AUE_NULL NOPROTO { int sctp_generic_sendmsg(int sd, caddr_t msg, int mlen, \
+ caddr_t to, __socklen_t tolen, \
+ struct sctp_sndrcvinfo *sinfo, int flags); }
+473 AUE_NULL NOPROTO { int sctp_generic_sendmsg_iov(int sd, struct iovec *iov, int iovlen, \
+ caddr_t to, __socklen_t tolen, \
+ struct sctp_sndrcvinfo *sinfo, int flags); }
+474 AUE_NULL NOPROTO { int sctp_generic_recvmsg(int sd, struct iovec *iov, int iovlen, \
+ struct sockaddr * from, __socklen_t *fromlenaddr, \
+ struct sctp_sndrcvinfo *sinfo, int *msg_flags); }
+#ifdef PAD64_REQUIRED
+475 AUE_PREAD STD { ssize_t freebsd32_pread(int fd, \
+ void *buf,size_t nbyte, \
+ int pad, \
+ uint32_t offset1, uint32_t offset2); }
+476 AUE_PWRITE STD { ssize_t freebsd32_pwrite(int fd, \
+ const void *buf, size_t nbyte, \
+ int pad, \
+ uint32_t offset1, uint32_t offset2); }
+477 AUE_MMAP STD { caddr_t freebsd32_mmap(caddr_t addr, \
+ size_t len, int prot, int flags, int fd, \
+ int pad, \
+ uint32_t pos1, uint32_t pos2); }
+478 AUE_LSEEK STD { off_t freebsd32_lseek(int fd, \
+ int pad, \
+ uint32_t offset1, uint32_t offset2, \
+ int whence); }
+479 AUE_TRUNCATE STD { int freebsd32_truncate(char *path, \
+ int pad, \
+ uint32_t length1, uint32_t length2); }
+480 AUE_FTRUNCATE STD { int freebsd32_ftruncate(int fd, \
+ int pad, \
+ uint32_t length1, uint32_t length2); }
+#else
+475 AUE_PREAD STD { ssize_t freebsd32_pread(int fd, \
+ void *buf,size_t nbyte, \
+ uint32_t offset1, uint32_t offset2); }
+476 AUE_PWRITE STD { ssize_t freebsd32_pwrite(int fd, \
+ const void *buf, size_t nbyte, \
+ uint32_t offset1, uint32_t offset2); }
+477 AUE_MMAP STD { caddr_t freebsd32_mmap(caddr_t addr, \
+ size_t len, int prot, int flags, int fd, \
+ uint32_t pos1, uint32_t pos2); }
+478 AUE_LSEEK STD { off_t freebsd32_lseek(int fd, \
+ uint32_t offset1, uint32_t offset2, \
+ int whence); }
+479 AUE_TRUNCATE STD { int freebsd32_truncate(char *path, \
+ uint32_t length1, uint32_t length2); }
+480 AUE_FTRUNCATE STD { int freebsd32_ftruncate(int fd, \
+ uint32_t length1, uint32_t length2); }
+#endif
+481 AUE_KILL NOPROTO { int thr_kill2(pid_t pid, long id, int sig); }
+482 AUE_SHMOPEN NOPROTO { int shm_open(const char *path, int flags, \
+ mode_t mode); }
+483 AUE_SHMUNLINK NOPROTO { int shm_unlink(const char *path); }
+484 AUE_NULL NOPROTO { int cpuset(cpusetid_t *setid); }
+#ifdef PAD64_REQUIRED
+485 AUE_NULL STD { int freebsd32_cpuset_setid(cpuwhich_t which, \
+ int pad, \
+ uint32_t id1, uint32_t id2, \
+ cpusetid_t setid); }
+#else
+485 AUE_NULL STD { int freebsd32_cpuset_setid(cpuwhich_t which, \
+ uint32_t id1, uint32_t id2, \
+ cpusetid_t setid); }
+#endif
+486 AUE_NULL STD { int freebsd32_cpuset_getid(cpulevel_t level, \
+ cpuwhich_t which, \
+ uint32_t id1, uint32_t id2, \
+ cpusetid_t *setid); }
+487 AUE_NULL STD { int freebsd32_cpuset_getaffinity( \
+ cpulevel_t level, cpuwhich_t which, \
+ uint32_t id1, uint32_t id2, \
+ size_t cpusetsize, \
+ cpuset_t *mask); }
+488 AUE_NULL STD { int freebsd32_cpuset_setaffinity( \
+ cpulevel_t level, cpuwhich_t which, \
+ uint32_t id1, uint32_t id2, \
+ size_t cpusetsize, \
+ const cpuset_t *mask); }
+489 AUE_FACCESSAT NOPROTO { int faccessat(int fd, char *path, int amode, \
+ int flag); }
+490 AUE_FCHMODAT NOPROTO { int fchmodat(int fd, const char *path, \
+ mode_t mode, int flag); }
+491 AUE_FCHOWNAT NOPROTO { int fchownat(int fd, char *path, uid_t uid, \
+ gid_t gid, int flag); }
+492 AUE_FEXECVE STD { int freebsd32_fexecve(int fd, \
+ uint32_t *argv, uint32_t *envv); }
+493 AUE_FSTATAT STD { int freebsd32_fstatat(int fd, char *path, \
+ struct stat *buf, int flag); }
+494 AUE_FUTIMESAT STD { int freebsd32_futimesat(int fd, char *path, \
+ struct timeval *times); }
+495 AUE_LINKAT NOPROTO { int linkat(int fd1, char *path1, int fd2, \
+ char *path2, int flag); }
+496 AUE_MKDIRAT NOPROTO { int mkdirat(int fd, char *path, \
+ mode_t mode); }
+497 AUE_MKFIFOAT NOPROTO { int mkfifoat(int fd, char *path, \
+ mode_t mode); }
+498 AUE_MKNODAT NOPROTO { int mknodat(int fd, char *path, \
+ mode_t mode, dev_t dev); }
+499 AUE_OPENAT_RWTC NOPROTO { int openat(int fd, char *path, int flag, \
+ mode_t mode); }
+500 AUE_READLINKAT NOPROTO { int readlinkat(int fd, char *path, char *buf, \
+ size_t bufsize); }
+501 AUE_RENAMEAT NOPROTO { int renameat(int oldfd, char *old, int newfd, \
+ const char *new); }
+502 AUE_SYMLINKAT NOPROTO { int symlinkat(char *path1, int fd, \
+ char *path2); }
+503 AUE_UNLINKAT NOPROTO { int unlinkat(int fd, char *path, \
+ int flag); }
+504 AUE_POSIX_OPENPT NOPROTO { int posix_openpt(int flags); }
+; 505 is initialised by the kgssapi code, if present.
+505 AUE_NULL UNIMPL gssd_syscall
+506 AUE_NULL STD { int freebsd32_jail_get(struct iovec32 *iovp, \
+ unsigned int iovcnt, int flags); }
+507 AUE_NULL STD { int freebsd32_jail_set(struct iovec32 *iovp, \
+ unsigned int iovcnt, int flags); }
+508 AUE_NULL NOPROTO { int jail_remove(int jid); }
+509 AUE_CLOSEFROM NOPROTO { int closefrom(int lowfd); }
+510 AUE_SEMCTL NOSTD { int freebsd32_semctl(int semid, int semnum, \
+ int cmd, union semun32 *arg); }
+511 AUE_MSGCTL NOSTD { int freebsd32_msgctl(int msqid, int cmd, \
+ struct msqid_ds32 *buf); }
+512 AUE_SHMCTL NOSTD { int freebsd32_shmctl(int shmid, int cmd, \
+ struct shmid_ds32 *buf); }
+513 AUE_LPATHCONF NOPROTO { int lpathconf(char *path, int name); }
+514 AUE_CAP_NEW NOPROTO { int cap_new(int fd, uint64_t rights); }
+515 AUE_CAP_RIGHTS_GET NOPROTO { int cap_rights_get(int fd, \
+ uint64_t *rightsp); }
+516 AUE_CAP_ENTER NOPROTO { int cap_enter(void); }
+517 AUE_CAP_GETMODE NOPROTO { int cap_getmode(u_int *modep); }
+518 AUE_PDFORK UNIMPL pdfork
+519 AUE_PDKILL UNIMPL pdkill
+520 AUE_PDGETPID UNIMPL pdgetpid
+521 AUE_PDWAIT UNIMPL pdwait
+522 AUE_SELECT STD { int freebsd32_pselect(int nd, fd_set *in, \
+ fd_set *ou, fd_set *ex, \
+ const struct timespec32 *ts, \
+ const sigset_t *sm); }
+523 AUE_NULL NOPROTO { int getloginclass(char *namebuf, \
+ size_t namelen); }
+524 AUE_NULL NOPROTO { int setloginclass(const char *namebuf); }
+525 AUE_NULL NOPROTO { int rctl_get_racct(const void *inbufp, \
+ size_t inbuflen, void *outbufp, \
+ size_t outbuflen); }
+526 AUE_NULL NOPROTO { int rctl_get_rules(const void *inbufp, \
+ size_t inbuflen, void *outbufp, \
+ size_t outbuflen); }
+527 AUE_NULL NOPROTO { int rctl_get_limits(const void *inbufp, \
+ size_t inbuflen, void *outbufp, \
+ size_t outbuflen); }
+528 AUE_NULL NOPROTO { int rctl_add_rule(const void *inbufp, \
+ size_t inbuflen, void *outbufp, \
+ size_t outbuflen); }
+529 AUE_NULL NOPROTO { int rctl_remove_rule(const void *inbufp, \
+ size_t inbuflen, void *outbufp, \
+ size_t outbuflen); }
+#ifdef PAD64_REQUIRED
+530 AUE_NULL STD { int freebsd32_posix_fallocate(int fd, \
+ int pad, \
+ uint32_t offset1, uint32_t offset2,\
+ uint32_t len1, uint32_t len2); }
+531 AUE_NULL STD { int freebsd32_posix_fadvise(int fd, \
+ int pad, \
+ uint32_t offset1, uint32_t offset2,\
+ uint32_t len1, uint32_t len2, \
+ int advice); }
+532 AUE_WAIT6 STD { int freebsd32_wait6(int idtype, int pad, \
+ uint32_t id1, uint32_t id2, \
+ int *status, int options, \
+ struct wrusage32 *wrusage, \
+ siginfo_t *info); }
+#else
+530 AUE_NULL STD { int freebsd32_posix_fallocate(int fd,\
+ uint32_t offset1, uint32_t offset2,\
+ uint32_t len1, uint32_t len2); }
+531 AUE_NULL STD { int freebsd32_posix_fadvise(int fd, \
+ uint32_t offset1, uint32_t offset2,\
+ uint32_t len1, uint32_t len2, \
+ int advice); }
+532 AUE_WAIT6 STD { int freebsd32_wait6(int idtype, \
+ uint32_t id1, uint32_t id2, \
+ int *status, int options, \
+ struct wrusage32 *wrusage, \
+ siginfo_t *info); }
+#endif
+533 AUE_CAP_RIGHTS_LIMIT NOPROTO { int cap_rights_limit(int fd, \
+ uint64_t rights); }
+534 AUE_CAP_IOCTLS_LIMIT NOPROTO { int cap_ioctls_limit(int fd, \
+ const u_long *cmds, size_t ncmds); }
+535 AUE_CAP_IOCTLS_GET NOPROTO { ssize_t cap_ioctls_get(int fd, \
+ u_long *cmds, size_t maxcmds); }
+536 AUE_CAP_FCNTLS_LIMIT NOPROTO { int cap_fcntls_limit(int fd, \
+ uint32_t fcntlrights); }
+537 AUE_CAP_FCNTLS_GET NOPROTO { int cap_fcntls_get(int fd, \
+ uint32_t *fcntlrightsp); }
+538 AUE_BINDAT NOPROTO { int bindat(int fd, int s, caddr_t name, \
+ int namelen); }
+539 AUE_CONNECTAT NOPROTO { int connectat(int fd, int s, caddr_t name, \
+ int namelen); }
+540 AUE_CHFLAGSAT NOPROTO { int chflagsat(int fd, const char *path, \
+ u_long flags, int atflag); }
+541 AUE_ACCEPT NOPROTO { int accept4(int s, \
+ struct sockaddr * __restrict name, \
+ __socklen_t * __restrict anamelen, \
+ int flags); }
+542 AUE_PIPE NOPROTO { int pipe2(int *fildes, int flags); }
+543 AUE_NULL NOSTD { int freebsd32_aio_mlock( \
+ struct aiocb32 *aiocbp); }
diff --git a/sys/compat/ia32/ia32_genassym.c b/sys/compat/ia32/ia32_genassym.c
new file mode 100644
index 0000000..5462a8b
--- /dev/null
+++ b/sys/compat/ia32/ia32_genassym.c
@@ -0,0 +1,29 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_compat.h"
+
+#include <sys/param.h>
+#include <sys/assym.h>
+#include <sys/systm.h>
+#include <sys/signal.h>
+
+#include <compat/freebsd32/freebsd32_signal.h>
+#include <compat/ia32/ia32_signal.h>
+
+ASSYM(IA32_SIGF_HANDLER, offsetof(struct ia32_sigframe, sf_ah));
+ASSYM(IA32_SIGF_UC, offsetof(struct ia32_sigframe, sf_uc));
+#ifdef COMPAT_43
+ASSYM(IA32_SIGF_SC, offsetof(struct ia32_sigframe3, sf_siginfo.si_sc));
+#endif
+ASSYM(IA32_UC_GS, offsetof(struct ia32_ucontext, uc_mcontext.mc_gs));
+ASSYM(IA32_UC_FS, offsetof(struct ia32_ucontext, uc_mcontext.mc_fs));
+ASSYM(IA32_UC_ES, offsetof(struct ia32_ucontext, uc_mcontext.mc_es));
+ASSYM(IA32_UC_DS, offsetof(struct ia32_ucontext, uc_mcontext.mc_ds));
+#ifdef COMPAT_FREEBSD4
+ASSYM(IA32_SIGF_UC4, offsetof(struct ia32_sigframe4, sf_uc));
+ASSYM(IA32_UC4_GS, offsetof(struct ia32_ucontext4, uc_mcontext.mc_gs));
+ASSYM(IA32_UC4_FS, offsetof(struct ia32_ucontext4, uc_mcontext.mc_fs));
+ASSYM(IA32_UC4_ES, offsetof(struct ia32_ucontext4, uc_mcontext.mc_es));
+ASSYM(IA32_UC4_DS, offsetof(struct ia32_ucontext4, uc_mcontext.mc_ds));
+#endif
diff --git a/sys/compat/ia32/ia32_signal.h b/sys/compat/ia32/ia32_signal.h
new file mode 100644
index 0000000..78cb82a
--- /dev/null
+++ b/sys/compat/ia32/ia32_signal.h
@@ -0,0 +1,208 @@
+/*-
+ * Copyright (c) 1999 Marcel Moolenaar
+ * Copyright (c) 2003 Peter Wemm
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _COMPAT_IA32_IA32_SIGNAL_H
+#define _COMPAT_IA32_IA32_SIGNAL_H
+
+#define _MC_IA32_HASSEGS 0x1
+#define _MC_IA32_HASBASES 0x2
+#define _MC_IA32_HASFPXSTATE 0x4
+#define _MC_IA32_FLAG_MASK \
+ (_MC_IA32_HASSEGS | _MC_IA32_HASBASES | _MC_IA32_HASFPXSTATE)
+
+struct ia32_mcontext {
+ u_int32_t mc_onstack; /* XXX - sigcontext compat. */
+ u_int32_t mc_gs; /* machine state (struct trapframe) */
+ u_int32_t mc_fs;
+ u_int32_t mc_es;
+ u_int32_t mc_ds;
+ u_int32_t mc_edi;
+ u_int32_t mc_esi;
+ u_int32_t mc_ebp;
+ u_int32_t mc_isp;
+ u_int32_t mc_ebx;
+ u_int32_t mc_edx;
+ u_int32_t mc_ecx;
+ u_int32_t mc_eax;
+ u_int32_t mc_trapno;
+ u_int32_t mc_err;
+ u_int32_t mc_eip;
+ u_int32_t mc_cs;
+ u_int32_t mc_eflags;
+ u_int32_t mc_esp;
+ u_int32_t mc_ss;
+ u_int32_t mc_len; /* sizeof(struct ia32_mcontext) */
+ /* We use the same values for fpformat and ownedfp */
+ u_int32_t mc_fpformat;
+ u_int32_t mc_ownedfp;
+ u_int32_t mc_flags;
+ /*
+ * See <i386/include/npx.h> for the internals of mc_fpstate[].
+ */
+ u_int32_t mc_fpstate[128] __aligned(16);
+ u_int32_t mc_fsbase;
+ u_int32_t mc_gsbase;
+ u_int32_t mc_xfpustate;
+ u_int32_t mc_xfpustate_len;
+ u_int32_t mc_spare2[4];
+};
+
+struct ia32_ucontext {
+ sigset_t uc_sigmask;
+ struct ia32_mcontext uc_mcontext;
+ u_int32_t uc_link;
+ struct sigaltstack32 uc_stack;
+ u_int32_t uc_flags;
+ u_int32_t __spare__[4];
+};
+
+
+#if defined(COMPAT_FREEBSD4)
+struct ia32_mcontext4 {
+ u_int32_t mc_onstack; /* XXX - sigcontext compat. */
+ u_int32_t mc_gs; /* machine state (struct trapframe) */
+ u_int32_t mc_fs;
+ u_int32_t mc_es;
+ u_int32_t mc_ds;
+ u_int32_t mc_edi;
+ u_int32_t mc_esi;
+ u_int32_t mc_ebp;
+ u_int32_t mc_isp;
+ u_int32_t mc_ebx;
+ u_int32_t mc_edx;
+ u_int32_t mc_ecx;
+ u_int32_t mc_eax;
+ u_int32_t mc_trapno;
+ u_int32_t mc_err;
+ u_int32_t mc_eip;
+ u_int32_t mc_cs;
+ u_int32_t mc_eflags;
+ u_int32_t mc_esp;
+ u_int32_t mc_ss;
+ u_int32_t mc_fpregs[28];
+ u_int32_t __spare__[17];
+};
+
+struct ia32_ucontext4 {
+ sigset_t uc_sigmask;
+ struct ia32_mcontext4 uc_mcontext;
+ u_int32_t uc_link;
+ struct sigaltstack32 uc_stack;
+ u_int32_t __spare__[8];
+};
+#endif
+
+#ifdef COMPAT_43
+struct ia32_sigcontext3 {
+ u_int32_t sc_onstack;
+ u_int32_t sc_mask;
+ u_int32_t sc_esp;
+ u_int32_t sc_ebp;
+ u_int32_t sc_isp;
+ u_int32_t sc_eip;
+ u_int32_t sc_eflags;
+ u_int32_t sc_es;
+ u_int32_t sc_ds;
+ u_int32_t sc_cs;
+ u_int32_t sc_ss;
+ u_int32_t sc_edi;
+ u_int32_t sc_esi;
+ u_int32_t sc_ebx;
+ u_int32_t sc_edx;
+ u_int32_t sc_ecx;
+ u_int32_t sc_eax;
+ u_int32_t sc_gs;
+ u_int32_t sc_fs;
+ u_int32_t sc_trapno;
+ u_int32_t sc_err;
+};
+#endif
+
+/*
+ * Signal frames, arguments passed to application signal handlers.
+ */
+
+#ifdef COMPAT_FREEBSD4
+struct ia32_sigframe4 {
+ u_int32_t sf_signum;
+ u_int32_t sf_siginfo; /* code or pointer to sf_si */
+ u_int32_t sf_ucontext; /* points to sf_uc */
+ u_int32_t sf_addr; /* undocumented 4th arg */
+ u_int32_t sf_ah; /* action/handler pointer */
+ struct ia32_ucontext4 sf_uc; /* = *sf_ucontext */
+ struct siginfo32 sf_si; /* = *sf_siginfo (SA_SIGINFO case) */
+};
+#endif
+
+struct ia32_sigframe {
+ u_int32_t sf_signum;
+ u_int32_t sf_siginfo; /* code or pointer to sf_si */
+ u_int32_t sf_ucontext; /* points to sf_uc */
+ u_int32_t sf_addr; /* undocumented 4th arg */
+ u_int32_t sf_ah; /* action/handler pointer */
+ /* Beware, hole due to ucontext being 16 byte aligned! */
+ struct ia32_ucontext sf_uc; /* = *sf_ucontext */
+ struct siginfo32 sf_si; /* = *sf_siginfo (SA_SIGINFO case) */
+};
+
+#ifdef COMPAT_43
+struct ia32_siginfo3 {
+ struct ia32_sigcontext3 si_sc;
+ int si_signo;
+ int si_code;
+ union sigval32 si_value;
+};
+struct ia32_sigframe3 {
+ int sf_signum;
+ u_int32_t sf_arg2; /* int or siginfo_t */
+ u_int32_t sf_scp;
+ u_int32_t sf_addr;
+ u_int32_t sf_ah; /* action/handler pointer */
+ struct ia32_siginfo3 sf_siginfo;
+};
+#endif
+
+struct ksiginfo;
+struct image_params;
+extern char ia32_sigcode[];
+extern char freebsd4_ia32_sigcode[];
+extern char ia32_osigcode[];
+extern char lcall_tramp;
+extern int sz_ia32_sigcode;
+extern int sz_freebsd4_ia32_sigcode;
+extern int sz_ia32_osigcode;
+extern int sz_lcall_tramp;
+void ia32_sendsig(sig_t, struct ksiginfo *, sigset_t *);
+void ia32_setregs(struct thread *td, struct image_params *imgp,
+ u_long stack);
+int setup_lcall_gate(void);
+
+#endif
diff --git a/sys/compat/ia32/ia32_sysvec.c b/sys/compat/ia32/ia32_sysvec.c
new file mode 100644
index 0000000..a8e52e8
--- /dev/null
+++ b/sys/compat/ia32/ia32_sysvec.c
@@ -0,0 +1,228 @@
+/*-
+ * Copyright (c) 2002 Doug Rabson
+ * Copyright (c) 2003 Peter Wemm
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_compat.h"
+
+#define __ELF_WORD_SIZE 32
+
+#include <sys/param.h>
+#include <sys/exec.h>
+#include <sys/fcntl.h>
+#include <sys/imgact.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/mman.h>
+#include <sys/namei.h>
+#include <sys/pioctl.h>
+#include <sys/proc.h>
+#include <sys/procfs.h>
+#include <sys/resourcevar.h>
+#include <sys/systm.h>
+#include <sys/signalvar.h>
+#include <sys/stat.h>
+#include <sys/sx.h>
+#include <sys/syscall.h>
+#include <sys/sysctl.h>
+#include <sys/sysent.h>
+#include <sys/vnode.h>
+#include <sys/imgact_elf.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+
+#include <compat/freebsd32/freebsd32_signal.h>
+#include <compat/freebsd32/freebsd32_util.h>
+#include <compat/freebsd32/freebsd32_proto.h>
+#include <compat/freebsd32/freebsd32_syscall.h>
+#include <compat/ia32/ia32_signal.h>
+#include <machine/frame.h>
+#include <machine/md_var.h>
+#include <machine/pcb.h>
+#include <machine/cpufunc.h>
+
+CTASSERT(sizeof(struct ia32_mcontext) == 640);
+CTASSERT(sizeof(struct ia32_ucontext) == 704);
+CTASSERT(sizeof(struct ia32_sigframe) == 800);
+CTASSERT(sizeof(struct siginfo32) == 64);
+#ifdef COMPAT_FREEBSD4
+CTASSERT(sizeof(struct ia32_mcontext4) == 260);
+CTASSERT(sizeof(struct ia32_ucontext4) == 324);
+CTASSERT(sizeof(struct ia32_sigframe4) == 408);
+#endif
+
+extern const char *freebsd32_syscallnames[];
+
+static SYSCTL_NODE(_compat, OID_AUTO, ia32, CTLFLAG_RW, 0, "ia32 mode");
+
+static u_long ia32_maxdsiz = IA32_MAXDSIZ;
+SYSCTL_ULONG(_compat_ia32, OID_AUTO, maxdsiz, CTLFLAG_RW, &ia32_maxdsiz, 0, "");
+TUNABLE_ULONG("compat.ia32.maxdsiz", &ia32_maxdsiz);
+u_long ia32_maxssiz = IA32_MAXSSIZ;
+SYSCTL_ULONG(_compat_ia32, OID_AUTO, maxssiz, CTLFLAG_RW, &ia32_maxssiz, 0, "");
+TUNABLE_ULONG("compat.ia32.maxssiz", &ia32_maxssiz);
+static u_long ia32_maxvmem = IA32_MAXVMEM;
+SYSCTL_ULONG(_compat_ia32, OID_AUTO, maxvmem, CTLFLAG_RW, &ia32_maxvmem, 0, "");
+TUNABLE_ULONG("compat.ia32.maxvmem", &ia32_maxvmem);
+
+struct sysentvec ia32_freebsd_sysvec = {
+ .sv_size = FREEBSD32_SYS_MAXSYSCALL,
+ .sv_table = freebsd32_sysent,
+ .sv_mask = 0,
+ .sv_sigsize = 0,
+ .sv_sigtbl = NULL,
+ .sv_errsize = 0,
+ .sv_errtbl = NULL,
+ .sv_transtrap = NULL,
+ .sv_fixup = elf32_freebsd_fixup,
+ .sv_sendsig = ia32_sendsig,
+ .sv_sigcode = ia32_sigcode,
+ .sv_szsigcode = &sz_ia32_sigcode,
+ .sv_prepsyscall = NULL,
+ .sv_name = "FreeBSD ELF32",
+ .sv_coredump = elf32_coredump,
+ .sv_imgact_try = NULL,
+ .sv_minsigstksz = MINSIGSTKSZ,
+ .sv_pagesize = IA32_PAGE_SIZE,
+ .sv_minuser = FREEBSD32_MINUSER,
+ .sv_maxuser = FREEBSD32_MAXUSER,
+ .sv_usrstack = FREEBSD32_USRSTACK,
+ .sv_psstrings = FREEBSD32_PS_STRINGS,
+ .sv_stackprot = VM_PROT_ALL,
+ .sv_copyout_strings = freebsd32_copyout_strings,
+ .sv_setregs = ia32_setregs,
+ .sv_fixlimit = ia32_fixlimit,
+ .sv_maxssiz = &ia32_maxssiz,
+ .sv_flags = SV_ABI_FREEBSD | SV_IA32 | SV_ILP32 |
+#ifdef __amd64__
+ SV_SHP
+#else
+ 0
+#endif
+ ,
+ .sv_set_syscall_retval = ia32_set_syscall_retval,
+ .sv_fetch_syscall_args = ia32_fetch_syscall_args,
+ .sv_syscallnames = freebsd32_syscallnames,
+ .sv_shared_page_base = FREEBSD32_SHAREDPAGE,
+ .sv_shared_page_len = PAGE_SIZE,
+ .sv_schedtail = NULL,
+};
+INIT_SYSENTVEC(elf_ia32_sysvec, &ia32_freebsd_sysvec);
+
+static Elf32_Brandinfo ia32_brand_info = {
+ .brand = ELFOSABI_FREEBSD,
+ .machine = EM_386,
+ .compat_3_brand = "FreeBSD",
+ .emul_path = NULL,
+ .interp_path = "/libexec/ld-elf.so.1",
+ .sysvec = &ia32_freebsd_sysvec,
+ .interp_newpath = "/libexec/ld-elf32.so.1",
+ .brand_note = &elf32_freebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
+};
+
+SYSINIT(ia32, SI_SUB_EXEC, SI_ORDER_MIDDLE,
+ (sysinit_cfunc_t) elf32_insert_brand_entry,
+ &ia32_brand_info);
+
+static Elf32_Brandinfo ia32_brand_oinfo = {
+ .brand = ELFOSABI_FREEBSD,
+ .machine = EM_386,
+ .compat_3_brand = "FreeBSD",
+ .emul_path = NULL,
+ .interp_path = "/usr/libexec/ld-elf.so.1",
+ .sysvec = &ia32_freebsd_sysvec,
+ .interp_newpath = "/libexec/ld-elf32.so.1",
+ .brand_note = &elf32_freebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
+};
+
+SYSINIT(oia32, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf32_insert_brand_entry,
+ &ia32_brand_oinfo);
+
+static Elf32_Brandinfo kia32_brand_info = {
+ .brand = ELFOSABI_FREEBSD,
+ .machine = EM_386,
+ .compat_3_brand = "FreeBSD",
+ .emul_path = NULL,
+ .interp_path = "/lib/ld.so.1",
+ .sysvec = &ia32_freebsd_sysvec,
+ .brand_note = &elf32_kfreebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE_MANDATORY
+};
+
+SYSINIT(kia32, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf32_insert_brand_entry,
+ &kia32_brand_info);
+
+void
+elf32_dump_thread(struct thread *td __unused, void *dst __unused,
+ size_t *off __unused)
+{
+}
+
+void
+ia32_fixlimit(struct rlimit *rl, int which)
+{
+
+ switch (which) {
+ case RLIMIT_DATA:
+ if (ia32_maxdsiz != 0) {
+ if (rl->rlim_cur > ia32_maxdsiz)
+ rl->rlim_cur = ia32_maxdsiz;
+ if (rl->rlim_max > ia32_maxdsiz)
+ rl->rlim_max = ia32_maxdsiz;
+ }
+ break;
+ case RLIMIT_STACK:
+ if (ia32_maxssiz != 0) {
+ if (rl->rlim_cur > ia32_maxssiz)
+ rl->rlim_cur = ia32_maxssiz;
+ if (rl->rlim_max > ia32_maxssiz)
+ rl->rlim_max = ia32_maxssiz;
+ }
+ break;
+ case RLIMIT_VMEM:
+ if (ia32_maxvmem != 0) {
+ if (rl->rlim_cur > ia32_maxvmem)
+ rl->rlim_cur = ia32_maxvmem;
+ if (rl->rlim_max > ia32_maxvmem)
+ rl->rlim_max = ia32_maxvmem;
+ }
+ break;
+ }
+}
diff --git a/sys/compat/ia32/ia32_util.h b/sys/compat/ia32/ia32_util.h
new file mode 100644
index 0000000..fe87b72
--- /dev/null
+++ b/sys/compat/ia32/ia32_util.h
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 1998-1999 Andrew Gallatin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _COMPAT_IA32_IA32_UTIL_H
+#define _COMPAT_IA32_IA32_UTIL_H
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
+#include <sys/exec.h>
+#include <sys/sysent.h>
+#include <sys/cdefs.h>
+
+#ifdef __ia64__
+#define FREEBSD32_MAXUSER ((1ul << 32) - IA32_PAGE_SIZE * 2)
+#define FREEBSD32_MINUSER 0
+#define FREEBSD32_SHAREDPAGE 0
+#define FREEBSD32_USRSTACK FREEBSD32_MAXUSER
+#else /* __ia64__ */
+#define FREEBSD32_MAXUSER ((1ul << 32) - IA32_PAGE_SIZE)
+#define FREEBSD32_MINUSER 0
+#define FREEBSD32_SHAREDPAGE (FREEBSD32_MAXUSER - IA32_PAGE_SIZE)
+#define FREEBSD32_USRSTACK FREEBSD32_SHAREDPAGE
+#endif /* __ia64 */
+
+#define IA32_PAGE_SIZE 4096
+#define IA32_MAXDSIZ (512*1024*1024) /* 512MB */
+#define IA32_MAXSSIZ (64*1024*1024) /* 64MB */
+#define IA32_MAXVMEM 0 /* Unlimited */
+
+struct syscall_args;
+int ia32_fetch_syscall_args(struct thread *td, struct syscall_args *sa);
+void ia32_set_syscall_retval(struct thread *, int);
+void ia32_fixlimit(struct rlimit *rl, int which);
+
+#endif /* _COMPAT_IA32_IA32_UTIL_H */
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c
new file mode 100644
index 0000000..28b683a
--- /dev/null
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -0,0 +1,1456 @@
+/*-
+ * Copyright (c) 2000 Dag-Erling Coïdan Smørgrav
+ * Copyright (c) 1999 Pierre Beyssac
+ * Copyright (c) 1993 Jan-Simon Pendry
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)procfs_status.c 8.4 (Berkeley) 6/15/94
+ */
+
+#include "opt_compat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/blist.h>
+#include <sys/conf.h>
+#include <sys/exec.h>
+#include <sys/fcntl.h>
+#include <sys/filedesc.h>
+#include <sys/jail.h>
+#include <sys/kernel.h>
+#include <sys/linker.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/msg.h>
+#include <sys/mutex.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/ptrace.h>
+#include <sys/resourcevar.h>
+#include <sys/sbuf.h>
+#include <sys/sem.h>
+#include <sys/smp.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+#include <sys/tty.h>
+#include <sys/user.h>
+#include <sys/vmmeter.h>
+#include <sys/vnode.h>
+#include <sys/bus.h>
+
+#include <net/if.h>
+#include <net/vnet.h>
+
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_param.h>
+#include <vm/vm_object.h>
+#include <vm/swap_pager.h>
+
+#include <machine/clock.h>
+
+#include <geom/geom.h>
+#include <geom/geom_int.h>
+
+#if defined(__i386__) || defined(__amd64__)
+#include <machine/cputypes.h>
+#include <machine/md_var.h>
+#endif /* __i386__ || __amd64__ */
+
+#ifdef COMPAT_FREEBSD32
+#include <compat/freebsd32/freebsd32_util.h>
+#endif
+
+#include <compat/linux/linux_ioctl.h>
+#include <compat/linux/linux_mib.h>
+#include <compat/linux/linux_misc.h>
+#include <compat/linux/linux_util.h>
+#include <fs/pseudofs/pseudofs.h>
+#include <fs/procfs/procfs.h>
+
+/*
+ * Various conversion macros
+ */
+#define T2J(x) ((long)(((x) * 100ULL) / (stathz ? stathz : hz))) /* ticks to jiffies */
+#define T2CS(x) ((unsigned long)(((x) * 100ULL) / (stathz ? stathz : hz))) /* ticks to centiseconds */
+#define T2S(x) ((x) / (stathz ? stathz : hz)) /* ticks to seconds */
+#define B2K(x) ((x) >> 10) /* bytes to kbytes */
+#define B2P(x) ((x) >> PAGE_SHIFT) /* bytes to pages */
+#define P2B(x) ((x) << PAGE_SHIFT) /* pages to bytes */
+#define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */
+#define TV2J(x) ((x)->tv_sec * 100UL + (x)->tv_usec / 10000)
+
+/**
+ * @brief Mapping of ki_stat in struct kinfo_proc to the linux state
+ *
+ * The linux procfs state field displays one of the characters RSDZTW to
+ * denote running, sleeping in an interruptible wait, waiting in an
+ * uninterruptible disk sleep, a zombie process, process is being traced
+ * or stopped, or process is paging respectively.
+ *
+ * Our struct kinfo_proc contains the variable ki_stat which contains a
+ * value out of SIDL, SRUN, SSLEEP, SSTOP, SZOMB, SWAIT and SLOCK.
+ *
+ * This character array is used with ki_stati-1 as an index and tries to
+ * map our states to suitable linux states.
+ */
+static char linux_state[] = "RRSTZDD";
+
+/*
+ * Filler function for proc/meminfo
+ */
+static int
+linprocfs_domeminfo(PFS_FILL_ARGS)
+{
+ unsigned long memtotal; /* total memory in bytes */
+ unsigned long memused; /* used memory in bytes */
+ unsigned long memfree; /* free memory in bytes */
+ unsigned long memshared; /* shared memory ??? */
+ unsigned long buffers, cached; /* buffer / cache memory ??? */
+ unsigned long long swaptotal; /* total swap space in bytes */
+ unsigned long long swapused; /* used swap space in bytes */
+ unsigned long long swapfree; /* free swap space in bytes */
+ vm_object_t object;
+ int i, j;
+
+ memtotal = physmem * PAGE_SIZE;
+ /*
+ * The correct thing here would be:
+ *
+ memfree = cnt.v_free_count * PAGE_SIZE;
+ memused = memtotal - memfree;
+ *
+ * but it might mislead linux binaries into thinking there
+ * is very little memory left, so we cheat and tell them that
+ * all memory that isn't wired down is free.
+ */
+ memused = cnt.v_wire_count * PAGE_SIZE;
+ memfree = memtotal - memused;
+ swap_pager_status(&i, &j);
+ swaptotal = (unsigned long long)i * PAGE_SIZE;
+ swapused = (unsigned long long)j * PAGE_SIZE;
+ swapfree = swaptotal - swapused;
+ memshared = 0;
+ mtx_lock(&vm_object_list_mtx);
+ TAILQ_FOREACH(object, &vm_object_list, object_list)
+ if (object->shadow_count > 1)
+ memshared += object->resident_page_count;
+ mtx_unlock(&vm_object_list_mtx);
+ memshared *= PAGE_SIZE;
+ /*
+ * We'd love to be able to write:
+ *
+ buffers = bufspace;
+ *
+ * but bufspace is internal to vfs_bio.c and we don't feel
+ * like unstaticizing it just for linprocfs's sake.
+ */
+ buffers = 0;
+ cached = cnt.v_cache_count * PAGE_SIZE;
+
+ sbuf_printf(sb,
+ " total: used: free: shared: buffers: cached:\n"
+ "Mem: %lu %lu %lu %lu %lu %lu\n"
+ "Swap: %llu %llu %llu\n"
+ "MemTotal: %9lu kB\n"
+ "MemFree: %9lu kB\n"
+ "MemShared:%9lu kB\n"
+ "Buffers: %9lu kB\n"
+ "Cached: %9lu kB\n"
+ "SwapTotal:%9llu kB\n"
+ "SwapFree: %9llu kB\n",
+ memtotal, memused, memfree, memshared, buffers, cached,
+ swaptotal, swapused, swapfree,
+ B2K(memtotal), B2K(memfree),
+ B2K(memshared), B2K(buffers), B2K(cached),
+ B2K(swaptotal), B2K(swapfree));
+
+ return (0);
+}
+
+#if defined(__i386__) || defined(__amd64__)
+/*
+ * Filler function for proc/cpuinfo (i386 & amd64 version)
+ */
+static int
+linprocfs_docpuinfo(PFS_FILL_ARGS)
+{
+ int hw_model[2];
+ char model[128];
+ uint64_t freq;
+ size_t size;
+ int class, fqmhz, fqkhz;
+ int i;
+
+ /*
+ * We default the flags to include all non-conflicting flags,
+ * and the Intel versions of conflicting flags.
+ */
+ static char *flags[] = {
+ "fpu", "vme", "de", "pse", "tsc",
+ "msr", "pae", "mce", "cx8", "apic",
+ "sep", "sep", "mtrr", "pge", "mca",
+ "cmov", "pat", "pse36", "pn", "b19",
+ "b20", "b21", "mmxext", "mmx", "fxsr",
+ "xmm", "sse2", "b27", "b28", "b29",
+ "3dnowext", "3dnow"
+ };
+
+ switch (cpu_class) {
+#ifdef __i386__
+ case CPUCLASS_286:
+ class = 2;
+ break;
+ case CPUCLASS_386:
+ class = 3;
+ break;
+ case CPUCLASS_486:
+ class = 4;
+ break;
+ case CPUCLASS_586:
+ class = 5;
+ break;
+ case CPUCLASS_686:
+ class = 6;
+ break;
+ default:
+ class = 0;
+ break;
+#else /* __amd64__ */
+ default:
+ class = 15;
+ break;
+#endif
+ }
+
+ hw_model[0] = CTL_HW;
+ hw_model[1] = HW_MODEL;
+ model[0] = '\0';
+ size = sizeof(model);
+ if (kernel_sysctl(td, hw_model, 2, &model, &size, 0, 0, 0, 0) != 0)
+ strcpy(model, "unknown");
+ for (i = 0; i < mp_ncpus; ++i) {
+ sbuf_printf(sb,
+ "processor\t: %d\n"
+ "vendor_id\t: %.20s\n"
+ "cpu family\t: %u\n"
+ "model\t\t: %u\n"
+ "model name\t: %s\n"
+ "stepping\t: %u\n\n",
+ i, cpu_vendor, CPUID_TO_FAMILY(cpu_id),
+ CPUID_TO_MODEL(cpu_id), model, cpu_id & CPUID_STEPPING);
+ /* XXX per-cpu vendor / class / model / id? */
+ }
+
+ sbuf_cat(sb, "flags\t\t:");
+
+#ifdef __i386__
+ switch (cpu_vendor_id) {
+ case CPU_VENDOR_AMD:
+ if (class < 6)
+ flags[16] = "fcmov";
+ break;
+ case CPU_VENDOR_CYRIX:
+ flags[24] = "cxmmx";
+ break;
+ }
+#endif
+
+ for (i = 0; i < 32; i++)
+ if (cpu_feature & (1 << i))
+ sbuf_printf(sb, " %s", flags[i]);
+ sbuf_cat(sb, "\n");
+ freq = atomic_load_acq_64(&tsc_freq);
+ if (freq != 0) {
+ fqmhz = (freq + 4999) / 1000000;
+ fqkhz = ((freq + 4999) / 10000) % 100;
+ sbuf_printf(sb,
+ "cpu MHz\t\t: %d.%02d\n"
+ "bogomips\t: %d.%02d\n",
+ fqmhz, fqkhz, fqmhz, fqkhz);
+ }
+
+ return (0);
+}
+#endif /* __i386__ || __amd64__ */
+
+/*
+ * Filler function for proc/mtab
+ *
+ * This file doesn't exist in Linux' procfs, but is included here so
+ * users can symlink /compat/linux/etc/mtab to /proc/mtab
+ */
+static int
+linprocfs_domtab(PFS_FILL_ARGS)
+{
+ struct nameidata nd;
+ struct mount *mp;
+ const char *lep;
+ char *dlep, *flep, *mntto, *mntfrom, *fstype;
+ size_t lep_len;
+ int error;
+
+ /* resolve symlinks etc. in the emulation tree prefix */
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td);
+ flep = NULL;
+ error = namei(&nd);
+ lep = linux_emul_path;
+ if (error == 0) {
+ if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
+ lep = dlep;
+ vrele(nd.ni_vp);
+ }
+ lep_len = strlen(lep);
+
+ mtx_lock(&mountlist_mtx);
+ error = 0;
+ TAILQ_FOREACH(mp, &mountlist, mnt_list) {
+ /* determine device name */
+ mntfrom = mp->mnt_stat.f_mntfromname;
+
+ /* determine mount point */
+ mntto = mp->mnt_stat.f_mntonname;
+ if (strncmp(mntto, lep, lep_len) == 0 &&
+ mntto[lep_len] == '/')
+ mntto += lep_len;
+
+ /* determine fs type */
+ fstype = mp->mnt_stat.f_fstypename;
+ if (strcmp(fstype, pn->pn_info->pi_name) == 0)
+ mntfrom = fstype = "proc";
+ else if (strcmp(fstype, "procfs") == 0)
+ continue;
+
+ if (strcmp(fstype, "linsysfs") == 0) {
+ sbuf_printf(sb, "/sys %s sysfs %s", mntto,
+ mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
+ } else {
+ /* For Linux msdosfs is called vfat */
+ if (strcmp(fstype, "msdosfs") == 0)
+ fstype = "vfat";
+ sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype,
+ mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
+ }
+#define ADD_OPTION(opt, name) \
+ if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name);
+ ADD_OPTION(MNT_SYNCHRONOUS, "sync");
+ ADD_OPTION(MNT_NOEXEC, "noexec");
+ ADD_OPTION(MNT_NOSUID, "nosuid");
+ ADD_OPTION(MNT_UNION, "union");
+ ADD_OPTION(MNT_ASYNC, "async");
+ ADD_OPTION(MNT_SUIDDIR, "suiddir");
+ ADD_OPTION(MNT_NOSYMFOLLOW, "nosymfollow");
+ ADD_OPTION(MNT_NOATIME, "noatime");
+#undef ADD_OPTION
+ /* a real Linux mtab will also show NFS options */
+ sbuf_printf(sb, " 0 0\n");
+ }
+ mtx_unlock(&mountlist_mtx);
+ free(flep, M_TEMP);
+ return (error);
+}
+
+/*
+ * Filler function for proc/partitions
+ *
+ */
+static int
+linprocfs_dopartitions(PFS_FILL_ARGS)
+{
+ struct g_class *cp;
+ struct g_geom *gp;
+ struct g_provider *pp;
+ struct nameidata nd;
+ const char *lep;
+ char *dlep, *flep;
+ size_t lep_len;
+ int error;
+ int major, minor;
+
+ /* resolve symlinks etc. in the emulation tree prefix */
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td);
+ flep = NULL;
+ error = namei(&nd);
+ lep = linux_emul_path;
+ if (error == 0) {
+ if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
+ lep = dlep;
+ vrele(nd.ni_vp);
+ }
+ lep_len = strlen(lep);
+
+ g_topology_lock();
+ error = 0;
+ sbuf_printf(sb, "major minor #blocks name rio rmerge rsect "
+ "ruse wio wmerge wsect wuse running use aveq\n");
+
+ LIST_FOREACH(cp, &g_classes, class) {
+ if (strcmp(cp->name, "DISK") == 0 ||
+ strcmp(cp->name, "PART") == 0)
+ LIST_FOREACH(gp, &cp->geom, geom) {
+ LIST_FOREACH(pp, &gp->provider, provider) {
+ if (linux_driver_get_major_minor(
+ pp->name, &major, &minor) != 0) {
+ major = 0;
+ minor = 0;
+ }
+ sbuf_printf(sb, "%d %d %lld %s "
+ "%d %d %d %d %d "
+ "%d %d %d %d %d %d\n",
+ major, minor,
+ (long long)pp->mediasize, pp->name,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0);
+ }
+ }
+ }
+ g_topology_unlock();
+
+ free(flep, M_TEMP);
+ return (error);
+}
+
+
+/*
+ * Filler function for proc/stat
+ */
+static int
+linprocfs_dostat(PFS_FILL_ARGS)
+{
+ struct pcpu *pcpu;
+ long cp_time[CPUSTATES];
+ long *cp;
+ int i;
+
+ read_cpu_time(cp_time);
+ sbuf_printf(sb, "cpu %ld %ld %ld %ld\n",
+ T2J(cp_time[CP_USER]),
+ T2J(cp_time[CP_NICE]),
+ T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/),
+ T2J(cp_time[CP_IDLE]));
+ CPU_FOREACH(i) {
+ pcpu = pcpu_find(i);
+ cp = pcpu->pc_cp_time;
+ sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i,
+ T2J(cp[CP_USER]),
+ T2J(cp[CP_NICE]),
+ T2J(cp[CP_SYS] /*+ cp[CP_INTR]*/),
+ T2J(cp[CP_IDLE]));
+ }
+ sbuf_printf(sb,
+ "disk 0 0 0 0\n"
+ "page %u %u\n"
+ "swap %u %u\n"
+ "intr %u\n"
+ "ctxt %u\n"
+ "btime %lld\n",
+ cnt.v_vnodepgsin,
+ cnt.v_vnodepgsout,
+ cnt.v_swappgsin,
+ cnt.v_swappgsout,
+ cnt.v_intr,
+ cnt.v_swtch,
+ (long long)boottime.tv_sec);
+ return (0);
+}
+
+static int
+linprocfs_doswaps(PFS_FILL_ARGS)
+{
+ struct xswdev xsw;
+ uintmax_t total, used;
+ int n;
+ char devname[SPECNAMELEN + 1];
+
+ sbuf_printf(sb, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n");
+ mtx_lock(&Giant);
+ for (n = 0; ; n++) {
+ if (swap_dev_info(n, &xsw, devname, sizeof(devname)) != 0)
+ break;
+ total = (uintmax_t)xsw.xsw_nblks * PAGE_SIZE / 1024;
+ used = (uintmax_t)xsw.xsw_used * PAGE_SIZE / 1024;
+
+ /*
+ * The space and not tab after the device name is on
+ * purpose. Linux does so.
+ */
+ sbuf_printf(sb, "/dev/%-34s unknown\t\t%jd\t%jd\t-1\n",
+ devname, total, used);
+ }
+ mtx_unlock(&Giant);
+ return (0);
+}
+
+/*
+ * Filler function for proc/uptime
+ */
+static int
+linprocfs_douptime(PFS_FILL_ARGS)
+{
+ long cp_time[CPUSTATES];
+ struct timeval tv;
+
+ getmicrouptime(&tv);
+ read_cpu_time(cp_time);
+ sbuf_printf(sb, "%lld.%02ld %ld.%02lu\n",
+ (long long)tv.tv_sec, tv.tv_usec / 10000,
+ T2S(cp_time[CP_IDLE] / mp_ncpus),
+ T2CS(cp_time[CP_IDLE] / mp_ncpus) % 100);
+ return (0);
+}
+
+/*
+ * Get OS build date
+ */
+static void
+linprocfs_osbuild(struct thread *td, struct sbuf *sb)
+{
+#if 0
+ char osbuild[256];
+ char *cp1, *cp2;
+
+ strncpy(osbuild, version, 256);
+ osbuild[255] = '\0';
+ cp1 = strstr(osbuild, "\n");
+ cp2 = strstr(osbuild, ":");
+ if (cp1 && cp2) {
+ *cp1 = *cp2 = '\0';
+ cp1 = strstr(osbuild, "#");
+ } else
+ cp1 = NULL;
+ if (cp1)
+ sbuf_printf(sb, "%s%s", cp1, cp2 + 1);
+ else
+#endif
+ sbuf_cat(sb, "#4 Sun Dec 18 04:30:00 CET 1977");
+}
+
+/*
+ * Get OS builder
+ */
+static void
+linprocfs_osbuilder(struct thread *td, struct sbuf *sb)
+{
+#if 0
+ char builder[256];
+ char *cp;
+
+ cp = strstr(version, "\n ");
+ if (cp) {
+ strncpy(builder, cp + 5, 256);
+ builder[255] = '\0';
+ cp = strstr(builder, ":");
+ if (cp)
+ *cp = '\0';
+ }
+ if (cp)
+ sbuf_cat(sb, builder);
+ else
+#endif
+ sbuf_cat(sb, "des@freebsd.org");
+}
+
+/*
+ * Filler function for proc/version
+ */
+static int
+linprocfs_doversion(PFS_FILL_ARGS)
+{
+ char osname[LINUX_MAX_UTSNAME];
+ char osrelease[LINUX_MAX_UTSNAME];
+
+ linux_get_osname(td, osname);
+ linux_get_osrelease(td, osrelease);
+ sbuf_printf(sb, "%s version %s (", osname, osrelease);
+ linprocfs_osbuilder(td, sb);
+ sbuf_cat(sb, ") (gcc version " __VERSION__ ") ");
+ linprocfs_osbuild(td, sb);
+ sbuf_cat(sb, "\n");
+
+ return (0);
+}
+
+/*
+ * Filler function for proc/loadavg
+ */
+static int
+linprocfs_doloadavg(PFS_FILL_ARGS)
+{
+
+ sbuf_printf(sb,
+ "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
+ (int)(averunnable.ldavg[0] / averunnable.fscale),
+ (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
+ (int)(averunnable.ldavg[1] / averunnable.fscale),
+ (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
+ (int)(averunnable.ldavg[2] / averunnable.fscale),
+ (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
+ 1, /* number of running tasks */
+ nprocs, /* number of tasks */
+ lastpid /* the last pid */
+ );
+ return (0);
+}
+
+/*
+ * Filler function for proc/pid/stat
+ */
+static int
+linprocfs_doprocstat(PFS_FILL_ARGS)
+{
+ struct kinfo_proc kp;
+ char state;
+ static int ratelimit = 0;
+ vm_offset_t startcode, startdata;
+
+ PROC_LOCK(p);
+ fill_kinfo_proc(p, &kp);
+ if (p->p_vmspace) {
+ startcode = (vm_offset_t)p->p_vmspace->vm_taddr;
+ startdata = (vm_offset_t)p->p_vmspace->vm_daddr;
+ } else {
+ startcode = 0;
+ startdata = 0;
+ };
+ sbuf_printf(sb, "%d", p->p_pid);
+#define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg)
+ PS_ADD("comm", "(%s)", p->p_comm);
+ if (kp.ki_stat > sizeof(linux_state)) {
+ state = 'R';
+
+ if (ratelimit == 0) {
+ printf("linprocfs: don't know how to handle unknown FreeBSD state %d/%zd, mapping to R\n",
+ kp.ki_stat, sizeof(linux_state));
+ ++ratelimit;
+ }
+ } else
+ state = linux_state[kp.ki_stat - 1];
+ PS_ADD("state", "%c", state);
+ PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0);
+ PS_ADD("pgrp", "%d", p->p_pgid);
+ PS_ADD("session", "%d", p->p_session->s_sid);
+ PROC_UNLOCK(p);
+ PS_ADD("tty", "%d", kp.ki_tdev);
+ PS_ADD("tpgid", "%d", kp.ki_tpgid);
+ PS_ADD("flags", "%u", 0); /* XXX */
+ PS_ADD("minflt", "%lu", kp.ki_rusage.ru_minflt);
+ PS_ADD("cminflt", "%lu", kp.ki_rusage_ch.ru_minflt);
+ PS_ADD("majflt", "%lu", kp.ki_rusage.ru_majflt);
+ PS_ADD("cmajflt", "%lu", kp.ki_rusage_ch.ru_majflt);
+ PS_ADD("utime", "%ld", TV2J(&kp.ki_rusage.ru_utime));
+ PS_ADD("stime", "%ld", TV2J(&kp.ki_rusage.ru_stime));
+ PS_ADD("cutime", "%ld", TV2J(&kp.ki_rusage_ch.ru_utime));
+ PS_ADD("cstime", "%ld", TV2J(&kp.ki_rusage_ch.ru_stime));
+ PS_ADD("priority", "%d", kp.ki_pri.pri_user);
+ PS_ADD("nice", "%d", kp.ki_nice); /* 19 (nicest) to -19 */
+ PS_ADD("0", "%d", 0); /* removed field */
+ PS_ADD("itrealvalue", "%d", 0); /* XXX */
+ PS_ADD("starttime", "%lu", TV2J(&kp.ki_start) - TV2J(&boottime));
+ PS_ADD("vsize", "%ju", P2K((uintmax_t)kp.ki_size));
+ PS_ADD("rss", "%ju", (uintmax_t)kp.ki_rssize);
+ PS_ADD("rlim", "%lu", kp.ki_rusage.ru_maxrss);
+ PS_ADD("startcode", "%ju", (uintmax_t)startcode);
+ PS_ADD("endcode", "%ju", (uintmax_t)startdata);
+ PS_ADD("startstack", "%u", 0); /* XXX */
+ PS_ADD("kstkesp", "%u", 0); /* XXX */
+ PS_ADD("kstkeip", "%u", 0); /* XXX */
+ PS_ADD("signal", "%u", 0); /* XXX */
+ PS_ADD("blocked", "%u", 0); /* XXX */
+ PS_ADD("sigignore", "%u", 0); /* XXX */
+ PS_ADD("sigcatch", "%u", 0); /* XXX */
+ PS_ADD("wchan", "%u", 0); /* XXX */
+ PS_ADD("nswap", "%lu", kp.ki_rusage.ru_nswap);
+ PS_ADD("cnswap", "%lu", kp.ki_rusage_ch.ru_nswap);
+ PS_ADD("exitsignal", "%d", 0); /* XXX */
+ PS_ADD("processor", "%u", kp.ki_lastcpu);
+ PS_ADD("rt_priority", "%u", 0); /* XXX */ /* >= 2.5.19 */
+ PS_ADD("policy", "%u", kp.ki_pri.pri_class); /* >= 2.5.19 */
+#undef PS_ADD
+ sbuf_putc(sb, '\n');
+
+ return (0);
+}
+
+/*
+ * Filler function for proc/pid/statm
+ */
+static int
+linprocfs_doprocstatm(PFS_FILL_ARGS)
+{
+ struct kinfo_proc kp;
+ segsz_t lsize;
+
+ PROC_LOCK(p);
+ fill_kinfo_proc(p, &kp);
+ PROC_UNLOCK(p);
+
+ /*
+ * See comments in linprocfs_doprocstatus() regarding the
+ * computation of lsize.
+ */
+ /* size resident share trs drs lrs dt */
+ sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size));
+ sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize);
+ sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */
+ sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_tsize);
+ sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize));
+ lsize = B2P(kp.ki_size) - kp.ki_dsize -
+ kp.ki_ssize - kp.ki_tsize - 1;
+ sbuf_printf(sb, "%ju ", (uintmax_t)lsize);
+ sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */
+
+ return (0);
+}
+
+/*
+ * Filler function for proc/pid/status
+ */
+static int
+linprocfs_doprocstatus(PFS_FILL_ARGS)
+{
+ struct kinfo_proc kp;
+ char *state;
+ segsz_t lsize;
+ struct thread *td2;
+ struct sigacts *ps;
+ int i;
+
+ PROC_LOCK(p);
+ td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */
+
+ if (P_SHOULDSTOP(p)) {
+ state = "T (stopped)";
+ } else {
+ switch(p->p_state) {
+ case PRS_NEW:
+ state = "I (idle)";
+ break;
+ case PRS_NORMAL:
+ if (p->p_flag & P_WEXIT) {
+ state = "X (exiting)";
+ break;
+ }
+ switch(td2->td_state) {
+ case TDS_INHIBITED:
+ state = "S (sleeping)";
+ break;
+ case TDS_RUNQ:
+ case TDS_RUNNING:
+ state = "R (running)";
+ break;
+ default:
+ state = "? (unknown)";
+ break;
+ }
+ break;
+ case PRS_ZOMBIE:
+ state = "Z (zombie)";
+ break;
+ default:
+ state = "? (unknown)";
+ break;
+ }
+ }
+
+ fill_kinfo_proc(p, &kp);
+ sbuf_printf(sb, "Name:\t%s\n", p->p_comm); /* XXX escape */
+ sbuf_printf(sb, "State:\t%s\n", state);
+
+ /*
+ * Credentials
+ */
+ sbuf_printf(sb, "Pid:\t%d\n", p->p_pid);
+ sbuf_printf(sb, "PPid:\t%d\n", p->p_pptr ?
+ p->p_pptr->p_pid : 0);
+ sbuf_printf(sb, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid,
+ p->p_ucred->cr_uid,
+ p->p_ucred->cr_svuid,
+ /* FreeBSD doesn't have fsuid */
+ p->p_ucred->cr_uid);
+ sbuf_printf(sb, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid,
+ p->p_ucred->cr_gid,
+ p->p_ucred->cr_svgid,
+ /* FreeBSD doesn't have fsgid */
+ p->p_ucred->cr_gid);
+ sbuf_cat(sb, "Groups:\t");
+ for (i = 0; i < p->p_ucred->cr_ngroups; i++)
+ sbuf_printf(sb, "%d ", p->p_ucred->cr_groups[i]);
+ PROC_UNLOCK(p);
+ sbuf_putc(sb, '\n');
+
+ /*
+ * Memory
+ *
+ * While our approximation of VmLib may not be accurate (I
+ * don't know of a simple way to verify it, and I'm not sure
+ * it has much meaning anyway), I believe it's good enough.
+ *
+ * The same code that could (I think) accurately compute VmLib
+ * could also compute VmLck, but I don't really care enough to
+ * implement it. Submissions are welcome.
+ */
+ sbuf_printf(sb, "VmSize:\t%8ju kB\n", B2K((uintmax_t)kp.ki_size));
+ sbuf_printf(sb, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */
+ sbuf_printf(sb, "VmRSS:\t%8ju kB\n", P2K((uintmax_t)kp.ki_rssize));
+ sbuf_printf(sb, "VmData:\t%8ju kB\n", P2K((uintmax_t)kp.ki_dsize));
+ sbuf_printf(sb, "VmStk:\t%8ju kB\n", P2K((uintmax_t)kp.ki_ssize));
+ sbuf_printf(sb, "VmExe:\t%8ju kB\n", P2K((uintmax_t)kp.ki_tsize));
+ lsize = B2P(kp.ki_size) - kp.ki_dsize -
+ kp.ki_ssize - kp.ki_tsize - 1;
+ sbuf_printf(sb, "VmLib:\t%8ju kB\n", P2K((uintmax_t)lsize));
+
+ /*
+ * Signal masks
+ *
+ * We support up to 128 signals, while Linux supports 32,
+ * but we only define 32 (the same 32 as Linux, to boot), so
+ * just show the lower 32 bits of each mask. XXX hack.
+ *
+ * NB: on certain platforms (Sparc at least) Linux actually
+ * supports 64 signals, but this code is a long way from
+ * running on anything but i386, so ignore that for now.
+ */
+ PROC_LOCK(p);
+ sbuf_printf(sb, "SigPnd:\t%08x\n", p->p_siglist.__bits[0]);
+ /*
+ * I can't seem to find out where the signal mask is in
+ * relation to struct proc, so SigBlk is left unimplemented.
+ */
+ sbuf_printf(sb, "SigBlk:\t%08x\n", 0); /* XXX */
+ ps = p->p_sigacts;
+ mtx_lock(&ps->ps_mtx);
+ sbuf_printf(sb, "SigIgn:\t%08x\n", ps->ps_sigignore.__bits[0]);
+ sbuf_printf(sb, "SigCgt:\t%08x\n", ps->ps_sigcatch.__bits[0]);
+ mtx_unlock(&ps->ps_mtx);
+ PROC_UNLOCK(p);
+
+ /*
+ * Linux also prints the capability masks, but we don't have
+ * capabilities yet, and when we do get them they're likely to
+ * be meaningless to Linux programs, so we lie. XXX
+ */
+ sbuf_printf(sb, "CapInh:\t%016x\n", 0);
+ sbuf_printf(sb, "CapPrm:\t%016x\n", 0);
+ sbuf_printf(sb, "CapEff:\t%016x\n", 0);
+
+ return (0);
+}
+
+
+/*
+ * Filler function for proc/pid/cwd
+ */
+static int
+linprocfs_doproccwd(PFS_FILL_ARGS)
+{
+ char *fullpath = "unknown";
+ char *freepath = NULL;
+
+ vn_fullpath(td, p->p_fd->fd_cdir, &fullpath, &freepath);
+ sbuf_printf(sb, "%s", fullpath);
+ if (freepath)
+ free(freepath, M_TEMP);
+ return (0);
+}
+
+/*
+ * Filler function for proc/pid/root
+ */
+static int
+linprocfs_doprocroot(PFS_FILL_ARGS)
+{
+ struct vnode *rvp;
+ char *fullpath = "unknown";
+ char *freepath = NULL;
+
+ rvp = jailed(p->p_ucred) ? p->p_fd->fd_jdir : p->p_fd->fd_rdir;
+ vn_fullpath(td, rvp, &fullpath, &freepath);
+ sbuf_printf(sb, "%s", fullpath);
+ if (freepath)
+ free(freepath, M_TEMP);
+ return (0);
+}
+
+/*
+ * Filler function for proc/pid/cmdline
+ */
+static int
+linprocfs_doproccmdline(PFS_FILL_ARGS)
+{
+ int ret;
+
+ PROC_LOCK(p);
+ if ((ret = p_cansee(td, p)) != 0) {
+ PROC_UNLOCK(p);
+ return (ret);
+ }
+
+ /*
+ * Mimic linux behavior and pass only processes with usermode
+ * address space as valid. Return zero silently otherwize.
+ */
+ if (p->p_vmspace == &vmspace0) {
+ PROC_UNLOCK(p);
+ return (0);
+ }
+ if (p->p_args != NULL) {
+ sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length);
+ PROC_UNLOCK(p);
+ return (0);
+ }
+
+ if ((p->p_flag & P_SYSTEM) != 0) {
+ PROC_UNLOCK(p);
+ return (0);
+ }
+
+ PROC_UNLOCK(p);
+
+ ret = proc_getargv(td, p, sb);
+ return (ret);
+}
+
+/*
+ * Filler function for proc/pid/environ
+ */
+static int
+linprocfs_doprocenviron(PFS_FILL_ARGS)
+{
+ int ret;
+
+ PROC_LOCK(p);
+ if ((ret = p_candebug(td, p)) != 0) {
+ PROC_UNLOCK(p);
+ return (ret);
+ }
+
+ /*
+ * Mimic linux behavior and pass only processes with usermode
+ * address space as valid. Return zero silently otherwize.
+ */
+ if (p->p_vmspace == &vmspace0) {
+ PROC_UNLOCK(p);
+ return (0);
+ }
+
+ if ((p->p_flag & P_SYSTEM) != 0) {
+ PROC_UNLOCK(p);
+ return (0);
+ }
+
+ PROC_UNLOCK(p);
+
+ ret = proc_getenvv(td, p, sb);
+ return (ret);
+}
+
+/*
+ * Filler function for proc/pid/maps
+ */
+static int
+linprocfs_doprocmaps(PFS_FILL_ARGS)
+{
+ struct vmspace *vm;
+ vm_map_t map;
+ vm_map_entry_t entry, tmp_entry;
+ vm_object_t obj, tobj, lobj;
+ vm_offset_t e_start, e_end;
+ vm_ooffset_t off = 0;
+ vm_prot_t e_prot;
+ unsigned int last_timestamp;
+ char *name = "", *freename = NULL;
+ ino_t ino;
+ int ref_count, shadow_count, flags;
+ int error;
+ struct vnode *vp;
+ struct vattr vat;
+
+ PROC_LOCK(p);
+ error = p_candebug(td, p);
+ PROC_UNLOCK(p);
+ if (error)
+ return (error);
+
+ if (uio->uio_rw != UIO_READ)
+ return (EOPNOTSUPP);
+
+ error = 0;
+ vm = vmspace_acquire_ref(p);
+ if (vm == NULL)
+ return (ESRCH);
+ map = &vm->vm_map;
+ vm_map_lock_read(map);
+ for (entry = map->header.next; entry != &map->header;
+ entry = entry->next) {
+ name = "";
+ freename = NULL;
+ if (entry->eflags & MAP_ENTRY_IS_SUB_MAP)
+ continue;
+ e_prot = entry->protection;
+ e_start = entry->start;
+ e_end = entry->end;
+ obj = entry->object.vm_object;
+ for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) {
+ VM_OBJECT_RLOCK(tobj);
+ if (lobj != obj)
+ VM_OBJECT_RUNLOCK(lobj);
+ lobj = tobj;
+ }
+ last_timestamp = map->timestamp;
+ vm_map_unlock_read(map);
+ ino = 0;
+ if (lobj) {
+ off = IDX_TO_OFF(lobj->size);
+ if (lobj->type == OBJT_VNODE) {
+ vp = lobj->handle;
+ if (vp)
+ vref(vp);
+ }
+ else
+ vp = NULL;
+ if (lobj != obj)
+ VM_OBJECT_RUNLOCK(lobj);
+ flags = obj->flags;
+ ref_count = obj->ref_count;
+ shadow_count = obj->shadow_count;
+ VM_OBJECT_RUNLOCK(obj);
+ if (vp) {
+ vn_fullpath(td, vp, &name, &freename);
+ vn_lock(vp, LK_SHARED | LK_RETRY);
+ VOP_GETATTR(vp, &vat, td->td_ucred);
+ ino = vat.va_fileid;
+ vput(vp);
+ }
+ } else {
+ flags = 0;
+ ref_count = 0;
+ shadow_count = 0;
+ }
+
+ /*
+ * format:
+ * start, end, access, offset, major, minor, inode, name.
+ */
+ error = sbuf_printf(sb,
+ "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n",
+ (u_long)e_start, (u_long)e_end,
+ (e_prot & VM_PROT_READ)?"r":"-",
+ (e_prot & VM_PROT_WRITE)?"w":"-",
+ (e_prot & VM_PROT_EXECUTE)?"x":"-",
+ "p",
+ (u_long)off,
+ 0,
+ 0,
+ (u_long)ino,
+ *name ? " " : "",
+ name
+ );
+ if (freename)
+ free(freename, M_TEMP);
+ vm_map_lock_read(map);
+ if (error == -1) {
+ error = 0;
+ break;
+ }
+ if (last_timestamp != map->timestamp) {
+ /*
+ * Look again for the entry because the map was
+ * modified while it was unlocked. Specifically,
+ * the entry may have been clipped, merged, or deleted.
+ */
+ vm_map_lookup_entry(map, e_end - 1, &tmp_entry);
+ entry = tmp_entry;
+ }
+ }
+ vm_map_unlock_read(map);
+ vmspace_free(vm);
+
+ return (error);
+}
+
+/*
+ * Filler function for proc/net/dev
+ */
+static int
+linprocfs_donetdev(PFS_FILL_ARGS)
+{
+ char ifname[16]; /* XXX LINUX_IFNAMSIZ */
+ struct ifnet *ifp;
+
+ sbuf_printf(sb, "%6s|%58s|%s\n"
+ "%6s|%58s|%58s\n",
+ "Inter-", " Receive", " Transmit",
+ " face",
+ "bytes packets errs drop fifo frame compressed multicast",
+ "bytes packets errs drop fifo colls carrier compressed");
+
+ CURVNET_SET(TD_TO_VNET(curthread));
+ IFNET_RLOCK();
+ TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
+ linux_ifname(ifp, ifname, sizeof ifname);
+ sbuf_printf(sb, "%6.6s: ", ifname);
+ sbuf_printf(sb, "%7lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ",
+ ifp->if_ibytes, /* rx_bytes */
+ ifp->if_ipackets, /* rx_packets */
+ ifp->if_ierrors, /* rx_errors */
+ ifp->if_iqdrops, /* rx_dropped +
+ * rx_missed_errors */
+ 0UL, /* rx_fifo_errors */
+ 0UL, /* rx_length_errors +
+ * rx_over_errors +
+ * rx_crc_errors +
+ * rx_frame_errors */
+ 0UL, /* rx_compressed */
+ ifp->if_imcasts); /* multicast, XXX-BZ rx only? */
+ sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
+ ifp->if_obytes, /* tx_bytes */
+ ifp->if_opackets, /* tx_packets */
+ ifp->if_oerrors, /* tx_errors */
+ 0UL, /* tx_dropped */
+ 0UL, /* tx_fifo_errors */
+ ifp->if_collisions, /* collisions */
+ 0UL, /* tx_carrier_errors +
+ * tx_aborted_errors +
+ * tx_window_errors +
+ * tx_heartbeat_errors */
+ 0UL); /* tx_compressed */
+ }
+ IFNET_RUNLOCK();
+ CURVNET_RESTORE();
+
+ return (0);
+}
+
+/*
+ * Filler function for proc/sys/kernel/osrelease
+ */
+static int
+linprocfs_doosrelease(PFS_FILL_ARGS)
+{
+ char osrelease[LINUX_MAX_UTSNAME];
+
+ linux_get_osrelease(td, osrelease);
+ sbuf_printf(sb, "%s\n", osrelease);
+
+ return (0);
+}
+
+/*
+ * Filler function for proc/sys/kernel/ostype
+ */
+static int
+linprocfs_doostype(PFS_FILL_ARGS)
+{
+ char osname[LINUX_MAX_UTSNAME];
+
+ linux_get_osname(td, osname);
+ sbuf_printf(sb, "%s\n", osname);
+
+ return (0);
+}
+
+/*
+ * Filler function for proc/sys/kernel/version
+ */
+static int
+linprocfs_doosbuild(PFS_FILL_ARGS)
+{
+
+ linprocfs_osbuild(td, sb);
+ sbuf_cat(sb, "\n");
+ return (0);
+}
+
+/*
+ * Filler function for proc/sys/kernel/msgmni
+ */
+static int
+linprocfs_domsgmni(PFS_FILL_ARGS)
+{
+
+ sbuf_printf(sb, "%d\n", msginfo.msgmni);
+ return (0);
+}
+
+/*
+ * Filler function for proc/sys/kernel/pid_max
+ */
+static int
+linprocfs_dopid_max(PFS_FILL_ARGS)
+{
+
+ sbuf_printf(sb, "%i\n", PID_MAX);
+ return (0);
+}
+
+/*
+ * Filler function for proc/sys/kernel/sem
+ */
+static int
+linprocfs_dosem(PFS_FILL_ARGS)
+{
+
+ sbuf_printf(sb, "%d %d %d %d\n", seminfo.semmsl, seminfo.semmns,
+ seminfo.semopm, seminfo.semmni);
+ return (0);
+}
+
+/*
+ * Filler function for proc/scsi/device_info
+ */
+static int
+linprocfs_doscsidevinfo(PFS_FILL_ARGS)
+{
+
+ return (0);
+}
+
+/*
+ * Filler function for proc/scsi/scsi
+ */
+static int
+linprocfs_doscsiscsi(PFS_FILL_ARGS)
+{
+
+ return (0);
+}
+
+extern struct cdevsw *cdevsw[];
+
+/*
+ * Filler function for proc/devices
+ */
+static int
+linprocfs_dodevices(PFS_FILL_ARGS)
+{
+ char *char_devices;
+ sbuf_printf(sb, "Character devices:\n");
+
+ char_devices = linux_get_char_devices();
+ sbuf_printf(sb, "%s", char_devices);
+ linux_free_get_char_devices(char_devices);
+
+ sbuf_printf(sb, "\nBlock devices:\n");
+
+ return (0);
+}
+
+/*
+ * Filler function for proc/cmdline
+ */
+static int
+linprocfs_docmdline(PFS_FILL_ARGS)
+{
+
+ sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname);
+ sbuf_printf(sb, " ro root=302\n");
+ return (0);
+}
+
+/*
+ * Filler function for proc/filesystems
+ */
+static int
+linprocfs_dofilesystems(PFS_FILL_ARGS)
+{
+ struct vfsconf *vfsp;
+
+ mtx_lock(&Giant);
+ TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) {
+ if (vfsp->vfc_flags & VFCF_SYNTHETIC)
+ sbuf_printf(sb, "nodev");
+ sbuf_printf(sb, "\t%s\n", vfsp->vfc_name);
+ }
+ mtx_unlock(&Giant);
+ return(0);
+}
+
+#if 0
+/*
+ * Filler function for proc/modules
+ */
+static int
+linprocfs_domodules(PFS_FILL_ARGS)
+{
+ struct linker_file *lf;
+
+ TAILQ_FOREACH(lf, &linker_files, link) {
+ sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename,
+ (unsigned long)lf->size, lf->refs);
+ }
+ return (0);
+}
+#endif
+
+/*
+ * Filler function for proc/pid/fd
+ */
+static int
+linprocfs_dofdescfs(PFS_FILL_ARGS)
+{
+
+ if (p == curproc)
+ sbuf_printf(sb, "/dev/fd");
+ else
+ sbuf_printf(sb, "unknown");
+ return (0);
+}
+
+/*
+ * Constructor
+ */
+static int
+linprocfs_init(PFS_INIT_ARGS)
+{
+ struct pfs_node *root;
+ struct pfs_node *dir;
+
+ root = pi->pi_root;
+
+ /* /proc/... */
+ pfs_create_file(root, "cmdline", &linprocfs_docmdline,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(root, "devices", &linprocfs_dodevices,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(root, "filesystems", &linprocfs_dofilesystems,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(root, "loadavg", &linprocfs_doloadavg,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(root, "meminfo", &linprocfs_domeminfo,
+ NULL, NULL, NULL, PFS_RD);
+#if 0
+ pfs_create_file(root, "modules", &linprocfs_domodules,
+ NULL, NULL, NULL, PFS_RD);
+#endif
+ pfs_create_file(root, "mounts", &linprocfs_domtab,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(root, "mtab", &linprocfs_domtab,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(root, "partitions", &linprocfs_dopartitions,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_link(root, "self", &procfs_docurproc,
+ NULL, NULL, NULL, 0);
+ pfs_create_file(root, "stat", &linprocfs_dostat,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(root, "swaps", &linprocfs_doswaps,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(root, "uptime", &linprocfs_douptime,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(root, "version", &linprocfs_doversion,
+ NULL, NULL, NULL, PFS_RD);
+
+ /* /proc/net/... */
+ dir = pfs_create_dir(root, "net", NULL, NULL, NULL, 0);
+ pfs_create_file(dir, "dev", &linprocfs_donetdev,
+ NULL, NULL, NULL, PFS_RD);
+
+ /* /proc/<pid>/... */
+ dir = pfs_create_dir(root, "pid", NULL, NULL, NULL, PFS_PROCDEP);
+ pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_link(dir, "cwd", &linprocfs_doproccwd,
+ NULL, NULL, NULL, 0);
+ pfs_create_file(dir, "environ", &linprocfs_doprocenviron,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_link(dir, "exe", &procfs_doprocfile,
+ NULL, &procfs_notsystem, NULL, 0);
+ pfs_create_file(dir, "maps", &linprocfs_doprocmaps,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(dir, "mem", &procfs_doprocmem,
+ &procfs_attr, &procfs_candebug, NULL, PFS_RDWR|PFS_RAW);
+ pfs_create_link(dir, "root", &linprocfs_doprocroot,
+ NULL, NULL, NULL, 0);
+ pfs_create_file(dir, "stat", &linprocfs_doprocstat,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(dir, "statm", &linprocfs_doprocstatm,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(dir, "status", &linprocfs_doprocstatus,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_link(dir, "fd", &linprocfs_dofdescfs,
+ NULL, NULL, NULL, 0);
+
+ /* /proc/scsi/... */
+ dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0);
+ pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi,
+ NULL, NULL, NULL, PFS_RD);
+
+ /* /proc/sys/... */
+ dir = pfs_create_dir(root, "sys", NULL, NULL, NULL, 0);
+ /* /proc/sys/kernel/... */
+ dir = pfs_create_dir(dir, "kernel", NULL, NULL, NULL, 0);
+ pfs_create_file(dir, "osrelease", &linprocfs_doosrelease,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(dir, "ostype", &linprocfs_doostype,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(dir, "version", &linprocfs_doosbuild,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(dir, "msgmni", &linprocfs_domsgmni,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(dir, "pid_max", &linprocfs_dopid_max,
+ NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(dir, "sem", &linprocfs_dosem,
+ NULL, NULL, NULL, PFS_RD);
+
+ return (0);
+}
+
+/*
+ * Destructor
+ */
+static int
+linprocfs_uninit(PFS_INIT_ARGS)
+{
+
+ /* nothing to do, pseudofs will GC */
+ return (0);
+}
+
+PSEUDOFS(linprocfs, 1, 0);
+MODULE_DEPEND(linprocfs, linux, 1, 1, 1);
+MODULE_DEPEND(linprocfs, procfs, 1, 1, 1);
+MODULE_DEPEND(linprocfs, sysvmsg, 1, 1, 1);
+MODULE_DEPEND(linprocfs, sysvsem, 1, 1, 1);
diff --git a/sys/compat/linsysfs/linsysfs.c b/sys/compat/linsysfs/linsysfs.c
new file mode 100644
index 0000000..45f44af
--- /dev/null
+++ b/sys/compat/linsysfs/linsysfs.c
@@ -0,0 +1,284 @@
+/*-
+ * Copyright (c) 2006 IronPort Systems
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/blist.h>
+#include <sys/conf.h>
+#include <sys/exec.h>
+#include <sys/filedesc.h>
+#include <sys/kernel.h>
+#include <sys/linker.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/resourcevar.h>
+#include <sys/sbuf.h>
+#include <sys/smp.h>
+#include <sys/socket.h>
+#include <sys/vnode.h>
+#include <sys/bus.h>
+#include <sys/pciio.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <net/if.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_param.h>
+#include <vm/vm_object.h>
+#include <vm/swap_pager.h>
+
+#include <machine/bus.h>
+
+#include "opt_compat.h"
+#ifdef COMPAT_LINUX32 /* XXX */
+#include <machine/../linux32/linux.h>
+#else
+#include <machine/../linux/linux.h>
+#endif
+#include <compat/linux/linux_ioctl.h>
+#include <compat/linux/linux_mib.h>
+#include <compat/linux/linux_util.h>
+#include <fs/pseudofs/pseudofs.h>
+
+struct scsi_host_queue {
+ TAILQ_ENTRY(scsi_host_queue) scsi_host_next;
+ char *path;
+ char *name;
+};
+
+TAILQ_HEAD(,scsi_host_queue) scsi_host_q;
+
+static int host_number = 0;
+
+static int
+atoi(const char *str)
+{
+ return (int)strtol(str, (char **)NULL, 10);
+}
+
+/*
+ * Filler function for proc_name
+ */
+static int
+linsysfs_scsiname(PFS_FILL_ARGS)
+{
+ struct scsi_host_queue *scsi_host;
+ int index;
+
+ if (strncmp(pn->pn_parent->pn_name, "host", 4) == 0) {
+ index = atoi(&pn->pn_parent->pn_name[4]);
+ } else {
+ sbuf_printf(sb, "unknown\n");
+ return (0);
+ }
+ TAILQ_FOREACH(scsi_host, &scsi_host_q, scsi_host_next) {
+ if (index-- == 0) {
+ sbuf_printf(sb, "%s\n", scsi_host->name);
+ return (0);
+ }
+ }
+ sbuf_printf(sb, "unknown\n");
+ return (0);
+}
+
+/*
+ * Filler function for device sym-link
+ */
+static int
+linsysfs_link_scsi_host(PFS_FILL_ARGS)
+{
+ struct scsi_host_queue *scsi_host;
+ int index;
+
+ if (strncmp(pn->pn_parent->pn_name, "host", 4) == 0) {
+ index = atoi(&pn->pn_parent->pn_name[4]);
+ } else {
+ sbuf_printf(sb, "unknown\n");
+ return (0);
+ }
+ TAILQ_FOREACH(scsi_host, &scsi_host_q, scsi_host_next) {
+ if (index-- == 0) {
+ sbuf_printf(sb, "../../../devices%s", scsi_host->path);
+ return(0);
+ }
+ }
+ sbuf_printf(sb, "unknown\n");
+ return (0);
+}
+
+#define PCI_DEV "pci"
+static int
+linsysfs_run_bus(device_t dev, struct pfs_node *dir, struct pfs_node *scsi, char *path,
+ char *prefix)
+{
+ struct scsi_host_queue *scsi_host;
+ struct pfs_node *sub_dir;
+ int i, nchildren;
+ device_t *children, parent;
+ devclass_t devclass;
+ const char *name = NULL;
+ struct pci_devinfo *dinfo;
+ char *device, *host, *new_path = path;
+
+ parent = device_get_parent(dev);
+ if (parent) {
+ devclass = device_get_devclass(parent);
+ if (devclass != NULL)
+ name = devclass_get_name(devclass);
+ if (name && strcmp(name, PCI_DEV) == 0) {
+ dinfo = device_get_ivars(dev);
+ if (dinfo) {
+ device = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+ new_path = malloc(MAXPATHLEN, M_TEMP,
+ M_WAITOK);
+ new_path[0] = '\000';
+ strcpy(new_path, path);
+ host = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+ device[0] = '\000';
+ sprintf(device, "%s:%02x:%02x.%x",
+ prefix,
+ dinfo->cfg.bus,
+ dinfo->cfg.slot,
+ dinfo->cfg.func);
+ strcat(new_path, "/");
+ strcat(new_path, device);
+ dir = pfs_create_dir(dir, device,
+ NULL, NULL, NULL, 0);
+
+ if (dinfo->cfg.baseclass == PCIC_STORAGE) {
+ /* DJA only make this if needed */
+ sprintf(host, "host%d", host_number++);
+ strcat(new_path, "/");
+ strcat(new_path, host);
+ pfs_create_dir(dir, host,
+ NULL, NULL, NULL, 0);
+ scsi_host = malloc(sizeof(
+ struct scsi_host_queue),
+ M_DEVBUF, M_NOWAIT);
+ scsi_host->path = malloc(
+ strlen(new_path) + 1,
+ M_DEVBUF, M_NOWAIT);
+ scsi_host->path[0] = '\000';
+ bcopy(new_path, scsi_host->path,
+ strlen(new_path) + 1);
+ scsi_host->name = "unknown";
+
+ sub_dir = pfs_create_dir(scsi, host,
+ NULL, NULL, NULL, 0);
+ pfs_create_link(sub_dir, "device",
+ &linsysfs_link_scsi_host,
+ NULL, NULL, NULL, 0);
+ pfs_create_file(sub_dir, "proc_name",
+ &linsysfs_scsiname,
+ NULL, NULL, NULL, PFS_RD);
+ scsi_host->name
+ = linux_driver_get_name_dev(dev);
+ TAILQ_INSERT_TAIL(&scsi_host_q,
+ scsi_host, scsi_host_next);
+ }
+ free(device, M_TEMP);
+ free(host, M_TEMP);
+ }
+ }
+ }
+
+ device_get_children(dev, &children, &nchildren);
+ for (i = 0; i < nchildren; i++) {
+ if (children[i])
+ linsysfs_run_bus(children[i], dir, scsi, new_path, prefix);
+ }
+ if (new_path != path)
+ free(new_path, M_TEMP);
+
+ return (1);
+}
+
+/*
+ * Constructor
+ */
+static int
+linsysfs_init(PFS_INIT_ARGS)
+{
+ struct pfs_node *root;
+ struct pfs_node *dir;
+ struct pfs_node *pci;
+ struct pfs_node *scsi;
+ devclass_t devclass;
+ device_t dev;
+
+ TAILQ_INIT(&scsi_host_q);
+
+ root = pi->pi_root;
+
+ /* /sys/class/... */
+ scsi = pfs_create_dir(root, "class", NULL, NULL, NULL, 0);
+ scsi = pfs_create_dir(scsi, "scsi_host", NULL, NULL, NULL, 0);
+
+ /* /sys/device */
+ dir = pfs_create_dir(root, "devices", NULL, NULL, NULL, 0);
+
+ /* /sys/device/pci0000:00 */
+ pci = pfs_create_dir(dir, "pci0000:00", NULL, NULL, NULL, 0);
+
+ devclass = devclass_find("root");
+ if (devclass == NULL) {
+ return (0);
+ }
+
+ dev = devclass_get_device(devclass, 0);
+ linsysfs_run_bus(dev, pci, scsi, "/pci0000:00", "0000");
+ return (0);
+}
+
+/*
+ * Destructor
+ */
+static int
+linsysfs_uninit(PFS_INIT_ARGS)
+{
+ struct scsi_host_queue *scsi_host, *scsi_host_tmp;
+
+ TAILQ_FOREACH_SAFE(scsi_host, &scsi_host_q, scsi_host_next,
+ scsi_host_tmp) {
+ TAILQ_REMOVE(&scsi_host_q, scsi_host, scsi_host_next);
+ free(scsi_host->path, M_TEMP);
+ free(scsi_host, M_TEMP);
+ }
+
+ return (0);
+}
+
+PSEUDOFS(linsysfs, 1, 0);
+MODULE_DEPEND(linsysfs, linux, 1, 1, 1);
diff --git a/sys/compat/linux/check_error.d b/sys/compat/linux/check_error.d
new file mode 100644
index 0000000..9e3c00a
--- /dev/null
+++ b/sys/compat/linux/check_error.d
@@ -0,0 +1,144 @@
+#!/usr/sbin/dtrace -qs
+
+/*-
+ * Copyright (c) 2008-2012 Alexander Leidinger <netchild@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Report error conditions:
+ * - emulation errors (unsupportet stuff, unknown stuff, ...)
+ * - kernel errors (resource shortage, ...)
+ * - programming errors (errors which can happen, but should not happen)
+ */
+
+linuxulator*:dummy::not_implemented,
+linuxulator*:emul:proc_exit:child_clear_tid_error,
+linuxulator*:emul:proc_exit:futex_failed,
+linuxulator*:emul:linux_schedtail:copyout_error,
+linuxulator*:futex:futex_get:error,
+linuxulator*:futex:futex_sleep:requeue_error,
+linuxulator*:futex:futex_sleep:sleep_error,
+linuxulator*:futex:futex_wait:copyin_error,
+linuxulator*:futex:futex_wait:itimerfix_error,
+linuxulator*:futex:futex_wait:sleep_error,
+linuxulator*:futex:futex_atomic_op:missing_access_check,
+linuxulator*:futex:futex_atomic_op:unimplemented_op,
+linuxulator*:futex:futex_atomic_op:unimplemented_cmp,
+linuxulator*:futex:linux_sys_futex:unimplemented_clockswitch,
+linuxulator*:futex:linux_sys_futex:copyin_error,
+linuxulator*:futex:linux_sys_futex:unhandled_efault,
+linuxulator*:futex:linux_sys_futex:unimplemented_lock_pi,
+linuxulator*:futex:linux_sys_futex:unimplemented_unlock_pi,
+linuxulator*:futex:linux_sys_futex:unimplemented_trylock_pi,
+linuxulator*:futex:linux_sys_futex:unimplemented_wait_requeue_pi,
+linuxulator*:futex:linux_sys_futex:unimplemented_cmp_requeue_pi,
+linuxulator*:futex:linux_sys_futex:unknown_operation,
+linuxulator*:futex:linux_get_robust_list:copyout_error,
+linuxulator*:futex:handle_futex_death:copyin_error,
+linuxulator*:futex:fetch_robust_entry:copyin_error,
+linuxulator*:futex:release_futexes:copyin_error,
+linuxulator*:time:linux_clock_gettime:conversion_error,
+linuxulator*:time:linux_clock_gettime:gettime_error,
+linuxulator*:time:linux_clock_gettime:copyout_error,
+linuxulator*:time:linux_clock_settime:conversion_error,
+linuxulator*:time:linux_clock_settime:settime_error,
+linuxulator*:time:linux_clock_settime:copyin_error,
+linuxulator*:time:linux_clock_getres:conversion_error,
+linuxulator*:time:linux_clock_getres:getres_error,
+linuxulator*:time:linux_clock_getres:copyout_error,
+linuxulator*:time:linux_nanosleep:conversion_error,
+linuxulator*:time:linux_nanosleep:nanosleep_error,
+linuxulator*:time:linux_nanosleep:copyout_error,
+linuxulator*:time:linux_nanosleep:copyin_error,
+linuxulator*:time:linux_clock_nanosleep:copyin_error,
+linuxulator*:time:linux_clock_nanosleep:conversion_error,
+linuxulator*:time:linux_clock_nanosleep:copyout_error,
+linuxulator*:time:linux_clock_nanosleep:nanosleep_error,
+linuxulator*:sysctl:handle_string:copyout_error,
+linuxulator*:sysctl:linux_sysctl:copyin_error,
+linuxulator*:mib:linux_sysctl_osname:sysctl_string_error,
+linuxulator*:mib:linux_sysctl_osrelease:sysctl_string_error,
+linuxulator*:mib:linux_sysctl_oss_version:sysctl_string_error,
+linuxulator*:mib:linux_prison_create:vfs_copyopt_error,
+linuxulator*:mib:linux_prison_check:vfs_copyopt_error,
+linuxulator*:mib:linux_prison_check:vfs_getopt_error,
+linuxulator*:mib:linux_prison_set:vfs_copyopt_error,
+linuxulator*:mib:linux_prison_set:vfs_getopt_error,
+linuxulator*:mib:linux_prison_get:vfs_setopt_error,
+linuxulator*:mib:linux_prison_get:vfs_setopts_error
+{
+ printf("ERROR: %s in %s:%s:%s\n", probename, probeprov, probemod, probefunc);
+ stack();
+ ustack();
+}
+
+linuxulator*:util:linux_driver_get_name_dev:nullcall,
+linuxulator*:util:linux_driver_get_major_minor:nullcall,
+linuxulator*:futex:linux_sys_futex:invalid_cmp_requeue_use,
+linuxulator*:futex:linux_sys_futex:deprecated_requeue,
+linuxulator*:futex:linux_set_robust_list:size_error,
+linuxulator*:time:linux_clock_getres:nullcall
+{
+ printf("WARNING: %s:%s:%s:%s in application %s, maybe an application error?\n", probename, probeprov, probemod, probefunc, execname);
+ stack();
+ ustack();
+}
+
+linuxulator*:util:linux_driver_get_major_minor:notfound
+{
+ printf("WARNING: Application %s failed to find %s in %s:%s:%s, this may or may not be a problem.\n", execname, stringof(args[0]), probename, probeprov, probemod);
+ stack();
+ ustack();
+}
+
+linuxulator*:time:linux_to_native_clockid:unknown_clockid
+{
+ printf("INFO: Application %s tried to use unknown clockid %d. Please report this to freebsd-emulation@FreeBSD.org.\n", execname, arg0);
+}
+
+linuxulator*:time:linux_to_native_clockid:unsupported_clockid,
+linuxulator*:time:linux_clock_nanosleep:unsupported_clockid
+{
+ printf("WARNING: Application %s tried to use unsupported clockid (%d), this may or may not be a problem for the application.\nPatches to support this clockid are welcome on the freebsd-emulation@FreeBSD.org mailinglist.\n", execname, arg0);
+}
+
+linuxulator*:time:linux_clock_nanosleep:unsupported_flags
+{
+ printf("WARNING: Application %s tried to use unsupported flags (%d), this may or may not be a problem for the application.\nPatches to support those flags are welcome on the freebsd-emulation@FreeBSD.org mailinglist.\n", execname, arg0);
+}
+
+linuxulator*:sysctl:linux_sysctl:wrong_length
+{
+ printf("ERROR: Application %s issued a sysctl which failed the length restrictions.\nThe length passed is %d, the min length supported is 1 and the max length supported is %d.\n", execname, arg0, arg1);
+ stack();
+ ustack();
+}
+
+linuxulator*:sysctl:linux_sysctl:unsupported_sysctl
+{
+ printf("ERROR: Application %s issued an unsupported sysctl (%s).\nPatches to support this sysctl are welcome on the freebsd-emulation@FreeBSD.org mailinglist.\n", execname, stringof(args[0]));
+}
diff --git a/sys/compat/linux/check_internal_locks.d b/sys/compat/linux/check_internal_locks.d
new file mode 100644
index 0000000..2bdef68
--- /dev/null
+++ b/sys/compat/linux/check_internal_locks.d
@@ -0,0 +1,132 @@
+#!/usr/sbin/dtrace -qs
+
+/*-
+ * Copyright (c) 2008-2012 Alexander Leidinger <netchild@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * Check if the internal locks are correctly acquired/released:
+ * - no recursive locking (mtx locks, write locks)
+ * - no unlocking of already unlocked one
+ *
+ * Print stacktrace if a lock is longer locked than about 10sec or more.
+ */
+
+#pragma D option dynvarsize=32m
+#pragma D option specsize=32m
+
+BEGIN
+{
+ check["emul_lock"] = 0;
+ check["emul_shared_rlock"] = 0;
+ check["emul_shared_wlock"] = 0;
+ check["futex_mtx"] = 0;
+}
+
+linuxulator*:locks:emul_lock:locked,
+linuxulator*:locks:emul_shared_wlock:locked,
+linuxulator*:locks:futex_mtx:locked
+/check[probefunc] > 0/
+{
+ printf("ERROR: recursive lock of %s (%p),", probefunc, arg0);
+ printf(" or missing SDT probe in kernel. Stack trace follows:");
+ stack();
+}
+
+linuxulator*:locks:emul_lock:locked,
+linuxulator*:locks:emul_shared_rlock:locked,
+linuxulator*:locks:emul_shared_wlock:locked,
+linuxulator*:locks:futex_mtx:locked
+{
+ ++check[probefunc];
+ @stats[probefunc] = count();
+
+ ts[probefunc] = timestamp;
+ spec[probefunc] = speculation();
+}
+
+linuxulator*:locks:emul_lock:unlock,
+linuxulator*:locks:emul_shared_rlock:unlock,
+linuxulator*:locks:emul_shared_wlock:unlock,
+linuxulator*:locks:futex_mtx:unlock
+/check[probefunc] == 0/
+{
+ printf("ERROR: unlock attemt of unlocked %s (%p),", probefunc, arg0);
+ printf(" missing SDT probe in kernel, or dtrace program started");
+ printf(" while the %s was already held (race condition).", probefunc);
+ printf(" Stack trace follows:");
+ stack();
+}
+
+linuxulator*:locks:emul_lock:unlock,
+linuxulator*:locks:emul_shared_rlock:unlock,
+linuxulator*:locks:emul_shared_wlock:unlock,
+linuxulator*:locks:futex_mtx:unlock
+{
+ discard(spec[probefunc]);
+ spec[probefunc] = 0;
+ --check[probefunc];
+}
+
+/* Timeout handling */
+
+tick-10s
+/spec["emul_lock"] != 0 && timestamp - ts["emul_lock"] >= 9999999000/
+{
+ commit(spec["emul_lock"]);
+ spec["emul_lock"] = 0;
+}
+
+tick-10s
+/spec["emul_shared_wlock"] != 0 && timestamp - ts["emul_shared_wlock"] >= 9999999000/
+{
+ commit(spec["emul_shared_wlock"]);
+ spec["emul_shared_wlock"] = 0;
+}
+
+tick-10s
+/spec["emul_shared_rlock"] != 0 && timestamp - ts["emul_shared_rlock"] >= 9999999000/
+{
+ commit(spec["emul_shared_rlock"]);
+ spec["emul_shared_rlock"] = 0;
+}
+
+tick-10s
+/spec["futex_mtx"] != 0 && timestamp - ts["futex_mtx"] >= 9999999000/
+{
+ commit(spec["futex_mtx"]);
+ spec["futex_mtx"] = 0;
+}
+
+
+/* Statistics */
+
+END
+{
+ printf("Number of locks per type:");
+ printa(@stats);
+}
diff --git a/sys/compat/linux/linux_dtrace.h b/sys/compat/linux/linux_dtrace.h
new file mode 100644
index 0000000..b6a2b33
--- /dev/null
+++ b/sys/compat/linux/linux_dtrace.h
@@ -0,0 +1,95 @@
+/*-
+ * Copyright (c) 2008-2012 Alexander Leidinger <netchild@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LINUX_DTRACE_H_
+#define _LINUX_DTRACE_H_
+
+/**
+ * DTrace support macros for the linuxulator.
+ *
+ * Some wrapper macros to make it more easy to handle the linuxulator
+ * providers and to allow to make the name depend upon the bitsize.
+ *
+ * Basically this is the same as the normal SDT macros in sys/sdt.h. The
+ * difference is that the provider name is automatically inserted, and
+ * we do not use a different name for the probe-description.
+ */
+
+#define LIN_SDT_PROVIDER_DEFINE(x) SDT_PROVIDER_DEFINE(x)
+#define LIN_SDT_PROVIDER_DECLARE(x) SDT_PROVIDER_DECLARE(x)
+
+#define _LIN_SDT_PROBE_DECLARE(a, b, c, d) SDT_PROBE_DECLARE(a, b, c, d)
+#define LIN_SDT_PROBE_DECLARE(a, b, c) _LIN_SDT_PROBE_DECLARE( \
+ LINUX_DTRACE, a, b, c)
+
+#define _LIN_SDT_PROBE_DEFINE0(a, b, c, d) SDT_PROBE_DEFINE(a, \
+ b, c, d, d)
+#define LIN_SDT_PROBE_DEFINE0(a, b, c) _LIN_SDT_PROBE_DEFINE0(\
+ LINUX_DTRACE, a, b, c)
+#define _LIN_SDT_PROBE_DEFINE1(a, b, c, d, e) SDT_PROBE_DEFINE1(a, \
+ b, c, d, d, e)
+#define LIN_SDT_PROBE_DEFINE1(a, b, c, d) _LIN_SDT_PROBE_DEFINE1(\
+ LINUX_DTRACE, a, b, c, d)
+#define _LIN_SDT_PROBE_DEFINE2(a, b, c, d, e, f) SDT_PROBE_DEFINE2(a, \
+ b, c, d, d, e, f)
+#define LIN_SDT_PROBE_DEFINE2(a, b, c, d, e) _LIN_SDT_PROBE_DEFINE2(\
+ LINUX_DTRACE, a, b, c, d, e)
+#define _LIN_SDT_PROBE_DEFINE3(a, b, c, d, e, f, g) SDT_PROBE_DEFINE3(a, \
+ b, c, d, d, e, f, g)
+#define LIN_SDT_PROBE_DEFINE3(a, b, c, d, e, f) _LIN_SDT_PROBE_DEFINE3(\
+ LINUX_DTRACE, a, b, c, d, e, f)
+#define _LIN_SDT_PROBE_DEFINE4(a, b, c, d, e, f, g, h) SDT_PROBE_DEFINE4(a, \
+ b, c, d, d, e, f, g, h)
+#define LIN_SDT_PROBE_DEFINE4(a, b, c, d, e, f, g) _LIN_SDT_PROBE_DEFINE4(\
+ LINUX_DTRACE, a, b, c, d, e, f, g)
+#define _LIN_SDT_PROBE_DEFINE5(a, b, c, d, e, f, g, h, i) \
+ SDT_PROBE_DEFINE5(a, b, c, d, d, e, f, g, h, i)
+#define LIN_SDT_PROBE_DEFINE5(a, b, c, d, e, f, g, h) _LIN_SDT_PROBE_DEFINE5(\
+ LINUX_DTRACE, a, b, c, d, e, f, g, h)
+
+#define _LIN_SDT_PROBE_ARGTYPE(a, b, c, d, e, f) SDT_PROBE_ARGTYPE(a, b,\
+ c, d, e, f)
+#define LIN_SDT_PROBE_ARGTYPE(a, b, c, d, e) _LIN_SDT_PROBE_ARGTYPE( \
+ LINUX_DTRACE, a, b, c, d, e)
+
+#define LIN_SDT_PROBE0(a, b, c) SDT_PROBE1(LINUX_DTRACE, a, b, \
+ c, 0)
+#define LIN_SDT_PROBE1(a, b, c, d) SDT_PROBE1(LINUX_DTRACE, a, b, \
+ c, d)
+#define LIN_SDT_PROBE2(a, b, c, d, e) SDT_PROBE2(LINUX_DTRACE, a, b, \
+ c, d, e)
+#define LIN_SDT_PROBE3(a, b, c, d, e, f) SDT_PROBE3(LINUX_DTRACE, a, b, \
+ c, d, e, f)
+#define LIN_SDT_PROBE4(a, b, c, d, e, f, g) SDT_PROBE4(LINUX_DTRACE, a, b, \
+ c, d, e, f, g)
+#define _LIN_SDT_PROBE5(a, b, c, d, e, f, g, h, i) SDT_PROBE(a, b, c, d, \
+ e, f, g, h, i)
+#define LIN_SDT_PROBE5(a, b, c, d, e, f, g, h) _LIN_SDT_PROBE5(LINUX_DTRACE, \
+ a, b, c, d, e, f, g, h)
+
+#endif /* _LINUX_DTRACE_H_ */
diff --git a/sys/compat/linux/linux_emul.c b/sys/compat/linux/linux_emul.c
new file mode 100644
index 0000000..61156ba
--- /dev/null
+++ b/sys/compat/linux/linux_emul.c
@@ -0,0 +1,474 @@
+/*-
+ * Copyright (c) 2006 Roman Divacky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_compat.h"
+#include "opt_kdtrace.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/imgact.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/sdt.h>
+#include <sys/sx.h>
+#include <sys/proc.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <sys/unistd.h>
+
+#ifdef COMPAT_LINUX32
+#include <machine/../linux32/linux.h>
+#include <machine/../linux32/linux32_proto.h>
+#else
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#endif
+
+#include <compat/linux/linux_dtrace.h>
+#include <compat/linux/linux_emul.h>
+#include <compat/linux/linux_futex.h>
+#include <compat/linux/linux_misc.h>
+
+/**
+ * Special DTrace provider for the linuxulator.
+ *
+ * In this file we define the provider for the entire linuxulator. All
+ * modules (= files of the linuxulator) use it.
+ *
+ * We define a different name depending on the emulated bitsize, see
+ * ../../<ARCH>/linux{,32}/linux.h, e.g.:
+ * native bitsize = linuxulator
+ * amd64, 32bit emulation = linuxulator32
+ */
+LIN_SDT_PROVIDER_DEFINE(LINUX_DTRACE);
+
+/**
+ * Special DTrace module "locks", it covers some linuxulator internal
+ * locks.
+ */
+LIN_SDT_PROBE_DEFINE1(locks, emul_lock, locked, "struct mtx *");
+LIN_SDT_PROBE_DEFINE1(locks, emul_lock, unlock, "struct mtx *");
+LIN_SDT_PROBE_DEFINE1(locks, emul_shared_rlock, locked, "struct sx *");
+LIN_SDT_PROBE_DEFINE1(locks, emul_shared_rlock, unlock, "struct sx *");
+LIN_SDT_PROBE_DEFINE1(locks, emul_shared_wlock, locked, "struct sx *");
+LIN_SDT_PROBE_DEFINE1(locks, emul_shared_wlock, unlock, "struct sx *");
+
+/**
+ * DTrace probes in this module.
+ */
+LIN_SDT_PROBE_DEFINE2(emul, em_find, entry, "struct proc *", "int");
+LIN_SDT_PROBE_DEFINE0(emul, em_find, return);
+LIN_SDT_PROBE_DEFINE3(emul, proc_init, entry, "struct thread *", "pid_t",
+ "int");
+LIN_SDT_PROBE_DEFINE0(emul, proc_init, create_thread);
+LIN_SDT_PROBE_DEFINE0(emul, proc_init, fork);
+LIN_SDT_PROBE_DEFINE0(emul, proc_init, exec);
+LIN_SDT_PROBE_DEFINE0(emul, proc_init, return);
+LIN_SDT_PROBE_DEFINE1(emul, proc_exit, entry, "struct proc *");
+LIN_SDT_PROBE_DEFINE0(emul, proc_exit, futex_failed);
+LIN_SDT_PROBE_DEFINE3(emul, proc_exit, reparent, "pid_t", "pid_t",
+ "struct proc *");
+LIN_SDT_PROBE_DEFINE1(emul, proc_exit, child_clear_tid_error, "int");
+LIN_SDT_PROBE_DEFINE0(emul, proc_exit, return);
+LIN_SDT_PROBE_DEFINE2(emul, proc_exec, entry, "struct proc *",
+ "struct image_params *");
+LIN_SDT_PROBE_DEFINE0(emul, proc_exec, return);
+LIN_SDT_PROBE_DEFINE0(emul, linux_schedtail, entry);
+LIN_SDT_PROBE_DEFINE1(emul, linux_schedtail, copyout_error, "int");
+LIN_SDT_PROBE_DEFINE0(emul, linux_schedtail, return);
+LIN_SDT_PROBE_DEFINE1(emul, linux_set_tid_address, entry, "int *");
+LIN_SDT_PROBE_DEFINE0(emul, linux_set_tid_address, return);
+LIN_SDT_PROBE_DEFINE2(emul, linux_kill_threads, entry, "struct thread *",
+ "int");
+LIN_SDT_PROBE_DEFINE1(emul, linux_kill_threads, kill, "pid_t");
+LIN_SDT_PROBE_DEFINE0(emul, linux_kill_threads, return);
+
+struct sx emul_shared_lock;
+struct mtx emul_lock;
+
+/* this returns locked reference to the emuldata entry (if found) */
+struct linux_emuldata *
+em_find(struct proc *p, int locked)
+{
+ struct linux_emuldata *em;
+
+ LIN_SDT_PROBE2(emul, em_find, entry, p, locked);
+
+ if (locked == EMUL_DOLOCK)
+ EMUL_LOCK(&emul_lock);
+
+ em = p->p_emuldata;
+
+ if (em == NULL && locked == EMUL_DOLOCK)
+ EMUL_UNLOCK(&emul_lock);
+
+ LIN_SDT_PROBE1(emul, em_find, return, em);
+ return (em);
+}
+
+int
+linux_proc_init(struct thread *td, pid_t child, int flags)
+{
+ struct linux_emuldata *em, *p_em;
+ struct proc *p;
+
+ LIN_SDT_PROBE3(emul, proc_init, entry, td, child, flags);
+
+ if (child != 0) {
+ /* fork or create a thread */
+ em = malloc(sizeof *em, M_LINUX, M_WAITOK | M_ZERO);
+ em->pid = child;
+ em->pdeath_signal = 0;
+ em->flags = 0;
+ em->robust_futexes = NULL;
+ if (flags & LINUX_CLONE_THREAD) {
+ /* handled later in the code */
+ LIN_SDT_PROBE0(emul, proc_init, create_thread);
+ } else {
+ struct linux_emuldata_shared *s;
+
+ LIN_SDT_PROBE0(emul, proc_init, fork);
+
+ s = malloc(sizeof *s, M_LINUX, M_WAITOK | M_ZERO);
+ s->refs = 1;
+ s->group_pid = child;
+
+ LIST_INIT(&s->threads);
+ em->shared = s;
+ }
+ } else {
+ /* exec */
+ LIN_SDT_PROBE0(emul, proc_init, exec);
+
+ /* lookup the old one */
+ em = em_find(td->td_proc, EMUL_DOLOCK);
+ KASSERT(em != NULL, ("proc_init: emuldata not found in exec case.\n"));
+ }
+
+ em->child_clear_tid = NULL;
+ em->child_set_tid = NULL;
+
+ /*
+ * allocate the shared struct only in clone()/fork cases in the case
+ * of clone() td = calling proc and child = pid of the newly created
+ * proc
+ */
+ if (child != 0) {
+ if (flags & LINUX_CLONE_THREAD) {
+ /* lookup the parent */
+ /*
+ * we dont have to lock the p_em because
+ * its waiting for us in linux_clone so
+ * there is no chance of it changing the
+ * p_em->shared address
+ */
+ p_em = em_find(td->td_proc, EMUL_DONTLOCK);
+ KASSERT(p_em != NULL, ("proc_init: parent emuldata not found for CLONE_THREAD\n"));
+ em->shared = p_em->shared;
+ EMUL_SHARED_WLOCK(&emul_shared_lock);
+ em->shared->refs++;
+ EMUL_SHARED_WUNLOCK(&emul_shared_lock);
+ } else {
+ /*
+ * handled earlier to avoid malloc(M_WAITOK) with
+ * rwlock held
+ */
+ }
+
+ EMUL_SHARED_WLOCK(&emul_shared_lock);
+ LIST_INSERT_HEAD(&em->shared->threads, em, threads);
+ EMUL_SHARED_WUNLOCK(&emul_shared_lock);
+
+ p = pfind(child);
+ KASSERT(p != NULL, ("process not found in proc_init\n"));
+ p->p_emuldata = em;
+ PROC_UNLOCK(p);
+ } else
+ EMUL_UNLOCK(&emul_lock);
+
+ LIN_SDT_PROBE0(emul, proc_init, return);
+ return (0);
+}
+
+void
+linux_proc_exit(void *arg __unused, struct proc *p)
+{
+ struct linux_emuldata *em;
+ int error, shared_flags, shared_xstat;
+ struct thread *td = FIRST_THREAD_IN_PROC(p);
+ int *child_clear_tid;
+ struct proc *q, *nq;
+
+ if (__predict_true(p->p_sysent != &elf_linux_sysvec))
+ return;
+
+ LIN_SDT_PROBE1(emul, proc_exit, entry, p);
+
+ release_futexes(p);
+
+ /* find the emuldata */
+ em = em_find(p, EMUL_DOLOCK);
+
+ KASSERT(em != NULL, ("proc_exit: emuldata not found.\n"));
+
+ /* reparent all procs that are not a thread leader to initproc */
+ if (em->shared->group_pid != p->p_pid) {
+ LIN_SDT_PROBE3(emul, proc_exit, reparent,
+ em->shared->group_pid, p->p_pid, p);
+
+ child_clear_tid = em->child_clear_tid;
+ EMUL_UNLOCK(&emul_lock);
+ sx_xlock(&proctree_lock);
+ wakeup(initproc);
+ PROC_LOCK(p);
+ proc_reparent(p, initproc);
+ p->p_sigparent = SIGCHLD;
+ PROC_UNLOCK(p);
+ sx_xunlock(&proctree_lock);
+ } else {
+ child_clear_tid = em->child_clear_tid;
+ EMUL_UNLOCK(&emul_lock);
+ }
+
+ EMUL_SHARED_WLOCK(&emul_shared_lock);
+ shared_flags = em->shared->flags;
+ shared_xstat = em->shared->xstat;
+ LIST_REMOVE(em, threads);
+
+ em->shared->refs--;
+ if (em->shared->refs == 0) {
+ EMUL_SHARED_WUNLOCK(&emul_shared_lock);
+ free(em->shared, M_LINUX);
+ } else
+ EMUL_SHARED_WUNLOCK(&emul_shared_lock);
+
+ if ((shared_flags & EMUL_SHARED_HASXSTAT) != 0)
+ p->p_xstat = shared_xstat;
+
+ if (child_clear_tid != NULL) {
+ struct linux_sys_futex_args cup;
+ int null = 0;
+
+ error = copyout(&null, child_clear_tid, sizeof(null));
+ if (error) {
+ LIN_SDT_PROBE1(emul, proc_exit,
+ child_clear_tid_error, error);
+
+ free(em, M_LINUX);
+
+ LIN_SDT_PROBE0(emul, proc_exit, return);
+ return;
+ }
+
+ /* futexes stuff */
+ cup.uaddr = child_clear_tid;
+ cup.op = LINUX_FUTEX_WAKE;
+ cup.val = 0x7fffffff; /* Awake everyone */
+ cup.timeout = NULL;
+ cup.uaddr2 = NULL;
+ cup.val3 = 0;
+ error = linux_sys_futex(FIRST_THREAD_IN_PROC(p), &cup);
+ /*
+ * this cannot happen at the moment and if this happens it
+ * probably means there is a user space bug
+ */
+ if (error) {
+ LIN_SDT_PROBE0(emul, proc_exit, futex_failed);
+ printf(LMSG("futex stuff in proc_exit failed.\n"));
+ }
+ }
+
+ /* clean the stuff up */
+ free(em, M_LINUX);
+
+ /* this is a little weird but rewritten from exit1() */
+ sx_xlock(&proctree_lock);
+ q = LIST_FIRST(&p->p_children);
+ for (; q != NULL; q = nq) {
+ nq = LIST_NEXT(q, p_sibling);
+ if (q->p_flag & P_WEXIT)
+ continue;
+ if (__predict_false(q->p_sysent != &elf_linux_sysvec))
+ continue;
+ em = em_find(q, EMUL_DOLOCK);
+ KASSERT(em != NULL, ("linux_reparent: emuldata not found: %i\n", q->p_pid));
+ PROC_LOCK(q);
+ if ((q->p_flag & P_WEXIT) == 0 && em->pdeath_signal != 0) {
+ kern_psignal(q, em->pdeath_signal);
+ }
+ PROC_UNLOCK(q);
+ EMUL_UNLOCK(&emul_lock);
+ }
+ sx_xunlock(&proctree_lock);
+
+ LIN_SDT_PROBE0(emul, proc_exit, return);
+}
+
+/*
+ * This is used in a case of transition from FreeBSD binary execing to linux binary
+ * in this case we create linux emuldata proc entry with the pid of the currently running
+ * process.
+ */
+void
+linux_proc_exec(void *arg __unused, struct proc *p, struct image_params *imgp)
+{
+ if (__predict_false(imgp->sysent == &elf_linux_sysvec)) {
+ LIN_SDT_PROBE2(emul, proc_exec, entry, p, imgp);
+ }
+ if (__predict_false(imgp->sysent == &elf_linux_sysvec
+ && p->p_sysent != &elf_linux_sysvec))
+ linux_proc_init(FIRST_THREAD_IN_PROC(p), p->p_pid, 0);
+ if (__predict_false((p->p_sysent->sv_flags & SV_ABI_MASK) ==
+ SV_ABI_LINUX))
+ /* Kill threads regardless of imgp->sysent value */
+ linux_kill_threads(FIRST_THREAD_IN_PROC(p), SIGKILL);
+ if (__predict_false(imgp->sysent != &elf_linux_sysvec
+ && p->p_sysent == &elf_linux_sysvec)) {
+ struct linux_emuldata *em;
+
+ /*
+ * XXX:There's a race because here we assign p->p_emuldata NULL
+ * but the process is still counted as linux one for a short
+ * time so some other process might reference it and try to
+ * access its p->p_emuldata and panicing on a NULL reference.
+ */
+ em = em_find(p, EMUL_DONTLOCK);
+
+ KASSERT(em != NULL, ("proc_exec: emuldata not found.\n"));
+
+ EMUL_SHARED_WLOCK(&emul_shared_lock);
+ LIST_REMOVE(em, threads);
+
+ PROC_LOCK(p);
+ p->p_emuldata = NULL;
+ PROC_UNLOCK(p);
+
+ em->shared->refs--;
+ if (em->shared->refs == 0) {
+ EMUL_SHARED_WUNLOCK(&emul_shared_lock);
+ free(em->shared, M_LINUX);
+ } else
+ EMUL_SHARED_WUNLOCK(&emul_shared_lock);
+
+ free(em, M_LINUX);
+ }
+
+ if (__predict_false(imgp->sysent == &elf_linux_sysvec)) {
+ LIN_SDT_PROBE0(emul, proc_exec, return);
+ }
+}
+
+void
+linux_schedtail(struct thread *td)
+{
+ struct linux_emuldata *em;
+ struct proc *p;
+ int error = 0;
+ int *child_set_tid;
+
+ p = td->td_proc;
+
+ LIN_SDT_PROBE1(emul, linux_schedtail, entry, p);
+
+ /* find the emuldata */
+ em = em_find(p, EMUL_DOLOCK);
+
+ KASSERT(em != NULL, ("linux_schedtail: emuldata not found.\n"));
+ child_set_tid = em->child_set_tid;
+ EMUL_UNLOCK(&emul_lock);
+
+ if (child_set_tid != NULL) {
+ error = copyout(&p->p_pid, (int *)child_set_tid,
+ sizeof(p->p_pid));
+
+ if (error != 0) {
+ LIN_SDT_PROBE1(emul, linux_schedtail, copyout_error,
+ error);
+ }
+ }
+
+ LIN_SDT_PROBE0(emul, linux_schedtail, return);
+
+ return;
+}
+
+int
+linux_set_tid_address(struct thread *td, struct linux_set_tid_address_args *args)
+{
+ struct linux_emuldata *em;
+
+ LIN_SDT_PROBE1(emul, linux_set_tid_address, entry, args->tidptr);
+
+ /* find the emuldata */
+ em = em_find(td->td_proc, EMUL_DOLOCK);
+
+ KASSERT(em != NULL, ("set_tid_address: emuldata not found.\n"));
+
+ em->child_clear_tid = args->tidptr;
+ td->td_retval[0] = td->td_proc->p_pid;
+
+ EMUL_UNLOCK(&emul_lock);
+
+ LIN_SDT_PROBE0(emul, linux_set_tid_address, return);
+ return 0;
+}
+
+void
+linux_kill_threads(struct thread *td, int sig)
+{
+ struct linux_emuldata *em, *td_em, *tmp_em;
+ struct proc *sp;
+
+ LIN_SDT_PROBE2(emul, linux_kill_threads, entry, td, sig);
+
+ td_em = em_find(td->td_proc, EMUL_DONTLOCK);
+
+ KASSERT(td_em != NULL, ("linux_kill_threads: emuldata not found.\n"));
+
+ EMUL_SHARED_RLOCK(&emul_shared_lock);
+ LIST_FOREACH_SAFE(em, &td_em->shared->threads, threads, tmp_em) {
+ if (em->pid == td_em->pid)
+ continue;
+
+ sp = pfind(em->pid);
+ if ((sp->p_flag & P_WEXIT) == 0)
+ kern_psignal(sp, sig);
+ PROC_UNLOCK(sp);
+
+ LIN_SDT_PROBE1(emul, linux_kill_threads, kill, em->pid);
+ }
+ EMUL_SHARED_RUNLOCK(&emul_shared_lock);
+
+ LIN_SDT_PROBE0(emul, linux_kill_threads, return);
+}
diff --git a/sys/compat/linux/linux_emul.h b/sys/compat/linux/linux_emul.h
new file mode 100644
index 0000000..f409a34
--- /dev/null
+++ b/sys/compat/linux/linux_emul.h
@@ -0,0 +1,121 @@
+/*-
+ * Copyright (c) 2006 Roman Divacky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LINUX_EMUL_H_
+#define _LINUX_EMUL_H_
+
+#define EMUL_SHARED_HASXSTAT 0x01
+
+struct linux_emuldata_shared {
+ int refs;
+ int flags;
+ int xstat;
+ pid_t group_pid;
+
+ LIST_HEAD(, linux_emuldata) threads; /* head of list of linux threads */
+};
+
+/*
+ * modeled after similar structure in NetBSD
+ * this will be extended as we need more functionality
+ */
+struct linux_emuldata {
+ pid_t pid;
+
+ int *child_set_tid; /* in clone(): Child's TID to set on clone */
+ int *child_clear_tid;/* in clone(): Child's TID to clear on exit */
+
+ struct linux_emuldata_shared *shared;
+
+ int pdeath_signal; /* parent death signal */
+ int flags; /* different emuldata flags */
+
+ struct linux_robust_list_head *robust_futexes;
+
+ LIST_ENTRY(linux_emuldata) threads; /* list of linux threads */
+};
+
+struct linux_emuldata *em_find(struct proc *, int locked);
+
+/*
+ * DTrace probes for locks should be fired after locking and before releasing
+ * to prevent races (to provide data/function stability in dtrace, see the
+ * output of "dtrace -v ..." and the corresponding dtrace docs).
+ */
+#define EMUL_LOCK(l) do { \
+ mtx_lock(l); \
+ LIN_SDT_PROBE1(locks, emul_lock, \
+ locked, l); \
+ } while (0)
+#define EMUL_UNLOCK(l) do { \
+ LIN_SDT_PROBE1(locks, emul_lock, \
+ unlock, l); \
+ mtx_unlock(l); \
+ } while (0)
+
+#define EMUL_SHARED_RLOCK(l) do { \
+ sx_slock(l); \
+ LIN_SDT_PROBE1(locks, emul_shared_rlock, \
+ locked, l); \
+ } while (0)
+#define EMUL_SHARED_RUNLOCK(l) do { \
+ LIN_SDT_PROBE1(locks, emul_shared_rlock, \
+ unlock, l); \
+ sx_sunlock(l); \
+ } while (0)
+#define EMUL_SHARED_WLOCK(l) do { \
+ sx_xlock(l); \
+ LIN_SDT_PROBE1(locks, emul_shared_wlock, \
+ locked, l); \
+ } while (0)
+#define EMUL_SHARED_WUNLOCK(l) do { \
+ LIN_SDT_PROBE1(locks, emul_shared_wlock, \
+ unlock, l); \
+ sx_xunlock(l); \
+ } while (0)
+
+/* for em_find use */
+#define EMUL_DOLOCK 1
+#define EMUL_DONTLOCK 0
+
+/* emuldata flags */
+#define LINUX_XDEPR_REQUEUEOP 0x00000001 /* uses deprecated
+ futex REQUEUE op*/
+
+int linux_proc_init(struct thread *, pid_t, int);
+void linux_proc_exit(void *, struct proc *);
+void linux_schedtail(struct thread *);
+void linux_proc_exec(void *, struct proc *, struct image_params *);
+void linux_kill_threads(struct thread *, int);
+
+extern struct sx emul_shared_lock;
+extern struct mtx emul_lock;
+
+#endif /* !_LINUX_EMUL_H_ */
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
new file mode 100644
index 0000000..49c3fdf
--- /dev/null
+++ b/sys/compat/linux/linux_file.c
@@ -0,0 +1,1617 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_compat.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/capability.h>
+#include <sys/conf.h>
+#include <sys/dirent.h>
+#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/mutex.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/stat.h>
+#include <sys/sx.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysproto.h>
+#include <sys/tty.h>
+#include <sys/unistd.h>
+#include <sys/vnode.h>
+
+#include <security/mac/mac_framework.h>
+
+#include <ufs/ufs/extattr.h>
+#include <ufs/ufs/quota.h>
+#include <ufs/ufs/ufsmount.h>
+
+#ifdef COMPAT_LINUX32
+#include <machine/../linux32/linux.h>
+#include <machine/../linux32/linux32_proto.h>
+#else
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#endif
+#include <compat/linux/linux_misc.h>
+#include <compat/linux/linux_util.h>
+#include <compat/linux/linux_file.h>
+
+int
+linux_creat(struct thread *td, struct linux_creat_args *args)
+{
+ char *path;
+ int error;
+
+ LCONVPATHEXIST(td, args->path, &path);
+
+#ifdef DEBUG
+ if (ldebug(creat))
+ printf(ARGS(creat, "%s, %d"), path, args->mode);
+#endif
+ error = kern_open(td, path, UIO_SYSSPACE, O_WRONLY | O_CREAT | O_TRUNC,
+ args->mode);
+ LFREEPATH(path);
+ return (error);
+}
+
+
+static int
+linux_common_open(struct thread *td, int dirfd, char *path, int l_flags, int mode)
+{
+ struct proc *p = td->td_proc;
+ struct file *fp;
+ int fd;
+ int bsd_flags, error;
+
+ bsd_flags = 0;
+ switch (l_flags & LINUX_O_ACCMODE) {
+ case LINUX_O_WRONLY:
+ bsd_flags |= O_WRONLY;
+ break;
+ case LINUX_O_RDWR:
+ bsd_flags |= O_RDWR;
+ break;
+ default:
+ bsd_flags |= O_RDONLY;
+ }
+ if (l_flags & LINUX_O_NDELAY)
+ bsd_flags |= O_NONBLOCK;
+ if (l_flags & LINUX_O_APPEND)
+ bsd_flags |= O_APPEND;
+ if (l_flags & LINUX_O_SYNC)
+ bsd_flags |= O_FSYNC;
+ if (l_flags & LINUX_O_NONBLOCK)
+ bsd_flags |= O_NONBLOCK;
+ if (l_flags & LINUX_FASYNC)
+ bsd_flags |= O_ASYNC;
+ if (l_flags & LINUX_O_CREAT)
+ bsd_flags |= O_CREAT;
+ if (l_flags & LINUX_O_TRUNC)
+ bsd_flags |= O_TRUNC;
+ if (l_flags & LINUX_O_EXCL)
+ bsd_flags |= O_EXCL;
+ if (l_flags & LINUX_O_NOCTTY)
+ bsd_flags |= O_NOCTTY;
+ if (l_flags & LINUX_O_DIRECT)
+ bsd_flags |= O_DIRECT;
+ if (l_flags & LINUX_O_NOFOLLOW)
+ bsd_flags |= O_NOFOLLOW;
+ if (l_flags & LINUX_O_DIRECTORY)
+ bsd_flags |= O_DIRECTORY;
+ /* XXX LINUX_O_NOATIME: unable to be easily implemented. */
+
+ error = kern_openat(td, dirfd, path, UIO_SYSSPACE, bsd_flags, mode);
+
+ if (!error) {
+ fd = td->td_retval[0];
+ /*
+ * XXX In between kern_open() and fget(), another process
+ * having the same filedesc could use that fd without
+ * checking below.
+ */
+ error = fget(td, fd, CAP_IOCTL, &fp);
+ if (!error) {
+ sx_slock(&proctree_lock);
+ PROC_LOCK(p);
+ if (!(bsd_flags & O_NOCTTY) &&
+ SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
+ PROC_UNLOCK(p);
+ sx_unlock(&proctree_lock);
+ /* XXXPJD: Verify if TIOCSCTTY is allowed. */
+ if (fp->f_type == DTYPE_VNODE)
+ (void) fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0,
+ td->td_ucred, td);
+ } else {
+ PROC_UNLOCK(p);
+ sx_sunlock(&proctree_lock);
+ }
+ fdrop(fp, td);
+ /*
+ * XXX as above, fdrop()/kern_close() pair is racy.
+ */
+ if (error)
+ kern_close(td, fd);
+ }
+ }
+
+#ifdef DEBUG
+ if (ldebug(open))
+ printf(LMSG("open returns error %d"), error);
+#endif
+ LFREEPATH(path);
+ return (error);
+}
+
+int
+linux_openat(struct thread *td, struct linux_openat_args *args)
+{
+ char *path;
+ int dfd;
+
+ dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
+ if (args->flags & LINUX_O_CREAT)
+ LCONVPATH_AT(td, args->filename, &path, 1, dfd);
+ else
+ LCONVPATH_AT(td, args->filename, &path, 0, dfd);
+#ifdef DEBUG
+ if (ldebug(openat))
+ printf(ARGS(openat, "%i, %s, 0x%x, 0x%x"), args->dfd,
+ path, args->flags, args->mode);
+#endif
+ return (linux_common_open(td, dfd, path, args->flags, args->mode));
+}
+
+int
+linux_open(struct thread *td, struct linux_open_args *args)
+{
+ char *path;
+
+ if (args->flags & LINUX_O_CREAT)
+ LCONVPATHCREAT(td, args->path, &path);
+ else
+ LCONVPATHEXIST(td, args->path, &path);
+
+#ifdef DEBUG
+ if (ldebug(open))
+ printf(ARGS(open, "%s, 0x%x, 0x%x"),
+ path, args->flags, args->mode);
+#endif
+
+ return (linux_common_open(td, AT_FDCWD, path, args->flags, args->mode));
+}
+
+int
+linux_lseek(struct thread *td, struct linux_lseek_args *args)
+{
+
+ struct lseek_args /* {
+ int fd;
+ int pad;
+ off_t offset;
+ int whence;
+ } */ tmp_args;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(lseek))
+ printf(ARGS(lseek, "%d, %ld, %d"),
+ args->fdes, (long)args->off, args->whence);
+#endif
+ tmp_args.fd = args->fdes;
+ tmp_args.offset = (off_t)args->off;
+ tmp_args.whence = args->whence;
+ error = sys_lseek(td, &tmp_args);
+ return error;
+}
+
+int
+linux_llseek(struct thread *td, struct linux_llseek_args *args)
+{
+ struct lseek_args bsd_args;
+ int error;
+ off_t off;
+
+#ifdef DEBUG
+ if (ldebug(llseek))
+ printf(ARGS(llseek, "%d, %d:%d, %d"),
+ args->fd, args->ohigh, args->olow, args->whence);
+#endif
+ off = (args->olow) | (((off_t) args->ohigh) << 32);
+
+ bsd_args.fd = args->fd;
+ bsd_args.offset = off;
+ bsd_args.whence = args->whence;
+
+ if ((error = sys_lseek(td, &bsd_args)))
+ return error;
+
+ if ((error = copyout(td->td_retval, args->res, sizeof (off_t))))
+ return error;
+
+ td->td_retval[0] = 0;
+ return 0;
+}
+
+int
+linux_readdir(struct thread *td, struct linux_readdir_args *args)
+{
+ struct linux_getdents_args lda;
+
+ lda.fd = args->fd;
+ lda.dent = args->dent;
+ lda.count = 1;
+ return linux_getdents(td, &lda);
+}
+
+/*
+ * Note that linux_getdents(2) and linux_getdents64(2) have the same
+ * arguments. They only differ in the definition of struct dirent they
+ * operate on. We use this to common the code, with the exception of
+ * accessing struct dirent. Note that linux_readdir(2) is implemented
+ * by means of linux_getdents(2). In this case we never operate on
+ * struct dirent64 and thus don't need to handle it...
+ */
+
+struct l_dirent {
+ l_ulong d_ino;
+ l_off_t d_off;
+ l_ushort d_reclen;
+ char d_name[LINUX_NAME_MAX + 1];
+};
+
+struct l_dirent64 {
+ uint64_t d_ino;
+ int64_t d_off;
+ l_ushort d_reclen;
+ u_char d_type;
+ char d_name[LINUX_NAME_MAX + 1];
+};
+
+/*
+ * Linux uses the last byte in the dirent buffer to store d_type,
+ * at least glibc-2.7 requires it. That is why l_dirent is padded with 2 bytes.
+ */
+#define LINUX_RECLEN(namlen) \
+ roundup((offsetof(struct l_dirent, d_name) + (namlen) + 2), \
+ sizeof(l_ulong))
+
+#define LINUX_RECLEN64(namlen) \
+ roundup((offsetof(struct l_dirent64, d_name) + (namlen) + 1), \
+ sizeof(uint64_t))
+
+#define LINUX_MAXRECLEN max(LINUX_RECLEN(LINUX_NAME_MAX), \
+ LINUX_RECLEN64(LINUX_NAME_MAX))
+#define LINUX_DIRBLKSIZ 512
+
+static int
+getdents_common(struct thread *td, struct linux_getdents64_args *args,
+ int is64bit)
+{
+ struct dirent *bdp;
+ struct vnode *vp;
+ caddr_t inp, buf; /* BSD-format */
+ int len, reclen; /* BSD-format */
+ caddr_t outp; /* Linux-format */
+ int resid, linuxreclen=0; /* Linux-format */
+ caddr_t lbuf; /* Linux-format */
+ struct file *fp;
+ struct uio auio;
+ struct iovec aiov;
+ off_t off;
+ struct l_dirent *linux_dirent;
+ struct l_dirent64 *linux_dirent64;
+ int buflen, error, eofflag, nbytes, justone;
+ u_long *cookies = NULL, *cookiep;
+ int ncookies;
+
+ nbytes = args->count;
+ if (nbytes == 1) {
+ /* readdir(2) case. Always struct dirent. */
+ if (is64bit)
+ return (EINVAL);
+ nbytes = sizeof(*linux_dirent);
+ justone = 1;
+ } else
+ justone = 0;
+
+ if ((error = getvnode(td->td_proc->p_fd, args->fd, CAP_READ, &fp)) != 0)
+ return (error);
+
+ if ((fp->f_flag & FREAD) == 0) {
+ fdrop(fp, td);
+ return (EBADF);
+ }
+
+ off = foffset_lock(fp, 0);
+ vp = fp->f_vnode;
+ if (vp->v_type != VDIR) {
+ foffset_unlock(fp, off, 0);
+ fdrop(fp, td);
+ return (EINVAL);
+ }
+
+
+ buflen = max(LINUX_DIRBLKSIZ, nbytes);
+ buflen = min(buflen, MAXBSIZE);
+ buf = malloc(buflen, M_TEMP, M_WAITOK);
+ lbuf = malloc(LINUX_MAXRECLEN, M_TEMP, M_WAITOK | M_ZERO);
+ vn_lock(vp, LK_SHARED | LK_RETRY);
+
+ aiov.iov_base = buf;
+ aiov.iov_len = buflen;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_rw = UIO_READ;
+ auio.uio_segflg = UIO_SYSSPACE;
+ auio.uio_td = td;
+ auio.uio_resid = buflen;
+ auio.uio_offset = off;
+
+#ifdef MAC
+ /*
+ * Do directory search MAC check using non-cached credentials.
+ */
+ if ((error = mac_vnode_check_readdir(td->td_ucred, vp)))
+ goto out;
+#endif /* MAC */
+ if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies,
+ &cookies)))
+ goto out;
+
+ inp = buf;
+ outp = (caddr_t)args->dirent;
+ resid = nbytes;
+ if ((len = buflen - auio.uio_resid) <= 0)
+ goto eof;
+
+ cookiep = cookies;
+
+ if (cookies) {
+ /*
+ * When using cookies, the vfs has the option of reading from
+ * a different offset than that supplied (UFS truncates the
+ * offset to a block boundary to make sure that it never reads
+ * partway through a directory entry, even if the directory
+ * has been compacted).
+ */
+ while (len > 0 && ncookies > 0 && *cookiep <= off) {
+ bdp = (struct dirent *) inp;
+ len -= bdp->d_reclen;
+ inp += bdp->d_reclen;
+ cookiep++;
+ ncookies--;
+ }
+ }
+
+ while (len > 0) {
+ if (cookiep && ncookies == 0)
+ break;
+ bdp = (struct dirent *) inp;
+ reclen = bdp->d_reclen;
+ if (reclen & 3) {
+ error = EFAULT;
+ goto out;
+ }
+
+ if (bdp->d_fileno == 0) {
+ inp += reclen;
+ if (cookiep) {
+ off = *cookiep++;
+ ncookies--;
+ } else
+ off += reclen;
+
+ len -= reclen;
+ continue;
+ }
+
+ linuxreclen = (is64bit)
+ ? LINUX_RECLEN64(bdp->d_namlen)
+ : LINUX_RECLEN(bdp->d_namlen);
+
+ if (reclen > len || resid < linuxreclen) {
+ outp++;
+ break;
+ }
+
+ if (justone) {
+ /* readdir(2) case. */
+ linux_dirent = (struct l_dirent*)lbuf;
+ linux_dirent->d_ino = bdp->d_fileno;
+ linux_dirent->d_off = (l_off_t)linuxreclen;
+ linux_dirent->d_reclen = (l_ushort)bdp->d_namlen;
+ strlcpy(linux_dirent->d_name, bdp->d_name,
+ linuxreclen - offsetof(struct l_dirent, d_name));
+ error = copyout(linux_dirent, outp, linuxreclen);
+ }
+ if (is64bit) {
+ linux_dirent64 = (struct l_dirent64*)lbuf;
+ linux_dirent64->d_ino = bdp->d_fileno;
+ linux_dirent64->d_off = (cookiep)
+ ? (l_off_t)*cookiep
+ : (l_off_t)(off + reclen);
+ linux_dirent64->d_reclen = (l_ushort)linuxreclen;
+ linux_dirent64->d_type = bdp->d_type;
+ strlcpy(linux_dirent64->d_name, bdp->d_name,
+ linuxreclen - offsetof(struct l_dirent64, d_name));
+ error = copyout(linux_dirent64, outp, linuxreclen);
+ } else if (!justone) {
+ linux_dirent = (struct l_dirent*)lbuf;
+ linux_dirent->d_ino = bdp->d_fileno;
+ linux_dirent->d_off = (cookiep)
+ ? (l_off_t)*cookiep
+ : (l_off_t)(off + reclen);
+ linux_dirent->d_reclen = (l_ushort)linuxreclen;
+ /*
+ * Copy d_type to last byte of l_dirent buffer
+ */
+ lbuf[linuxreclen-1] = bdp->d_type;
+ strlcpy(linux_dirent->d_name, bdp->d_name,
+ linuxreclen - offsetof(struct l_dirent, d_name)-1);
+ error = copyout(linux_dirent, outp, linuxreclen);
+ }
+
+ if (error)
+ goto out;
+
+ inp += reclen;
+ if (cookiep) {
+ off = *cookiep++;
+ ncookies--;
+ } else
+ off += reclen;
+
+ outp += linuxreclen;
+ resid -= linuxreclen;
+ len -= reclen;
+ if (justone)
+ break;
+ }
+
+ if (outp == (caddr_t)args->dirent) {
+ nbytes = resid;
+ goto eof;
+ }
+
+ if (justone)
+ nbytes = resid + linuxreclen;
+
+eof:
+ td->td_retval[0] = nbytes - resid;
+
+out:
+ free(cookies, M_TEMP);
+
+ VOP_UNLOCK(vp, 0);
+ foffset_unlock(fp, off, 0);
+ fdrop(fp, td);
+ free(buf, M_TEMP);
+ free(lbuf, M_TEMP);
+ return (error);
+}
+
+int
+linux_getdents(struct thread *td, struct linux_getdents_args *args)
+{
+
+#ifdef DEBUG
+ if (ldebug(getdents))
+ printf(ARGS(getdents, "%d, *, %d"), args->fd, args->count);
+#endif
+
+ return (getdents_common(td, (struct linux_getdents64_args*)args, 0));
+}
+
+int
+linux_getdents64(struct thread *td, struct linux_getdents64_args *args)
+{
+
+#ifdef DEBUG
+ if (ldebug(getdents64))
+ printf(ARGS(getdents64, "%d, *, %d"), args->fd, args->count);
+#endif
+
+ return (getdents_common(td, args, 1));
+}
+
+/*
+ * These exist mainly for hooks for doing /compat/linux translation.
+ */
+
+int
+linux_access(struct thread *td, struct linux_access_args *args)
+{
+ char *path;
+ int error;
+
+ /* linux convention */
+ if (args->amode & ~(F_OK | X_OK | W_OK | R_OK))
+ return (EINVAL);
+
+ LCONVPATHEXIST(td, args->path, &path);
+
+#ifdef DEBUG
+ if (ldebug(access))
+ printf(ARGS(access, "%s, %d"), path, args->amode);
+#endif
+ error = kern_access(td, path, UIO_SYSSPACE, args->amode);
+ LFREEPATH(path);
+
+ return (error);
+}
+
+int
+linux_faccessat(struct thread *td, struct linux_faccessat_args *args)
+{
+ char *path;
+ int error, dfd, flag;
+
+ if (args->flag & ~LINUX_AT_EACCESS)
+ return (EINVAL);
+ /* linux convention */
+ if (args->amode & ~(F_OK | X_OK | W_OK | R_OK))
+ return (EINVAL);
+
+ dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
+ LCONVPATHEXIST_AT(td, args->filename, &path, dfd);
+
+#ifdef DEBUG
+ if (ldebug(access))
+ printf(ARGS(access, "%s, %d"), path, args->amode);
+#endif
+
+ flag = (args->flag & LINUX_AT_EACCESS) == 0 ? 0 : AT_EACCESS;
+ error = kern_accessat(td, dfd, path, UIO_SYSSPACE, flag, args->amode);
+ LFREEPATH(path);
+
+ return (error);
+}
+
+int
+linux_unlink(struct thread *td, struct linux_unlink_args *args)
+{
+ char *path;
+ int error;
+ struct stat st;
+
+ LCONVPATHEXIST(td, args->path, &path);
+
+#ifdef DEBUG
+ if (ldebug(unlink))
+ printf(ARGS(unlink, "%s"), path);
+#endif
+
+ error = kern_unlink(td, path, UIO_SYSSPACE);
+ if (error == EPERM)
+ /* Introduce POSIX noncompliant behaviour of Linux */
+ if (kern_stat(td, path, UIO_SYSSPACE, &st) == 0)
+ if (S_ISDIR(st.st_mode))
+ error = EISDIR;
+ LFREEPATH(path);
+ return (error);
+}
+
+int
+linux_unlinkat(struct thread *td, struct linux_unlinkat_args *args)
+{
+ char *path;
+ int error, dfd;
+ struct stat st;
+
+ if (args->flag & ~LINUX_AT_REMOVEDIR)
+ return (EINVAL);
+
+ dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
+ LCONVPATHEXIST_AT(td, args->pathname, &path, dfd);
+
+#ifdef DEBUG
+ if (ldebug(unlinkat))
+ printf(ARGS(unlinkat, "%s"), path);
+#endif
+
+ if (args->flag & LINUX_AT_REMOVEDIR)
+ error = kern_rmdirat(td, dfd, path, UIO_SYSSPACE);
+ else
+ error = kern_unlinkat(td, dfd, path, UIO_SYSSPACE, 0);
+ if (error == EPERM && !(args->flag & LINUX_AT_REMOVEDIR)) {
+ /* Introduce POSIX noncompliant behaviour of Linux */
+ if (kern_statat(td, AT_SYMLINK_NOFOLLOW, dfd, path,
+ UIO_SYSSPACE, &st) == 0 && S_ISDIR(st.st_mode))
+ error = EISDIR;
+ }
+ LFREEPATH(path);
+ return (error);
+}
+int
+linux_chdir(struct thread *td, struct linux_chdir_args *args)
+{
+ char *path;
+ int error;
+
+ LCONVPATHEXIST(td, args->path, &path);
+
+#ifdef DEBUG
+ if (ldebug(chdir))
+ printf(ARGS(chdir, "%s"), path);
+#endif
+ error = kern_chdir(td, path, UIO_SYSSPACE);
+ LFREEPATH(path);
+ return (error);
+}
+
+int
+linux_chmod(struct thread *td, struct linux_chmod_args *args)
+{
+ char *path;
+ int error;
+
+ LCONVPATHEXIST(td, args->path, &path);
+
+#ifdef DEBUG
+ if (ldebug(chmod))
+ printf(ARGS(chmod, "%s, %d"), path, args->mode);
+#endif
+ error = kern_chmod(td, path, UIO_SYSSPACE, args->mode);
+ LFREEPATH(path);
+ return (error);
+}
+
+int
+linux_fchmodat(struct thread *td, struct linux_fchmodat_args *args)
+{
+ char *path;
+ int error, dfd;
+
+ dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
+ LCONVPATHEXIST_AT(td, args->filename, &path, dfd);
+
+#ifdef DEBUG
+ if (ldebug(fchmodat))
+ printf(ARGS(fchmodat, "%s, %d"), path, args->mode);
+#endif
+
+ error = kern_fchmodat(td, dfd, path, UIO_SYSSPACE, args->mode, 0);
+ LFREEPATH(path);
+ return (error);
+}
+
+int
+linux_mkdir(struct thread *td, struct linux_mkdir_args *args)
+{
+ char *path;
+ int error;
+
+ LCONVPATHCREAT(td, args->path, &path);
+
+#ifdef DEBUG
+ if (ldebug(mkdir))
+ printf(ARGS(mkdir, "%s, %d"), path, args->mode);
+#endif
+ error = kern_mkdir(td, path, UIO_SYSSPACE, args->mode);
+ LFREEPATH(path);
+ return (error);
+}
+
+int
+linux_mkdirat(struct thread *td, struct linux_mkdirat_args *args)
+{
+ char *path;
+ int error, dfd;
+
+ dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
+ LCONVPATHCREAT_AT(td, args->pathname, &path, dfd);
+
+#ifdef DEBUG
+ if (ldebug(mkdirat))
+ printf(ARGS(mkdirat, "%s, %d"), path, args->mode);
+#endif
+ error = kern_mkdirat(td, dfd, path, UIO_SYSSPACE, args->mode);
+ LFREEPATH(path);
+ return (error);
+}
+
+int
+linux_rmdir(struct thread *td, struct linux_rmdir_args *args)
+{
+ char *path;
+ int error;
+
+ LCONVPATHEXIST(td, args->path, &path);
+
+#ifdef DEBUG
+ if (ldebug(rmdir))
+ printf(ARGS(rmdir, "%s"), path);
+#endif
+ error = kern_rmdir(td, path, UIO_SYSSPACE);
+ LFREEPATH(path);
+ return (error);
+}
+
+int
+linux_rename(struct thread *td, struct linux_rename_args *args)
+{
+ char *from, *to;
+ int error;
+
+ LCONVPATHEXIST(td, args->from, &from);
+ /* Expand LCONVPATHCREATE so that `from' can be freed on errors */
+ error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1, AT_FDCWD);
+ if (to == NULL) {
+ LFREEPATH(from);
+ return (error);
+ }
+
+#ifdef DEBUG
+ if (ldebug(rename))
+ printf(ARGS(rename, "%s, %s"), from, to);
+#endif
+ error = kern_rename(td, from, to, UIO_SYSSPACE);
+ LFREEPATH(from);
+ LFREEPATH(to);
+ return (error);
+}
+
+int
+linux_renameat(struct thread *td, struct linux_renameat_args *args)
+{
+ char *from, *to;
+ int error, olddfd, newdfd;
+
+ olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd;
+ newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd;
+ LCONVPATHEXIST_AT(td, args->oldname, &from, olddfd);
+ /* Expand LCONVPATHCREATE so that `from' can be freed on errors */
+ error = linux_emul_convpath(td, args->newname, UIO_USERSPACE, &to, 1, newdfd);
+ if (to == NULL) {
+ LFREEPATH(from);
+ return (error);
+ }
+
+#ifdef DEBUG
+ if (ldebug(renameat))
+ printf(ARGS(renameat, "%s, %s"), from, to);
+#endif
+ error = kern_renameat(td, olddfd, from, newdfd, to, UIO_SYSSPACE);
+ LFREEPATH(from);
+ LFREEPATH(to);
+ return (error);
+}
+
+int
+linux_symlink(struct thread *td, struct linux_symlink_args *args)
+{
+ char *path, *to;
+ int error;
+
+ LCONVPATHEXIST(td, args->path, &path);
+ /* Expand LCONVPATHCREATE so that `path' can be freed on errors */
+ error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1, AT_FDCWD);
+ if (to == NULL) {
+ LFREEPATH(path);
+ return (error);
+ }
+
+#ifdef DEBUG
+ if (ldebug(symlink))
+ printf(ARGS(symlink, "%s, %s"), path, to);
+#endif
+ error = kern_symlink(td, path, to, UIO_SYSSPACE);
+ LFREEPATH(path);
+ LFREEPATH(to);
+ return (error);
+}
+
+int
+linux_symlinkat(struct thread *td, struct linux_symlinkat_args *args)
+{
+ char *path, *to;
+ int error, dfd;
+
+ dfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd;
+ LCONVPATHEXIST_AT(td, args->oldname, &path, dfd);
+ /* Expand LCONVPATHCREATE so that `path' can be freed on errors */
+ error = linux_emul_convpath(td, args->newname, UIO_USERSPACE, &to, 1, dfd);
+ if (to == NULL) {
+ LFREEPATH(path);
+ return (error);
+ }
+
+#ifdef DEBUG
+ if (ldebug(symlinkat))
+ printf(ARGS(symlinkat, "%s, %s"), path, to);
+#endif
+
+ error = kern_symlinkat(td, path, dfd, to, UIO_SYSSPACE);
+ LFREEPATH(path);
+ LFREEPATH(to);
+ return (error);
+}
+
+int
+linux_readlink(struct thread *td, struct linux_readlink_args *args)
+{
+ char *name;
+ int error;
+
+ LCONVPATHEXIST(td, args->name, &name);
+
+#ifdef DEBUG
+ if (ldebug(readlink))
+ printf(ARGS(readlink, "%s, %p, %d"), name, (void *)args->buf,
+ args->count);
+#endif
+ error = kern_readlink(td, name, UIO_SYSSPACE, args->buf, UIO_USERSPACE,
+ args->count);
+ LFREEPATH(name);
+ return (error);
+}
+
+int
+linux_readlinkat(struct thread *td, struct linux_readlinkat_args *args)
+{
+ char *name;
+ int error, dfd;
+
+ dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
+ LCONVPATHEXIST_AT(td, args->path, &name, dfd);
+
+#ifdef DEBUG
+ if (ldebug(readlinkat))
+ printf(ARGS(readlinkat, "%s, %p, %d"), name, (void *)args->buf,
+ args->bufsiz);
+#endif
+
+ error = kern_readlinkat(td, dfd, name, UIO_SYSSPACE, args->buf,
+ UIO_USERSPACE, args->bufsiz);
+ LFREEPATH(name);
+ return (error);
+}
+
+int
+linux_truncate(struct thread *td, struct linux_truncate_args *args)
+{
+ char *path;
+ int error;
+
+ LCONVPATHEXIST(td, args->path, &path);
+
+#ifdef DEBUG
+ if (ldebug(truncate))
+ printf(ARGS(truncate, "%s, %ld"), path, (long)args->length);
+#endif
+
+ error = kern_truncate(td, path, UIO_SYSSPACE, args->length);
+ LFREEPATH(path);
+ return (error);
+}
+
+int
+linux_truncate64(struct thread *td, struct linux_truncate64_args *args)
+{
+ char *path;
+ int error;
+
+ LCONVPATHEXIST(td, args->path, &path);
+
+#ifdef DEBUG
+ if (ldebug(truncate64))
+ printf(ARGS(truncate64, "%s, %jd"), path, args->length);
+#endif
+
+ error = kern_truncate(td, path, UIO_SYSSPACE, args->length);
+ LFREEPATH(path);
+ return (error);
+}
+int
+linux_ftruncate(struct thread *td, struct linux_ftruncate_args *args)
+{
+ struct ftruncate_args /* {
+ int fd;
+ int pad;
+ off_t length;
+ } */ nuap;
+
+ nuap.fd = args->fd;
+ nuap.length = args->length;
+ return (sys_ftruncate(td, &nuap));
+}
+
+int
+linux_link(struct thread *td, struct linux_link_args *args)
+{
+ char *path, *to;
+ int error;
+
+ LCONVPATHEXIST(td, args->path, &path);
+ /* Expand LCONVPATHCREATE so that `path' can be freed on errors */
+ error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1, AT_FDCWD);
+ if (to == NULL) {
+ LFREEPATH(path);
+ return (error);
+ }
+
+#ifdef DEBUG
+ if (ldebug(link))
+ printf(ARGS(link, "%s, %s"), path, to);
+#endif
+ error = kern_link(td, path, to, UIO_SYSSPACE);
+ LFREEPATH(path);
+ LFREEPATH(to);
+ return (error);
+}
+
+int
+linux_linkat(struct thread *td, struct linux_linkat_args *args)
+{
+ char *path, *to;
+ int error, olddfd, newdfd, follow;
+
+ if (args->flag & ~LINUX_AT_SYMLINK_FOLLOW)
+ return (EINVAL);
+
+ olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd;
+ newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd;
+ LCONVPATHEXIST_AT(td, args->oldname, &path, olddfd);
+ /* Expand LCONVPATHCREATE so that `path' can be freed on errors */
+ error = linux_emul_convpath(td, args->newname, UIO_USERSPACE, &to, 1, newdfd);
+ if (to == NULL) {
+ LFREEPATH(path);
+ return (error);
+ }
+
+#ifdef DEBUG
+ if (ldebug(linkat))
+ printf(ARGS(linkat, "%i, %s, %i, %s, %i"), args->olddfd, path,
+ args->newdfd, to, args->flag);
+#endif
+
+ follow = (args->flag & LINUX_AT_SYMLINK_FOLLOW) == 0 ? NOFOLLOW :
+ FOLLOW;
+ error = kern_linkat(td, olddfd, newdfd, path, to, UIO_SYSSPACE, follow);
+ LFREEPATH(path);
+ LFREEPATH(to);
+ return (error);
+}
+
+int
+linux_fdatasync(td, uap)
+ struct thread *td;
+ struct linux_fdatasync_args *uap;
+{
+ struct fsync_args bsd;
+
+ bsd.fd = uap->fd;
+ return sys_fsync(td, &bsd);
+}
+
+int
+linux_pread(td, uap)
+ struct thread *td;
+ struct linux_pread_args *uap;
+{
+ struct pread_args bsd;
+ struct vnode *vp;
+ int error;
+
+ bsd.fd = uap->fd;
+ bsd.buf = uap->buf;
+ bsd.nbyte = uap->nbyte;
+ bsd.offset = uap->offset;
+
+ error = sys_pread(td, &bsd);
+
+ if (error == 0) {
+ /* This seems to violate POSIX but linux does it */
+ if ((error = fgetvp(td, uap->fd, CAP_PREAD, &vp)) != 0)
+ return (error);
+ if (vp->v_type == VDIR) {
+ vrele(vp);
+ return (EISDIR);
+ }
+ vrele(vp);
+ }
+
+ return (error);
+}
+
+int
+linux_pwrite(td, uap)
+ struct thread *td;
+ struct linux_pwrite_args *uap;
+{
+ struct pwrite_args bsd;
+
+ bsd.fd = uap->fd;
+ bsd.buf = uap->buf;
+ bsd.nbyte = uap->nbyte;
+ bsd.offset = uap->offset;
+ return sys_pwrite(td, &bsd);
+}
+
+int
+linux_mount(struct thread *td, struct linux_mount_args *args)
+{
+ struct ufs_args ufs;
+ char fstypename[MFSNAMELEN];
+ char mntonname[MNAMELEN], mntfromname[MNAMELEN];
+ int error;
+ int fsflags;
+ void *fsdata;
+
+ error = copyinstr(args->filesystemtype, fstypename, MFSNAMELEN - 1,
+ NULL);
+ if (error)
+ return (error);
+ error = copyinstr(args->specialfile, mntfromname, MNAMELEN - 1, NULL);
+ if (error)
+ return (error);
+ error = copyinstr(args->dir, mntonname, MNAMELEN - 1, NULL);
+ if (error)
+ return (error);
+
+#ifdef DEBUG
+ if (ldebug(mount))
+ printf(ARGS(mount, "%s, %s, %s"),
+ fstypename, mntfromname, mntonname);
+#endif
+
+ if (strcmp(fstypename, "ext2") == 0) {
+ strcpy(fstypename, "ext2fs");
+ fsdata = &ufs;
+ ufs.fspec = mntfromname;
+#define DEFAULT_ROOTID -2
+ ufs.export.ex_root = DEFAULT_ROOTID;
+ ufs.export.ex_flags =
+ args->rwflag & LINUX_MS_RDONLY ? MNT_EXRDONLY : 0;
+ } else if (strcmp(fstypename, "proc") == 0) {
+ strcpy(fstypename, "linprocfs");
+ fsdata = NULL;
+ } else if (strcmp(fstypename, "vfat") == 0) {
+ strcpy(fstypename, "msdosfs");
+ fsdata = NULL;
+ } else {
+ return (ENODEV);
+ }
+
+ fsflags = 0;
+
+ if ((args->rwflag & 0xffff0000) == 0xc0ed0000) {
+ /*
+ * Linux SYNC flag is not included; the closest equivalent
+ * FreeBSD has is !ASYNC, which is our default.
+ */
+ if (args->rwflag & LINUX_MS_RDONLY)
+ fsflags |= MNT_RDONLY;
+ if (args->rwflag & LINUX_MS_NOSUID)
+ fsflags |= MNT_NOSUID;
+ if (args->rwflag & LINUX_MS_NOEXEC)
+ fsflags |= MNT_NOEXEC;
+ if (args->rwflag & LINUX_MS_REMOUNT)
+ fsflags |= MNT_UPDATE;
+ }
+
+ if (strcmp(fstypename, "linprocfs") == 0) {
+ error = kernel_vmount(fsflags,
+ "fstype", fstypename,
+ "fspath", mntonname,
+ NULL);
+ } else if (strcmp(fstypename, "msdosfs") == 0) {
+ error = kernel_vmount(fsflags,
+ "fstype", fstypename,
+ "fspath", mntonname,
+ "from", mntfromname,
+ NULL);
+ } else
+ error = EOPNOTSUPP;
+ return (error);
+}
+
+int
+linux_oldumount(struct thread *td, struct linux_oldumount_args *args)
+{
+ struct linux_umount_args args2;
+
+ args2.path = args->path;
+ args2.flags = 0;
+ return (linux_umount(td, &args2));
+}
+
+int
+linux_umount(struct thread *td, struct linux_umount_args *args)
+{
+ struct unmount_args bsd;
+
+ bsd.path = args->path;
+ bsd.flags = args->flags; /* XXX correct? */
+ return (sys_unmount(td, &bsd));
+}
+
+/*
+ * fcntl family of syscalls
+ */
+
+struct l_flock {
+ l_short l_type;
+ l_short l_whence;
+ l_off_t l_start;
+ l_off_t l_len;
+ l_pid_t l_pid;
+}
+#if defined(__amd64__) && defined(COMPAT_LINUX32)
+__packed
+#endif
+;
+
+static void
+linux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock)
+{
+ switch (linux_flock->l_type) {
+ case LINUX_F_RDLCK:
+ bsd_flock->l_type = F_RDLCK;
+ break;
+ case LINUX_F_WRLCK:
+ bsd_flock->l_type = F_WRLCK;
+ break;
+ case LINUX_F_UNLCK:
+ bsd_flock->l_type = F_UNLCK;
+ break;
+ default:
+ bsd_flock->l_type = -1;
+ break;
+ }
+ bsd_flock->l_whence = linux_flock->l_whence;
+ bsd_flock->l_start = (off_t)linux_flock->l_start;
+ bsd_flock->l_len = (off_t)linux_flock->l_len;
+ bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
+ bsd_flock->l_sysid = 0;
+}
+
+static void
+bsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock)
+{
+ switch (bsd_flock->l_type) {
+ case F_RDLCK:
+ linux_flock->l_type = LINUX_F_RDLCK;
+ break;
+ case F_WRLCK:
+ linux_flock->l_type = LINUX_F_WRLCK;
+ break;
+ case F_UNLCK:
+ linux_flock->l_type = LINUX_F_UNLCK;
+ break;
+ }
+ linux_flock->l_whence = bsd_flock->l_whence;
+ linux_flock->l_start = (l_off_t)bsd_flock->l_start;
+ linux_flock->l_len = (l_off_t)bsd_flock->l_len;
+ linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid;
+}
+
+#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
+struct l_flock64 {
+ l_short l_type;
+ l_short l_whence;
+ l_loff_t l_start;
+ l_loff_t l_len;
+ l_pid_t l_pid;
+}
+#if defined(__amd64__) && defined(COMPAT_LINUX32)
+__packed
+#endif
+;
+
+static void
+linux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock)
+{
+ switch (linux_flock->l_type) {
+ case LINUX_F_RDLCK:
+ bsd_flock->l_type = F_RDLCK;
+ break;
+ case LINUX_F_WRLCK:
+ bsd_flock->l_type = F_WRLCK;
+ break;
+ case LINUX_F_UNLCK:
+ bsd_flock->l_type = F_UNLCK;
+ break;
+ default:
+ bsd_flock->l_type = -1;
+ break;
+ }
+ bsd_flock->l_whence = linux_flock->l_whence;
+ bsd_flock->l_start = (off_t)linux_flock->l_start;
+ bsd_flock->l_len = (off_t)linux_flock->l_len;
+ bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
+ bsd_flock->l_sysid = 0;
+}
+
+static void
+bsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock)
+{
+ switch (bsd_flock->l_type) {
+ case F_RDLCK:
+ linux_flock->l_type = LINUX_F_RDLCK;
+ break;
+ case F_WRLCK:
+ linux_flock->l_type = LINUX_F_WRLCK;
+ break;
+ case F_UNLCK:
+ linux_flock->l_type = LINUX_F_UNLCK;
+ break;
+ }
+ linux_flock->l_whence = bsd_flock->l_whence;
+ linux_flock->l_start = (l_loff_t)bsd_flock->l_start;
+ linux_flock->l_len = (l_loff_t)bsd_flock->l_len;
+ linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid;
+}
+#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
+
+static int
+fcntl_common(struct thread *td, struct linux_fcntl64_args *args)
+{
+ struct l_flock linux_flock;
+ struct flock bsd_flock;
+ struct file *fp;
+ long arg;
+ int error, result;
+
+ switch (args->cmd) {
+ case LINUX_F_DUPFD:
+ return (kern_fcntl(td, args->fd, F_DUPFD, args->arg));
+
+ case LINUX_F_GETFD:
+ return (kern_fcntl(td, args->fd, F_GETFD, 0));
+
+ case LINUX_F_SETFD:
+ return (kern_fcntl(td, args->fd, F_SETFD, args->arg));
+
+ case LINUX_F_GETFL:
+ error = kern_fcntl(td, args->fd, F_GETFL, 0);
+ result = td->td_retval[0];
+ td->td_retval[0] = 0;
+ if (result & O_RDONLY)
+ td->td_retval[0] |= LINUX_O_RDONLY;
+ if (result & O_WRONLY)
+ td->td_retval[0] |= LINUX_O_WRONLY;
+ if (result & O_RDWR)
+ td->td_retval[0] |= LINUX_O_RDWR;
+ if (result & O_NDELAY)
+ td->td_retval[0] |= LINUX_O_NONBLOCK;
+ if (result & O_APPEND)
+ td->td_retval[0] |= LINUX_O_APPEND;
+ if (result & O_FSYNC)
+ td->td_retval[0] |= LINUX_O_SYNC;
+ if (result & O_ASYNC)
+ td->td_retval[0] |= LINUX_FASYNC;
+#ifdef LINUX_O_NOFOLLOW
+ if (result & O_NOFOLLOW)
+ td->td_retval[0] |= LINUX_O_NOFOLLOW;
+#endif
+#ifdef LINUX_O_DIRECT
+ if (result & O_DIRECT)
+ td->td_retval[0] |= LINUX_O_DIRECT;
+#endif
+ return (error);
+
+ case LINUX_F_SETFL:
+ arg = 0;
+ if (args->arg & LINUX_O_NDELAY)
+ arg |= O_NONBLOCK;
+ if (args->arg & LINUX_O_APPEND)
+ arg |= O_APPEND;
+ if (args->arg & LINUX_O_SYNC)
+ arg |= O_FSYNC;
+ if (args->arg & LINUX_FASYNC)
+ arg |= O_ASYNC;
+#ifdef LINUX_O_NOFOLLOW
+ if (args->arg & LINUX_O_NOFOLLOW)
+ arg |= O_NOFOLLOW;
+#endif
+#ifdef LINUX_O_DIRECT
+ if (args->arg & LINUX_O_DIRECT)
+ arg |= O_DIRECT;
+#endif
+ return (kern_fcntl(td, args->fd, F_SETFL, arg));
+
+ case LINUX_F_GETLK:
+ error = copyin((void *)args->arg, &linux_flock,
+ sizeof(linux_flock));
+ if (error)
+ return (error);
+ linux_to_bsd_flock(&linux_flock, &bsd_flock);
+ error = kern_fcntl(td, args->fd, F_GETLK, (intptr_t)&bsd_flock);
+ if (error)
+ return (error);
+ bsd_to_linux_flock(&bsd_flock, &linux_flock);
+ return (copyout(&linux_flock, (void *)args->arg,
+ sizeof(linux_flock)));
+
+ case LINUX_F_SETLK:
+ error = copyin((void *)args->arg, &linux_flock,
+ sizeof(linux_flock));
+ if (error)
+ return (error);
+ linux_to_bsd_flock(&linux_flock, &bsd_flock);
+ return (kern_fcntl(td, args->fd, F_SETLK,
+ (intptr_t)&bsd_flock));
+
+ case LINUX_F_SETLKW:
+ error = copyin((void *)args->arg, &linux_flock,
+ sizeof(linux_flock));
+ if (error)
+ return (error);
+ linux_to_bsd_flock(&linux_flock, &bsd_flock);
+ return (kern_fcntl(td, args->fd, F_SETLKW,
+ (intptr_t)&bsd_flock));
+
+ case LINUX_F_GETOWN:
+ return (kern_fcntl(td, args->fd, F_GETOWN, 0));
+
+ case LINUX_F_SETOWN:
+ /*
+ * XXX some Linux applications depend on F_SETOWN having no
+ * significant effect for pipes (SIGIO is not delivered for
+ * pipes under Linux-2.2.35 at least).
+ */
+ error = fget(td, args->fd, CAP_FCNTL, &fp);
+ if (error)
+ return (error);
+ if (fp->f_type == DTYPE_PIPE) {
+ fdrop(fp, td);
+ return (EINVAL);
+ }
+ fdrop(fp, td);
+
+ return (kern_fcntl(td, args->fd, F_SETOWN, args->arg));
+ }
+
+ return (EINVAL);
+}
+
+int
+linux_fcntl(struct thread *td, struct linux_fcntl_args *args)
+{
+ struct linux_fcntl64_args args64;
+
+#ifdef DEBUG
+ if (ldebug(fcntl))
+ printf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd);
+#endif
+
+ args64.fd = args->fd;
+ args64.cmd = args->cmd;
+ args64.arg = args->arg;
+ return (fcntl_common(td, &args64));
+}
+
+#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
+int
+linux_fcntl64(struct thread *td, struct linux_fcntl64_args *args)
+{
+ struct l_flock64 linux_flock;
+ struct flock bsd_flock;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(fcntl64))
+ printf(ARGS(fcntl64, "%d, %08x, *"), args->fd, args->cmd);
+#endif
+
+ switch (args->cmd) {
+ case LINUX_F_GETLK64:
+ error = copyin((void *)args->arg, &linux_flock,
+ sizeof(linux_flock));
+ if (error)
+ return (error);
+ linux_to_bsd_flock64(&linux_flock, &bsd_flock);
+ error = kern_fcntl(td, args->fd, F_GETLK, (intptr_t)&bsd_flock);
+ if (error)
+ return (error);
+ bsd_to_linux_flock64(&bsd_flock, &linux_flock);
+ return (copyout(&linux_flock, (void *)args->arg,
+ sizeof(linux_flock)));
+
+ case LINUX_F_SETLK64:
+ error = copyin((void *)args->arg, &linux_flock,
+ sizeof(linux_flock));
+ if (error)
+ return (error);
+ linux_to_bsd_flock64(&linux_flock, &bsd_flock);
+ return (kern_fcntl(td, args->fd, F_SETLK,
+ (intptr_t)&bsd_flock));
+
+ case LINUX_F_SETLKW64:
+ error = copyin((void *)args->arg, &linux_flock,
+ sizeof(linux_flock));
+ if (error)
+ return (error);
+ linux_to_bsd_flock64(&linux_flock, &bsd_flock);
+ return (kern_fcntl(td, args->fd, F_SETLKW,
+ (intptr_t)&bsd_flock));
+ }
+
+ return (fcntl_common(td, args));
+}
+#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
+
+int
+linux_chown(struct thread *td, struct linux_chown_args *args)
+{
+ char *path;
+ int error;
+
+ LCONVPATHEXIST(td, args->path, &path);
+
+#ifdef DEBUG
+ if (ldebug(chown))
+ printf(ARGS(chown, "%s, %d, %d"), path, args->uid, args->gid);
+#endif
+ error = kern_chown(td, path, UIO_SYSSPACE, args->uid, args->gid);
+ LFREEPATH(path);
+ return (error);
+}
+
+int
+linux_fchownat(struct thread *td, struct linux_fchownat_args *args)
+{
+ char *path;
+ int error, dfd, flag;
+
+ if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW)
+ return (EINVAL);
+
+ dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
+ LCONVPATHEXIST_AT(td, args->filename, &path, dfd);
+
+#ifdef DEBUG
+ if (ldebug(fchownat))
+ printf(ARGS(fchownat, "%s, %d, %d"), path, args->uid, args->gid);
+#endif
+
+ flag = (args->flag & LINUX_AT_SYMLINK_NOFOLLOW) == 0 ? 0 :
+ AT_SYMLINK_NOFOLLOW;
+ error = kern_fchownat(td, dfd, path, UIO_SYSSPACE, args->uid, args->gid,
+ flag);
+ LFREEPATH(path);
+ return (error);
+}
+
+int
+linux_lchown(struct thread *td, struct linux_lchown_args *args)
+{
+ char *path;
+ int error;
+
+ LCONVPATHEXIST(td, args->path, &path);
+
+#ifdef DEBUG
+ if (ldebug(lchown))
+ printf(ARGS(lchown, "%s, %d, %d"), path, args->uid, args->gid);
+#endif
+ error = kern_lchown(td, path, UIO_SYSSPACE, args->uid, args->gid);
+ LFREEPATH(path);
+ return (error);
+}
+
+static int
+convert_fadvice(int advice)
+{
+ switch (advice) {
+ case LINUX_POSIX_FADV_NORMAL:
+ return (POSIX_FADV_NORMAL);
+ case LINUX_POSIX_FADV_RANDOM:
+ return (POSIX_FADV_RANDOM);
+ case LINUX_POSIX_FADV_SEQUENTIAL:
+ return (POSIX_FADV_SEQUENTIAL);
+ case LINUX_POSIX_FADV_WILLNEED:
+ return (POSIX_FADV_WILLNEED);
+ case LINUX_POSIX_FADV_DONTNEED:
+ return (POSIX_FADV_DONTNEED);
+ case LINUX_POSIX_FADV_NOREUSE:
+ return (POSIX_FADV_NOREUSE);
+ default:
+ return (-1);
+ }
+}
+
+int
+linux_fadvise64(struct thread *td, struct linux_fadvise64_args *args)
+{
+ int advice;
+
+ advice = convert_fadvice(args->advice);
+ if (advice == -1)
+ return (EINVAL);
+ return (kern_posix_fadvise(td, args->fd, args->offset, args->len,
+ advice));
+}
+
+int
+linux_fadvise64_64(struct thread *td, struct linux_fadvise64_64_args *args)
+{
+ int advice;
+
+ advice = convert_fadvice(args->advice);
+ if (advice == -1)
+ return (EINVAL);
+ return (kern_posix_fadvise(td, args->fd, args->offset, args->len,
+ advice));
+}
+
+int
+linux_pipe(struct thread *td, struct linux_pipe_args *args)
+{
+ int fildes[2];
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(pipe))
+ printf(ARGS(pipe, "*"));
+#endif
+
+ error = kern_pipe2(td, fildes, 0);
+ if (error)
+ return (error);
+
+ /* XXX: Close descriptors on error. */
+ return (copyout(fildes, args->pipefds, sizeof(fildes)));
+}
+
+int
+linux_pipe2(struct thread *td, struct linux_pipe2_args *args)
+{
+ int fildes[2];
+ int error, flags;
+
+#ifdef DEBUG
+ if (ldebug(pipe2))
+ printf(ARGS(pipe2, "*, %d"), args->flags);
+#endif
+
+ if ((args->flags & ~(LINUX_O_NONBLOCK | LINUX_O_CLOEXEC)) != 0)
+ return (EINVAL);
+
+ flags = 0;
+ if ((args->flags & LINUX_O_NONBLOCK) != 0)
+ flags |= O_NONBLOCK;
+ if ((args->flags & LINUX_O_CLOEXEC) != 0)
+ flags |= O_CLOEXEC;
+ error = kern_pipe2(td, fildes, flags);
+ if (error)
+ return (error);
+
+ /* XXX: Close descriptors on error. */
+ return (copyout(fildes, args->pipefds, sizeof(fildes)));
+}
diff --git a/sys/compat/linux/linux_file.h b/sys/compat/linux/linux_file.h
new file mode 100644
index 0000000..2d3106f
--- /dev/null
+++ b/sys/compat/linux/linux_file.h
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2007 Roman Divacky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LINUX_FILE_H_
+#define _LINUX_FILE_H_
+
+#define LINUX_AT_FDCWD -100
+#define LINUX_AT_SYMLINK_NOFOLLOW 0x100
+#define LINUX_AT_EACCESS 0x200
+#define LINUX_AT_REMOVEDIR 0x200
+#define LINUX_AT_SYMLINK_FOLLOW 0x400
+
+/*
+ * posix_fadvise advice
+ */
+#define LINUX_POSIX_FADV_NORMAL 0
+#define LINUX_POSIX_FADV_RANDOM 1
+#define LINUX_POSIX_FADV_SEQUENTIAL 2
+#define LINUX_POSIX_FADV_WILLNEED 3
+#define LINUX_POSIX_FADV_DONTNEED 4
+#define LINUX_POSIX_FADV_NOREUSE 5
+
+/*
+ * mount flags
+ */
+#define LINUX_MS_RDONLY 0x0001
+#define LINUX_MS_NOSUID 0x0002
+#define LINUX_MS_NODEV 0x0004
+#define LINUX_MS_NOEXEC 0x0008
+#define LINUX_MS_REMOUNT 0x0020
+
+#endif /* !_LINUX_FILE_H_ */
diff --git a/sys/compat/linux/linux_fork.c b/sys/compat/linux/linux_fork.c
new file mode 100644
index 0000000..2103636
--- /dev/null
+++ b/sys/compat/linux/linux_fork.c
@@ -0,0 +1,300 @@
+/*-
+ * Copyright (c) 2004 Tim J. Robbins
+ * Copyright (c) 2002 Doug Rabson
+ * Copyright (c) 2000 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_compat.h"
+#include "opt_kdtrace.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/imgact.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/sched.h>
+#include <sys/sdt.h>
+#include <sys/sx.h>
+#include <sys/unistd.h>
+
+#ifdef COMPAT_LINUX32
+#include <machine/../linux32/linux.h>
+#include <machine/../linux32/linux32_proto.h>
+#else
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#endif
+#include <compat/linux/linux_dtrace.h>
+#include <compat/linux/linux_signal.h>
+#include <compat/linux/linux_emul.h>
+#include <compat/linux/linux_misc.h>
+
+/* DTrace init */
+LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
+
+/* Linuxulator-global DTrace probes */
+LIN_SDT_PROBE_DECLARE(locks, emul_lock, locked);
+LIN_SDT_PROBE_DECLARE(locks, emul_lock, unlock);
+
+
+int
+linux_fork(struct thread *td, struct linux_fork_args *args)
+{
+ int error;
+ struct proc *p2;
+ struct thread *td2;
+
+#ifdef DEBUG
+ if (ldebug(fork))
+ printf(ARGS(fork, ""));
+#endif
+
+ if ((error = fork1(td, RFFDG | RFPROC | RFSTOPPED, 0, &p2, NULL, 0))
+ != 0)
+ return (error);
+
+ td->td_retval[0] = p2->p_pid;
+ td->td_retval[1] = 0;
+
+ error = linux_proc_init(td, td->td_retval[0], 0);
+ if (error)
+ return (error);
+
+ td2 = FIRST_THREAD_IN_PROC(p2);
+
+ /*
+ * Make this runnable after we are finished with it.
+ */
+ thread_lock(td2);
+ TD_SET_CAN_RUN(td2);
+ sched_add(td2, SRQ_BORING);
+ thread_unlock(td2);
+
+ return (0);
+}
+
+int
+linux_vfork(struct thread *td, struct linux_vfork_args *args)
+{
+ int error;
+ struct proc *p2;
+ struct thread *td2;
+
+#ifdef DEBUG
+ if (ldebug(vfork))
+ printf(ARGS(vfork, ""));
+#endif
+
+ /* Exclude RFPPWAIT */
+ if ((error = fork1(td, RFFDG | RFPROC | RFMEM | RFSTOPPED, 0, &p2,
+ NULL, 0)) != 0)
+ return (error);
+
+ td->td_retval[0] = p2->p_pid;
+
+ error = linux_proc_init(td, td->td_retval[0], 0);
+ if (error)
+ return (error);
+
+ PROC_LOCK(p2);
+ p2->p_flag |= P_PPWAIT;
+ PROC_UNLOCK(p2);
+
+ td2 = FIRST_THREAD_IN_PROC(p2);
+
+ /*
+ * Make this runnable after we are finished with it.
+ */
+ thread_lock(td2);
+ TD_SET_CAN_RUN(td2);
+ sched_add(td2, SRQ_BORING);
+ thread_unlock(td2);
+
+ /* wait for the children to exit, ie. emulate vfork */
+ PROC_LOCK(p2);
+ while (p2->p_flag & P_PPWAIT)
+ cv_wait(&p2->p_pwait, &p2->p_mtx);
+ PROC_UNLOCK(p2);
+
+ return (0);
+}
+
+int
+linux_clone(struct thread *td, struct linux_clone_args *args)
+{
+ int error, ff = RFPROC | RFSTOPPED;
+ struct proc *p2;
+ struct thread *td2;
+ int exit_signal;
+ struct linux_emuldata *em;
+
+#ifdef DEBUG
+ if (ldebug(clone)) {
+ printf(ARGS(clone, "flags %x, stack %p, parent tid: %p, "
+ "child tid: %p"), (unsigned)args->flags,
+ args->stack, args->parent_tidptr, args->child_tidptr);
+ }
+#endif
+
+ exit_signal = args->flags & 0x000000ff;
+ if (LINUX_SIG_VALID(exit_signal)) {
+ if (exit_signal <= LINUX_SIGTBLSZ)
+ exit_signal =
+ linux_to_bsd_signal[_SIG_IDX(exit_signal)];
+ } else if (exit_signal != 0)
+ return (EINVAL);
+
+ if (args->flags & LINUX_CLONE_VM)
+ ff |= RFMEM;
+ if (args->flags & LINUX_CLONE_SIGHAND)
+ ff |= RFSIGSHARE;
+ /*
+ * XXX: In Linux, sharing of fs info (chroot/cwd/umask)
+ * and open files is independant. In FreeBSD, its in one
+ * structure but in reality it does not cause any problems
+ * because both of these flags are usually set together.
+ */
+ if (!(args->flags & (LINUX_CLONE_FILES | LINUX_CLONE_FS)))
+ ff |= RFFDG;
+
+ /*
+ * Attempt to detect when linux_clone(2) is used for creating
+ * kernel threads. Unfortunately despite the existence of the
+ * CLONE_THREAD flag, version of linuxthreads package used in
+ * most popular distros as of beginning of 2005 doesn't make
+ * any use of it. Therefore, this detection relies on
+ * empirical observation that linuxthreads sets certain
+ * combination of flags, so that we can make more or less
+ * precise detection and notify the FreeBSD kernel that several
+ * processes are in fact part of the same threading group, so
+ * that special treatment is necessary for signal delivery
+ * between those processes and fd locking.
+ */
+ if ((args->flags & 0xffffff00) == LINUX_THREADING_FLAGS)
+ ff |= RFTHREAD;
+
+ if (args->flags & LINUX_CLONE_PARENT_SETTID)
+ if (args->parent_tidptr == NULL)
+ return (EINVAL);
+
+ error = fork1(td, ff, 0, &p2, NULL, 0);
+ if (error)
+ return (error);
+
+ if (args->flags & (LINUX_CLONE_PARENT | LINUX_CLONE_THREAD)) {
+ sx_xlock(&proctree_lock);
+ PROC_LOCK(p2);
+ proc_reparent(p2, td->td_proc->p_pptr);
+ PROC_UNLOCK(p2);
+ sx_xunlock(&proctree_lock);
+ }
+
+ /* create the emuldata */
+ error = linux_proc_init(td, p2->p_pid, args->flags);
+ /* reference it - no need to check this */
+ em = em_find(p2, EMUL_DOLOCK);
+ KASSERT(em != NULL, ("clone: emuldata not found."));
+ /* and adjust it */
+
+ if (args->flags & LINUX_CLONE_THREAD) {
+#ifdef notyet
+ PROC_LOCK(p2);
+ p2->p_pgrp = td->td_proc->p_pgrp;
+ PROC_UNLOCK(p2);
+#endif
+ exit_signal = 0;
+ }
+
+ if (args->flags & LINUX_CLONE_CHILD_SETTID)
+ em->child_set_tid = args->child_tidptr;
+ else
+ em->child_set_tid = NULL;
+
+ if (args->flags & LINUX_CLONE_CHILD_CLEARTID)
+ em->child_clear_tid = args->child_tidptr;
+ else
+ em->child_clear_tid = NULL;
+
+ EMUL_UNLOCK(&emul_lock);
+
+ if (args->flags & LINUX_CLONE_PARENT_SETTID) {
+ error = copyout(&p2->p_pid, args->parent_tidptr,
+ sizeof(p2->p_pid));
+ if (error)
+ printf(LMSG("copyout failed!"));
+ }
+
+ PROC_LOCK(p2);
+ p2->p_sigparent = exit_signal;
+ PROC_UNLOCK(p2);
+ td2 = FIRST_THREAD_IN_PROC(p2);
+ /*
+ * In a case of stack = NULL, we are supposed to COW calling process
+ * stack. This is what normal fork() does, so we just keep tf_rsp arg
+ * intact.
+ */
+ if (args->stack)
+ linux_set_upcall_kse(td2, PTROUT(args->stack));
+
+ if (args->flags & LINUX_CLONE_SETTLS)
+ linux_set_cloned_tls(td2, args->tls);
+
+#ifdef DEBUG
+ if (ldebug(clone))
+ printf(LMSG("clone: successful rfork to %d, "
+ "stack %p sig = %d"), (int)p2->p_pid, args->stack,
+ exit_signal);
+#endif
+ if (args->flags & LINUX_CLONE_VFORK) {
+ PROC_LOCK(p2);
+ p2->p_flag |= P_PPWAIT;
+ PROC_UNLOCK(p2);
+ }
+
+ /*
+ * Make this runnable after we are finished with it.
+ */
+ thread_lock(td2);
+ TD_SET_CAN_RUN(td2);
+ sched_add(td2, SRQ_BORING);
+ thread_unlock(td2);
+
+ td->td_retval[0] = p2->p_pid;
+ td->td_retval[1] = 0;
+
+ if (args->flags & LINUX_CLONE_VFORK) {
+ /* wait for the children to exit, ie. emulate vfork */
+ PROC_LOCK(p2);
+ while (p2->p_flag & P_PPWAIT)
+ cv_wait(&p2->p_pwait, &p2->p_mtx);
+ PROC_UNLOCK(p2);
+ }
+
+ return (0);
+}
diff --git a/sys/compat/linux/linux_futex.c b/sys/compat/linux/linux_futex.c
new file mode 100644
index 0000000..c1531d0
--- /dev/null
+++ b/sys/compat/linux/linux_futex.c
@@ -0,0 +1,1228 @@
+/* $NetBSD: linux_futex.c,v 1.7 2006/07/24 19:01:49 manu Exp $ */
+
+/*-
+ * Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Emmanuel Dreyfus
+ * 4. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE THE AUTHOR AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#if 0
+__KERNEL_RCSID(1, "$NetBSD: linux_futex.c,v 1.7 2006/07/24 19:01:49 manu Exp $");
+#endif
+
+#include "opt_compat.h"
+#include "opt_kdtrace.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/imgact.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/priv.h>
+#include <sys/proc.h>
+#include <sys/queue.h>
+#include <sys/sched.h>
+#include <sys/sdt.h>
+#include <sys/sx.h>
+#include <sys/umtx.h>
+
+#ifdef COMPAT_LINUX32
+#include <machine/../linux32/linux.h>
+#include <machine/../linux32/linux32_proto.h>
+#else
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#endif
+#include <compat/linux/linux_dtrace.h>
+#include <compat/linux/linux_emul.h>
+#include <compat/linux/linux_futex.h>
+#include <compat/linux/linux_util.h>
+
+/* DTrace init */
+LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
+
+/* Linuxulator-global DTrace probes */
+LIN_SDT_PROBE_DECLARE(locks, emul_lock, locked);
+LIN_SDT_PROBE_DECLARE(locks, emul_lock, unlock);
+
+/**
+ * Futex part for the special DTrace module "locks".
+ */
+LIN_SDT_PROBE_DEFINE1(locks, futex_mtx, locked, "struct mtx *");
+LIN_SDT_PROBE_DEFINE1(locks, futex_mtx, unlock, "struct mtx *");
+
+/**
+ * Per futex probes.
+ */
+LIN_SDT_PROBE_DEFINE1(futex, futex, create, "struct sx *");
+LIN_SDT_PROBE_DEFINE1(futex, futex, destroy, "struct sx *");
+
+/**
+ * DTrace probes in this module.
+ */
+LIN_SDT_PROBE_DEFINE2(futex, futex_put, entry, "struct futex *",
+ "struct waiting_proc *");
+LIN_SDT_PROBE_DEFINE3(futex, futex_put, destroy, "uint32_t *", "uint32_t",
+ "int");
+LIN_SDT_PROBE_DEFINE3(futex, futex_put, unlock, "uint32_t *", "uint32_t",
+ "int");
+LIN_SDT_PROBE_DEFINE0(futex, futex_put, return);
+LIN_SDT_PROBE_DEFINE3(futex, futex_get0, entry, "uint32_t *", "struct futex **",
+ "uint32_t");
+LIN_SDT_PROBE_DEFINE1(futex, futex_get0, umtx_key_get_error, "int");
+LIN_SDT_PROBE_DEFINE3(futex, futex_get0, shared, "uint32_t *", "uint32_t",
+ "int");
+LIN_SDT_PROBE_DEFINE1(futex, futex_get0, null, "uint32_t *");
+LIN_SDT_PROBE_DEFINE3(futex, futex_get0, new, "uint32_t *", "uint32_t", "int");
+LIN_SDT_PROBE_DEFINE1(futex, futex_get0, return, "int");
+LIN_SDT_PROBE_DEFINE3(futex, futex_get, entry, "uint32_t *",
+ "struct waiting_proc **", "struct futex **");
+LIN_SDT_PROBE_DEFINE0(futex, futex_get, error);
+LIN_SDT_PROBE_DEFINE1(futex, futex_get, return, "int");
+LIN_SDT_PROBE_DEFINE3(futex, futex_sleep, entry, "struct futex *",
+ "struct waiting_proc **", "int");
+LIN_SDT_PROBE_DEFINE5(futex, futex_sleep, requeue_error, "int", "uint32_t *",
+ "struct waiting_proc *", "uint32_t *", "uint32_t");
+LIN_SDT_PROBE_DEFINE3(futex, futex_sleep, sleep_error, "int", "uint32_t *",
+ "struct waiting_proc *");
+LIN_SDT_PROBE_DEFINE1(futex, futex_sleep, return, "int");
+LIN_SDT_PROBE_DEFINE3(futex, futex_wake, entry, "struct futex *", "int",
+ "uint32_t");
+LIN_SDT_PROBE_DEFINE3(futex, futex_wake, iterate, "uint32_t",
+ "struct waiting_proc *", "uin32_t");
+LIN_SDT_PROBE_DEFINE1(futex, futex_wake, wakeup, "struct waiting_proc *");
+LIN_SDT_PROBE_DEFINE1(futex, futex_wake, return, "int");
+LIN_SDT_PROBE_DEFINE4(futex, futex_requeue, entry, "struct futex *", "int",
+ "struct futex *", "int");
+LIN_SDT_PROBE_DEFINE1(futex, futex_requeue, wakeup, "struct waiting_proc *");
+LIN_SDT_PROBE_DEFINE3(futex, futex_requeue, requeue, "uint32_t *",
+ "struct waiting_proc *", "uint32_t");
+LIN_SDT_PROBE_DEFINE1(futex, futex_requeue, return, "int");
+LIN_SDT_PROBE_DEFINE4(futex, futex_wait, entry, "struct futex *",
+ "struct waiting_proc **", "struct l_timespec *", "uint32_t");
+LIN_SDT_PROBE_DEFINE1(futex, futex_wait, copyin_error, "int");
+LIN_SDT_PROBE_DEFINE1(futex, futex_wait, itimerfix_error, "int");
+LIN_SDT_PROBE_DEFINE1(futex, futex_wait, sleep_error, "int");
+LIN_SDT_PROBE_DEFINE1(futex, futex_wait, return, "int");
+LIN_SDT_PROBE_DEFINE3(futex, futex_atomic_op, entry, "struct thread *",
+ "int", "uint32_t");
+LIN_SDT_PROBE_DEFINE4(futex, futex_atomic_op, decoded_op, "int", "int", "int",
+ "int");
+LIN_SDT_PROBE_DEFINE0(futex, futex_atomic_op, missing_access_check);
+LIN_SDT_PROBE_DEFINE1(futex, futex_atomic_op, unimplemented_op, "int");
+LIN_SDT_PROBE_DEFINE1(futex, futex_atomic_op, unimplemented_cmp, "int");
+LIN_SDT_PROBE_DEFINE1(futex, futex_atomic_op, return, "int");
+LIN_SDT_PROBE_DEFINE2(futex, linux_sys_futex, entry, "struct thread *",
+ "struct linux_sys_futex_args *");
+LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, unimplemented_clockswitch);
+LIN_SDT_PROBE_DEFINE1(futex, linux_sys_futex, copyin_error, "int");
+LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, invalid_cmp_requeue_use);
+LIN_SDT_PROBE_DEFINE3(futex, linux_sys_futex, debug_wait, "uint32_t *",
+ "uint32_t", "uint32_t");
+LIN_SDT_PROBE_DEFINE4(futex, linux_sys_futex, debug_wait_value_neq,
+ "uint32_t *", "uint32_t", "int", "uint32_t");
+LIN_SDT_PROBE_DEFINE3(futex, linux_sys_futex, debug_wake, "uint32_t *",
+ "uint32_t", "uint32_t");
+LIN_SDT_PROBE_DEFINE5(futex, linux_sys_futex, debug_cmp_requeue, "uint32_t *",
+ "uint32_t", "uint32_t", "uint32_t *", "struct l_timespec *");
+LIN_SDT_PROBE_DEFINE2(futex, linux_sys_futex, debug_cmp_requeue_value_neq,
+ "uint32_t", "int");
+LIN_SDT_PROBE_DEFINE5(futex, linux_sys_futex, debug_wake_op, "uint32_t *",
+ "int", "uint32_t", "uint32_t *", "uint32_t");
+LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, unhandled_efault);
+LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, unimplemented_lock_pi);
+LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, unimplemented_unlock_pi);
+LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, unimplemented_trylock_pi);
+LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, deprecated_requeue);
+LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, unimplemented_wait_requeue_pi);
+LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, unimplemented_cmp_requeue_pi);
+LIN_SDT_PROBE_DEFINE1(futex, linux_sys_futex, unknown_operation, "int");
+LIN_SDT_PROBE_DEFINE1(futex, linux_sys_futex, return, "int");
+LIN_SDT_PROBE_DEFINE2(futex, linux_set_robust_list, entry, "struct thread *",
+ "struct linux_set_robust_list_args *");
+LIN_SDT_PROBE_DEFINE0(futex, linux_set_robust_list, size_error);
+LIN_SDT_PROBE_DEFINE1(futex, linux_set_robust_list, return, "int");
+LIN_SDT_PROBE_DEFINE2(futex, linux_get_robust_list, entry, "struct thread *",
+ "struct linux_get_robust_list_args *");
+LIN_SDT_PROBE_DEFINE1(futex, linux_get_robust_list, copyout_error, "int");
+LIN_SDT_PROBE_DEFINE1(futex, linux_get_robust_list, return, "int");
+LIN_SDT_PROBE_DEFINE3(futex, handle_futex_death, entry, "struct proc *",
+ "uint32_t *", "int");
+LIN_SDT_PROBE_DEFINE1(futex, handle_futex_death, copyin_error, "int");
+LIN_SDT_PROBE_DEFINE1(futex, handle_futex_death, return, "int");
+LIN_SDT_PROBE_DEFINE3(futex, fetch_robust_entry, entry,
+ "struct linux_robust_list **", "struct linux_robust_list **", "int *");
+LIN_SDT_PROBE_DEFINE1(futex, fetch_robust_entry, copyin_error, "int");
+LIN_SDT_PROBE_DEFINE1(futex, fetch_robust_entry, return, "int");
+LIN_SDT_PROBE_DEFINE1(futex, release_futexes, entry, "struct proc *");
+LIN_SDT_PROBE_DEFINE1(futex, release_futexes, copyin_error, "int");
+LIN_SDT_PROBE_DEFINE0(futex, release_futexes, return);
+
+static MALLOC_DEFINE(M_FUTEX, "futex", "Linux futexes");
+static MALLOC_DEFINE(M_FUTEX_WP, "futex wp", "Linux futexes wp");
+
+struct futex;
+
+struct waiting_proc {
+ uint32_t wp_flags;
+ struct futex *wp_futex;
+ TAILQ_ENTRY(waiting_proc) wp_list;
+};
+
+struct futex {
+ struct sx f_lck;
+ uint32_t *f_uaddr; /* user-supplied value, for debug */
+ struct umtx_key f_key;
+ uint32_t f_refcount;
+ uint32_t f_bitset;
+ LIST_ENTRY(futex) f_list;
+ TAILQ_HEAD(lf_waiting_proc, waiting_proc) f_waiting_proc;
+};
+
+struct futex_list futex_list;
+
+#define FUTEX_LOCK(f) sx_xlock(&(f)->f_lck)
+#define FUTEX_UNLOCK(f) sx_xunlock(&(f)->f_lck)
+#define FUTEX_INIT(f) do { \
+ sx_init_flags(&(f)->f_lck, "ftlk", \
+ SX_DUPOK); \
+ LIN_SDT_PROBE1(futex, futex, create, \
+ &(f)->f_lck); \
+ } while (0)
+#define FUTEX_DESTROY(f) do { \
+ LIN_SDT_PROBE1(futex, futex, destroy, \
+ &(f)->f_lck); \
+ sx_destroy(&(f)->f_lck); \
+ } while (0)
+#define FUTEX_ASSERT_LOCKED(f) sx_assert(&(f)->f_lck, SA_XLOCKED)
+
+struct mtx futex_mtx; /* protects the futex list */
+#define FUTEXES_LOCK do { \
+ mtx_lock(&futex_mtx); \
+ LIN_SDT_PROBE1(locks, futex_mtx, \
+ locked, &futex_mtx); \
+ } while (0)
+#define FUTEXES_UNLOCK do { \
+ LIN_SDT_PROBE1(locks, futex_mtx, \
+ unlock, &futex_mtx); \
+ mtx_unlock(&futex_mtx); \
+ } while (0)
+
+/* flags for futex_get() */
+#define FUTEX_CREATE_WP 0x1 /* create waiting_proc */
+#define FUTEX_DONTCREATE 0x2 /* don't create futex if not exists */
+#define FUTEX_DONTEXISTS 0x4 /* return EINVAL if futex exists */
+#define FUTEX_SHARED 0x8 /* shared futex */
+
+/* wp_flags */
+#define FUTEX_WP_REQUEUED 0x1 /* wp requeued - wp moved from wp_list
+ * of futex where thread sleep to wp_list
+ * of another futex.
+ */
+#define FUTEX_WP_REMOVED 0x2 /* wp is woken up and removed from futex
+ * wp_list to prevent double wakeup.
+ */
+
+/* support.s */
+int futex_xchgl(int oparg, uint32_t *uaddr, int *oldval);
+int futex_addl(int oparg, uint32_t *uaddr, int *oldval);
+int futex_orl(int oparg, uint32_t *uaddr, int *oldval);
+int futex_andl(int oparg, uint32_t *uaddr, int *oldval);
+int futex_xorl(int oparg, uint32_t *uaddr, int *oldval);
+
+static void
+futex_put(struct futex *f, struct waiting_proc *wp)
+{
+ LIN_SDT_PROBE2(futex, futex_put, entry, f, wp);
+
+ FUTEX_ASSERT_LOCKED(f);
+ if (wp != NULL) {
+ if ((wp->wp_flags & FUTEX_WP_REMOVED) == 0)
+ TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list);
+ free(wp, M_FUTEX_WP);
+ }
+
+ FUTEXES_LOCK;
+ if (--f->f_refcount == 0) {
+ LIST_REMOVE(f, f_list);
+ FUTEXES_UNLOCK;
+ FUTEX_UNLOCK(f);
+
+ LIN_SDT_PROBE3(futex, futex_put, destroy, f->f_uaddr,
+ f->f_refcount, f->f_key.shared);
+ LINUX_CTR3(sys_futex, "futex_put destroy uaddr %p ref %d "
+ "shared %d", f->f_uaddr, f->f_refcount, f->f_key.shared);
+ umtx_key_release(&f->f_key);
+ FUTEX_DESTROY(f);
+ free(f, M_FUTEX);
+
+ LIN_SDT_PROBE0(futex, futex_put, return);
+ return;
+ }
+
+ LIN_SDT_PROBE3(futex, futex_put, unlock, f->f_uaddr, f->f_refcount,
+ f->f_key.shared);
+ LINUX_CTR3(sys_futex, "futex_put uaddr %p ref %d shared %d",
+ f->f_uaddr, f->f_refcount, f->f_key.shared);
+ FUTEXES_UNLOCK;
+ FUTEX_UNLOCK(f);
+
+ LIN_SDT_PROBE0(futex, futex_put, return);
+}
+
+static int
+futex_get0(uint32_t *uaddr, struct futex **newf, uint32_t flags)
+{
+ struct futex *f, *tmpf;
+ struct umtx_key key;
+ int error;
+
+ LIN_SDT_PROBE3(futex, futex_get0, entry, uaddr, newf, flags);
+
+ *newf = tmpf = NULL;
+
+ error = umtx_key_get(uaddr, TYPE_FUTEX, (flags & FUTEX_SHARED) ?
+ AUTO_SHARE : THREAD_SHARE, &key);
+ if (error) {
+ LIN_SDT_PROBE1(futex, futex_get0, umtx_key_get_error, error);
+ LIN_SDT_PROBE1(futex, futex_get0, return, error);
+ return (error);
+ }
+retry:
+ FUTEXES_LOCK;
+ LIST_FOREACH(f, &futex_list, f_list) {
+ if (umtx_key_match(&f->f_key, &key)) {
+ if (tmpf != NULL) {
+ FUTEX_UNLOCK(tmpf);
+ FUTEX_DESTROY(tmpf);
+ free(tmpf, M_FUTEX);
+ }
+ if (flags & FUTEX_DONTEXISTS) {
+ FUTEXES_UNLOCK;
+ umtx_key_release(&key);
+
+ LIN_SDT_PROBE1(futex, futex_get0, return,
+ EINVAL);
+ return (EINVAL);
+ }
+
+ /*
+ * Increment refcount of the found futex to
+ * prevent it from deallocation before FUTEX_LOCK()
+ */
+ ++f->f_refcount;
+ FUTEXES_UNLOCK;
+ umtx_key_release(&key);
+
+ FUTEX_LOCK(f);
+ *newf = f;
+ LIN_SDT_PROBE3(futex, futex_get0, shared, uaddr,
+ f->f_refcount, f->f_key.shared);
+ LINUX_CTR3(sys_futex, "futex_get uaddr %p ref %d shared %d",
+ uaddr, f->f_refcount, f->f_key.shared);
+
+ LIN_SDT_PROBE1(futex, futex_get0, return, 0);
+ return (0);
+ }
+ }
+
+ if (flags & FUTEX_DONTCREATE) {
+ FUTEXES_UNLOCK;
+ umtx_key_release(&key);
+ LIN_SDT_PROBE1(futex, futex_get0, null, uaddr);
+ LINUX_CTR1(sys_futex, "futex_get uaddr %p null", uaddr);
+
+ LIN_SDT_PROBE1(futex, futex_get0, return, 0);
+ return (0);
+ }
+
+ if (tmpf == NULL) {
+ FUTEXES_UNLOCK;
+ tmpf = malloc(sizeof(*tmpf), M_FUTEX, M_WAITOK | M_ZERO);
+ tmpf->f_uaddr = uaddr;
+ tmpf->f_key = key;
+ tmpf->f_refcount = 1;
+ tmpf->f_bitset = FUTEX_BITSET_MATCH_ANY;
+ FUTEX_INIT(tmpf);
+ TAILQ_INIT(&tmpf->f_waiting_proc);
+
+ /*
+ * Lock the new futex before an insert into the futex_list
+ * to prevent futex usage by other.
+ */
+ FUTEX_LOCK(tmpf);
+ goto retry;
+ }
+
+ LIST_INSERT_HEAD(&futex_list, tmpf, f_list);
+ FUTEXES_UNLOCK;
+
+ LIN_SDT_PROBE3(futex, futex_get0, new, uaddr, tmpf->f_refcount,
+ tmpf->f_key.shared);
+ LINUX_CTR3(sys_futex, "futex_get uaddr %p ref %d shared %d new",
+ uaddr, tmpf->f_refcount, tmpf->f_key.shared);
+ *newf = tmpf;
+
+ LIN_SDT_PROBE1(futex, futex_get0, return, 0);
+ return (0);
+}
+
+static int
+futex_get(uint32_t *uaddr, struct waiting_proc **wp, struct futex **f,
+ uint32_t flags)
+{
+ int error;
+
+ LIN_SDT_PROBE3(futex, futex_get, entry, uaddr, wp, f);
+
+ if (flags & FUTEX_CREATE_WP) {
+ *wp = malloc(sizeof(struct waiting_proc), M_FUTEX_WP, M_WAITOK);
+ (*wp)->wp_flags = 0;
+ }
+ error = futex_get0(uaddr, f, flags);
+ if (error) {
+ LIN_SDT_PROBE0(futex, futex_get, error);
+
+ if (flags & FUTEX_CREATE_WP)
+ free(*wp, M_FUTEX_WP);
+
+ LIN_SDT_PROBE1(futex, futex_get, return, error);
+ return (error);
+ }
+ if (flags & FUTEX_CREATE_WP) {
+ TAILQ_INSERT_HEAD(&(*f)->f_waiting_proc, *wp, wp_list);
+ (*wp)->wp_futex = *f;
+ }
+
+ LIN_SDT_PROBE1(futex, futex_get, return, error);
+ return (error);
+}
+
+static int
+futex_sleep(struct futex *f, struct waiting_proc *wp, int timeout)
+{
+ int error;
+
+ FUTEX_ASSERT_LOCKED(f);
+ LIN_SDT_PROBE3(futex, futex_sleep, entry, f, wp, timeout);
+ LINUX_CTR4(sys_futex, "futex_sleep enter uaddr %p wp %p timo %d ref %d",
+ f->f_uaddr, wp, timeout, f->f_refcount);
+ error = sx_sleep(wp, &f->f_lck, PCATCH, "futex", timeout);
+ if (wp->wp_flags & FUTEX_WP_REQUEUED) {
+ KASSERT(f != wp->wp_futex, ("futex != wp_futex"));
+
+ if (error) {
+ LIN_SDT_PROBE5(futex, futex_sleep, requeue_error, error,
+ f->f_uaddr, wp, wp->wp_futex->f_uaddr,
+ wp->wp_futex->f_refcount);
+ }
+
+ LINUX_CTR5(sys_futex, "futex_sleep out error %d uaddr %p wp"
+ " %p requeued uaddr %p ref %d",
+ error, f->f_uaddr, wp, wp->wp_futex->f_uaddr,
+ wp->wp_futex->f_refcount);
+ futex_put(f, NULL);
+ f = wp->wp_futex;
+ FUTEX_LOCK(f);
+ } else {
+ if (error) {
+ LIN_SDT_PROBE3(futex, futex_sleep, sleep_error, error,
+ f->f_uaddr, wp);
+ }
+ LINUX_CTR3(sys_futex, "futex_sleep out error %d uaddr %p wp %p",
+ error, f->f_uaddr, wp);
+ }
+
+ futex_put(f, wp);
+
+ LIN_SDT_PROBE1(futex, futex_sleep, return, error);
+ return (error);
+}
+
+static int
+futex_wake(struct futex *f, int n, uint32_t bitset)
+{
+ struct waiting_proc *wp, *wpt;
+ int count = 0;
+
+ LIN_SDT_PROBE3(futex, futex_wake, entry, f, n, bitset);
+
+ if (bitset == 0) {
+ LIN_SDT_PROBE1(futex, futex_wake, return, EINVAL);
+ return (EINVAL);
+ }
+
+ FUTEX_ASSERT_LOCKED(f);
+ TAILQ_FOREACH_SAFE(wp, &f->f_waiting_proc, wp_list, wpt) {
+ LIN_SDT_PROBE3(futex, futex_wake, iterate, f->f_uaddr, wp,
+ f->f_refcount);
+ LINUX_CTR3(sys_futex, "futex_wake uaddr %p wp %p ref %d",
+ f->f_uaddr, wp, f->f_refcount);
+ /*
+ * Unless we find a matching bit in
+ * the bitset, continue searching.
+ */
+ if (!(wp->wp_futex->f_bitset & bitset))
+ continue;
+
+ wp->wp_flags |= FUTEX_WP_REMOVED;
+ TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list);
+ LIN_SDT_PROBE1(futex, futex_wake, wakeup, wp);
+ wakeup_one(wp);
+ if (++count == n)
+ break;
+ }
+
+ LIN_SDT_PROBE1(futex, futex_wake, return, count);
+ return (count);
+}
+
+static int
+futex_requeue(struct futex *f, int n, struct futex *f2, int n2)
+{
+ struct waiting_proc *wp, *wpt;
+ int count = 0;
+
+ LIN_SDT_PROBE4(futex, futex_requeue, entry, f, n, f2, n2);
+
+ FUTEX_ASSERT_LOCKED(f);
+ FUTEX_ASSERT_LOCKED(f2);
+
+ TAILQ_FOREACH_SAFE(wp, &f->f_waiting_proc, wp_list, wpt) {
+ if (++count <= n) {
+ LINUX_CTR2(sys_futex, "futex_req_wake uaddr %p wp %p",
+ f->f_uaddr, wp);
+ wp->wp_flags |= FUTEX_WP_REMOVED;
+ TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list);
+ LIN_SDT_PROBE1(futex, futex_requeue, wakeup, wp);
+ wakeup_one(wp);
+ } else {
+ LIN_SDT_PROBE3(futex, futex_requeue, requeue,
+ f->f_uaddr, wp, f2->f_uaddr);
+ LINUX_CTR3(sys_futex, "futex_requeue uaddr %p wp %p to %p",
+ f->f_uaddr, wp, f2->f_uaddr);
+ wp->wp_flags |= FUTEX_WP_REQUEUED;
+ /* Move wp to wp_list of f2 futex */
+ TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list);
+ TAILQ_INSERT_HEAD(&f2->f_waiting_proc, wp, wp_list);
+
+ /*
+ * Thread which sleeps on wp after waking should
+ * acquire f2 lock, so increment refcount of f2 to
+ * prevent it from premature deallocation.
+ */
+ wp->wp_futex = f2;
+ FUTEXES_LOCK;
+ ++f2->f_refcount;
+ FUTEXES_UNLOCK;
+ if (count - n >= n2)
+ break;
+ }
+ }
+
+ LIN_SDT_PROBE1(futex, futex_requeue, return, count);
+ return (count);
+}
+
+static int
+futex_wait(struct futex *f, struct waiting_proc *wp, struct l_timespec *ts,
+ uint32_t bitset)
+{
+ struct l_timespec timeout;
+ struct timeval tv;
+ int timeout_hz;
+ int error;
+
+ LIN_SDT_PROBE4(futex, futex_wait, entry, f, wp, ts, bitset);
+
+ if (bitset == 0) {
+ LIN_SDT_PROBE1(futex, futex_wait, return, EINVAL);
+ return (EINVAL);
+ }
+
+ f->f_bitset = bitset;
+
+ if (ts != NULL) {
+ error = copyin(ts, &timeout, sizeof(timeout));
+ if (error) {
+ LIN_SDT_PROBE1(futex, futex_wait, copyin_error, error);
+ LIN_SDT_PROBE1(futex, futex_wait, return, error);
+ return (error);
+ }
+ TIMESPEC_TO_TIMEVAL(&tv, &timeout);
+ error = itimerfix(&tv);
+ if (error) {
+ LIN_SDT_PROBE1(futex, futex_wait, itimerfix_error,
+ error);
+ LIN_SDT_PROBE1(futex, futex_wait, return, error);
+ return (error);
+ }
+ timeout_hz = tvtohz(&tv);
+ } else
+ timeout_hz = 0;
+
+ error = futex_sleep(f, wp, timeout_hz);
+ if (error) {
+ LIN_SDT_PROBE1(futex, futex_wait, sleep_error, error);
+ }
+ if (error == EWOULDBLOCK)
+ error = ETIMEDOUT;
+
+ LIN_SDT_PROBE1(futex, futex_wait, return, error);
+ return (error);
+}
+
+static int
+futex_atomic_op(struct thread *td, int encoded_op, uint32_t *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret;
+
+ LIN_SDT_PROBE3(futex, futex_atomic_op, entry, td, encoded_op, uaddr);
+
+ if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+ oparg = 1 << oparg;
+
+ LIN_SDT_PROBE4(futex, futex_atomic_op, decoded_op, op, cmp, oparg,
+ cmparg);
+
+ /* XXX: Linux verifies access here and returns EFAULT */
+ LIN_SDT_PROBE0(futex, futex_atomic_op, missing_access_check);
+
+ switch (op) {
+ case FUTEX_OP_SET:
+ ret = futex_xchgl(oparg, uaddr, &oldval);
+ break;
+ case FUTEX_OP_ADD:
+ ret = futex_addl(oparg, uaddr, &oldval);
+ break;
+ case FUTEX_OP_OR:
+ ret = futex_orl(oparg, uaddr, &oldval);
+ break;
+ case FUTEX_OP_ANDN:
+ ret = futex_andl(~oparg, uaddr, &oldval);
+ break;
+ case FUTEX_OP_XOR:
+ ret = futex_xorl(oparg, uaddr, &oldval);
+ break;
+ default:
+ LIN_SDT_PROBE1(futex, futex_atomic_op, unimplemented_op, op);
+ ret = -ENOSYS;
+ break;
+ }
+
+ if (ret) {
+ LIN_SDT_PROBE1(futex, futex_atomic_op, return, ret);
+ return (ret);
+ }
+
+ switch (cmp) {
+ case FUTEX_OP_CMP_EQ:
+ ret = (oldval == cmparg);
+ break;
+ case FUTEX_OP_CMP_NE:
+ ret = (oldval != cmparg);
+ break;
+ case FUTEX_OP_CMP_LT:
+ ret = (oldval < cmparg);
+ break;
+ case FUTEX_OP_CMP_GE:
+ ret = (oldval >= cmparg);
+ break;
+ case FUTEX_OP_CMP_LE:
+ ret = (oldval <= cmparg);
+ break;
+ case FUTEX_OP_CMP_GT:
+ ret = (oldval > cmparg);
+ break;
+ default:
+ LIN_SDT_PROBE1(futex, futex_atomic_op, unimplemented_cmp, cmp);
+ ret = -ENOSYS;
+ }
+
+ LIN_SDT_PROBE1(futex, futex_atomic_op, return, ret);
+ return (ret);
+}
+
+int
+linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
+{
+ int clockrt, nrwake, op_ret, ret, val;
+ struct linux_emuldata *em;
+ struct waiting_proc *wp;
+ struct futex *f, *f2;
+ int error;
+ uint32_t flags;
+
+ LIN_SDT_PROBE2(futex, linux_sys_futex, entry, td, args);
+
+ if (args->op & LINUX_FUTEX_PRIVATE_FLAG) {
+ flags = 0;
+ args->op &= ~LINUX_FUTEX_PRIVATE_FLAG;
+ } else
+ flags = FUTEX_SHARED;
+
+ /*
+ * Currently support for switching between CLOCK_MONOTONIC and
+ * CLOCK_REALTIME is not present. However Linux forbids the use of
+ * FUTEX_CLOCK_REALTIME with any op except FUTEX_WAIT_BITSET and
+ * FUTEX_WAIT_REQUEUE_PI.
+ */
+ clockrt = args->op & LINUX_FUTEX_CLOCK_REALTIME;
+ args->op = args->op & ~LINUX_FUTEX_CLOCK_REALTIME;
+ if (clockrt && args->op != LINUX_FUTEX_WAIT_BITSET &&
+ args->op != LINUX_FUTEX_WAIT_REQUEUE_PI) {
+ LIN_SDT_PROBE0(futex, linux_sys_futex,
+ unimplemented_clockswitch);
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return, ENOSYS);
+ return (ENOSYS);
+ }
+
+ error = 0;
+ f = f2 = NULL;
+
+ switch (args->op) {
+ case LINUX_FUTEX_WAIT:
+ args->val3 = FUTEX_BITSET_MATCH_ANY;
+ /* FALLTHROUGH */
+
+ case LINUX_FUTEX_WAIT_BITSET:
+ LIN_SDT_PROBE3(futex, linux_sys_futex, debug_wait, args->uaddr,
+ args->val, args->val3);
+ LINUX_CTR3(sys_futex, "WAIT uaddr %p val %d val3 %d",
+ args->uaddr, args->val, args->val3);
+
+ error = futex_get(args->uaddr, &wp, &f,
+ flags | FUTEX_CREATE_WP);
+ if (error) {
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return, error);
+ return (error);
+ }
+
+ error = copyin(args->uaddr, &val, sizeof(val));
+ if (error) {
+ LIN_SDT_PROBE1(futex, linux_sys_futex, copyin_error,
+ error);
+ LINUX_CTR1(sys_futex, "WAIT copyin failed %d",
+ error);
+ futex_put(f, wp);
+
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return, error);
+ return (error);
+ }
+ if (val != args->val) {
+ LIN_SDT_PROBE4(futex, linux_sys_futex,
+ debug_wait_value_neq, args->uaddr, args->val, val,
+ args->val3);
+ LINUX_CTR4(sys_futex,
+ "WAIT uaddr %p val %d != uval %d val3 %d",
+ args->uaddr, args->val, val, args->val3);
+ futex_put(f, wp);
+
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return,
+ EWOULDBLOCK);
+ return (EWOULDBLOCK);
+ }
+
+ error = futex_wait(f, wp, args->timeout, args->val3);
+ break;
+
+ case LINUX_FUTEX_WAKE:
+ args->val3 = FUTEX_BITSET_MATCH_ANY;
+ /* FALLTHROUGH */
+
+ case LINUX_FUTEX_WAKE_BITSET:
+ LIN_SDT_PROBE3(futex, linux_sys_futex, debug_wake, args->uaddr,
+ args->val, args->val3);
+ LINUX_CTR3(sys_futex, "WAKE uaddr %p val % d val3 %d",
+ args->uaddr, args->val, args->val3);
+
+ error = futex_get(args->uaddr, NULL, &f,
+ flags | FUTEX_DONTCREATE);
+ if (error) {
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return, error);
+ return (error);
+ }
+
+ if (f == NULL) {
+ td->td_retval[0] = 0;
+
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return, error);
+ return (error);
+ }
+ td->td_retval[0] = futex_wake(f, args->val, args->val3);
+ futex_put(f, NULL);
+ break;
+
+ case LINUX_FUTEX_CMP_REQUEUE:
+ LIN_SDT_PROBE5(futex, linux_sys_futex, debug_cmp_requeue,
+ args->uaddr, args->val, args->val3, args->uaddr2,
+ args->timeout);
+ LINUX_CTR5(sys_futex, "CMP_REQUEUE uaddr %p "
+ "val %d val3 %d uaddr2 %p val2 %d",
+ args->uaddr, args->val, args->val3, args->uaddr2,
+ (int)(unsigned long)args->timeout);
+
+ /*
+ * Linux allows this, we would not, it is an incorrect
+ * usage of declared ABI, so return EINVAL.
+ */
+ if (args->uaddr == args->uaddr2) {
+ LIN_SDT_PROBE0(futex, linux_sys_futex,
+ invalid_cmp_requeue_use);
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return, EINVAL);
+ return (EINVAL);
+ }
+
+ error = futex_get(args->uaddr, NULL, &f, flags);
+ if (error) {
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return, error);
+ return (error);
+ }
+
+ /*
+ * To avoid deadlocks return EINVAL if second futex
+ * exists at this time.
+ *
+ * Glibc fall back to FUTEX_WAKE in case of any error
+ * returned by FUTEX_CMP_REQUEUE.
+ */
+ error = futex_get(args->uaddr2, NULL, &f2,
+ flags | FUTEX_DONTEXISTS);
+ if (error) {
+ futex_put(f, NULL);
+
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return, error);
+ return (error);
+ }
+ error = copyin(args->uaddr, &val, sizeof(val));
+ if (error) {
+ LIN_SDT_PROBE1(futex, linux_sys_futex, copyin_error,
+ error);
+ LINUX_CTR1(sys_futex, "CMP_REQUEUE copyin failed %d",
+ error);
+ futex_put(f2, NULL);
+ futex_put(f, NULL);
+
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return, error);
+ return (error);
+ }
+ if (val != args->val3) {
+ LIN_SDT_PROBE2(futex, linux_sys_futex,
+ debug_cmp_requeue_value_neq, args->val, val);
+ LINUX_CTR2(sys_futex, "CMP_REQUEUE val %d != uval %d",
+ args->val, val);
+ futex_put(f2, NULL);
+ futex_put(f, NULL);
+
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return, EAGAIN);
+ return (EAGAIN);
+ }
+
+ nrwake = (int)(unsigned long)args->timeout;
+ td->td_retval[0] = futex_requeue(f, args->val, f2, nrwake);
+ futex_put(f2, NULL);
+ futex_put(f, NULL);
+ break;
+
+ case LINUX_FUTEX_WAKE_OP:
+ LIN_SDT_PROBE5(futex, linux_sys_futex, debug_wake_op,
+ args->uaddr, args->op, args->val, args->uaddr2, args->val3);
+ LINUX_CTR5(sys_futex, "WAKE_OP "
+ "uaddr %p op %d val %x uaddr2 %p val3 %x",
+ args->uaddr, args->op, args->val,
+ args->uaddr2, args->val3);
+
+ error = futex_get(args->uaddr, NULL, &f, flags);
+ if (error) {
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return, error);
+ return (error);
+ }
+
+ if (args->uaddr != args->uaddr2)
+ error = futex_get(args->uaddr2, NULL, &f2, flags);
+ if (error) {
+ futex_put(f, NULL);
+
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return, error);
+ return (error);
+ }
+
+ /*
+ * This function returns positive number as results and
+ * negative as errors
+ */
+ op_ret = futex_atomic_op(td, args->val3, args->uaddr2);
+
+ if (op_ret < 0) {
+ /* XXX: We don't handle the EFAULT yet. */
+ if (op_ret != -EFAULT) {
+ if (f2 != NULL)
+ futex_put(f2, NULL);
+ futex_put(f, NULL);
+
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return,
+ -op_ret);
+ return (-op_ret);
+ } else {
+ LIN_SDT_PROBE0(futex, linux_sys_futex,
+ unhandled_efault);
+ }
+ if (f2 != NULL)
+ futex_put(f2, NULL);
+ futex_put(f, NULL);
+
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return, EFAULT);
+ return (EFAULT);
+ }
+
+ ret = futex_wake(f, args->val, args->val3);
+
+ if (op_ret > 0) {
+ op_ret = 0;
+ nrwake = (int)(unsigned long)args->timeout;
+
+ if (f2 != NULL)
+ op_ret += futex_wake(f2, nrwake, args->val3);
+ else
+ op_ret += futex_wake(f, nrwake, args->val3);
+ ret += op_ret;
+
+ }
+ if (f2 != NULL)
+ futex_put(f2, NULL);
+ futex_put(f, NULL);
+ td->td_retval[0] = ret;
+ break;
+
+ case LINUX_FUTEX_LOCK_PI:
+ /* not yet implemented */
+ linux_msg(td,
+ "linux_sys_futex: "
+ "op LINUX_FUTEX_LOCK_PI not implemented\n");
+ LIN_SDT_PROBE0(futex, linux_sys_futex, unimplemented_lock_pi);
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return, ENOSYS);
+ return (ENOSYS);
+
+ case LINUX_FUTEX_UNLOCK_PI:
+ /* not yet implemented */
+ linux_msg(td,
+ "linux_sys_futex: "
+ "op LINUX_FUTEX_UNLOCK_PI not implemented\n");
+ LIN_SDT_PROBE0(futex, linux_sys_futex, unimplemented_unlock_pi);
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return, ENOSYS);
+ return (ENOSYS);
+
+ case LINUX_FUTEX_TRYLOCK_PI:
+ /* not yet implemented */
+ linux_msg(td,
+ "linux_sys_futex: "
+ "op LINUX_FUTEX_TRYLOCK_PI not implemented\n");
+ LIN_SDT_PROBE0(futex, linux_sys_futex,
+ unimplemented_trylock_pi);
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return, ENOSYS);
+ return (ENOSYS);
+
+ case LINUX_FUTEX_REQUEUE:
+
+ /*
+ * Glibc does not use this operation since version 2.3.3,
+ * as it is racy and replaced by FUTEX_CMP_REQUEUE operation.
+ * Glibc versions prior to 2.3.3 fall back to FUTEX_WAKE when
+ * FUTEX_REQUEUE returned EINVAL.
+ */
+ em = em_find(td->td_proc, EMUL_DONTLOCK);
+ if ((em->flags & LINUX_XDEPR_REQUEUEOP) == 0) {
+ linux_msg(td,
+ "linux_sys_futex: "
+ "unsupported futex_requeue op\n");
+ em->flags |= LINUX_XDEPR_REQUEUEOP;
+ LIN_SDT_PROBE0(futex, linux_sys_futex,
+ deprecated_requeue);
+ }
+
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return, EINVAL);
+ return (EINVAL);
+
+ case LINUX_FUTEX_WAIT_REQUEUE_PI:
+ /* not yet implemented */
+ linux_msg(td,
+ "linux_sys_futex: "
+ "op FUTEX_WAIT_REQUEUE_PI not implemented\n");
+ LIN_SDT_PROBE0(futex, linux_sys_futex,
+ unimplemented_wait_requeue_pi);
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return, ENOSYS);
+ return (ENOSYS);
+
+ case LINUX_FUTEX_CMP_REQUEUE_PI:
+ /* not yet implemented */
+ linux_msg(td,
+ "linux_sys_futex: "
+ "op LINUX_FUTEX_CMP_REQUEUE_PI not implemented\n");
+ LIN_SDT_PROBE0(futex, linux_sys_futex,
+ unimplemented_cmp_requeue_pi);
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return, ENOSYS);
+ return (ENOSYS);
+
+ default:
+ linux_msg(td,
+ "linux_sys_futex: unknown op %d\n", args->op);
+ LIN_SDT_PROBE1(futex, linux_sys_futex, unknown_operation,
+ args->op);
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return, ENOSYS);
+ return (ENOSYS);
+ }
+
+ LIN_SDT_PROBE1(futex, linux_sys_futex, return, error);
+ return (error);
+}
+
+int
+linux_set_robust_list(struct thread *td, struct linux_set_robust_list_args *args)
+{
+ struct linux_emuldata *em;
+
+ LIN_SDT_PROBE2(futex, linux_set_robust_list, entry, td, args);
+
+ if (args->len != sizeof(struct linux_robust_list_head)) {
+ LIN_SDT_PROBE0(futex, linux_set_robust_list, size_error);
+ LIN_SDT_PROBE1(futex, linux_set_robust_list, return, EINVAL);
+ return (EINVAL);
+ }
+
+ em = em_find(td->td_proc, EMUL_DOLOCK);
+ em->robust_futexes = args->head;
+ EMUL_UNLOCK(&emul_lock);
+
+ LIN_SDT_PROBE1(futex, linux_set_robust_list, return, 0);
+ return (0);
+}
+
+int
+linux_get_robust_list(struct thread *td, struct linux_get_robust_list_args *args)
+{
+ struct linux_emuldata *em;
+ struct linux_robust_list_head *head;
+ l_size_t len = sizeof(struct linux_robust_list_head);
+ int error = 0;
+
+ LIN_SDT_PROBE2(futex, linux_get_robust_list, entry, td, args);
+
+ if (!args->pid) {
+ em = em_find(td->td_proc, EMUL_DONTLOCK);
+ head = em->robust_futexes;
+ } else {
+ struct proc *p;
+
+ p = pfind(args->pid);
+ if (p == NULL) {
+ LIN_SDT_PROBE1(futex, linux_get_robust_list, return,
+ ESRCH);
+ return (ESRCH);
+ }
+
+ em = em_find(p, EMUL_DONTLOCK);
+ /* XXX: ptrace? */
+ if (priv_check(td, PRIV_CRED_SETUID) ||
+ priv_check(td, PRIV_CRED_SETEUID) ||
+ p_candebug(td, p)) {
+ PROC_UNLOCK(p);
+
+ LIN_SDT_PROBE1(futex, linux_get_robust_list, return,
+ EPERM);
+ return (EPERM);
+ }
+ head = em->robust_futexes;
+
+ PROC_UNLOCK(p);
+ }
+
+ error = copyout(&len, args->len, sizeof(l_size_t));
+ if (error) {
+ LIN_SDT_PROBE1(futex, linux_get_robust_list, copyout_error,
+ error);
+ LIN_SDT_PROBE1(futex, linux_get_robust_list, return, EFAULT);
+ return (EFAULT);
+ }
+
+ error = copyout(head, args->head, sizeof(struct linux_robust_list_head));
+ if (error) {
+ LIN_SDT_PROBE1(futex, linux_get_robust_list, copyout_error,
+ error);
+ }
+
+ LIN_SDT_PROBE1(futex, linux_get_robust_list, return, error);
+ return (error);
+}
+
+static int
+handle_futex_death(struct proc *p, uint32_t *uaddr, int pi)
+{
+ uint32_t uval, nval, mval;
+ struct futex *f;
+ int error;
+
+ LIN_SDT_PROBE3(futex, handle_futex_death, entry, p, uaddr, pi);
+
+retry:
+ error = copyin(uaddr, &uval, 4);
+ if (error) {
+ LIN_SDT_PROBE1(futex, handle_futex_death, copyin_error, error);
+ LIN_SDT_PROBE1(futex, handle_futex_death, return, EFAULT);
+ return (EFAULT);
+ }
+ if ((uval & FUTEX_TID_MASK) == p->p_pid) {
+ mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
+ nval = casuword32(uaddr, uval, mval);
+
+ if (nval == -1) {
+ LIN_SDT_PROBE1(futex, handle_futex_death, return,
+ EFAULT);
+ return (EFAULT);
+ }
+
+ if (nval != uval)
+ goto retry;
+
+ if (!pi && (uval & FUTEX_WAITERS)) {
+ error = futex_get(uaddr, NULL, &f,
+ FUTEX_DONTCREATE | FUTEX_SHARED);
+ if (error) {
+ LIN_SDT_PROBE1(futex, handle_futex_death,
+ return, error);
+ return (error);
+ }
+ if (f != NULL) {
+ futex_wake(f, 1, FUTEX_BITSET_MATCH_ANY);
+ futex_put(f, NULL);
+ }
+ }
+ }
+
+ LIN_SDT_PROBE1(futex, handle_futex_death, return, 0);
+ return (0);
+}
+
+static int
+fetch_robust_entry(struct linux_robust_list **entry,
+ struct linux_robust_list **head, int *pi)
+{
+ l_ulong uentry;
+ int error;
+
+ LIN_SDT_PROBE3(futex, fetch_robust_entry, entry, entry, head, pi);
+
+ error = copyin((const void *)head, &uentry, sizeof(l_ulong));
+ if (error) {
+ LIN_SDT_PROBE1(futex, fetch_robust_entry, copyin_error, error);
+ LIN_SDT_PROBE1(futex, fetch_robust_entry, return, EFAULT);
+ return (EFAULT);
+ }
+
+ *entry = (void *)(uentry & ~1UL);
+ *pi = uentry & 1;
+
+ LIN_SDT_PROBE1(futex, fetch_robust_entry, return, 0);
+ return (0);
+}
+
+/* This walks the list of robust futexes releasing them. */
+void
+release_futexes(struct proc *p)
+{
+ struct linux_robust_list_head *head = NULL;
+ struct linux_robust_list *entry, *next_entry, *pending;
+ unsigned int limit = 2048, pi, next_pi, pip;
+ struct linux_emuldata *em;
+ l_long futex_offset;
+ int rc, error;
+
+ LIN_SDT_PROBE1(futex, release_futexes, entry, p);
+
+ em = em_find(p, EMUL_DONTLOCK);
+ head = em->robust_futexes;
+
+ if (head == NULL) {
+ LIN_SDT_PROBE0(futex, release_futexes, return);
+ return;
+ }
+
+ if (fetch_robust_entry(&entry, PTRIN(&head->list.next), &pi)) {
+ LIN_SDT_PROBE0(futex, release_futexes, return);
+ return;
+ }
+
+ error = copyin(&head->futex_offset, &futex_offset,
+ sizeof(futex_offset));
+ if (error) {
+ LIN_SDT_PROBE1(futex, release_futexes, copyin_error, error);
+ LIN_SDT_PROBE0(futex, release_futexes, return);
+ return;
+ }
+
+ if (fetch_robust_entry(&pending, PTRIN(&head->pending_list), &pip)) {
+ LIN_SDT_PROBE0(futex, release_futexes, return);
+ return;
+ }
+
+ while (entry != &head->list) {
+ rc = fetch_robust_entry(&next_entry, PTRIN(&entry->next), &next_pi);
+
+ if (entry != pending)
+ if (handle_futex_death(p,
+ (uint32_t *)((caddr_t)entry + futex_offset), pi)) {
+ LIN_SDT_PROBE0(futex, release_futexes, return);
+ return;
+ }
+ if (rc) {
+ LIN_SDT_PROBE0(futex, release_futexes, return);
+ return;
+ }
+
+ entry = next_entry;
+ pi = next_pi;
+
+ if (!--limit)
+ break;
+
+ sched_relinquish(curthread);
+ }
+
+ if (pending)
+ handle_futex_death(p, (uint32_t *)((caddr_t)pending + futex_offset), pip);
+
+ LIN_SDT_PROBE0(futex, release_futexes, return);
+}
diff --git a/sys/compat/linux/linux_futex.h b/sys/compat/linux/linux_futex.h
new file mode 100644
index 0000000..0990daa
--- /dev/null
+++ b/sys/compat/linux/linux_futex.h
@@ -0,0 +1,81 @@
+/* $NetBSD: linux_futex.h,v 1.2 2005/12/11 12:20:19 christos Exp $ */
+
+/*-
+ * Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Emmanuel Dreyfus
+ * 4. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE THE AUTHOR AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LINUX_FUTEX_H
+#define _LINUX_FUTEX_H
+
+extern LIST_HEAD(futex_list, futex) futex_list;
+extern struct mtx futex_mtx;
+
+#define LINUX_FUTEX_WAIT 0
+#define LINUX_FUTEX_WAKE 1
+#define LINUX_FUTEX_FD 2 /* unused */
+#define LINUX_FUTEX_REQUEUE 3
+#define LINUX_FUTEX_CMP_REQUEUE 4
+#define LINUX_FUTEX_WAKE_OP 5
+#define LINUX_FUTEX_LOCK_PI 6
+#define LINUX_FUTEX_UNLOCK_PI 7
+#define LINUX_FUTEX_TRYLOCK_PI 8
+#define LINUX_FUTEX_WAIT_BITSET 9
+#define LINUX_FUTEX_WAKE_BITSET 10
+#define LINUX_FUTEX_WAIT_REQUEUE_PI 11
+#define LINUX_FUTEX_CMP_REQUEUE_PI 12
+
+#define LINUX_FUTEX_PRIVATE_FLAG 128
+#define LINUX_FUTEX_CLOCK_REALTIME 256
+
+#define FUTEX_OP_SET 0 /* *(int *)UADDR2 = OPARG; */
+#define FUTEX_OP_ADD 1 /* *(int *)UADDR2 += OPARG; */
+#define FUTEX_OP_OR 2 /* *(int *)UADDR2 |= OPARG; */
+#define FUTEX_OP_ANDN 3 /* *(int *)UADDR2 &= ~OPARG; */
+#define FUTEX_OP_XOR 4 /* *(int *)UADDR2 ^= OPARG; */
+
+#define FUTEX_OP_OPARG_SHIFT 8 /* Use (1 << OPARG) instead of OPARG. */
+
+#define FUTEX_OP_CMP_EQ 0 /* if (oldval == CMPARG) wake */
+#define FUTEX_OP_CMP_NE 1 /* if (oldval != CMPARG) wake */
+#define FUTEX_OP_CMP_LT 2 /* if (oldval < CMPARG) wake */
+#define FUTEX_OP_CMP_LE 3 /* if (oldval <= CMPARG) wake */
+#define FUTEX_OP_CMP_GT 4 /* if (oldval > CMPARG) wake */
+#define FUTEX_OP_CMP_GE 5 /* if (oldval >= CMPARG) wake */
+
+#define FUTEX_WAITERS 0x80000000
+#define FUTEX_OWNER_DIED 0x40000000
+#define FUTEX_TID_MASK 0x3fffffff
+#define FUTEX_BITSET_MATCH_ANY 0xffffffff
+
+void release_futexes(struct proc *);
+
+#endif /* !_LINUX_FUTEX_H */
diff --git a/sys/compat/linux/linux_getcwd.c b/sys/compat/linux/linux_getcwd.c
new file mode 100644
index 0000000..cad5a22
--- /dev/null
+++ b/sys/compat/linux/linux_getcwd.c
@@ -0,0 +1,469 @@
+/* $OpenBSD: linux_getcwd.c,v 1.2 2001/05/16 12:50:21 ho Exp $ */
+/* $NetBSD: vfs_getcwd.c,v 1.3.2.3 1999/07/11 10:24:09 sommerfeld Exp $ */
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Bill Sommerfeld.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_compat.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/namei.h>
+#include <sys/filedesc.h>
+#include <sys/kernel.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/syscallsubr.h>
+#include <sys/vnode.h>
+#include <sys/mount.h>
+#include <sys/proc.h>
+#include <sys/uio.h>
+#include <sys/malloc.h>
+#include <sys/dirent.h>
+#include <ufs/ufs/dir.h> /* XXX only for DIRBLKSIZ */
+
+#ifdef COMPAT_LINUX32
+#include <machine/../linux32/linux.h>
+#include <machine/../linux32/linux32_proto.h>
+#else
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#endif
+#include <compat/linux/linux_util.h>
+
+#include <security/mac/mac_framework.h>
+
+static int
+linux_getcwd_scandir(struct vnode **, struct vnode **,
+ char **, char *, struct thread *);
+static int
+linux_getcwd_common(struct vnode *, struct vnode *,
+ char **, char *, int, int, struct thread *);
+
+#define DIRENT_MINSIZE (sizeof(struct dirent) - (MAXNAMLEN+1) + 4)
+
+/*
+ * Vnode variable naming conventions in this file:
+ *
+ * rvp: the current root we're aiming towards.
+ * lvp, *lvpp: the "lower" vnode
+ * uvp, *uvpp: the "upper" vnode.
+ *
+ * Since all the vnodes we're dealing with are directories, and the
+ * lookups are going *up* in the filesystem rather than *down*, the
+ * usual "pvp" (parent) or "dvp" (directory) naming conventions are
+ * too confusing.
+ */
+
+/*
+ * XXX Will infinite loop in certain cases if a directory read reliably
+ * returns EINVAL on last block.
+ * XXX is EINVAL the right thing to return if a directory is malformed?
+ */
+
+/*
+ * XXX Untested vs. mount -o union; probably does the wrong thing.
+ */
+
+/*
+ * Find parent vnode of *lvpp, return in *uvpp
+ *
+ * If we care about the name, scan it looking for name of directory
+ * entry pointing at lvp.
+ *
+ * Place the name in the buffer which starts at bufp, immediately
+ * before *bpp, and move bpp backwards to point at the start of it.
+ *
+ * On entry, *lvpp is a locked vnode reference; on exit, it is vput and NULL'ed
+ * On exit, *uvpp is either NULL or is a locked vnode reference.
+ */
+static int
+linux_getcwd_scandir(lvpp, uvpp, bpp, bufp, td)
+ struct vnode **lvpp;
+ struct vnode **uvpp;
+ char **bpp;
+ char *bufp;
+ struct thread *td;
+{
+ int error = 0;
+ int eofflag;
+ off_t off;
+ int tries;
+ struct uio uio;
+ struct iovec iov;
+ char *dirbuf = NULL;
+ int dirbuflen;
+ ino_t fileno;
+ struct vattr va;
+ struct vnode *uvp = NULL;
+ struct vnode *lvp = *lvpp;
+ struct componentname cn;
+ int len, reclen;
+ tries = 0;
+
+ /*
+ * If we want the filename, get some info we need while the
+ * current directory is still locked.
+ */
+ if (bufp != NULL) {
+ error = VOP_GETATTR(lvp, &va, td->td_ucred);
+ if (error) {
+ vput(lvp);
+ *lvpp = NULL;
+ *uvpp = NULL;
+ return error;
+ }
+ }
+
+ /*
+ * Ok, we have to do it the hard way..
+ * Next, get parent vnode using lookup of ..
+ */
+ cn.cn_nameiop = LOOKUP;
+ cn.cn_flags = ISLASTCN | ISDOTDOT | RDONLY;
+ cn.cn_thread = td;
+ cn.cn_cred = td->td_ucred;
+ cn.cn_pnbuf = NULL;
+ cn.cn_nameptr = "..";
+ cn.cn_namelen = 2;
+ cn.cn_consume = 0;
+ cn.cn_lkflags = LK_SHARED;
+
+ /*
+ * At this point, lvp is locked and will be unlocked by the lookup.
+ * On successful return, *uvpp will be locked
+ */
+#ifdef MAC
+ error = mac_vnode_check_lookup(td->td_ucred, lvp, &cn);
+ if (error == 0)
+#endif
+ error = VOP_LOOKUP(lvp, uvpp, &cn);
+ if (error) {
+ vput(lvp);
+ *lvpp = NULL;
+ *uvpp = NULL;
+ return error;
+ }
+ uvp = *uvpp;
+
+ /* If we don't care about the pathname, we're done */
+ if (bufp == NULL) {
+ vput(lvp);
+ *lvpp = NULL;
+ return 0;
+ }
+
+ fileno = va.va_fileid;
+
+ dirbuflen = DIRBLKSIZ;
+ if (dirbuflen < va.va_blocksize)
+ dirbuflen = va.va_blocksize;
+ dirbuf = (char *)malloc(dirbuflen, M_TEMP, M_WAITOK);
+
+#if 0
+unionread:
+#endif
+ off = 0;
+ do {
+ /* call VOP_READDIR of parent */
+ iov.iov_base = dirbuf;
+ iov.iov_len = dirbuflen;
+
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_offset = off;
+ uio.uio_resid = dirbuflen;
+ uio.uio_segflg = UIO_SYSSPACE;
+ uio.uio_rw = UIO_READ;
+ uio.uio_td = td;
+
+ eofflag = 0;
+
+#ifdef MAC
+ error = mac_vnode_check_readdir(td->td_ucred, uvp);
+ if (error == 0)
+#endif /* MAC */
+ error = VOP_READDIR(uvp, &uio, td->td_ucred, &eofflag,
+ 0, 0);
+
+ off = uio.uio_offset;
+
+ /*
+ * Try again if NFS tosses its cookies.
+ * XXX this can still loop forever if the directory is busted
+ * such that the second or subsequent page of it always
+ * returns EINVAL
+ */
+ if ((error == EINVAL) && (tries < 3)) {
+ off = 0;
+ tries++;
+ continue; /* once more, with feeling */
+ }
+
+ if (!error) {
+ char *cpos;
+ struct dirent *dp;
+
+ cpos = dirbuf;
+ tries = 0;
+
+ /* scan directory page looking for matching vnode */
+ for (len = (dirbuflen - uio.uio_resid); len > 0; len -= reclen) {
+ dp = (struct dirent *) cpos;
+ reclen = dp->d_reclen;
+
+ /* check for malformed directory.. */
+ if (reclen < DIRENT_MINSIZE) {
+ error = EINVAL;
+ goto out;
+ }
+ /*
+ * XXX should perhaps do VOP_LOOKUP to
+ * check that we got back to the right place,
+ * but getting the locking games for that
+ * right would be heinous.
+ */
+ if ((dp->d_type != DT_WHT) &&
+ (dp->d_fileno == fileno)) {
+ char *bp = *bpp;
+ bp -= dp->d_namlen;
+
+ if (bp <= bufp) {
+ error = ERANGE;
+ goto out;
+ }
+ bcopy(dp->d_name, bp, dp->d_namlen);
+ error = 0;
+ *bpp = bp;
+ goto out;
+ }
+ cpos += reclen;
+ }
+ }
+ } while (!eofflag);
+ error = ENOENT;
+
+out:
+ vput(lvp);
+ *lvpp = NULL;
+ free(dirbuf, M_TEMP);
+ return error;
+}
+
+
+/*
+ * common routine shared by sys___getcwd() and linux_vn_isunder()
+ */
+
+#define GETCWD_CHECK_ACCESS 0x0001
+
+static int
+linux_getcwd_common (lvp, rvp, bpp, bufp, limit, flags, td)
+ struct vnode *lvp;
+ struct vnode *rvp;
+ char **bpp;
+ char *bufp;
+ int limit;
+ int flags;
+ struct thread *td;
+{
+ struct filedesc *fdp = td->td_proc->p_fd;
+ struct vnode *uvp = NULL;
+ char *bp = NULL;
+ int error;
+ accmode_t accmode = VEXEC;
+
+ if (rvp == NULL) {
+ rvp = fdp->fd_rdir;
+ if (rvp == NULL)
+ rvp = rootvnode;
+ }
+
+ VREF(rvp);
+ VREF(lvp);
+
+ /*
+ * Error handling invariant:
+ * Before a `goto out':
+ * lvp is either NULL, or locked and held.
+ * uvp is either NULL, or locked and held.
+ */
+
+ error = vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY);
+ if (error != 0)
+ panic("vn_lock LK_RETRY returned error %d", error);
+ if (bufp)
+ bp = *bpp;
+ /*
+ * this loop will terminate when one of the following happens:
+ * - we hit the root
+ * - getdirentries or lookup fails
+ * - we run out of space in the buffer.
+ */
+ if (lvp == rvp) {
+ if (bp)
+ *(--bp) = '/';
+ goto out;
+ }
+ do {
+ if (lvp->v_type != VDIR) {
+ error = ENOTDIR;
+ goto out;
+ }
+
+ /*
+ * access check here is optional, depending on
+ * whether or not caller cares.
+ */
+ if (flags & GETCWD_CHECK_ACCESS) {
+ error = VOP_ACCESS(lvp, accmode, td->td_ucred, td);
+ if (error)
+ goto out;
+ accmode = VEXEC|VREAD;
+ }
+
+ /*
+ * step up if we're a covered vnode..
+ */
+ while (lvp->v_vflag & VV_ROOT) {
+ struct vnode *tvp;
+
+ if (lvp == rvp)
+ goto out;
+
+ tvp = lvp;
+ lvp = lvp->v_mount->mnt_vnodecovered;
+ vput(tvp);
+ /*
+ * hodie natus est radici frater
+ */
+ if (lvp == NULL) {
+ error = ENOENT;
+ goto out;
+ }
+ VREF(lvp);
+ error = vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY);
+ if (error != 0)
+ panic("vn_lock LK_RETRY returned %d", error);
+ }
+ error = linux_getcwd_scandir(&lvp, &uvp, &bp, bufp, td);
+ if (error)
+ goto out;
+#ifdef DIAGNOSTIC
+ if (lvp != NULL)
+ panic("getcwd: oops, forgot to null lvp");
+ if (bufp && (bp <= bufp)) {
+ panic("getcwd: oops, went back too far");
+ }
+#endif
+ if (bp)
+ *(--bp) = '/';
+ lvp = uvp;
+ uvp = NULL;
+ limit--;
+ } while ((lvp != rvp) && (limit > 0));
+
+out:
+ if (bpp)
+ *bpp = bp;
+ if (uvp)
+ vput(uvp);
+ if (lvp)
+ vput(lvp);
+ vrele(rvp);
+ return error;
+}
+
+
+/*
+ * Find pathname of process's current directory.
+ *
+ * Use vfs vnode-to-name reverse cache; if that fails, fall back
+ * to reading directory contents.
+ */
+
+int
+linux_getcwd(struct thread *td, struct linux_getcwd_args *args)
+{
+ caddr_t bp, bend, path;
+ int error, len, lenused;
+
+#ifdef DEBUG
+ if (ldebug(getcwd))
+ printf(ARGS(getcwd, "%p, %ld"), args->buf, (long)args->bufsize);
+#endif
+
+ len = args->bufsize;
+
+ if (len > MAXPATHLEN*4)
+ len = MAXPATHLEN*4;
+ else if (len < 2)
+ return ERANGE;
+
+ path = (char *)malloc(len, M_TEMP, M_WAITOK);
+
+ error = kern___getcwd(td, path, UIO_SYSSPACE, len);
+ if (!error) {
+ lenused = strlen(path) + 1;
+ if (lenused <= args->bufsize) {
+ td->td_retval[0] = lenused;
+ error = copyout(path, args->buf, lenused);
+ }
+ else
+ error = ERANGE;
+ } else {
+ bp = &path[len];
+ bend = bp;
+ *(--bp) = '\0';
+
+ /*
+ * 5th argument here is "max number of vnodes to traverse".
+ * Since each entry takes up at least 2 bytes in the output buffer,
+ * limit it to N/2 vnodes for an N byte buffer.
+ */
+
+ mtx_lock(&Giant);
+ error = linux_getcwd_common (td->td_proc->p_fd->fd_cdir, NULL,
+ &bp, path, len/2, GETCWD_CHECK_ACCESS, td);
+ mtx_unlock(&Giant);
+
+ if (error)
+ goto out;
+ lenused = bend - bp;
+ td->td_retval[0] = lenused;
+ /* put the result into user buffer */
+ error = copyout(bp, args->buf, lenused);
+ }
+out:
+ free(path, M_TEMP);
+ return (error);
+}
+
diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c
new file mode 100644
index 0000000..192b9fd
--- /dev/null
+++ b/sys/compat/linux/linux_ioctl.c
@@ -0,0 +1,3532 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opt_compat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysproto.h>
+#include <sys/capability.h>
+#include <sys/cdio.h>
+#include <sys/dvdio.h>
+#include <sys/conf.h>
+#include <sys/disk.h>
+#include <sys/consio.h>
+#include <sys/ctype.h>
+#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/filio.h>
+#include <sys/jail.h>
+#include <sys/kbio.h>
+#include <sys/kernel.h>
+#include <sys/linker_set.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/sbuf.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/soundcard.h>
+#include <sys/stdint.h>
+#include <sys/sx.h>
+#include <sys/sysctl.h>
+#include <sys/tty.h>
+#include <sys/uio.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/resourcevar.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/vnet.h>
+
+#include <dev/usb/usb_ioctl.h>
+
+#ifdef COMPAT_LINUX32
+#include <machine/../linux32/linux.h>
+#include <machine/../linux32/linux32_proto.h>
+#else
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#endif
+
+#include <compat/linux/linux_ioctl.h>
+#include <compat/linux/linux_mib.h>
+#include <compat/linux/linux_socket.h>
+#include <compat/linux/linux_util.h>
+
+#include <contrib/v4l/videodev.h>
+#include <compat/linux/linux_videodev_compat.h>
+
+#include <contrib/v4l/videodev2.h>
+#include <compat/linux/linux_videodev2_compat.h>
+
+CTASSERT(LINUX_IFNAMSIZ == IFNAMSIZ);
+
+FEATURE(linuxulator_v4l, "V4L ioctl wrapper support in the linuxulator");
+FEATURE(linuxulator_v4l2, "V4L2 ioctl wrapper support in the linuxulator");
+
+static linux_ioctl_function_t linux_ioctl_cdrom;
+static linux_ioctl_function_t linux_ioctl_vfat;
+static linux_ioctl_function_t linux_ioctl_console;
+static linux_ioctl_function_t linux_ioctl_hdio;
+static linux_ioctl_function_t linux_ioctl_disk;
+static linux_ioctl_function_t linux_ioctl_socket;
+static linux_ioctl_function_t linux_ioctl_sound;
+static linux_ioctl_function_t linux_ioctl_termio;
+static linux_ioctl_function_t linux_ioctl_private;
+static linux_ioctl_function_t linux_ioctl_drm;
+static linux_ioctl_function_t linux_ioctl_sg;
+static linux_ioctl_function_t linux_ioctl_v4l;
+static linux_ioctl_function_t linux_ioctl_v4l2;
+static linux_ioctl_function_t linux_ioctl_special;
+static linux_ioctl_function_t linux_ioctl_fbsd_usb;
+
+static struct linux_ioctl_handler cdrom_handler =
+{ linux_ioctl_cdrom, LINUX_IOCTL_CDROM_MIN, LINUX_IOCTL_CDROM_MAX };
+static struct linux_ioctl_handler vfat_handler =
+{ linux_ioctl_vfat, LINUX_IOCTL_VFAT_MIN, LINUX_IOCTL_VFAT_MAX };
+static struct linux_ioctl_handler console_handler =
+{ linux_ioctl_console, LINUX_IOCTL_CONSOLE_MIN, LINUX_IOCTL_CONSOLE_MAX };
+static struct linux_ioctl_handler hdio_handler =
+{ linux_ioctl_hdio, LINUX_IOCTL_HDIO_MIN, LINUX_IOCTL_HDIO_MAX };
+static struct linux_ioctl_handler disk_handler =
+{ linux_ioctl_disk, LINUX_IOCTL_DISK_MIN, LINUX_IOCTL_DISK_MAX };
+static struct linux_ioctl_handler socket_handler =
+{ linux_ioctl_socket, LINUX_IOCTL_SOCKET_MIN, LINUX_IOCTL_SOCKET_MAX };
+static struct linux_ioctl_handler sound_handler =
+{ linux_ioctl_sound, LINUX_IOCTL_SOUND_MIN, LINUX_IOCTL_SOUND_MAX };
+static struct linux_ioctl_handler termio_handler =
+{ linux_ioctl_termio, LINUX_IOCTL_TERMIO_MIN, LINUX_IOCTL_TERMIO_MAX };
+static struct linux_ioctl_handler private_handler =
+{ linux_ioctl_private, LINUX_IOCTL_PRIVATE_MIN, LINUX_IOCTL_PRIVATE_MAX };
+static struct linux_ioctl_handler drm_handler =
+{ linux_ioctl_drm, LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX };
+static struct linux_ioctl_handler sg_handler =
+{ linux_ioctl_sg, LINUX_IOCTL_SG_MIN, LINUX_IOCTL_SG_MAX };
+static struct linux_ioctl_handler video_handler =
+{ linux_ioctl_v4l, LINUX_IOCTL_VIDEO_MIN, LINUX_IOCTL_VIDEO_MAX };
+static struct linux_ioctl_handler video2_handler =
+{ linux_ioctl_v4l2, LINUX_IOCTL_VIDEO2_MIN, LINUX_IOCTL_VIDEO2_MAX };
+static struct linux_ioctl_handler fbsd_usb =
+{ linux_ioctl_fbsd_usb, FBSD_LUSB_MIN, FBSD_LUSB_MAX };
+
+DATA_SET(linux_ioctl_handler_set, cdrom_handler);
+DATA_SET(linux_ioctl_handler_set, vfat_handler);
+DATA_SET(linux_ioctl_handler_set, console_handler);
+DATA_SET(linux_ioctl_handler_set, hdio_handler);
+DATA_SET(linux_ioctl_handler_set, disk_handler);
+DATA_SET(linux_ioctl_handler_set, socket_handler);
+DATA_SET(linux_ioctl_handler_set, sound_handler);
+DATA_SET(linux_ioctl_handler_set, termio_handler);
+DATA_SET(linux_ioctl_handler_set, private_handler);
+DATA_SET(linux_ioctl_handler_set, drm_handler);
+DATA_SET(linux_ioctl_handler_set, sg_handler);
+DATA_SET(linux_ioctl_handler_set, video_handler);
+DATA_SET(linux_ioctl_handler_set, video2_handler);
+DATA_SET(linux_ioctl_handler_set, fbsd_usb);
+
+struct handler_element
+{
+ TAILQ_ENTRY(handler_element) list;
+ int (*func)(struct thread *, struct linux_ioctl_args *);
+ int low, high, span;
+};
+
+static TAILQ_HEAD(, handler_element) handlers =
+ TAILQ_HEAD_INITIALIZER(handlers);
+static struct sx linux_ioctl_sx;
+SX_SYSINIT(linux_ioctl, &linux_ioctl_sx, "linux ioctl handlers");
+
+/*
+ * hdio related ioctls for VMWare support
+ */
+
+struct linux_hd_geometry {
+ u_int8_t heads;
+ u_int8_t sectors;
+ u_int16_t cylinders;
+ u_int32_t start;
+};
+
+struct linux_hd_big_geometry {
+ u_int8_t heads;
+ u_int8_t sectors;
+ u_int32_t cylinders;
+ u_int32_t start;
+};
+
+static int
+linux_ioctl_hdio(struct thread *td, struct linux_ioctl_args *args)
+{
+ struct file *fp;
+ int error;
+ u_int sectorsize, fwcylinders, fwheads, fwsectors;
+ off_t mediasize, bytespercyl;
+
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ return (error);
+ switch (args->cmd & 0xffff) {
+ case LINUX_HDIO_GET_GEO:
+ case LINUX_HDIO_GET_GEO_BIG:
+ error = fo_ioctl(fp, DIOCGMEDIASIZE,
+ (caddr_t)&mediasize, td->td_ucred, td);
+ if (!error)
+ error = fo_ioctl(fp, DIOCGSECTORSIZE,
+ (caddr_t)&sectorsize, td->td_ucred, td);
+ if (!error)
+ error = fo_ioctl(fp, DIOCGFWHEADS,
+ (caddr_t)&fwheads, td->td_ucred, td);
+ if (!error)
+ error = fo_ioctl(fp, DIOCGFWSECTORS,
+ (caddr_t)&fwsectors, td->td_ucred, td);
+ /*
+ * XXX: DIOCGFIRSTOFFSET is not yet implemented, so
+ * so pretend that GEOM always says 0. This is NOT VALID
+ * for slices or partitions, only the per-disk raw devices.
+ */
+
+ fdrop(fp, td);
+ if (error)
+ return (error);
+ /*
+ * 1. Calculate the number of bytes in a cylinder,
+ * given the firmware's notion of heads and sectors
+ * per cylinder.
+ * 2. Calculate the number of cylinders, given the total
+ * size of the media.
+ * All internal calculations should have 64-bit precision.
+ */
+ bytespercyl = (off_t) sectorsize * fwheads * fwsectors;
+ fwcylinders = mediasize / bytespercyl;
+#if defined(DEBUG)
+ linux_msg(td, "HDIO_GET_GEO: mediasize %jd, c/h/s %d/%d/%d, "
+ "bpc %jd",
+ (intmax_t)mediasize, fwcylinders, fwheads, fwsectors,
+ (intmax_t)bytespercyl);
+#endif
+ if ((args->cmd & 0xffff) == LINUX_HDIO_GET_GEO) {
+ struct linux_hd_geometry hdg;
+
+ hdg.cylinders = fwcylinders;
+ hdg.heads = fwheads;
+ hdg.sectors = fwsectors;
+ hdg.start = 0;
+ error = copyout(&hdg, (void *)args->arg, sizeof(hdg));
+ } else if ((args->cmd & 0xffff) == LINUX_HDIO_GET_GEO_BIG) {
+ struct linux_hd_big_geometry hdbg;
+
+ hdbg.cylinders = fwcylinders;
+ hdbg.heads = fwheads;
+ hdbg.sectors = fwsectors;
+ hdbg.start = 0;
+ error = copyout(&hdbg, (void *)args->arg, sizeof(hdbg));
+ }
+ return (error);
+ break;
+ default:
+ /* XXX */
+ linux_msg(td,
+ "ioctl fd=%d, cmd=0x%x ('%c',%d) is not implemented",
+ args->fd, (int)(args->cmd & 0xffff),
+ (int)(args->cmd & 0xff00) >> 8,
+ (int)(args->cmd & 0xff));
+ break;
+ }
+ fdrop(fp, td);
+ return (ENOIOCTL);
+}
+
+static int
+linux_ioctl_disk(struct thread *td, struct linux_ioctl_args *args)
+{
+ struct file *fp;
+ int error;
+ u_int sectorsize;
+ off_t mediasize;
+
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ return (error);
+ switch (args->cmd & 0xffff) {
+ case LINUX_BLKGETSIZE:
+ error = fo_ioctl(fp, DIOCGSECTORSIZE,
+ (caddr_t)&sectorsize, td->td_ucred, td);
+ if (!error)
+ error = fo_ioctl(fp, DIOCGMEDIASIZE,
+ (caddr_t)&mediasize, td->td_ucred, td);
+ fdrop(fp, td);
+ if (error)
+ return (error);
+ sectorsize = mediasize / sectorsize;
+ /*
+ * XXX: How do we know we return the right size of integer ?
+ */
+ return (copyout(&sectorsize, (void *)args->arg,
+ sizeof(sectorsize)));
+ break;
+ }
+ fdrop(fp, td);
+ return (ENOIOCTL);
+}
+
+/*
+ * termio related ioctls
+ */
+
+struct linux_termio {
+ unsigned short c_iflag;
+ unsigned short c_oflag;
+ unsigned short c_cflag;
+ unsigned short c_lflag;
+ unsigned char c_line;
+ unsigned char c_cc[LINUX_NCC];
+};
+
+struct linux_termios {
+ unsigned int c_iflag;
+ unsigned int c_oflag;
+ unsigned int c_cflag;
+ unsigned int c_lflag;
+ unsigned char c_line;
+ unsigned char c_cc[LINUX_NCCS];
+};
+
+struct linux_winsize {
+ unsigned short ws_row, ws_col;
+ unsigned short ws_xpixel, ws_ypixel;
+};
+
+struct speedtab {
+ int sp_speed; /* Speed. */
+ int sp_code; /* Code. */
+};
+
+static struct speedtab sptab[] = {
+ { B0, LINUX_B0 }, { B50, LINUX_B50 },
+ { B75, LINUX_B75 }, { B110, LINUX_B110 },
+ { B134, LINUX_B134 }, { B150, LINUX_B150 },
+ { B200, LINUX_B200 }, { B300, LINUX_B300 },
+ { B600, LINUX_B600 }, { B1200, LINUX_B1200 },
+ { B1800, LINUX_B1800 }, { B2400, LINUX_B2400 },
+ { B4800, LINUX_B4800 }, { B9600, LINUX_B9600 },
+ { B19200, LINUX_B19200 }, { B38400, LINUX_B38400 },
+ { B57600, LINUX_B57600 }, { B115200, LINUX_B115200 },
+ {-1, -1 }
+};
+
+struct linux_serial_struct {
+ int type;
+ int line;
+ int port;
+ int irq;
+ int flags;
+ int xmit_fifo_size;
+ int custom_divisor;
+ int baud_base;
+ unsigned short close_delay;
+ char reserved_char[2];
+ int hub6;
+ unsigned short closing_wait;
+ unsigned short closing_wait2;
+ int reserved[4];
+};
+
+static int
+linux_to_bsd_speed(int code, struct speedtab *table)
+{
+ for ( ; table->sp_code != -1; table++)
+ if (table->sp_code == code)
+ return (table->sp_speed);
+ return -1;
+}
+
+static int
+bsd_to_linux_speed(int speed, struct speedtab *table)
+{
+ for ( ; table->sp_speed != -1; table++)
+ if (table->sp_speed == speed)
+ return (table->sp_code);
+ return -1;
+}
+
+static void
+bsd_to_linux_termios(struct termios *bios, struct linux_termios *lios)
+{
+ int i;
+
+#ifdef DEBUG
+ if (ldebug(ioctl)) {
+ printf("LINUX: BSD termios structure (input):\n");
+ printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
+ bios->c_iflag, bios->c_oflag, bios->c_cflag, bios->c_lflag,
+ bios->c_ispeed, bios->c_ospeed);
+ printf("c_cc ");
+ for (i=0; i<NCCS; i++)
+ printf("%02x ", bios->c_cc[i]);
+ printf("\n");
+ }
+#endif
+
+ lios->c_iflag = 0;
+ if (bios->c_iflag & IGNBRK)
+ lios->c_iflag |= LINUX_IGNBRK;
+ if (bios->c_iflag & BRKINT)
+ lios->c_iflag |= LINUX_BRKINT;
+ if (bios->c_iflag & IGNPAR)
+ lios->c_iflag |= LINUX_IGNPAR;
+ if (bios->c_iflag & PARMRK)
+ lios->c_iflag |= LINUX_PARMRK;
+ if (bios->c_iflag & INPCK)
+ lios->c_iflag |= LINUX_INPCK;
+ if (bios->c_iflag & ISTRIP)
+ lios->c_iflag |= LINUX_ISTRIP;
+ if (bios->c_iflag & INLCR)
+ lios->c_iflag |= LINUX_INLCR;
+ if (bios->c_iflag & IGNCR)
+ lios->c_iflag |= LINUX_IGNCR;
+ if (bios->c_iflag & ICRNL)
+ lios->c_iflag |= LINUX_ICRNL;
+ if (bios->c_iflag & IXON)
+ lios->c_iflag |= LINUX_IXON;
+ if (bios->c_iflag & IXANY)
+ lios->c_iflag |= LINUX_IXANY;
+ if (bios->c_iflag & IXOFF)
+ lios->c_iflag |= LINUX_IXOFF;
+ if (bios->c_iflag & IMAXBEL)
+ lios->c_iflag |= LINUX_IMAXBEL;
+
+ lios->c_oflag = 0;
+ if (bios->c_oflag & OPOST)
+ lios->c_oflag |= LINUX_OPOST;
+ if (bios->c_oflag & ONLCR)
+ lios->c_oflag |= LINUX_ONLCR;
+ if (bios->c_oflag & TAB3)
+ lios->c_oflag |= LINUX_XTABS;
+
+ lios->c_cflag = bsd_to_linux_speed(bios->c_ispeed, sptab);
+ lios->c_cflag |= (bios->c_cflag & CSIZE) >> 4;
+ if (bios->c_cflag & CSTOPB)
+ lios->c_cflag |= LINUX_CSTOPB;
+ if (bios->c_cflag & CREAD)
+ lios->c_cflag |= LINUX_CREAD;
+ if (bios->c_cflag & PARENB)
+ lios->c_cflag |= LINUX_PARENB;
+ if (bios->c_cflag & PARODD)
+ lios->c_cflag |= LINUX_PARODD;
+ if (bios->c_cflag & HUPCL)
+ lios->c_cflag |= LINUX_HUPCL;
+ if (bios->c_cflag & CLOCAL)
+ lios->c_cflag |= LINUX_CLOCAL;
+ if (bios->c_cflag & CRTSCTS)
+ lios->c_cflag |= LINUX_CRTSCTS;
+
+ lios->c_lflag = 0;
+ if (bios->c_lflag & ISIG)
+ lios->c_lflag |= LINUX_ISIG;
+ if (bios->c_lflag & ICANON)
+ lios->c_lflag |= LINUX_ICANON;
+ if (bios->c_lflag & ECHO)
+ lios->c_lflag |= LINUX_ECHO;
+ if (bios->c_lflag & ECHOE)
+ lios->c_lflag |= LINUX_ECHOE;
+ if (bios->c_lflag & ECHOK)
+ lios->c_lflag |= LINUX_ECHOK;
+ if (bios->c_lflag & ECHONL)
+ lios->c_lflag |= LINUX_ECHONL;
+ if (bios->c_lflag & NOFLSH)
+ lios->c_lflag |= LINUX_NOFLSH;
+ if (bios->c_lflag & TOSTOP)
+ lios->c_lflag |= LINUX_TOSTOP;
+ if (bios->c_lflag & ECHOCTL)
+ lios->c_lflag |= LINUX_ECHOCTL;
+ if (bios->c_lflag & ECHOPRT)
+ lios->c_lflag |= LINUX_ECHOPRT;
+ if (bios->c_lflag & ECHOKE)
+ lios->c_lflag |= LINUX_ECHOKE;
+ if (bios->c_lflag & FLUSHO)
+ lios->c_lflag |= LINUX_FLUSHO;
+ if (bios->c_lflag & PENDIN)
+ lios->c_lflag |= LINUX_PENDIN;
+ if (bios->c_lflag & IEXTEN)
+ lios->c_lflag |= LINUX_IEXTEN;
+
+ for (i=0; i<LINUX_NCCS; i++)
+ lios->c_cc[i] = LINUX_POSIX_VDISABLE;
+ lios->c_cc[LINUX_VINTR] = bios->c_cc[VINTR];
+ lios->c_cc[LINUX_VQUIT] = bios->c_cc[VQUIT];
+ lios->c_cc[LINUX_VERASE] = bios->c_cc[VERASE];
+ lios->c_cc[LINUX_VKILL] = bios->c_cc[VKILL];
+ lios->c_cc[LINUX_VEOF] = bios->c_cc[VEOF];
+ lios->c_cc[LINUX_VEOL] = bios->c_cc[VEOL];
+ lios->c_cc[LINUX_VMIN] = bios->c_cc[VMIN];
+ lios->c_cc[LINUX_VTIME] = bios->c_cc[VTIME];
+ lios->c_cc[LINUX_VEOL2] = bios->c_cc[VEOL2];
+ lios->c_cc[LINUX_VSUSP] = bios->c_cc[VSUSP];
+ lios->c_cc[LINUX_VSTART] = bios->c_cc[VSTART];
+ lios->c_cc[LINUX_VSTOP] = bios->c_cc[VSTOP];
+ lios->c_cc[LINUX_VREPRINT] = bios->c_cc[VREPRINT];
+ lios->c_cc[LINUX_VDISCARD] = bios->c_cc[VDISCARD];
+ lios->c_cc[LINUX_VWERASE] = bios->c_cc[VWERASE];
+ lios->c_cc[LINUX_VLNEXT] = bios->c_cc[VLNEXT];
+
+ for (i=0; i<LINUX_NCCS; i++) {
+ if (i != LINUX_VMIN && i != LINUX_VTIME &&
+ lios->c_cc[i] == _POSIX_VDISABLE)
+ lios->c_cc[i] = LINUX_POSIX_VDISABLE;
+ }
+ lios->c_line = 0;
+
+#ifdef DEBUG
+ if (ldebug(ioctl)) {
+ printf("LINUX: LINUX termios structure (output):\n");
+ printf("i=%08x o=%08x c=%08x l=%08x line=%d\n",
+ lios->c_iflag, lios->c_oflag, lios->c_cflag,
+ lios->c_lflag, (int)lios->c_line);
+ printf("c_cc ");
+ for (i=0; i<LINUX_NCCS; i++)
+ printf("%02x ", lios->c_cc[i]);
+ printf("\n");
+ }
+#endif
+}
+
+static void
+linux_to_bsd_termios(struct linux_termios *lios, struct termios *bios)
+{
+ int i;
+
+#ifdef DEBUG
+ if (ldebug(ioctl)) {
+ printf("LINUX: LINUX termios structure (input):\n");
+ printf("i=%08x o=%08x c=%08x l=%08x line=%d\n",
+ lios->c_iflag, lios->c_oflag, lios->c_cflag,
+ lios->c_lflag, (int)lios->c_line);
+ printf("c_cc ");
+ for (i=0; i<LINUX_NCCS; i++)
+ printf("%02x ", lios->c_cc[i]);
+ printf("\n");
+ }
+#endif
+
+ bios->c_iflag = 0;
+ if (lios->c_iflag & LINUX_IGNBRK)
+ bios->c_iflag |= IGNBRK;
+ if (lios->c_iflag & LINUX_BRKINT)
+ bios->c_iflag |= BRKINT;
+ if (lios->c_iflag & LINUX_IGNPAR)
+ bios->c_iflag |= IGNPAR;
+ if (lios->c_iflag & LINUX_PARMRK)
+ bios->c_iflag |= PARMRK;
+ if (lios->c_iflag & LINUX_INPCK)
+ bios->c_iflag |= INPCK;
+ if (lios->c_iflag & LINUX_ISTRIP)
+ bios->c_iflag |= ISTRIP;
+ if (lios->c_iflag & LINUX_INLCR)
+ bios->c_iflag |= INLCR;
+ if (lios->c_iflag & LINUX_IGNCR)
+ bios->c_iflag |= IGNCR;
+ if (lios->c_iflag & LINUX_ICRNL)
+ bios->c_iflag |= ICRNL;
+ if (lios->c_iflag & LINUX_IXON)
+ bios->c_iflag |= IXON;
+ if (lios->c_iflag & LINUX_IXANY)
+ bios->c_iflag |= IXANY;
+ if (lios->c_iflag & LINUX_IXOFF)
+ bios->c_iflag |= IXOFF;
+ if (lios->c_iflag & LINUX_IMAXBEL)
+ bios->c_iflag |= IMAXBEL;
+
+ bios->c_oflag = 0;
+ if (lios->c_oflag & LINUX_OPOST)
+ bios->c_oflag |= OPOST;
+ if (lios->c_oflag & LINUX_ONLCR)
+ bios->c_oflag |= ONLCR;
+ if (lios->c_oflag & LINUX_XTABS)
+ bios->c_oflag |= TAB3;
+
+ bios->c_cflag = (lios->c_cflag & LINUX_CSIZE) << 4;
+ if (lios->c_cflag & LINUX_CSTOPB)
+ bios->c_cflag |= CSTOPB;
+ if (lios->c_cflag & LINUX_CREAD)
+ bios->c_cflag |= CREAD;
+ if (lios->c_cflag & LINUX_PARENB)
+ bios->c_cflag |= PARENB;
+ if (lios->c_cflag & LINUX_PARODD)
+ bios->c_cflag |= PARODD;
+ if (lios->c_cflag & LINUX_HUPCL)
+ bios->c_cflag |= HUPCL;
+ if (lios->c_cflag & LINUX_CLOCAL)
+ bios->c_cflag |= CLOCAL;
+ if (lios->c_cflag & LINUX_CRTSCTS)
+ bios->c_cflag |= CRTSCTS;
+
+ bios->c_lflag = 0;
+ if (lios->c_lflag & LINUX_ISIG)
+ bios->c_lflag |= ISIG;
+ if (lios->c_lflag & LINUX_ICANON)
+ bios->c_lflag |= ICANON;
+ if (lios->c_lflag & LINUX_ECHO)
+ bios->c_lflag |= ECHO;
+ if (lios->c_lflag & LINUX_ECHOE)
+ bios->c_lflag |= ECHOE;
+ if (lios->c_lflag & LINUX_ECHOK)
+ bios->c_lflag |= ECHOK;
+ if (lios->c_lflag & LINUX_ECHONL)
+ bios->c_lflag |= ECHONL;
+ if (lios->c_lflag & LINUX_NOFLSH)
+ bios->c_lflag |= NOFLSH;
+ if (lios->c_lflag & LINUX_TOSTOP)
+ bios->c_lflag |= TOSTOP;
+ if (lios->c_lflag & LINUX_ECHOCTL)
+ bios->c_lflag |= ECHOCTL;
+ if (lios->c_lflag & LINUX_ECHOPRT)
+ bios->c_lflag |= ECHOPRT;
+ if (lios->c_lflag & LINUX_ECHOKE)
+ bios->c_lflag |= ECHOKE;
+ if (lios->c_lflag & LINUX_FLUSHO)
+ bios->c_lflag |= FLUSHO;
+ if (lios->c_lflag & LINUX_PENDIN)
+ bios->c_lflag |= PENDIN;
+ if (lios->c_lflag & LINUX_IEXTEN)
+ bios->c_lflag |= IEXTEN;
+
+ for (i=0; i<NCCS; i++)
+ bios->c_cc[i] = _POSIX_VDISABLE;
+ bios->c_cc[VINTR] = lios->c_cc[LINUX_VINTR];
+ bios->c_cc[VQUIT] = lios->c_cc[LINUX_VQUIT];
+ bios->c_cc[VERASE] = lios->c_cc[LINUX_VERASE];
+ bios->c_cc[VKILL] = lios->c_cc[LINUX_VKILL];
+ bios->c_cc[VEOF] = lios->c_cc[LINUX_VEOF];
+ bios->c_cc[VEOL] = lios->c_cc[LINUX_VEOL];
+ bios->c_cc[VMIN] = lios->c_cc[LINUX_VMIN];
+ bios->c_cc[VTIME] = lios->c_cc[LINUX_VTIME];
+ bios->c_cc[VEOL2] = lios->c_cc[LINUX_VEOL2];
+ bios->c_cc[VSUSP] = lios->c_cc[LINUX_VSUSP];
+ bios->c_cc[VSTART] = lios->c_cc[LINUX_VSTART];
+ bios->c_cc[VSTOP] = lios->c_cc[LINUX_VSTOP];
+ bios->c_cc[VREPRINT] = lios->c_cc[LINUX_VREPRINT];
+ bios->c_cc[VDISCARD] = lios->c_cc[LINUX_VDISCARD];
+ bios->c_cc[VWERASE] = lios->c_cc[LINUX_VWERASE];
+ bios->c_cc[VLNEXT] = lios->c_cc[LINUX_VLNEXT];
+
+ for (i=0; i<NCCS; i++) {
+ if (i != VMIN && i != VTIME &&
+ bios->c_cc[i] == LINUX_POSIX_VDISABLE)
+ bios->c_cc[i] = _POSIX_VDISABLE;
+ }
+
+ bios->c_ispeed = bios->c_ospeed =
+ linux_to_bsd_speed(lios->c_cflag & LINUX_CBAUD, sptab);
+
+#ifdef DEBUG
+ if (ldebug(ioctl)) {
+ printf("LINUX: BSD termios structure (output):\n");
+ printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
+ bios->c_iflag, bios->c_oflag, bios->c_cflag, bios->c_lflag,
+ bios->c_ispeed, bios->c_ospeed);
+ printf("c_cc ");
+ for (i=0; i<NCCS; i++)
+ printf("%02x ", bios->c_cc[i]);
+ printf("\n");
+ }
+#endif
+}
+
+static void
+bsd_to_linux_termio(struct termios *bios, struct linux_termio *lio)
+{
+ struct linux_termios lios;
+
+ bsd_to_linux_termios(bios, &lios);
+ lio->c_iflag = lios.c_iflag;
+ lio->c_oflag = lios.c_oflag;
+ lio->c_cflag = lios.c_cflag;
+ lio->c_lflag = lios.c_lflag;
+ lio->c_line = lios.c_line;
+ memcpy(lio->c_cc, lios.c_cc, LINUX_NCC);
+}
+
+static void
+linux_to_bsd_termio(struct linux_termio *lio, struct termios *bios)
+{
+ struct linux_termios lios;
+ int i;
+
+ lios.c_iflag = lio->c_iflag;
+ lios.c_oflag = lio->c_oflag;
+ lios.c_cflag = lio->c_cflag;
+ lios.c_lflag = lio->c_lflag;
+ for (i=LINUX_NCC; i<LINUX_NCCS; i++)
+ lios.c_cc[i] = LINUX_POSIX_VDISABLE;
+ memcpy(lios.c_cc, lio->c_cc, LINUX_NCC);
+ linux_to_bsd_termios(&lios, bios);
+}
+
+static int
+linux_ioctl_termio(struct thread *td, struct linux_ioctl_args *args)
+{
+ struct termios bios;
+ struct linux_termios lios;
+ struct linux_termio lio;
+ struct file *fp;
+ int error;
+
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ return (error);
+
+ switch (args->cmd & 0xffff) {
+
+ case LINUX_TCGETS:
+ error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td->td_ucred,
+ td);
+ if (error)
+ break;
+ bsd_to_linux_termios(&bios, &lios);
+ error = copyout(&lios, (void *)args->arg, sizeof(lios));
+ break;
+
+ case LINUX_TCSETS:
+ error = copyin((void *)args->arg, &lios, sizeof(lios));
+ if (error)
+ break;
+ linux_to_bsd_termios(&lios, &bios);
+ error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td->td_ucred,
+ td));
+ break;
+
+ case LINUX_TCSETSW:
+ error = copyin((void *)args->arg, &lios, sizeof(lios));
+ if (error)
+ break;
+ linux_to_bsd_termios(&lios, &bios);
+ error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td->td_ucred,
+ td));
+ break;
+
+ case LINUX_TCSETSF:
+ error = copyin((void *)args->arg, &lios, sizeof(lios));
+ if (error)
+ break;
+ linux_to_bsd_termios(&lios, &bios);
+ error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td->td_ucred,
+ td));
+ break;
+
+ case LINUX_TCGETA:
+ error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td->td_ucred,
+ td);
+ if (error)
+ break;
+ bsd_to_linux_termio(&bios, &lio);
+ error = (copyout(&lio, (void *)args->arg, sizeof(lio)));
+ break;
+
+ case LINUX_TCSETA:
+ error = copyin((void *)args->arg, &lio, sizeof(lio));
+ if (error)
+ break;
+ linux_to_bsd_termio(&lio, &bios);
+ error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td->td_ucred,
+ td));
+ break;
+
+ case LINUX_TCSETAW:
+ error = copyin((void *)args->arg, &lio, sizeof(lio));
+ if (error)
+ break;
+ linux_to_bsd_termio(&lio, &bios);
+ error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td->td_ucred,
+ td));
+ break;
+
+ case LINUX_TCSETAF:
+ error = copyin((void *)args->arg, &lio, sizeof(lio));
+ if (error)
+ break;
+ linux_to_bsd_termio(&lio, &bios);
+ error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td->td_ucred,
+ td));
+ break;
+
+ /* LINUX_TCSBRK */
+
+ case LINUX_TCXONC: {
+ switch (args->arg) {
+ case LINUX_TCOOFF:
+ args->cmd = TIOCSTOP;
+ break;
+ case LINUX_TCOON:
+ args->cmd = TIOCSTART;
+ break;
+ case LINUX_TCIOFF:
+ case LINUX_TCION: {
+ int c;
+ struct write_args wr;
+ error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios,
+ td->td_ucred, td);
+ if (error)
+ break;
+ fdrop(fp, td);
+ c = (args->arg == LINUX_TCIOFF) ? VSTOP : VSTART;
+ c = bios.c_cc[c];
+ if (c != _POSIX_VDISABLE) {
+ wr.fd = args->fd;
+ wr.buf = &c;
+ wr.nbyte = sizeof(c);
+ return (sys_write(td, &wr));
+ } else
+ return (0);
+ }
+ default:
+ fdrop(fp, td);
+ return (EINVAL);
+ }
+ args->arg = 0;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+ }
+
+ case LINUX_TCFLSH: {
+ int val;
+ switch (args->arg) {
+ case LINUX_TCIFLUSH:
+ val = FREAD;
+ break;
+ case LINUX_TCOFLUSH:
+ val = FWRITE;
+ break;
+ case LINUX_TCIOFLUSH:
+ val = FREAD | FWRITE;
+ break;
+ default:
+ fdrop(fp, td);
+ return (EINVAL);
+ }
+ error = (fo_ioctl(fp,TIOCFLUSH,(caddr_t)&val,td->td_ucred,td));
+ break;
+ }
+
+ case LINUX_TIOCEXCL:
+ args->cmd = TIOCEXCL;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCNXCL:
+ args->cmd = TIOCNXCL;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCSCTTY:
+ args->cmd = TIOCSCTTY;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCGPGRP:
+ args->cmd = TIOCGPGRP;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCSPGRP:
+ args->cmd = TIOCSPGRP;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ /* LINUX_TIOCOUTQ */
+ /* LINUX_TIOCSTI */
+
+ case LINUX_TIOCGWINSZ:
+ args->cmd = TIOCGWINSZ;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCSWINSZ:
+ args->cmd = TIOCSWINSZ;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCMGET:
+ args->cmd = TIOCMGET;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCMBIS:
+ args->cmd = TIOCMBIS;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCMBIC:
+ args->cmd = TIOCMBIC;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCMSET:
+ args->cmd = TIOCMSET;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ /* TIOCGSOFTCAR */
+ /* TIOCSSOFTCAR */
+
+ case LINUX_FIONREAD: /* LINUX_TIOCINQ */
+ args->cmd = FIONREAD;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ /* LINUX_TIOCLINUX */
+
+ case LINUX_TIOCCONS:
+ args->cmd = TIOCCONS;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCGSERIAL: {
+ struct linux_serial_struct lss;
+ lss.type = LINUX_PORT_16550A;
+ lss.flags = 0;
+ lss.close_delay = 0;
+ error = copyout(&lss, (void *)args->arg, sizeof(lss));
+ break;
+ }
+
+ case LINUX_TIOCSSERIAL: {
+ struct linux_serial_struct lss;
+ error = copyin((void *)args->arg, &lss, sizeof(lss));
+ if (error)
+ break;
+ /* XXX - It really helps to have an implementation that
+ * does nothing. NOT!
+ */
+ error = 0;
+ break;
+ }
+
+ case LINUX_TIOCPKT:
+ args->cmd = TIOCPKT;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_FIONBIO:
+ args->cmd = FIONBIO;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCNOTTY:
+ args->cmd = TIOCNOTTY;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCSETD: {
+ int line;
+ switch (args->arg) {
+ case LINUX_N_TTY:
+ line = TTYDISC;
+ break;
+ case LINUX_N_SLIP:
+ line = SLIPDISC;
+ break;
+ case LINUX_N_PPP:
+ line = PPPDISC;
+ break;
+ default:
+ fdrop(fp, td);
+ return (EINVAL);
+ }
+ error = (fo_ioctl(fp, TIOCSETD, (caddr_t)&line, td->td_ucred,
+ td));
+ break;
+ }
+
+ case LINUX_TIOCGETD: {
+ int linux_line;
+ int bsd_line = TTYDISC;
+ error = fo_ioctl(fp, TIOCGETD, (caddr_t)&bsd_line,
+ td->td_ucred, td);
+ if (error)
+ return (error);
+ switch (bsd_line) {
+ case TTYDISC:
+ linux_line = LINUX_N_TTY;
+ break;
+ case SLIPDISC:
+ linux_line = LINUX_N_SLIP;
+ break;
+ case PPPDISC:
+ linux_line = LINUX_N_PPP;
+ break;
+ default:
+ fdrop(fp, td);
+ return (EINVAL);
+ }
+ error = (copyout(&linux_line, (void *)args->arg, sizeof(int)));
+ break;
+ }
+
+ /* LINUX_TCSBRKP */
+ /* LINUX_TIOCTTYGSTRUCT */
+
+ case LINUX_FIONCLEX:
+ args->cmd = FIONCLEX;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_FIOCLEX:
+ args->cmd = FIOCLEX;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_FIOASYNC:
+ args->cmd = FIOASYNC;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ /* LINUX_TIOCSERCONFIG */
+ /* LINUX_TIOCSERGWILD */
+ /* LINUX_TIOCSERSWILD */
+ /* LINUX_TIOCGLCKTRMIOS */
+ /* LINUX_TIOCSLCKTRMIOS */
+
+ case LINUX_TIOCSBRK:
+ args->cmd = TIOCSBRK;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCCBRK:
+ args->cmd = TIOCCBRK;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+ case LINUX_TIOCGPTN: {
+ int nb;
+
+ error = fo_ioctl(fp, TIOCGPTN, (caddr_t)&nb, td->td_ucred, td);
+ if (!error)
+ error = copyout(&nb, (void *)args->arg,
+ sizeof(int));
+ break;
+ }
+ case LINUX_TIOCSPTLCK:
+ /* Our unlockpt() does nothing. */
+ error = 0;
+ break;
+ default:
+ error = ENOIOCTL;
+ break;
+ }
+
+ fdrop(fp, td);
+ return (error);
+}
+
+/*
+ * CDROM related ioctls
+ */
+
+struct linux_cdrom_msf
+{
+ u_char cdmsf_min0;
+ u_char cdmsf_sec0;
+ u_char cdmsf_frame0;
+ u_char cdmsf_min1;
+ u_char cdmsf_sec1;
+ u_char cdmsf_frame1;
+};
+
+struct linux_cdrom_tochdr
+{
+ u_char cdth_trk0;
+ u_char cdth_trk1;
+};
+
+union linux_cdrom_addr
+{
+ struct {
+ u_char minute;
+ u_char second;
+ u_char frame;
+ } msf;
+ int lba;
+};
+
+struct linux_cdrom_tocentry
+{
+ u_char cdte_track;
+ u_char cdte_adr:4;
+ u_char cdte_ctrl:4;
+ u_char cdte_format;
+ union linux_cdrom_addr cdte_addr;
+ u_char cdte_datamode;
+};
+
+struct linux_cdrom_subchnl
+{
+ u_char cdsc_format;
+ u_char cdsc_audiostatus;
+ u_char cdsc_adr:4;
+ u_char cdsc_ctrl:4;
+ u_char cdsc_trk;
+ u_char cdsc_ind;
+ union linux_cdrom_addr cdsc_absaddr;
+ union linux_cdrom_addr cdsc_reladdr;
+};
+
+struct l_cdrom_read_audio {
+ union linux_cdrom_addr addr;
+ u_char addr_format;
+ l_int nframes;
+ u_char *buf;
+};
+
+struct l_dvd_layer {
+ u_char book_version:4;
+ u_char book_type:4;
+ u_char min_rate:4;
+ u_char disc_size:4;
+ u_char layer_type:4;
+ u_char track_path:1;
+ u_char nlayers:2;
+ u_char track_density:4;
+ u_char linear_density:4;
+ u_char bca:1;
+ u_int32_t start_sector;
+ u_int32_t end_sector;
+ u_int32_t end_sector_l0;
+};
+
+struct l_dvd_physical {
+ u_char type;
+ u_char layer_num;
+ struct l_dvd_layer layer[4];
+};
+
+struct l_dvd_copyright {
+ u_char type;
+ u_char layer_num;
+ u_char cpst;
+ u_char rmi;
+};
+
+struct l_dvd_disckey {
+ u_char type;
+ l_uint agid:2;
+ u_char value[2048];
+};
+
+struct l_dvd_bca {
+ u_char type;
+ l_int len;
+ u_char value[188];
+};
+
+struct l_dvd_manufact {
+ u_char type;
+ u_char layer_num;
+ l_int len;
+ u_char value[2048];
+};
+
+typedef union {
+ u_char type;
+ struct l_dvd_physical physical;
+ struct l_dvd_copyright copyright;
+ struct l_dvd_disckey disckey;
+ struct l_dvd_bca bca;
+ struct l_dvd_manufact manufact;
+} l_dvd_struct;
+
+typedef u_char l_dvd_key[5];
+typedef u_char l_dvd_challenge[10];
+
+struct l_dvd_lu_send_agid {
+ u_char type;
+ l_uint agid:2;
+};
+
+struct l_dvd_host_send_challenge {
+ u_char type;
+ l_uint agid:2;
+ l_dvd_challenge chal;
+};
+
+struct l_dvd_send_key {
+ u_char type;
+ l_uint agid:2;
+ l_dvd_key key;
+};
+
+struct l_dvd_lu_send_challenge {
+ u_char type;
+ l_uint agid:2;
+ l_dvd_challenge chal;
+};
+
+struct l_dvd_lu_send_title_key {
+ u_char type;
+ l_uint agid:2;
+ l_dvd_key title_key;
+ l_int lba;
+ l_uint cpm:1;
+ l_uint cp_sec:1;
+ l_uint cgms:2;
+};
+
+struct l_dvd_lu_send_asf {
+ u_char type;
+ l_uint agid:2;
+ l_uint asf:1;
+};
+
+struct l_dvd_host_send_rpcstate {
+ u_char type;
+ u_char pdrc;
+};
+
+struct l_dvd_lu_send_rpcstate {
+ u_char type:2;
+ u_char vra:3;
+ u_char ucca:3;
+ u_char region_mask;
+ u_char rpc_scheme;
+};
+
+typedef union {
+ u_char type;
+ struct l_dvd_lu_send_agid lsa;
+ struct l_dvd_host_send_challenge hsc;
+ struct l_dvd_send_key lsk;
+ struct l_dvd_lu_send_challenge lsc;
+ struct l_dvd_send_key hsk;
+ struct l_dvd_lu_send_title_key lstk;
+ struct l_dvd_lu_send_asf lsasf;
+ struct l_dvd_host_send_rpcstate hrpcs;
+ struct l_dvd_lu_send_rpcstate lrpcs;
+} l_dvd_authinfo;
+
+static void
+bsd_to_linux_msf_lba(u_char af, union msf_lba *bp, union linux_cdrom_addr *lp)
+{
+ if (af == CD_LBA_FORMAT)
+ lp->lba = bp->lba;
+ else {
+ lp->msf.minute = bp->msf.minute;
+ lp->msf.second = bp->msf.second;
+ lp->msf.frame = bp->msf.frame;
+ }
+}
+
+static void
+set_linux_cdrom_addr(union linux_cdrom_addr *addr, int format, int lba)
+{
+ if (format == LINUX_CDROM_MSF) {
+ addr->msf.frame = lba % 75;
+ lba /= 75;
+ lba += 2;
+ addr->msf.second = lba % 60;
+ addr->msf.minute = lba / 60;
+ } else
+ addr->lba = lba;
+}
+
+static int
+linux_to_bsd_dvd_struct(l_dvd_struct *lp, struct dvd_struct *bp)
+{
+ bp->format = lp->type;
+ switch (bp->format) {
+ case DVD_STRUCT_PHYSICAL:
+ if (bp->layer_num >= 4)
+ return (EINVAL);
+ bp->layer_num = lp->physical.layer_num;
+ break;
+ case DVD_STRUCT_COPYRIGHT:
+ bp->layer_num = lp->copyright.layer_num;
+ break;
+ case DVD_STRUCT_DISCKEY:
+ bp->agid = lp->disckey.agid;
+ break;
+ case DVD_STRUCT_BCA:
+ case DVD_STRUCT_MANUFACT:
+ break;
+ default:
+ return (EINVAL);
+ }
+ return (0);
+}
+
+static int
+bsd_to_linux_dvd_struct(struct dvd_struct *bp, l_dvd_struct *lp)
+{
+ switch (bp->format) {
+ case DVD_STRUCT_PHYSICAL: {
+ struct dvd_layer *blp = (struct dvd_layer *)bp->data;
+ struct l_dvd_layer *llp = &lp->physical.layer[bp->layer_num];
+ memset(llp, 0, sizeof(*llp));
+ llp->book_version = blp->book_version;
+ llp->book_type = blp->book_type;
+ llp->min_rate = blp->max_rate;
+ llp->disc_size = blp->disc_size;
+ llp->layer_type = blp->layer_type;
+ llp->track_path = blp->track_path;
+ llp->nlayers = blp->nlayers;
+ llp->track_density = blp->track_density;
+ llp->linear_density = blp->linear_density;
+ llp->bca = blp->bca;
+ llp->start_sector = blp->start_sector;
+ llp->end_sector = blp->end_sector;
+ llp->end_sector_l0 = blp->end_sector_l0;
+ break;
+ }
+ case DVD_STRUCT_COPYRIGHT:
+ lp->copyright.cpst = bp->cpst;
+ lp->copyright.rmi = bp->rmi;
+ break;
+ case DVD_STRUCT_DISCKEY:
+ memcpy(lp->disckey.value, bp->data, sizeof(lp->disckey.value));
+ break;
+ case DVD_STRUCT_BCA:
+ lp->bca.len = bp->length;
+ memcpy(lp->bca.value, bp->data, sizeof(lp->bca.value));
+ break;
+ case DVD_STRUCT_MANUFACT:
+ lp->manufact.len = bp->length;
+ memcpy(lp->manufact.value, bp->data,
+ sizeof(lp->manufact.value));
+ /* lp->manufact.layer_num is unused in linux (redhat 7.0) */
+ break;
+ default:
+ return (EINVAL);
+ }
+ return (0);
+}
+
+static int
+linux_to_bsd_dvd_authinfo(l_dvd_authinfo *lp, int *bcode,
+ struct dvd_authinfo *bp)
+{
+ switch (lp->type) {
+ case LINUX_DVD_LU_SEND_AGID:
+ *bcode = DVDIOCREPORTKEY;
+ bp->format = DVD_REPORT_AGID;
+ bp->agid = lp->lsa.agid;
+ break;
+ case LINUX_DVD_HOST_SEND_CHALLENGE:
+ *bcode = DVDIOCSENDKEY;
+ bp->format = DVD_SEND_CHALLENGE;
+ bp->agid = lp->hsc.agid;
+ memcpy(bp->keychal, lp->hsc.chal, 10);
+ break;
+ case LINUX_DVD_LU_SEND_KEY1:
+ *bcode = DVDIOCREPORTKEY;
+ bp->format = DVD_REPORT_KEY1;
+ bp->agid = lp->lsk.agid;
+ break;
+ case LINUX_DVD_LU_SEND_CHALLENGE:
+ *bcode = DVDIOCREPORTKEY;
+ bp->format = DVD_REPORT_CHALLENGE;
+ bp->agid = lp->lsc.agid;
+ break;
+ case LINUX_DVD_HOST_SEND_KEY2:
+ *bcode = DVDIOCSENDKEY;
+ bp->format = DVD_SEND_KEY2;
+ bp->agid = lp->hsk.agid;
+ memcpy(bp->keychal, lp->hsk.key, 5);
+ break;
+ case LINUX_DVD_LU_SEND_TITLE_KEY:
+ *bcode = DVDIOCREPORTKEY;
+ bp->format = DVD_REPORT_TITLE_KEY;
+ bp->agid = lp->lstk.agid;
+ bp->lba = lp->lstk.lba;
+ break;
+ case LINUX_DVD_LU_SEND_ASF:
+ *bcode = DVDIOCREPORTKEY;
+ bp->format = DVD_REPORT_ASF;
+ bp->agid = lp->lsasf.agid;
+ break;
+ case LINUX_DVD_INVALIDATE_AGID:
+ *bcode = DVDIOCREPORTKEY;
+ bp->format = DVD_INVALIDATE_AGID;
+ bp->agid = lp->lsa.agid;
+ break;
+ case LINUX_DVD_LU_SEND_RPC_STATE:
+ *bcode = DVDIOCREPORTKEY;
+ bp->format = DVD_REPORT_RPC;
+ break;
+ case LINUX_DVD_HOST_SEND_RPC_STATE:
+ *bcode = DVDIOCSENDKEY;
+ bp->format = DVD_SEND_RPC;
+ bp->region = lp->hrpcs.pdrc;
+ break;
+ default:
+ return (EINVAL);
+ }
+ return (0);
+}
+
+static int
+bsd_to_linux_dvd_authinfo(struct dvd_authinfo *bp, l_dvd_authinfo *lp)
+{
+ switch (lp->type) {
+ case LINUX_DVD_LU_SEND_AGID:
+ lp->lsa.agid = bp->agid;
+ break;
+ case LINUX_DVD_HOST_SEND_CHALLENGE:
+ lp->type = LINUX_DVD_LU_SEND_KEY1;
+ break;
+ case LINUX_DVD_LU_SEND_KEY1:
+ memcpy(lp->lsk.key, bp->keychal, sizeof(lp->lsk.key));
+ break;
+ case LINUX_DVD_LU_SEND_CHALLENGE:
+ memcpy(lp->lsc.chal, bp->keychal, sizeof(lp->lsc.chal));
+ break;
+ case LINUX_DVD_HOST_SEND_KEY2:
+ lp->type = LINUX_DVD_AUTH_ESTABLISHED;
+ break;
+ case LINUX_DVD_LU_SEND_TITLE_KEY:
+ memcpy(lp->lstk.title_key, bp->keychal,
+ sizeof(lp->lstk.title_key));
+ lp->lstk.cpm = bp->cpm;
+ lp->lstk.cp_sec = bp->cp_sec;
+ lp->lstk.cgms = bp->cgms;
+ break;
+ case LINUX_DVD_LU_SEND_ASF:
+ lp->lsasf.asf = bp->asf;
+ break;
+ case LINUX_DVD_INVALIDATE_AGID:
+ break;
+ case LINUX_DVD_LU_SEND_RPC_STATE:
+ lp->lrpcs.type = bp->reg_type;
+ lp->lrpcs.vra = bp->vend_rsts;
+ lp->lrpcs.ucca = bp->user_rsts;
+ lp->lrpcs.region_mask = bp->region;
+ lp->lrpcs.rpc_scheme = bp->rpc_scheme;
+ break;
+ case LINUX_DVD_HOST_SEND_RPC_STATE:
+ break;
+ default:
+ return (EINVAL);
+ }
+ return (0);
+}
+
+static int
+linux_ioctl_cdrom(struct thread *td, struct linux_ioctl_args *args)
+{
+ struct file *fp;
+ int error;
+
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ return (error);
+ switch (args->cmd & 0xffff) {
+
+ case LINUX_CDROMPAUSE:
+ args->cmd = CDIOCPAUSE;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_CDROMRESUME:
+ args->cmd = CDIOCRESUME;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_CDROMPLAYMSF:
+ args->cmd = CDIOCPLAYMSF;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_CDROMPLAYTRKIND:
+ args->cmd = CDIOCPLAYTRACKS;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_CDROMREADTOCHDR: {
+ struct ioc_toc_header th;
+ struct linux_cdrom_tochdr lth;
+ error = fo_ioctl(fp, CDIOREADTOCHEADER, (caddr_t)&th,
+ td->td_ucred, td);
+ if (!error) {
+ lth.cdth_trk0 = th.starting_track;
+ lth.cdth_trk1 = th.ending_track;
+ copyout(&lth, (void *)args->arg, sizeof(lth));
+ }
+ break;
+ }
+
+ case LINUX_CDROMREADTOCENTRY: {
+ struct linux_cdrom_tocentry lte;
+ struct ioc_read_toc_single_entry irtse;
+
+ error = copyin((void *)args->arg, &lte, sizeof(lte));
+ if (error)
+ break;
+ irtse.address_format = lte.cdte_format;
+ irtse.track = lte.cdte_track;
+ error = fo_ioctl(fp, CDIOREADTOCENTRY, (caddr_t)&irtse,
+ td->td_ucred, td);
+ if (!error) {
+ lte.cdte_ctrl = irtse.entry.control;
+ lte.cdte_adr = irtse.entry.addr_type;
+ bsd_to_linux_msf_lba(irtse.address_format,
+ &irtse.entry.addr, &lte.cdte_addr);
+ error = copyout(&lte, (void *)args->arg, sizeof(lte));
+ }
+ break;
+ }
+
+ case LINUX_CDROMSTOP:
+ args->cmd = CDIOCSTOP;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_CDROMSTART:
+ args->cmd = CDIOCSTART;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_CDROMEJECT:
+ args->cmd = CDIOCEJECT;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ /* LINUX_CDROMVOLCTRL */
+
+ case LINUX_CDROMSUBCHNL: {
+ struct linux_cdrom_subchnl sc;
+ struct ioc_read_subchannel bsdsc;
+ struct cd_sub_channel_info bsdinfo;
+
+ bsdsc.address_format = CD_LBA_FORMAT;
+ bsdsc.data_format = CD_CURRENT_POSITION;
+ bsdsc.track = 0;
+ bsdsc.data_len = sizeof(bsdinfo);
+ bsdsc.data = &bsdinfo;
+ error = fo_ioctl(fp, CDIOCREADSUBCHANNEL_SYSSPACE,
+ (caddr_t)&bsdsc, td->td_ucred, td);
+ if (error)
+ break;
+ error = copyin((void *)args->arg, &sc, sizeof(sc));
+ if (error)
+ break;
+ sc.cdsc_audiostatus = bsdinfo.header.audio_status;
+ sc.cdsc_adr = bsdinfo.what.position.addr_type;
+ sc.cdsc_ctrl = bsdinfo.what.position.control;
+ sc.cdsc_trk = bsdinfo.what.position.track_number;
+ sc.cdsc_ind = bsdinfo.what.position.index_number;
+ set_linux_cdrom_addr(&sc.cdsc_absaddr, sc.cdsc_format,
+ bsdinfo.what.position.absaddr.lba);
+ set_linux_cdrom_addr(&sc.cdsc_reladdr, sc.cdsc_format,
+ bsdinfo.what.position.reladdr.lba);
+ error = copyout(&sc, (void *)args->arg, sizeof(sc));
+ break;
+ }
+
+ /* LINUX_CDROMREADMODE2 */
+ /* LINUX_CDROMREADMODE1 */
+ /* LINUX_CDROMREADAUDIO */
+ /* LINUX_CDROMEJECT_SW */
+ /* LINUX_CDROMMULTISESSION */
+ /* LINUX_CDROM_GET_UPC */
+
+ case LINUX_CDROMRESET:
+ args->cmd = CDIOCRESET;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ /* LINUX_CDROMVOLREAD */
+ /* LINUX_CDROMREADRAW */
+ /* LINUX_CDROMREADCOOKED */
+ /* LINUX_CDROMSEEK */
+ /* LINUX_CDROMPLAYBLK */
+ /* LINUX_CDROMREADALL */
+ /* LINUX_CDROMCLOSETRAY */
+ /* LINUX_CDROMLOADFROMSLOT */
+ /* LINUX_CDROMGETSPINDOWN */
+ /* LINUX_CDROMSETSPINDOWN */
+ /* LINUX_CDROM_SET_OPTIONS */
+ /* LINUX_CDROM_CLEAR_OPTIONS */
+ /* LINUX_CDROM_SELECT_SPEED */
+ /* LINUX_CDROM_SELECT_DISC */
+ /* LINUX_CDROM_MEDIA_CHANGED */
+ /* LINUX_CDROM_DRIVE_STATUS */
+ /* LINUX_CDROM_DISC_STATUS */
+ /* LINUX_CDROM_CHANGER_NSLOTS */
+ /* LINUX_CDROM_LOCKDOOR */
+ /* LINUX_CDROM_DEBUG */
+ /* LINUX_CDROM_GET_CAPABILITY */
+ /* LINUX_CDROMAUDIOBUFSIZ */
+
+ case LINUX_DVD_READ_STRUCT: {
+ l_dvd_struct *lds;
+ struct dvd_struct *bds;
+
+ lds = malloc(sizeof(*lds), M_LINUX, M_WAITOK);
+ bds = malloc(sizeof(*bds), M_LINUX, M_WAITOK);
+ error = copyin((void *)args->arg, lds, sizeof(*lds));
+ if (error)
+ goto out;
+ error = linux_to_bsd_dvd_struct(lds, bds);
+ if (error)
+ goto out;
+ error = fo_ioctl(fp, DVDIOCREADSTRUCTURE, (caddr_t)bds,
+ td->td_ucred, td);
+ if (error)
+ goto out;
+ error = bsd_to_linux_dvd_struct(bds, lds);
+ if (error)
+ goto out;
+ error = copyout(lds, (void *)args->arg, sizeof(*lds));
+ out:
+ free(bds, M_LINUX);
+ free(lds, M_LINUX);
+ break;
+ }
+
+ /* LINUX_DVD_WRITE_STRUCT */
+
+ case LINUX_DVD_AUTH: {
+ l_dvd_authinfo lda;
+ struct dvd_authinfo bda;
+ int bcode;
+
+ error = copyin((void *)args->arg, &lda, sizeof(lda));
+ if (error)
+ break;
+ error = linux_to_bsd_dvd_authinfo(&lda, &bcode, &bda);
+ if (error)
+ break;
+ error = fo_ioctl(fp, bcode, (caddr_t)&bda, td->td_ucred,
+ td);
+ if (error) {
+ if (lda.type == LINUX_DVD_HOST_SEND_KEY2) {
+ lda.type = LINUX_DVD_AUTH_FAILURE;
+ copyout(&lda, (void *)args->arg, sizeof(lda));
+ }
+ break;
+ }
+ error = bsd_to_linux_dvd_authinfo(&bda, &lda);
+ if (error)
+ break;
+ error = copyout(&lda, (void *)args->arg, sizeof(lda));
+ break;
+ }
+
+ case LINUX_SCSI_GET_BUS_NUMBER:
+ case LINUX_SCSI_GET_IDLUN:
+ error = linux_ioctl_sg(td, args);
+ break;
+
+ /* LINUX_CDROM_SEND_PACKET */
+ /* LINUX_CDROM_NEXT_WRITABLE */
+ /* LINUX_CDROM_LAST_WRITTEN */
+
+ default:
+ error = ENOIOCTL;
+ break;
+ }
+
+ fdrop(fp, td);
+ return (error);
+}
+
+static int
+linux_ioctl_vfat(struct thread *td, struct linux_ioctl_args *args)
+{
+
+ return (ENOTTY);
+}
+
+/*
+ * Sound related ioctls
+ */
+
+struct linux_mixer_info {
+ char id[16];
+ char name[32];
+ int modify_counter;
+ int fillers[10];
+};
+
+struct linux_old_mixer_info {
+ char id[16];
+ char name[32];
+};
+
+static u_int32_t dirbits[4] = { IOC_VOID, IOC_IN, IOC_OUT, IOC_INOUT };
+
+#define SETDIR(c) (((c) & ~IOC_DIRMASK) | dirbits[args->cmd >> 30])
+
+static int
+linux_ioctl_sound(struct thread *td, struct linux_ioctl_args *args)
+{
+
+ switch (args->cmd & 0xffff) {
+
+ case LINUX_SOUND_MIXER_WRITE_VOLUME:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_VOLUME);
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_BASS:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_BASS);
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_TREBLE:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_TREBLE);
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_SYNTH:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_SYNTH);
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_PCM:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_PCM);
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_SPEAKER:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_SPEAKER);
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_LINE:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE);
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_MIC:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_MIC);
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_CD:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_CD);
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_IMIX:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_IMIX);
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_ALTPCM:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_ALTPCM);
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_RECLEV:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_RECLEV);
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_IGAIN:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_IGAIN);
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_OGAIN:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_OGAIN);
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_LINE1:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE1);
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_LINE2:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE2);
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_LINE3:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE3);
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_INFO: {
+ /* Key on encoded length */
+ switch ((args->cmd >> 16) & 0x1fff) {
+ case 0x005c: { /* SOUND_MIXER_INFO */
+ struct linux_mixer_info info;
+ bzero(&info, sizeof(info));
+ strncpy(info.id, "OSS", sizeof(info.id) - 1);
+ strncpy(info.name, "FreeBSD OSS Mixer", sizeof(info.name) - 1);
+ copyout(&info, (void *)args->arg, sizeof(info));
+ return (0);
+ }
+ case 0x0030: { /* SOUND_OLD_MIXER_INFO */
+ struct linux_old_mixer_info info;
+ bzero(&info, sizeof(info));
+ strncpy(info.id, "OSS", sizeof(info.id) - 1);
+ strncpy(info.name, "FreeBSD OSS Mixer", sizeof(info.name) - 1);
+ copyout(&info, (void *)args->arg, sizeof(info));
+ return (0);
+ }
+ default:
+ return (ENOIOCTL);
+ }
+ break;
+ }
+
+ case LINUX_OSS_GETVERSION: {
+ int version = linux_get_oss_version(td);
+ return (copyout(&version, (void *)args->arg, sizeof(int)));
+ }
+
+ case LINUX_SOUND_MIXER_READ_STEREODEVS:
+ args->cmd = SOUND_MIXER_READ_STEREODEVS;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_READ_CAPS:
+ args->cmd = SOUND_MIXER_READ_CAPS;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_READ_RECMASK:
+ args->cmd = SOUND_MIXER_READ_RECMASK;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_READ_DEVMASK:
+ args->cmd = SOUND_MIXER_READ_DEVMASK;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_RECSRC:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_RECSRC);
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_RESET:
+ args->cmd = SNDCTL_DSP_RESET;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_SYNC:
+ args->cmd = SNDCTL_DSP_SYNC;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_SPEED:
+ args->cmd = SNDCTL_DSP_SPEED;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_STEREO:
+ args->cmd = SNDCTL_DSP_STEREO;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_GETBLKSIZE: /* LINUX_SNDCTL_DSP_SETBLKSIZE */
+ args->cmd = SNDCTL_DSP_GETBLKSIZE;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_SETFMT:
+ args->cmd = SNDCTL_DSP_SETFMT;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_PCM_WRITE_CHANNELS:
+ args->cmd = SOUND_PCM_WRITE_CHANNELS;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_PCM_WRITE_FILTER:
+ args->cmd = SOUND_PCM_WRITE_FILTER;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_POST:
+ args->cmd = SNDCTL_DSP_POST;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_SUBDIVIDE:
+ args->cmd = SNDCTL_DSP_SUBDIVIDE;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_SETFRAGMENT:
+ args->cmd = SNDCTL_DSP_SETFRAGMENT;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_GETFMTS:
+ args->cmd = SNDCTL_DSP_GETFMTS;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_GETOSPACE:
+ args->cmd = SNDCTL_DSP_GETOSPACE;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_GETISPACE:
+ args->cmd = SNDCTL_DSP_GETISPACE;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_NONBLOCK:
+ args->cmd = SNDCTL_DSP_NONBLOCK;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_GETCAPS:
+ args->cmd = SNDCTL_DSP_GETCAPS;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_SETTRIGGER: /* LINUX_SNDCTL_GETTRIGGER */
+ args->cmd = SNDCTL_DSP_SETTRIGGER;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_GETIPTR:
+ args->cmd = SNDCTL_DSP_GETIPTR;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_GETOPTR:
+ args->cmd = SNDCTL_DSP_GETOPTR;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_SETDUPLEX:
+ args->cmd = SNDCTL_DSP_SETDUPLEX;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_GETODELAY:
+ args->cmd = SNDCTL_DSP_GETODELAY;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SEQ_RESET:
+ args->cmd = SNDCTL_SEQ_RESET;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SEQ_SYNC:
+ args->cmd = SNDCTL_SEQ_SYNC;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SYNTH_INFO:
+ args->cmd = SNDCTL_SYNTH_INFO;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SEQ_CTRLRATE:
+ args->cmd = SNDCTL_SEQ_CTRLRATE;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SEQ_GETOUTCOUNT:
+ args->cmd = SNDCTL_SEQ_GETOUTCOUNT;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SEQ_GETINCOUNT:
+ args->cmd = SNDCTL_SEQ_GETINCOUNT;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SEQ_PERCMODE:
+ args->cmd = SNDCTL_SEQ_PERCMODE;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_FM_LOAD_INSTR:
+ args->cmd = SNDCTL_FM_LOAD_INSTR;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SEQ_TESTMIDI:
+ args->cmd = SNDCTL_SEQ_TESTMIDI;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SEQ_RESETSAMPLES:
+ args->cmd = SNDCTL_SEQ_RESETSAMPLES;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SEQ_NRSYNTHS:
+ args->cmd = SNDCTL_SEQ_NRSYNTHS;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SEQ_NRMIDIS:
+ args->cmd = SNDCTL_SEQ_NRMIDIS;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_MIDI_INFO:
+ args->cmd = SNDCTL_MIDI_INFO;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SEQ_TRESHOLD:
+ args->cmd = SNDCTL_SEQ_TRESHOLD;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SYNTH_MEMAVL:
+ args->cmd = SNDCTL_SYNTH_MEMAVL;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
+
+ }
+
+ return (ENOIOCTL);
+}
+
+/*
+ * Console related ioctls
+ */
+
+#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG)
+
+static int
+linux_ioctl_console(struct thread *td, struct linux_ioctl_args *args)
+{
+ struct file *fp;
+ int error;
+
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ return (error);
+ switch (args->cmd & 0xffff) {
+
+ case LINUX_KIOCSOUND:
+ args->cmd = KIOCSOUND;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_KDMKTONE:
+ args->cmd = KDMKTONE;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_KDGETLED:
+ args->cmd = KDGETLED;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_KDSETLED:
+ args->cmd = KDSETLED;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_KDSETMODE:
+ args->cmd = KDSETMODE;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_KDGETMODE:
+ args->cmd = KDGETMODE;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_KDGKBMODE:
+ args->cmd = KDGKBMODE;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_KDSKBMODE: {
+ int kbdmode;
+ switch (args->arg) {
+ case LINUX_KBD_RAW:
+ kbdmode = K_RAW;
+ break;
+ case LINUX_KBD_XLATE:
+ kbdmode = K_XLATE;
+ break;
+ case LINUX_KBD_MEDIUMRAW:
+ kbdmode = K_RAW;
+ break;
+ default:
+ fdrop(fp, td);
+ return (EINVAL);
+ }
+ error = (fo_ioctl(fp, KDSKBMODE, (caddr_t)&kbdmode,
+ td->td_ucred, td));
+ break;
+ }
+
+ case LINUX_VT_OPENQRY:
+ args->cmd = VT_OPENQRY;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_VT_GETMODE:
+ args->cmd = VT_GETMODE;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_VT_SETMODE: {
+ struct vt_mode mode;
+ if ((error = copyin((void *)args->arg, &mode, sizeof(mode))))
+ break;
+ if (!ISSIGVALID(mode.frsig) && ISSIGVALID(mode.acqsig))
+ mode.frsig = mode.acqsig;
+ if ((error = copyout(&mode, (void *)args->arg, sizeof(mode))))
+ break;
+ args->cmd = VT_SETMODE;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+ }
+
+ case LINUX_VT_GETSTATE:
+ args->cmd = VT_GETACTIVE;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_VT_RELDISP:
+ args->cmd = VT_RELDISP;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_VT_ACTIVATE:
+ args->cmd = VT_ACTIVATE;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_VT_WAITACTIVE:
+ args->cmd = VT_WAITACTIVE;
+ error = (sys_ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ default:
+ error = ENOIOCTL;
+ break;
+ }
+
+ fdrop(fp, td);
+ return (error);
+}
+
+/*
+ * Criteria for interface name translation
+ */
+#define IFP_IS_ETH(ifp) (ifp->if_type == IFT_ETHER)
+
+/*
+ * Interface function used by linprocfs (at the time of writing). It's not
+ * used by the Linuxulator itself.
+ */
+int
+linux_ifname(struct ifnet *ifp, char *buffer, size_t buflen)
+{
+ struct ifnet *ifscan;
+ int ethno;
+
+ IFNET_RLOCK_ASSERT();
+
+ /* Short-circuit non ethernet interfaces */
+ if (!IFP_IS_ETH(ifp))
+ return (strlcpy(buffer, ifp->if_xname, buflen));
+
+ /* Determine the (relative) unit number for ethernet interfaces */
+ ethno = 0;
+ TAILQ_FOREACH(ifscan, &V_ifnet, if_link) {
+ if (ifscan == ifp)
+ return (snprintf(buffer, buflen, "eth%d", ethno));
+ if (IFP_IS_ETH(ifscan))
+ ethno++;
+ }
+
+ return (0);
+}
+
+/*
+ * Translate a Linux interface name to a FreeBSD interface name,
+ * and return the associated ifnet structure
+ * bsdname and lxname need to be least IFNAMSIZ bytes long, but
+ * can point to the same buffer.
+ */
+
+static struct ifnet *
+ifname_linux_to_bsd(struct thread *td, const char *lxname, char *bsdname)
+{
+ struct ifnet *ifp;
+ int len, unit;
+ char *ep;
+ int is_eth, index;
+
+ for (len = 0; len < LINUX_IFNAMSIZ; ++len)
+ if (!isalpha(lxname[len]))
+ break;
+ if (len == 0 || len == LINUX_IFNAMSIZ)
+ return (NULL);
+ unit = (int)strtoul(lxname + len, &ep, 10);
+ if (ep == NULL || ep == lxname + len || ep >= lxname + LINUX_IFNAMSIZ)
+ return (NULL);
+ index = 0;
+ is_eth = (len == 3 && !strncmp(lxname, "eth", len)) ? 1 : 0;
+ CURVNET_SET(TD_TO_VNET(td));
+ IFNET_RLOCK();
+ TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
+ /*
+ * Allow Linux programs to use FreeBSD names. Don't presume
+ * we never have an interface named "eth", so don't make
+ * the test optional based on is_eth.
+ */
+ if (strncmp(ifp->if_xname, lxname, LINUX_IFNAMSIZ) == 0)
+ break;
+ if (is_eth && IFP_IS_ETH(ifp) && unit == index++)
+ break;
+ }
+ IFNET_RUNLOCK();
+ CURVNET_RESTORE();
+ if (ifp != NULL)
+ strlcpy(bsdname, ifp->if_xname, IFNAMSIZ);
+ return (ifp);
+}
+
+/*
+ * Implement the SIOCGIFCONF ioctl
+ */
+
+static int
+linux_ifconf(struct thread *td, struct ifconf *uifc)
+{
+#ifdef COMPAT_LINUX32
+ struct l_ifconf ifc;
+#else
+ struct ifconf ifc;
+#endif
+ struct l_ifreq ifr;
+ struct ifnet *ifp;
+ struct ifaddr *ifa;
+ struct sbuf *sb;
+ int error, ethno, full = 0, valid_len, max_len;
+
+ error = copyin(uifc, &ifc, sizeof(ifc));
+ if (error != 0)
+ return (error);
+
+ max_len = MAXPHYS - 1;
+
+ CURVNET_SET(TD_TO_VNET(td));
+ /* handle the 'request buffer size' case */
+ if ((l_uintptr_t)ifc.ifc_buf == PTROUT(NULL)) {
+ ifc.ifc_len = 0;
+ IFNET_RLOCK();
+ TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
+ TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ struct sockaddr *sa = ifa->ifa_addr;
+ if (sa->sa_family == AF_INET)
+ ifc.ifc_len += sizeof(ifr);
+ }
+ }
+ IFNET_RUNLOCK();
+ error = copyout(&ifc, uifc, sizeof(ifc));
+ CURVNET_RESTORE();
+ return (error);
+ }
+
+ if (ifc.ifc_len <= 0) {
+ CURVNET_RESTORE();
+ return (EINVAL);
+ }
+
+again:
+ /* Keep track of eth interfaces */
+ ethno = 0;
+ if (ifc.ifc_len <= max_len) {
+ max_len = ifc.ifc_len;
+ full = 1;
+ }
+ sb = sbuf_new(NULL, NULL, max_len + 1, SBUF_FIXEDLEN);
+ max_len = 0;
+ valid_len = 0;
+
+ /* Return all AF_INET addresses of all interfaces */
+ IFNET_RLOCK();
+ TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
+ int addrs = 0;
+
+ bzero(&ifr, sizeof(ifr));
+ if (IFP_IS_ETH(ifp))
+ snprintf(ifr.ifr_name, LINUX_IFNAMSIZ, "eth%d",
+ ethno++);
+ else
+ strlcpy(ifr.ifr_name, ifp->if_xname, LINUX_IFNAMSIZ);
+
+ /* Walk the address list */
+ TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ struct sockaddr *sa = ifa->ifa_addr;
+
+ if (sa->sa_family == AF_INET) {
+ ifr.ifr_addr.sa_family = LINUX_AF_INET;
+ memcpy(ifr.ifr_addr.sa_data, sa->sa_data,
+ sizeof(ifr.ifr_addr.sa_data));
+ sbuf_bcat(sb, &ifr, sizeof(ifr));
+ max_len += sizeof(ifr);
+ addrs++;
+ }
+
+ if (sbuf_error(sb) == 0)
+ valid_len = sbuf_len(sb);
+ }
+ if (addrs == 0) {
+ bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
+ sbuf_bcat(sb, &ifr, sizeof(ifr));
+ max_len += sizeof(ifr);
+
+ if (sbuf_error(sb) == 0)
+ valid_len = sbuf_len(sb);
+ }
+ }
+ IFNET_RUNLOCK();
+
+ if (valid_len != max_len && !full) {
+ sbuf_delete(sb);
+ goto again;
+ }
+
+ ifc.ifc_len = valid_len;
+ sbuf_finish(sb);
+ error = copyout(sbuf_data(sb), PTRIN(ifc.ifc_buf), ifc.ifc_len);
+ if (error == 0)
+ error = copyout(&ifc, uifc, sizeof(ifc));
+ sbuf_delete(sb);
+ CURVNET_RESTORE();
+
+ return (error);
+}
+
+static int
+linux_gifflags(struct thread *td, struct ifnet *ifp, struct l_ifreq *ifr)
+{
+ l_short flags;
+
+ flags = (ifp->if_flags | ifp->if_drv_flags) & 0xffff;
+ /* these flags have no Linux equivalent */
+ flags &= ~(IFF_SMART|IFF_DRV_OACTIVE|IFF_SIMPLEX|
+ IFF_LINK0|IFF_LINK1|IFF_LINK2);
+ /* Linux' multicast flag is in a different bit */
+ if (flags & IFF_MULTICAST) {
+ flags &= ~IFF_MULTICAST;
+ flags |= 0x1000;
+ }
+
+ return (copyout(&flags, &ifr->ifr_flags, sizeof(flags)));
+}
+
+#define ARPHRD_ETHER 1
+#define ARPHRD_LOOPBACK 772
+
+static int
+linux_gifhwaddr(struct ifnet *ifp, struct l_ifreq *ifr)
+{
+ struct ifaddr *ifa;
+ struct sockaddr_dl *sdl;
+ struct l_sockaddr lsa;
+
+ if (ifp->if_type == IFT_LOOP) {
+ bzero(&lsa, sizeof(lsa));
+ lsa.sa_family = ARPHRD_LOOPBACK;
+ return (copyout(&lsa, &ifr->ifr_hwaddr, sizeof(lsa)));
+ }
+
+ if (ifp->if_type != IFT_ETHER)
+ return (ENOENT);
+
+ TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ sdl = (struct sockaddr_dl*)ifa->ifa_addr;
+ if (sdl != NULL && (sdl->sdl_family == AF_LINK) &&
+ (sdl->sdl_type == IFT_ETHER)) {
+ bzero(&lsa, sizeof(lsa));
+ lsa.sa_family = ARPHRD_ETHER;
+ bcopy(LLADDR(sdl), lsa.sa_data, LINUX_IFHWADDRLEN);
+ return (copyout(&lsa, &ifr->ifr_hwaddr, sizeof(lsa)));
+ }
+ }
+
+ return (ENOENT);
+}
+
+
+ /*
+* If we fault in bsd_to_linux_ifreq() then we will fault when we call
+* the native ioctl(). Thus, we don't really need to check the return
+* value of this function.
+*/
+static int
+bsd_to_linux_ifreq(struct ifreq *arg)
+{
+ struct ifreq ifr;
+ size_t ifr_len = sizeof(struct ifreq);
+ int error;
+
+ if ((error = copyin(arg, &ifr, ifr_len)))
+ return (error);
+
+ *(u_short *)&ifr.ifr_addr = ifr.ifr_addr.sa_family;
+
+ error = copyout(&ifr, arg, ifr_len);
+
+ return (error);
+}
+
+/*
+ * Socket related ioctls
+ */
+
+static int
+linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args)
+{
+ char lifname[LINUX_IFNAMSIZ], ifname[IFNAMSIZ];
+ struct ifnet *ifp;
+ struct file *fp;
+ int error, type;
+
+ ifp = NULL;
+ error = 0;
+
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ return (error);
+ type = fp->f_type;
+ fdrop(fp, td);
+ if (type != DTYPE_SOCKET) {
+ /* not a socket - probably a tap / vmnet device */
+ switch (args->cmd) {
+ case LINUX_SIOCGIFADDR:
+ case LINUX_SIOCSIFADDR:
+ case LINUX_SIOCGIFFLAGS:
+ return (linux_ioctl_special(td, args));
+ default:
+ return (ENOIOCTL);
+ }
+ }
+
+ switch (args->cmd & 0xffff) {
+
+ case LINUX_FIOGETOWN:
+ case LINUX_FIOSETOWN:
+ case LINUX_SIOCADDMULTI:
+ case LINUX_SIOCATMARK:
+ case LINUX_SIOCDELMULTI:
+ case LINUX_SIOCGIFCONF:
+ case LINUX_SIOCGPGRP:
+ case LINUX_SIOCSPGRP:
+ case LINUX_SIOCGIFCOUNT:
+ /* these ioctls don't take an interface name */
+#ifdef DEBUG
+ printf("%s(): ioctl %d\n", __func__,
+ args->cmd & 0xffff);
+#endif
+ break;
+
+ case LINUX_SIOCGIFFLAGS:
+ case LINUX_SIOCGIFADDR:
+ case LINUX_SIOCSIFADDR:
+ case LINUX_SIOCGIFDSTADDR:
+ case LINUX_SIOCGIFBRDADDR:
+ case LINUX_SIOCGIFNETMASK:
+ case LINUX_SIOCSIFNETMASK:
+ case LINUX_SIOCGIFMTU:
+ case LINUX_SIOCSIFMTU:
+ case LINUX_SIOCSIFNAME:
+ case LINUX_SIOCGIFHWADDR:
+ case LINUX_SIOCSIFHWADDR:
+ case LINUX_SIOCDEVPRIVATE:
+ case LINUX_SIOCDEVPRIVATE+1:
+ case LINUX_SIOCGIFINDEX:
+ /* copy in the interface name and translate it. */
+ error = copyin((void *)args->arg, lifname, LINUX_IFNAMSIZ);
+ if (error != 0)
+ return (error);
+#ifdef DEBUG
+ printf("%s(): ioctl %d on %.*s\n", __func__,
+ args->cmd & 0xffff, LINUX_IFNAMSIZ, lifname);
+#endif
+ ifp = ifname_linux_to_bsd(td, lifname, ifname);
+ if (ifp == NULL)
+ return (EINVAL);
+ /*
+ * We need to copy it back out in case we pass the
+ * request on to our native ioctl(), which will expect
+ * the ifreq to be in user space and have the correct
+ * interface name.
+ */
+ error = copyout(ifname, (void *)args->arg, IFNAMSIZ);
+ if (error != 0)
+ return (error);
+#ifdef DEBUG
+ printf("%s(): %s translated to %s\n", __func__,
+ lifname, ifname);
+#endif
+ break;
+
+ default:
+ return (ENOIOCTL);
+ }
+
+ switch (args->cmd & 0xffff) {
+
+ case LINUX_FIOSETOWN:
+ args->cmd = FIOSETOWN;
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_SIOCSPGRP:
+ args->cmd = SIOCSPGRP;
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_FIOGETOWN:
+ args->cmd = FIOGETOWN;
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_SIOCGPGRP:
+ args->cmd = SIOCGPGRP;
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_SIOCATMARK:
+ args->cmd = SIOCATMARK;
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ /* LINUX_SIOCGSTAMP */
+
+ case LINUX_SIOCGIFCONF:
+ error = linux_ifconf(td, (struct ifconf *)args->arg);
+ break;
+
+ case LINUX_SIOCGIFFLAGS:
+ args->cmd = SIOCGIFFLAGS;
+ error = linux_gifflags(td, ifp, (struct l_ifreq *)args->arg);
+ break;
+
+ case LINUX_SIOCGIFADDR:
+ args->cmd = SIOCGIFADDR;
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ bsd_to_linux_ifreq((struct ifreq *)args->arg);
+ break;
+
+ case LINUX_SIOCSIFADDR:
+ /* XXX probably doesn't work, included for completeness */
+ args->cmd = SIOCSIFADDR;
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_SIOCGIFDSTADDR:
+ args->cmd = SIOCGIFDSTADDR;
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ bsd_to_linux_ifreq((struct ifreq *)args->arg);
+ break;
+
+ case LINUX_SIOCGIFBRDADDR:
+ args->cmd = SIOCGIFBRDADDR;
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ bsd_to_linux_ifreq((struct ifreq *)args->arg);
+ break;
+
+ case LINUX_SIOCGIFNETMASK:
+ args->cmd = SIOCGIFNETMASK;
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ bsd_to_linux_ifreq((struct ifreq *)args->arg);
+ break;
+
+ case LINUX_SIOCSIFNETMASK:
+ error = ENOIOCTL;
+ break;
+
+ case LINUX_SIOCGIFMTU:
+ args->cmd = SIOCGIFMTU;
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_SIOCSIFMTU:
+ args->cmd = SIOCSIFMTU;
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_SIOCSIFNAME:
+ error = ENOIOCTL;
+ break;
+
+ case LINUX_SIOCGIFHWADDR:
+ error = linux_gifhwaddr(ifp, (struct l_ifreq *)args->arg);
+ break;
+
+ case LINUX_SIOCSIFHWADDR:
+ error = ENOIOCTL;
+ break;
+
+ case LINUX_SIOCADDMULTI:
+ args->cmd = SIOCADDMULTI;
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_SIOCDELMULTI:
+ args->cmd = SIOCDELMULTI;
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_SIOCGIFINDEX:
+ args->cmd = SIOCGIFINDEX;
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_SIOCGIFCOUNT:
+ error = 0;
+ break;
+
+ /*
+ * XXX This is slightly bogus, but these ioctls are currently
+ * XXX only used by the aironet (if_an) network driver.
+ */
+ case LINUX_SIOCDEVPRIVATE:
+ args->cmd = SIOCGPRIVATE_0;
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_SIOCDEVPRIVATE+1:
+ args->cmd = SIOCGPRIVATE_1;
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ break;
+ }
+
+ if (ifp != NULL)
+ /* restore the original interface name */
+ copyout(lifname, (void *)args->arg, LINUX_IFNAMSIZ);
+
+#ifdef DEBUG
+ printf("%s(): returning %d\n", __func__, error);
+#endif
+ return (error);
+}
+
+/*
+ * Device private ioctl handler
+ */
+static int
+linux_ioctl_private(struct thread *td, struct linux_ioctl_args *args)
+{
+ struct file *fp;
+ int error, type;
+
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ return (error);
+ type = fp->f_type;
+ fdrop(fp, td);
+ if (type == DTYPE_SOCKET)
+ return (linux_ioctl_socket(td, args));
+ return (ENOIOCTL);
+}
+
+/*
+ * DRM ioctl handler (sys/dev/drm)
+ */
+static int
+linux_ioctl_drm(struct thread *td, struct linux_ioctl_args *args)
+{
+ args->cmd = SETDIR(args->cmd);
+ return sys_ioctl(td, (struct ioctl_args *)args);
+}
+
+static int
+linux_ioctl_sg(struct thread *td, struct linux_ioctl_args *args)
+{
+ struct file *fp;
+ u_long cmd;
+ int error;
+
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) {
+ printf("sg_linux_ioctl: fget returned %d\n", error);
+ return (error);
+ }
+ cmd = args->cmd;
+
+ error = (fo_ioctl(fp, cmd, (caddr_t)args->arg, td->td_ucred, td));
+ fdrop(fp, td);
+ return (error);
+}
+
+/*
+ * Video4Linux (V4L) ioctl handler
+ */
+static int
+linux_to_bsd_v4l_tuner(struct l_video_tuner *lvt, struct video_tuner *vt)
+{
+ vt->tuner = lvt->tuner;
+ strlcpy(vt->name, lvt->name, LINUX_VIDEO_TUNER_NAME_SIZE);
+ vt->rangelow = lvt->rangelow; /* possible long size conversion */
+ vt->rangehigh = lvt->rangehigh; /* possible long size conversion */
+ vt->flags = lvt->flags;
+ vt->mode = lvt->mode;
+ vt->signal = lvt->signal;
+ return (0);
+}
+
+static int
+bsd_to_linux_v4l_tuner(struct video_tuner *vt, struct l_video_tuner *lvt)
+{
+ lvt->tuner = vt->tuner;
+ strlcpy(lvt->name, vt->name, LINUX_VIDEO_TUNER_NAME_SIZE);
+ lvt->rangelow = vt->rangelow; /* possible long size conversion */
+ lvt->rangehigh = vt->rangehigh; /* possible long size conversion */
+ lvt->flags = vt->flags;
+ lvt->mode = vt->mode;
+ lvt->signal = vt->signal;
+ return (0);
+}
+
+#ifdef COMPAT_LINUX_V4L_CLIPLIST
+static int
+linux_to_bsd_v4l_clip(struct l_video_clip *lvc, struct video_clip *vc)
+{
+ vc->x = lvc->x;
+ vc->y = lvc->y;
+ vc->width = lvc->width;
+ vc->height = lvc->height;
+ vc->next = PTRIN(lvc->next); /* possible pointer size conversion */
+ return (0);
+}
+#endif
+
+static int
+linux_to_bsd_v4l_window(struct l_video_window *lvw, struct video_window *vw)
+{
+ vw->x = lvw->x;
+ vw->y = lvw->y;
+ vw->width = lvw->width;
+ vw->height = lvw->height;
+ vw->chromakey = lvw->chromakey;
+ vw->flags = lvw->flags;
+ vw->clips = PTRIN(lvw->clips); /* possible pointer size conversion */
+ vw->clipcount = lvw->clipcount;
+ return (0);
+}
+
+static int
+bsd_to_linux_v4l_window(struct video_window *vw, struct l_video_window *lvw)
+{
+ lvw->x = vw->x;
+ lvw->y = vw->y;
+ lvw->width = vw->width;
+ lvw->height = vw->height;
+ lvw->chromakey = vw->chromakey;
+ lvw->flags = vw->flags;
+ lvw->clips = PTROUT(vw->clips); /* possible pointer size conversion */
+ lvw->clipcount = vw->clipcount;
+ return (0);
+}
+
+static int
+linux_to_bsd_v4l_buffer(struct l_video_buffer *lvb, struct video_buffer *vb)
+{
+ vb->base = PTRIN(lvb->base); /* possible pointer size conversion */
+ vb->height = lvb->height;
+ vb->width = lvb->width;
+ vb->depth = lvb->depth;
+ vb->bytesperline = lvb->bytesperline;
+ return (0);
+}
+
+static int
+bsd_to_linux_v4l_buffer(struct video_buffer *vb, struct l_video_buffer *lvb)
+{
+ lvb->base = PTROUT(vb->base); /* possible pointer size conversion */
+ lvb->height = vb->height;
+ lvb->width = vb->width;
+ lvb->depth = vb->depth;
+ lvb->bytesperline = vb->bytesperline;
+ return (0);
+}
+
+static int
+linux_to_bsd_v4l_code(struct l_video_code *lvc, struct video_code *vc)
+{
+ strlcpy(vc->loadwhat, lvc->loadwhat, LINUX_VIDEO_CODE_LOADWHAT_SIZE);
+ vc->datasize = lvc->datasize;
+ vc->data = PTRIN(lvc->data); /* possible pointer size conversion */
+ return (0);
+}
+
+#ifdef COMPAT_LINUX_V4L_CLIPLIST
+static int
+linux_v4l_clip_copy(void *lvc, struct video_clip **ppvc)
+{
+ int error;
+ struct video_clip vclip;
+ struct l_video_clip l_vclip;
+
+ error = copyin(lvc, &l_vclip, sizeof(l_vclip));
+ if (error) return (error);
+ linux_to_bsd_v4l_clip(&l_vclip, &vclip);
+ /* XXX: If there can be no concurrency: s/M_NOWAIT/M_WAITOK/ */
+ if ((*ppvc = malloc(sizeof(**ppvc), M_LINUX, M_NOWAIT)) == NULL)
+ return (ENOMEM); /* XXX: linux has no ENOMEM here */
+ memcpy(*ppvc, &vclip, sizeof(vclip));
+ (*ppvc)->next = NULL;
+ return (0);
+}
+
+static int
+linux_v4l_cliplist_free(struct video_window *vw)
+{
+ struct video_clip **ppvc;
+ struct video_clip **ppvc_next;
+
+ for (ppvc = &(vw->clips); *ppvc != NULL; ppvc = ppvc_next) {
+ ppvc_next = &((*ppvc)->next);
+ free(*ppvc, M_LINUX);
+ }
+ vw->clips = NULL;
+
+ return (0);
+}
+
+static int
+linux_v4l_cliplist_copy(struct l_video_window *lvw, struct video_window *vw)
+{
+ int error;
+ int clipcount;
+ void *plvc;
+ struct video_clip **ppvc;
+
+ /*
+ * XXX: The cliplist is used to pass in a list of clipping
+ * rectangles or, if clipcount == VIDEO_CLIP_BITMAP, a
+ * clipping bitmap. Some Linux apps, however, appear to
+ * leave cliplist and clips uninitialized. In any case,
+ * the cliplist is not used by pwc(4), at the time of
+ * writing, FreeBSD's only V4L driver. When a driver
+ * that uses the cliplist is developed, this code may
+ * need re-examiniation.
+ */
+ error = 0;
+ clipcount = vw->clipcount;
+ if (clipcount == VIDEO_CLIP_BITMAP) {
+ /*
+ * In this case, the pointer (clips) is overloaded
+ * to be a "void *" to a bitmap, therefore there
+ * is no struct video_clip to copy now.
+ */
+ } else if (clipcount > 0 && clipcount <= 16384) {
+ /*
+ * Clips points to list of clip rectangles, so
+ * copy the list.
+ *
+ * XXX: Upper limit of 16384 was used here to try to
+ * avoid cases when clipcount and clips pointer
+ * are uninitialized and therefore have high random
+ * values, as is the case in the Linux Skype
+ * application. The value 16384 was chosen as that
+ * is what is used in the Linux stradis(4) MPEG
+ * decoder driver, the only place we found an
+ * example of cliplist use.
+ */
+ plvc = PTRIN(lvw->clips);
+ vw->clips = NULL;
+ ppvc = &(vw->clips);
+ while (clipcount-- > 0) {
+ if (plvc == 0) {
+ error = EFAULT;
+ break;
+ } else {
+ error = linux_v4l_clip_copy(plvc, ppvc);
+ if (error) {
+ linux_v4l_cliplist_free(vw);
+ break;
+ }
+ }
+ ppvc = &((*ppvc)->next);
+ plvc = PTRIN(((struct l_video_clip *) plvc)->next);
+ }
+ } else {
+ /*
+ * clipcount == 0 or negative (but not VIDEO_CLIP_BITMAP)
+ * Force cliplist to null.
+ */
+ vw->clipcount = 0;
+ vw->clips = NULL;
+ }
+ return (error);
+}
+#endif
+
+static int
+linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
+{
+ struct file *fp;
+ int error;
+ struct video_tuner vtun;
+ struct video_window vwin;
+ struct video_buffer vbuf;
+ struct video_code vcode;
+ struct l_video_tuner l_vtun;
+ struct l_video_window l_vwin;
+ struct l_video_buffer l_vbuf;
+ struct l_video_code l_vcode;
+
+ switch (args->cmd & 0xffff) {
+ case LINUX_VIDIOCGCAP: args->cmd = VIDIOCGCAP; break;
+ case LINUX_VIDIOCGCHAN: args->cmd = VIDIOCGCHAN; break;
+ case LINUX_VIDIOCSCHAN: args->cmd = VIDIOCSCHAN; break;
+
+ case LINUX_VIDIOCGTUNER:
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ return (error);
+ error = copyin((void *) args->arg, &l_vtun, sizeof(l_vtun));
+ if (error) {
+ fdrop(fp, td);
+ return (error);
+ }
+ linux_to_bsd_v4l_tuner(&l_vtun, &vtun);
+ error = fo_ioctl(fp, VIDIOCGTUNER, &vtun, td->td_ucred, td);
+ if (!error) {
+ bsd_to_linux_v4l_tuner(&vtun, &l_vtun);
+ error = copyout(&l_vtun, (void *) args->arg,
+ sizeof(l_vtun));
+ }
+ fdrop(fp, td);
+ return (error);
+
+ case LINUX_VIDIOCSTUNER:
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ return (error);
+ error = copyin((void *) args->arg, &l_vtun, sizeof(l_vtun));
+ if (error) {
+ fdrop(fp, td);
+ return (error);
+ }
+ linux_to_bsd_v4l_tuner(&l_vtun, &vtun);
+ error = fo_ioctl(fp, VIDIOCSTUNER, &vtun, td->td_ucred, td);
+ fdrop(fp, td);
+ return (error);
+
+ case LINUX_VIDIOCGPICT: args->cmd = VIDIOCGPICT; break;
+ case LINUX_VIDIOCSPICT: args->cmd = VIDIOCSPICT; break;
+ case LINUX_VIDIOCCAPTURE: args->cmd = VIDIOCCAPTURE; break;
+
+ case LINUX_VIDIOCGWIN:
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ return (error);
+ error = fo_ioctl(fp, VIDIOCGWIN, &vwin, td->td_ucred, td);
+ if (!error) {
+ bsd_to_linux_v4l_window(&vwin, &l_vwin);
+ error = copyout(&l_vwin, (void *) args->arg,
+ sizeof(l_vwin));
+ }
+ fdrop(fp, td);
+ return (error);
+
+ case LINUX_VIDIOCSWIN:
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ return (error);
+ error = copyin((void *) args->arg, &l_vwin, sizeof(l_vwin));
+ if (error) {
+ fdrop(fp, td);
+ return (error);
+ }
+ linux_to_bsd_v4l_window(&l_vwin, &vwin);
+#ifdef COMPAT_LINUX_V4L_CLIPLIST
+ error = linux_v4l_cliplist_copy(&l_vwin, &vwin);
+ if (error) {
+ fdrop(fp, td);
+ return (error);
+ }
+#endif
+ error = fo_ioctl(fp, VIDIOCSWIN, &vwin, td->td_ucred, td);
+ fdrop(fp, td);
+#ifdef COMPAT_LINUX_V4L_CLIPLIST
+ linux_v4l_cliplist_free(&vwin);
+#endif
+ return (error);
+
+ case LINUX_VIDIOCGFBUF:
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ return (error);
+ error = fo_ioctl(fp, VIDIOCGFBUF, &vbuf, td->td_ucred, td);
+ if (!error) {
+ bsd_to_linux_v4l_buffer(&vbuf, &l_vbuf);
+ error = copyout(&l_vbuf, (void *) args->arg,
+ sizeof(l_vbuf));
+ }
+ fdrop(fp, td);
+ return (error);
+
+ case LINUX_VIDIOCSFBUF:
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ return (error);
+ error = copyin((void *) args->arg, &l_vbuf, sizeof(l_vbuf));
+ if (error) {
+ fdrop(fp, td);
+ return (error);
+ }
+ linux_to_bsd_v4l_buffer(&l_vbuf, &vbuf);
+ error = fo_ioctl(fp, VIDIOCSFBUF, &vbuf, td->td_ucred, td);
+ fdrop(fp, td);
+ return (error);
+
+ case LINUX_VIDIOCKEY: args->cmd = VIDIOCKEY; break;
+ case LINUX_VIDIOCGFREQ: args->cmd = VIDIOCGFREQ; break;
+ case LINUX_VIDIOCSFREQ: args->cmd = VIDIOCSFREQ; break;
+ case LINUX_VIDIOCGAUDIO: args->cmd = VIDIOCGAUDIO; break;
+ case LINUX_VIDIOCSAUDIO: args->cmd = VIDIOCSAUDIO; break;
+ case LINUX_VIDIOCSYNC: args->cmd = VIDIOCSYNC; break;
+ case LINUX_VIDIOCMCAPTURE: args->cmd = VIDIOCMCAPTURE; break;
+ case LINUX_VIDIOCGMBUF: args->cmd = VIDIOCGMBUF; break;
+ case LINUX_VIDIOCGUNIT: args->cmd = VIDIOCGUNIT; break;
+ case LINUX_VIDIOCGCAPTURE: args->cmd = VIDIOCGCAPTURE; break;
+ case LINUX_VIDIOCSCAPTURE: args->cmd = VIDIOCSCAPTURE; break;
+ case LINUX_VIDIOCSPLAYMODE: args->cmd = VIDIOCSPLAYMODE; break;
+ case LINUX_VIDIOCSWRITEMODE: args->cmd = VIDIOCSWRITEMODE; break;
+ case LINUX_VIDIOCGPLAYINFO: args->cmd = VIDIOCGPLAYINFO; break;
+
+ case LINUX_VIDIOCSMICROCODE:
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ return (error);
+ error = copyin((void *) args->arg, &l_vcode, sizeof(l_vcode));
+ if (error) {
+ fdrop(fp, td);
+ return (error);
+ }
+ linux_to_bsd_v4l_code(&l_vcode, &vcode);
+ error = fo_ioctl(fp, VIDIOCSMICROCODE, &vcode, td->td_ucred, td);
+ fdrop(fp, td);
+ return (error);
+
+ case LINUX_VIDIOCGVBIFMT: args->cmd = VIDIOCGVBIFMT; break;
+ case LINUX_VIDIOCSVBIFMT: args->cmd = VIDIOCSVBIFMT; break;
+ default: return (ENOIOCTL);
+ }
+
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ return (error);
+}
+
+/*
+ * Special ioctl handler
+ */
+static int
+linux_ioctl_special(struct thread *td, struct linux_ioctl_args *args)
+{
+ int error;
+
+ switch (args->cmd) {
+ case LINUX_SIOCGIFADDR:
+ args->cmd = SIOCGIFADDR;
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ break;
+ case LINUX_SIOCSIFADDR:
+ args->cmd = SIOCSIFADDR;
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ break;
+ case LINUX_SIOCGIFFLAGS:
+ args->cmd = SIOCGIFFLAGS;
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ break;
+ default:
+ error = ENOIOCTL;
+ }
+
+ return (error);
+}
+
+static int
+linux_to_bsd_v4l2_standard(struct l_v4l2_standard *lvstd, struct v4l2_standard *vstd)
+{
+ vstd->index = lvstd->index;
+ vstd->id = lvstd->id;
+ memcpy(&vstd->name, &lvstd->name, sizeof(*lvstd) - offsetof(struct l_v4l2_standard, name));
+ return (0);
+}
+
+static int
+bsd_to_linux_v4l2_standard(struct v4l2_standard *vstd, struct l_v4l2_standard *lvstd)
+{
+ lvstd->index = vstd->index;
+ lvstd->id = vstd->id;
+ memcpy(&lvstd->name, &vstd->name, sizeof(*lvstd) - offsetof(struct l_v4l2_standard, name));
+ return (0);
+}
+
+static int
+linux_to_bsd_v4l2_buffer(struct l_v4l2_buffer *lvb, struct v4l2_buffer *vb)
+{
+ vb->index = lvb->index;
+ vb->type = lvb->type;
+ vb->bytesused = lvb->bytesused;
+ vb->flags = lvb->flags;
+ vb->field = lvb->field;
+ vb->timestamp.tv_sec = lvb->timestamp.tv_sec;
+ vb->timestamp.tv_usec = lvb->timestamp.tv_usec;
+ memcpy(&vb->timecode, &lvb->timecode, sizeof (lvb->timecode));
+ vb->sequence = lvb->sequence;
+ vb->memory = lvb->memory;
+ if (lvb->memory == V4L2_MEMORY_USERPTR)
+ /* possible pointer size conversion */
+ vb->m.userptr = (unsigned long)PTRIN(lvb->m.userptr);
+ else
+ vb->m.offset = lvb->m.offset;
+ vb->length = lvb->length;
+ vb->input = lvb->input;
+ vb->reserved = lvb->reserved;
+ return (0);
+}
+
+static int
+bsd_to_linux_v4l2_buffer(struct v4l2_buffer *vb, struct l_v4l2_buffer *lvb)
+{
+ lvb->index = vb->index;
+ lvb->type = vb->type;
+ lvb->bytesused = vb->bytesused;
+ lvb->flags = vb->flags;
+ lvb->field = vb->field;
+ lvb->timestamp.tv_sec = vb->timestamp.tv_sec;
+ lvb->timestamp.tv_usec = vb->timestamp.tv_usec;
+ memcpy(&lvb->timecode, &vb->timecode, sizeof (vb->timecode));
+ lvb->sequence = vb->sequence;
+ lvb->memory = vb->memory;
+ if (vb->memory == V4L2_MEMORY_USERPTR)
+ /* possible pointer size conversion */
+ lvb->m.userptr = PTROUT(vb->m.userptr);
+ else
+ lvb->m.offset = vb->m.offset;
+ lvb->length = vb->length;
+ lvb->input = vb->input;
+ lvb->reserved = vb->reserved;
+ return (0);
+}
+
+static int
+linux_to_bsd_v4l2_format(struct l_v4l2_format *lvf, struct v4l2_format *vf)
+{
+ vf->type = lvf->type;
+ if (lvf->type == V4L2_BUF_TYPE_VIDEO_OVERLAY
+#ifdef V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
+ || lvf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
+#endif
+ )
+ /*
+ * XXX TODO - needs 32 -> 64 bit conversion:
+ * (unused by webcams?)
+ */
+ return EINVAL;
+ memcpy(&vf->fmt, &lvf->fmt, sizeof(vf->fmt));
+ return 0;
+}
+
+static int
+bsd_to_linux_v4l2_format(struct v4l2_format *vf, struct l_v4l2_format *lvf)
+{
+ lvf->type = vf->type;
+ if (vf->type == V4L2_BUF_TYPE_VIDEO_OVERLAY
+#ifdef V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
+ || vf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
+#endif
+ )
+ /*
+ * XXX TODO - needs 32 -> 64 bit conversion:
+ * (unused by webcams?)
+ */
+ return EINVAL;
+ memcpy(&lvf->fmt, &vf->fmt, sizeof(vf->fmt));
+ return 0;
+}
+static int
+linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args)
+{
+ struct file *fp;
+ int error;
+ struct v4l2_format vformat;
+ struct l_v4l2_format l_vformat;
+ struct v4l2_standard vstd;
+ struct l_v4l2_standard l_vstd;
+ struct l_v4l2_buffer l_vbuf;
+ struct v4l2_buffer vbuf;
+ struct v4l2_input vinp;
+
+ switch (args->cmd & 0xffff) {
+ case LINUX_VIDIOC_RESERVED:
+ case LINUX_VIDIOC_LOG_STATUS:
+ if ((args->cmd & IOC_DIRMASK) != LINUX_IOC_VOID)
+ return ENOIOCTL;
+ args->cmd = (args->cmd & 0xffff) | IOC_VOID;
+ break;
+
+ case LINUX_VIDIOC_OVERLAY:
+ case LINUX_VIDIOC_STREAMON:
+ case LINUX_VIDIOC_STREAMOFF:
+ case LINUX_VIDIOC_S_STD:
+ case LINUX_VIDIOC_S_TUNER:
+ case LINUX_VIDIOC_S_AUDIO:
+ case LINUX_VIDIOC_S_AUDOUT:
+ case LINUX_VIDIOC_S_MODULATOR:
+ case LINUX_VIDIOC_S_FREQUENCY:
+ case LINUX_VIDIOC_S_CROP:
+ case LINUX_VIDIOC_S_JPEGCOMP:
+ case LINUX_VIDIOC_S_PRIORITY:
+ case LINUX_VIDIOC_DBG_S_REGISTER:
+ case LINUX_VIDIOC_S_HW_FREQ_SEEK:
+ case LINUX_VIDIOC_SUBSCRIBE_EVENT:
+ case LINUX_VIDIOC_UNSUBSCRIBE_EVENT:
+ args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_IN;
+ break;
+
+ case LINUX_VIDIOC_QUERYCAP:
+ case LINUX_VIDIOC_G_STD:
+ case LINUX_VIDIOC_G_AUDIO:
+ case LINUX_VIDIOC_G_INPUT:
+ case LINUX_VIDIOC_G_OUTPUT:
+ case LINUX_VIDIOC_G_AUDOUT:
+ case LINUX_VIDIOC_G_JPEGCOMP:
+ case LINUX_VIDIOC_QUERYSTD:
+ case LINUX_VIDIOC_G_PRIORITY:
+ case LINUX_VIDIOC_QUERY_DV_PRESET:
+ args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_OUT;
+ break;
+
+ case LINUX_VIDIOC_ENUM_FMT:
+ case LINUX_VIDIOC_REQBUFS:
+ case LINUX_VIDIOC_G_PARM:
+ case LINUX_VIDIOC_S_PARM:
+ case LINUX_VIDIOC_G_CTRL:
+ case LINUX_VIDIOC_S_CTRL:
+ case LINUX_VIDIOC_G_TUNER:
+ case LINUX_VIDIOC_QUERYCTRL:
+ case LINUX_VIDIOC_QUERYMENU:
+ case LINUX_VIDIOC_S_INPUT:
+ case LINUX_VIDIOC_S_OUTPUT:
+ case LINUX_VIDIOC_ENUMOUTPUT:
+ case LINUX_VIDIOC_G_MODULATOR:
+ case LINUX_VIDIOC_G_FREQUENCY:
+ case LINUX_VIDIOC_CROPCAP:
+ case LINUX_VIDIOC_G_CROP:
+ case LINUX_VIDIOC_ENUMAUDIO:
+ case LINUX_VIDIOC_ENUMAUDOUT:
+ case LINUX_VIDIOC_G_SLICED_VBI_CAP:
+#ifdef VIDIOC_ENUM_FRAMESIZES
+ case LINUX_VIDIOC_ENUM_FRAMESIZES:
+ case LINUX_VIDIOC_ENUM_FRAMEINTERVALS:
+ case LINUX_VIDIOC_ENCODER_CMD:
+ case LINUX_VIDIOC_TRY_ENCODER_CMD:
+#endif
+ case LINUX_VIDIOC_DBG_G_REGISTER:
+ case LINUX_VIDIOC_DBG_G_CHIP_IDENT:
+ case LINUX_VIDIOC_ENUM_DV_PRESETS:
+ case LINUX_VIDIOC_S_DV_PRESET:
+ case LINUX_VIDIOC_G_DV_PRESET:
+ case LINUX_VIDIOC_S_DV_TIMINGS:
+ case LINUX_VIDIOC_G_DV_TIMINGS:
+ args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_INOUT;
+ break;
+
+ case LINUX_VIDIOC_G_FMT:
+ case LINUX_VIDIOC_S_FMT:
+ case LINUX_VIDIOC_TRY_FMT:
+ error = copyin((void *)args->arg, &l_vformat, sizeof(l_vformat));
+ if (error)
+ return (error);
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ return (error);
+ if (linux_to_bsd_v4l2_format(&l_vformat, &vformat) != 0)
+ error = EINVAL;
+ else if ((args->cmd & 0xffff) == LINUX_VIDIOC_G_FMT)
+ error = fo_ioctl(fp, VIDIOC_G_FMT, &vformat,
+ td->td_ucred, td);
+ else if ((args->cmd & 0xffff) == LINUX_VIDIOC_S_FMT)
+ error = fo_ioctl(fp, VIDIOC_S_FMT, &vformat,
+ td->td_ucred, td);
+ else
+ error = fo_ioctl(fp, VIDIOC_TRY_FMT, &vformat,
+ td->td_ucred, td);
+ bsd_to_linux_v4l2_format(&vformat, &l_vformat);
+ copyout(&l_vformat, (void *)args->arg, sizeof(l_vformat));
+ fdrop(fp, td);
+ return (error);
+
+ case LINUX_VIDIOC_ENUMSTD:
+ error = copyin((void *)args->arg, &l_vstd, sizeof(l_vstd));
+ if (error)
+ return (error);
+ linux_to_bsd_v4l2_standard(&l_vstd, &vstd);
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ return (error);
+ error = fo_ioctl(fp, VIDIOC_ENUMSTD, (caddr_t)&vstd,
+ td->td_ucred, td);
+ if (error) {
+ fdrop(fp, td);
+ return (error);
+ }
+ bsd_to_linux_v4l2_standard(&vstd, &l_vstd);
+ error = copyout(&l_vstd, (void *)args->arg, sizeof(l_vstd));
+ fdrop(fp, td);
+ return (error);
+
+ case LINUX_VIDIOC_ENUMINPUT:
+ /*
+ * The Linux struct l_v4l2_input differs only in size,
+ * it has no padding at the end.
+ */
+ error = copyin((void *)args->arg, &vinp,
+ sizeof(struct l_v4l2_input));
+ if (error != 0)
+ return (error);
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ return (error);
+ error = fo_ioctl(fp, VIDIOC_ENUMINPUT, (caddr_t)&vinp,
+ td->td_ucred, td);
+ if (error) {
+ fdrop(fp, td);
+ return (error);
+ }
+ error = copyout(&vinp, (void *)args->arg,
+ sizeof(struct l_v4l2_input));
+ fdrop(fp, td);
+ return (error);
+
+ case LINUX_VIDIOC_QUERYBUF:
+ case LINUX_VIDIOC_QBUF:
+ case LINUX_VIDIOC_DQBUF:
+ error = copyin((void *)args->arg, &l_vbuf, sizeof(l_vbuf));
+ if (error)
+ return (error);
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ return (error);
+ linux_to_bsd_v4l2_buffer(&l_vbuf, &vbuf);
+ if ((args->cmd & 0xffff) == LINUX_VIDIOC_QUERYBUF)
+ error = fo_ioctl(fp, VIDIOC_QUERYBUF, &vbuf,
+ td->td_ucred, td);
+ else if ((args->cmd & 0xffff) == LINUX_VIDIOC_QBUF)
+ error = fo_ioctl(fp, VIDIOC_QBUF, &vbuf,
+ td->td_ucred, td);
+ else
+ error = fo_ioctl(fp, VIDIOC_DQBUF, &vbuf,
+ td->td_ucred, td);
+ bsd_to_linux_v4l2_buffer(&vbuf, &l_vbuf);
+ copyout(&l_vbuf, (void *)args->arg, sizeof(l_vbuf));
+ fdrop(fp, td);
+ return (error);
+
+ /*
+ * XXX TODO - these need 32 -> 64 bit conversion:
+ * (are any of them needed for webcams?)
+ */
+ case LINUX_VIDIOC_G_FBUF:
+ case LINUX_VIDIOC_S_FBUF:
+
+ case LINUX_VIDIOC_G_EXT_CTRLS:
+ case LINUX_VIDIOC_S_EXT_CTRLS:
+ case LINUX_VIDIOC_TRY_EXT_CTRLS:
+
+ case LINUX_VIDIOC_DQEVENT:
+
+ default: return (ENOIOCTL);
+ }
+
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ return (error);
+}
+
+/*
+ * Support for emulators/linux-libusb. This port uses FBSD_LUSB* macros
+ * instead of USB* ones. This lets us to provide correct values for cmd.
+ * 0xffffffe0 -- 0xffffffff range seemed to be the least collision-prone.
+ */
+static int
+linux_ioctl_fbsd_usb(struct thread *td, struct linux_ioctl_args *args)
+{
+ int error;
+
+ error = 0;
+ switch (args->cmd) {
+ case FBSD_LUSB_DEVICEENUMERATE:
+ args->cmd = USB_DEVICEENUMERATE;
+ break;
+ case FBSD_LUSB_DEV_QUIRK_ADD:
+ args->cmd = USB_DEV_QUIRK_ADD;
+ break;
+ case FBSD_LUSB_DEV_QUIRK_GET:
+ args->cmd = USB_DEV_QUIRK_GET;
+ break;
+ case FBSD_LUSB_DEV_QUIRK_REMOVE:
+ args->cmd = USB_DEV_QUIRK_REMOVE;
+ break;
+ case FBSD_LUSB_DO_REQUEST:
+ args->cmd = USB_DO_REQUEST;
+ break;
+ case FBSD_LUSB_FS_CLEAR_STALL_SYNC:
+ args->cmd = USB_FS_CLEAR_STALL_SYNC;
+ break;
+ case FBSD_LUSB_FS_CLOSE:
+ args->cmd = USB_FS_CLOSE;
+ break;
+ case FBSD_LUSB_FS_COMPLETE:
+ args->cmd = USB_FS_COMPLETE;
+ break;
+ case FBSD_LUSB_FS_INIT:
+ args->cmd = USB_FS_INIT;
+ break;
+ case FBSD_LUSB_FS_OPEN:
+ args->cmd = USB_FS_OPEN;
+ break;
+ case FBSD_LUSB_FS_START:
+ args->cmd = USB_FS_START;
+ break;
+ case FBSD_LUSB_FS_STOP:
+ args->cmd = USB_FS_STOP;
+ break;
+ case FBSD_LUSB_FS_UNINIT:
+ args->cmd = USB_FS_UNINIT;
+ break;
+ case FBSD_LUSB_GET_CONFIG:
+ args->cmd = USB_GET_CONFIG;
+ break;
+ case FBSD_LUSB_GET_DEVICEINFO:
+ args->cmd = USB_GET_DEVICEINFO;
+ break;
+ case FBSD_LUSB_GET_DEVICE_DESC:
+ args->cmd = USB_GET_DEVICE_DESC;
+ break;
+ case FBSD_LUSB_GET_FULL_DESC:
+ args->cmd = USB_GET_FULL_DESC;
+ break;
+ case FBSD_LUSB_GET_IFACE_DRIVER:
+ args->cmd = USB_GET_IFACE_DRIVER;
+ break;
+ case FBSD_LUSB_GET_PLUGTIME:
+ args->cmd = USB_GET_PLUGTIME;
+ break;
+ case FBSD_LUSB_GET_POWER_MODE:
+ args->cmd = USB_GET_POWER_MODE;
+ break;
+ case FBSD_LUSB_GET_REPORT_DESC:
+ args->cmd = USB_GET_REPORT_DESC;
+ break;
+ case FBSD_LUSB_GET_REPORT_ID:
+ args->cmd = USB_GET_REPORT_ID;
+ break;
+ case FBSD_LUSB_GET_TEMPLATE:
+ args->cmd = USB_GET_TEMPLATE;
+ break;
+ case FBSD_LUSB_IFACE_DRIVER_ACTIVE:
+ args->cmd = USB_IFACE_DRIVER_ACTIVE;
+ break;
+ case FBSD_LUSB_IFACE_DRIVER_DETACH:
+ args->cmd = USB_IFACE_DRIVER_DETACH;
+ break;
+ case FBSD_LUSB_QUIRK_NAME_GET:
+ args->cmd = USB_QUIRK_NAME_GET;
+ break;
+ case FBSD_LUSB_READ_DIR:
+ args->cmd = USB_READ_DIR;
+ break;
+ case FBSD_LUSB_SET_ALTINTERFACE:
+ args->cmd = USB_SET_ALTINTERFACE;
+ break;
+ case FBSD_LUSB_SET_CONFIG:
+ args->cmd = USB_SET_CONFIG;
+ break;
+ case FBSD_LUSB_SET_IMMED:
+ args->cmd = USB_SET_IMMED;
+ break;
+ case FBSD_LUSB_SET_POWER_MODE:
+ args->cmd = USB_SET_POWER_MODE;
+ break;
+ case FBSD_LUSB_SET_TEMPLATE:
+ args->cmd = USB_SET_TEMPLATE;
+ break;
+ default:
+ error = ENOIOCTL;
+ }
+ if (error != ENOIOCTL)
+ error = sys_ioctl(td, (struct ioctl_args *)args);
+ return (error);
+}
+
+/*
+ * main ioctl syscall function
+ */
+
+int
+linux_ioctl(struct thread *td, struct linux_ioctl_args *args)
+{
+ struct file *fp;
+ struct handler_element *he;
+ int error, cmd;
+
+#ifdef DEBUG
+ if (ldebug(ioctl))
+ printf(ARGS(ioctl, "%d, %04lx, *"), args->fd,
+ (unsigned long)args->cmd);
+#endif
+
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ return (error);
+ if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
+ fdrop(fp, td);
+ return (EBADF);
+ }
+
+ /* Iterate over the ioctl handlers */
+ cmd = args->cmd & 0xffff;
+ sx_slock(&linux_ioctl_sx);
+ mtx_lock(&Giant);
+ TAILQ_FOREACH(he, &handlers, list) {
+ if (cmd >= he->low && cmd <= he->high) {
+ error = (*he->func)(td, args);
+ if (error != ENOIOCTL) {
+ mtx_unlock(&Giant);
+ sx_sunlock(&linux_ioctl_sx);
+ fdrop(fp, td);
+ return (error);
+ }
+ }
+ }
+ mtx_unlock(&Giant);
+ sx_sunlock(&linux_ioctl_sx);
+ fdrop(fp, td);
+
+ linux_msg(td, "ioctl fd=%d, cmd=0x%x ('%c',%d) is not implemented",
+ args->fd, (int)(args->cmd & 0xffff),
+ (int)(args->cmd & 0xff00) >> 8, (int)(args->cmd & 0xff));
+
+ return (EINVAL);
+}
+
+int
+linux_ioctl_register_handler(struct linux_ioctl_handler *h)
+{
+ struct handler_element *he, *cur;
+
+ if (h == NULL || h->func == NULL)
+ return (EINVAL);
+
+ /*
+ * Reuse the element if the handler is already on the list, otherwise
+ * create a new element.
+ */
+ sx_xlock(&linux_ioctl_sx);
+ TAILQ_FOREACH(he, &handlers, list) {
+ if (he->func == h->func)
+ break;
+ }
+ if (he == NULL) {
+ he = malloc(sizeof(*he),
+ M_LINUX, M_WAITOK);
+ he->func = h->func;
+ } else
+ TAILQ_REMOVE(&handlers, he, list);
+
+ /* Initialize range information. */
+ he->low = h->low;
+ he->high = h->high;
+ he->span = h->high - h->low + 1;
+
+ /* Add the element to the list, sorted on span. */
+ TAILQ_FOREACH(cur, &handlers, list) {
+ if (cur->span > he->span) {
+ TAILQ_INSERT_BEFORE(cur, he, list);
+ sx_xunlock(&linux_ioctl_sx);
+ return (0);
+ }
+ }
+ TAILQ_INSERT_TAIL(&handlers, he, list);
+ sx_xunlock(&linux_ioctl_sx);
+
+ return (0);
+}
+
+int
+linux_ioctl_unregister_handler(struct linux_ioctl_handler *h)
+{
+ struct handler_element *he;
+
+ if (h == NULL || h->func == NULL)
+ return (EINVAL);
+
+ sx_xlock(&linux_ioctl_sx);
+ TAILQ_FOREACH(he, &handlers, list) {
+ if (he->func == h->func) {
+ TAILQ_REMOVE(&handlers, he, list);
+ sx_xunlock(&linux_ioctl_sx);
+ free(he, M_LINUX);
+ return (0);
+ }
+ }
+ sx_xunlock(&linux_ioctl_sx);
+
+ return (EINVAL);
+}
diff --git a/sys/compat/linux/linux_ioctl.h b/sys/compat/linux/linux_ioctl.h
new file mode 100644
index 0000000..aa7650b
--- /dev/null
+++ b/sys/compat/linux/linux_ioctl.h
@@ -0,0 +1,767 @@
+/*-
+ * Copyright (c) 1999 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LINUX_IOCTL_H_
+#define _LINUX_IOCTL_H_
+
+/*
+ * ioctl
+ *
+ * XXX comments in Linux' <asm-generic/ioctl.h> indicate these
+ * could be arch-dependant...
+ */
+#define LINUX_IOC_VOID 0
+#define LINUX_IOC_IN 0x40000000
+#define LINUX_IOC_OUT 0x80000000
+#define LINUX_IOC_INOUT (LINUX_IOC_IN|LINUX_IOC_OUT)
+
+/*
+ * disk
+ */
+#define LINUX_BLKROSET 0x125d
+#define LINUX_BLKROGET 0x125e
+#define LINUX_BLKRRPART 0x125f
+#define LINUX_BLKGETSIZE 0x1260
+#define LINUX_BLKFLSBUF 0x1261
+#define LINUX_BLKRASET 0x1262
+#define LINUX_BLKRAGET 0x1263
+#define LINUX_BLKFRASET 0x1264
+#define LINUX_BLKFRAGET 0x1265
+#define LINUX_BLKSECTSET 0x1266
+#define LINUX_BLKSECTGET 0x1267
+#define LINUX_BLKSSZGET 0x1268
+
+#define LINUX_IOCTL_DISK_MIN LINUX_BLKROSET
+#define LINUX_IOCTL_DISK_MAX LINUX_BLKSSZGET
+
+/*
+ * hdio
+ */
+#define LINUX_HDIO_GET_GEO 0x0301
+#define LINUX_HDIO_GET_IDENTITY 0x030D /* not yet implemented */
+#define LINUX_HDIO_GET_GEO_BIG 0x0330
+
+#define LINUX_IOCTL_HDIO_MIN LINUX_HDIO_GET_GEO
+#define LINUX_IOCTL_HDIO_MAX LINUX_HDIO_GET_GEO_BIG
+
+/*
+ * cdrom
+ */
+#define LINUX_CDROMPAUSE 0x5301
+#define LINUX_CDROMRESUME 0x5302
+#define LINUX_CDROMPLAYMSF 0x5303
+#define LINUX_CDROMPLAYTRKIND 0x5304
+#define LINUX_CDROMREADTOCHDR 0x5305
+#define LINUX_CDROMREADTOCENTRY 0x5306
+#define LINUX_CDROMSTOP 0x5307
+#define LINUX_CDROMSTART 0x5308
+#define LINUX_CDROMEJECT 0x5309
+#define LINUX_CDROMVOLCTRL 0x530a
+#define LINUX_CDROMSUBCHNL 0x530b
+#define LINUX_CDROMREADMODE2 0x530c
+#define LINUX_CDROMREADMODE1 0x530d
+#define LINUX_CDROMREADAUDIO 0x530e
+#define LINUX_CDROMEJECT_SW 0x530f
+#define LINUX_CDROMMULTISESSION 0x5310
+#define LINUX_CDROM_GET_UPC 0x5311
+#define LINUX_CDROMRESET 0x5312
+#define LINUX_CDROMVOLREAD 0x5313
+#define LINUX_CDROMREADRAW 0x5314
+#define LINUX_CDROMREADCOOKED 0x5315
+#define LINUX_CDROMSEEK 0x5316
+#define LINUX_CDROMPLAYBLK 0x5317
+#define LINUX_CDROMREADALL 0x5318
+#define LINUX_CDROMCLOSETRAY 0x5319
+#define LINUX_CDROMLOADFROMSLOT 0x531a
+#define LINUX_CDROMGETSPINDOWN 0x531d
+#define LINUX_CDROMSETSPINDOWN 0x531e
+#define LINUX_CDROM_SET_OPTIONS 0x5320
+#define LINUX_CDROM_CLEAR_OPTIONS 0x5321
+#define LINUX_CDROM_SELECT_SPEED 0x5322
+#define LINUX_CDROM_SELECT_DISC 0x5323
+#define LINUX_CDROM_MEDIA_CHANGED 0x5325
+#define LINUX_CDROM_DRIVE_STATUS 0x5326
+#define LINUX_CDROM_DISC_STATUS 0x5327
+#define LINUX_CDROM_CHANGER_NSLOTS 0x5328
+#define LINUX_CDROM_LOCKDOOR 0x5329
+#define LINUX_CDROM_DEBUG 0x5330
+#define LINUX_CDROM_GET_CAPABILITY 0x5331
+#define LINUX_CDROMAUDIOBUFSIZ 0x5382
+#define LINUX_SCSI_GET_IDLUN 0x5382
+#define LINUX_SCSI_GET_BUS_NUMBER 0x5386
+#define LINUX_DVD_READ_STRUCT 0x5390
+#define LINUX_DVD_WRITE_STRUCT 0x5391
+#define LINUX_DVD_AUTH 0x5392
+#define LINUX_CDROM_SEND_PACKET 0x5393
+#define LINUX_CDROM_NEXT_WRITABLE 0x5394
+#define LINUX_CDROM_LAST_WRITTEN 0x5395
+
+#define LINUX_IOCTL_CDROM_MIN LINUX_CDROMPAUSE
+#define LINUX_IOCTL_CDROM_MAX LINUX_CDROM_LAST_WRITTEN
+
+#define LINUX_CDROM_LBA 0x01
+#define LINUX_CDROM_MSF 0x02
+
+#define LINUX_DVD_LU_SEND_AGID 0
+#define LINUX_DVD_HOST_SEND_CHALLENGE 1
+#define LINUX_DVD_LU_SEND_KEY1 2
+#define LINUX_DVD_LU_SEND_CHALLENGE 3
+#define LINUX_DVD_HOST_SEND_KEY2 4
+#define LINUX_DVD_AUTH_ESTABLISHED 5
+#define LINUX_DVD_AUTH_FAILURE 6
+#define LINUX_DVD_LU_SEND_TITLE_KEY 7
+#define LINUX_DVD_LU_SEND_ASF 8
+#define LINUX_DVD_INVALIDATE_AGID 9
+#define LINUX_DVD_LU_SEND_RPC_STATE 10
+#define LINUX_DVD_HOST_SEND_RPC_STATE 11
+
+/*
+ * SG
+ */
+#define LINUX_SG_SET_TIMEOUT 0x2201
+#define LINUX_SG_GET_TIMEOUT 0x2202
+#define LINUX_SG_EMULATED_HOST 0x2203
+#define LINUX_SG_SET_TRANSFORM 0x2204
+#define LINUX_SG_GET_TRANSFORM 0x2205
+#define LINUX_SG_GET_COMMAND_Q 0x2270
+#define LINUX_SG_SET_COMMAND_Q 0x2271
+#define LINUX_SG_SET_RESERVED_SIZE 0x2275
+#define LINUX_SG_GET_RESERVED_SIZE 0x2272
+#define LINUX_SG_GET_SCSI_ID 0x2276
+#define LINUX_SG_SET_FORCE_LOW_DMA 0x2279
+#define LINUX_SG_GET_LOW_DMA 0x227a
+#define LINUX_SG_SET_FORCE_PACK_ID 0x227b
+#define LINUX_SG_GET_PACK_ID 0x227c
+#define LINUX_SG_GET_NUM_WAITING 0x227d
+#define LINUX_SG_SET_DEBUG 0x227e
+#define LINUX_SG_GET_SG_TABLESIZE 0x227f
+#define LINUX_SG_GET_VERSION_NUM 0x2282
+#define LINUX_SG_NEXT_CMD_LEN 0x2283
+#define LINUX_SG_SCSI_RESET 0x2284
+#define LINUX_SG_IO 0x2285
+#define LINUX_SG_GET_REQUEST_TABLE 0x2286
+#define LINUX_SG_SET_KEEP_ORPHAN 0x2287
+#define LINUX_SG_GET_KEEP_ORPHAN 0x2288
+#define LINUX_SG_GET_ACCESS_COUNT 0x2289
+
+#define LINUX_IOCTL_SG_MIN 0x2200
+#define LINUX_IOCTL_SG_MAX 0x22ff
+
+/*
+ * VFAT
+ */
+#define LINUX_VFAT_READDIR_BOTH 0x7201
+
+#define LINUX_IOCTL_VFAT_MIN LINUX_VFAT_READDIR_BOTH
+#define LINUX_IOCTL_VFAT_MAX LINUX_VFAT_READDIR_BOTH
+
+/*
+ * console
+ */
+#define LINUX_KIOCSOUND 0x4B2F
+#define LINUX_KDMKTONE 0x4B30
+#define LINUX_KDGETLED 0x4B31
+#define LINUX_KDSETLED 0x4B32
+#define LINUX_KDSETMODE 0x4B3A
+#define LINUX_KDGETMODE 0x4B3B
+#define LINUX_KDGKBMODE 0x4B44
+#define LINUX_KDSKBMODE 0x4B45
+#define LINUX_VT_OPENQRY 0x5600
+#define LINUX_VT_GETMODE 0x5601
+#define LINUX_VT_SETMODE 0x5602
+#define LINUX_VT_GETSTATE 0x5603
+#define LINUX_VT_RELDISP 0x5605
+#define LINUX_VT_ACTIVATE 0x5606
+#define LINUX_VT_WAITACTIVE 0x5607
+
+#define LINUX_IOCTL_CONSOLE_MIN LINUX_KIOCSOUND
+#define LINUX_IOCTL_CONSOLE_MAX LINUX_VT_WAITACTIVE
+
+#define LINUX_LED_SCR 0x01
+#define LINUX_LED_NUM 0x02
+#define LINUX_LED_CAP 0x04
+
+#define LINUX_KD_TEXT 0x0
+#define LINUX_KD_GRAPHICS 0x1
+#define LINUX_KD_TEXT0 0x2
+#define LINUX_KD_TEXT1 0x3
+
+#define LINUX_KBD_RAW 0
+#define LINUX_KBD_XLATE 1
+#define LINUX_KBD_MEDIUMRAW 2
+
+/*
+ * socket
+ */
+#define LINUX_FIOSETOWN 0x8901
+#define LINUX_SIOCSPGRP 0x8902
+#define LINUX_FIOGETOWN 0x8903
+#define LINUX_SIOCGPGRP 0x8904
+#define LINUX_SIOCATMARK 0x8905
+#define LINUX_SIOCGSTAMP 0x8906
+#define LINUX_SIOCGIFCONF 0x8912
+#define LINUX_SIOCGIFFLAGS 0x8913
+#define LINUX_SIOCGIFADDR 0x8915
+#define LINUX_SIOCSIFADDR 0x8916
+#define LINUX_SIOCGIFDSTADDR 0x8917
+#define LINUX_SIOCGIFBRDADDR 0x8919
+#define LINUX_SIOCGIFNETMASK 0x891b
+#define LINUX_SIOCSIFNETMASK 0x891c
+#define LINUX_SIOCGIFMTU 0x8921
+#define LINUX_SIOCSIFMTU 0x8922
+#define LINUX_SIOCSIFNAME 0x8923
+#define LINUX_SIOCSIFHWADDR 0x8924
+#define LINUX_SIOCGIFHWADDR 0x8927
+#define LINUX_SIOCADDMULTI 0x8931
+#define LINUX_SIOCDELMULTI 0x8932
+#define LINUX_SIOCGIFINDEX 0x8933
+#define LINUX_SIOGIFINDEX LINUX_SIOCGIFINDEX
+#define LINUX_SIOCGIFCOUNT 0x8938
+
+#define LINUX_IOCTL_SOCKET_MIN LINUX_FIOSETOWN
+#define LINUX_IOCTL_SOCKET_MAX LINUX_SIOCGIFCOUNT
+
+/*
+ * Device private ioctl calls
+ */
+#define LINUX_SIOCDEVPRIVATE 0x89F0 /* to 89FF */
+#define LINUX_IOCTL_PRIVATE_MIN LINUX_SIOCDEVPRIVATE
+#define LINUX_IOCTL_PRIVATE_MAX LINUX_SIOCDEVPRIVATE+0xf
+
+/*
+ * sound
+ */
+#define LINUX_SOUND_MIXER_WRITE_VOLUME 0x4d00
+#define LINUX_SOUND_MIXER_WRITE_BASS 0x4d01
+#define LINUX_SOUND_MIXER_WRITE_TREBLE 0x4d02
+#define LINUX_SOUND_MIXER_WRITE_SYNTH 0x4d03
+#define LINUX_SOUND_MIXER_WRITE_PCM 0x4d04
+#define LINUX_SOUND_MIXER_WRITE_SPEAKER 0x4d05
+#define LINUX_SOUND_MIXER_WRITE_LINE 0x4d06
+#define LINUX_SOUND_MIXER_WRITE_MIC 0x4d07
+#define LINUX_SOUND_MIXER_WRITE_CD 0x4d08
+#define LINUX_SOUND_MIXER_WRITE_IMIX 0x4d09
+#define LINUX_SOUND_MIXER_WRITE_ALTPCM 0x4d0A
+#define LINUX_SOUND_MIXER_WRITE_RECLEV 0x4d0B
+#define LINUX_SOUND_MIXER_WRITE_IGAIN 0x4d0C
+#define LINUX_SOUND_MIXER_WRITE_OGAIN 0x4d0D
+#define LINUX_SOUND_MIXER_WRITE_LINE1 0x4d0E
+#define LINUX_SOUND_MIXER_WRITE_LINE2 0x4d0F
+#define LINUX_SOUND_MIXER_WRITE_LINE3 0x4d10
+#define LINUX_SOUND_MIXER_INFO 0x4d65
+#define LINUX_OSS_GETVERSION 0x4d76
+#define LINUX_SOUND_MIXER_READ_STEREODEVS 0x4dfb
+#define LINUX_SOUND_MIXER_READ_CAPS 0x4dfc
+#define LINUX_SOUND_MIXER_READ_RECMASK 0x4dfd
+#define LINUX_SOUND_MIXER_READ_DEVMASK 0x4dfe
+#define LINUX_SOUND_MIXER_WRITE_RECSRC 0x4dff
+#define LINUX_SNDCTL_DSP_RESET 0x5000
+#define LINUX_SNDCTL_DSP_SYNC 0x5001
+#define LINUX_SNDCTL_DSP_SPEED 0x5002
+#define LINUX_SNDCTL_DSP_STEREO 0x5003
+#define LINUX_SNDCTL_DSP_GETBLKSIZE 0x5004
+#define LINUX_SNDCTL_DSP_SETBLKSIZE LINUX_SNDCTL_DSP_GETBLKSIZE
+#define LINUX_SNDCTL_DSP_SETFMT 0x5005
+#define LINUX_SOUND_PCM_WRITE_CHANNELS 0x5006
+#define LINUX_SOUND_PCM_WRITE_FILTER 0x5007
+#define LINUX_SNDCTL_DSP_POST 0x5008
+#define LINUX_SNDCTL_DSP_SUBDIVIDE 0x5009
+#define LINUX_SNDCTL_DSP_SETFRAGMENT 0x500A
+#define LINUX_SNDCTL_DSP_GETFMTS 0x500B
+#define LINUX_SNDCTL_DSP_GETOSPACE 0x500C
+#define LINUX_SNDCTL_DSP_GETISPACE 0x500D
+#define LINUX_SNDCTL_DSP_NONBLOCK 0x500E
+#define LINUX_SNDCTL_DSP_GETCAPS 0x500F
+#define LINUX_SNDCTL_DSP_GETTRIGGER 0x5010
+#define LINUX_SNDCTL_DSP_SETTRIGGER LINUX_SNDCTL_DSP_GETTRIGGER
+#define LINUX_SNDCTL_DSP_GETIPTR 0x5011
+#define LINUX_SNDCTL_DSP_GETOPTR 0x5012
+#define LINUX_SNDCTL_DSP_SETDUPLEX 0x5016
+#define LINUX_SNDCTL_DSP_GETODELAY 0x5017
+#define LINUX_SNDCTL_SEQ_RESET 0x5100
+#define LINUX_SNDCTL_SEQ_SYNC 0x5101
+#define LINUX_SNDCTL_SYNTH_INFO 0x5102
+#define LINUX_SNDCTL_SEQ_CTRLRATE 0x5103
+#define LINUX_SNDCTL_SEQ_GETOUTCOUNT 0x5104
+#define LINUX_SNDCTL_SEQ_GETINCOUNT 0x5105
+#define LINUX_SNDCTL_SEQ_PERCMODE 0x5106
+#define LINUX_SNDCTL_FM_LOAD_INSTR 0x5107
+#define LINUX_SNDCTL_SEQ_TESTMIDI 0x5108
+#define LINUX_SNDCTL_SEQ_RESETSAMPLES 0x5109
+#define LINUX_SNDCTL_SEQ_NRSYNTHS 0x510A
+#define LINUX_SNDCTL_SEQ_NRMIDIS 0x510B
+#define LINUX_SNDCTL_MIDI_INFO 0x510C
+#define LINUX_SNDCTL_SEQ_TRESHOLD 0x510D
+#define LINUX_SNDCTL_SYNTH_MEMAVL 0x510E
+
+#define LINUX_IOCTL_SOUND_MIN LINUX_SOUND_MIXER_WRITE_VOLUME
+#define LINUX_IOCTL_SOUND_MAX LINUX_SNDCTL_SYNTH_MEMAVL
+
+/*
+ * termio
+ */
+#define LINUX_TCGETS 0x5401
+#define LINUX_TCSETS 0x5402
+#define LINUX_TCSETSW 0x5403
+#define LINUX_TCSETSF 0x5404
+#define LINUX_TCGETA 0x5405
+#define LINUX_TCSETA 0x5406
+#define LINUX_TCSETAW 0x5407
+#define LINUX_TCSETAF 0x5408
+#define LINUX_TCSBRK 0x5409
+#define LINUX_TCXONC 0x540A
+#define LINUX_TCFLSH 0x540B
+
+#define LINUX_TIOCEXCL 0x540C
+#define LINUX_TIOCNXCL 0x540D
+#define LINUX_TIOCSCTTY 0x540E
+
+#define LINUX_TIOCGPGRP 0x540F
+#define LINUX_TIOCSPGRP 0x5410
+
+#define LINUX_TIOCOUTQ 0x5411
+#define LINUX_TIOCSTI 0x5412
+
+#define LINUX_TIOCGWINSZ 0x5413
+#define LINUX_TIOCSWINSZ 0x5414
+
+#define LINUX_TIOCMGET 0x5415
+#define LINUX_TIOCMBIS 0x5416
+#define LINUX_TIOCMBIC 0x5417
+#define LINUX_TIOCMSET 0x5418
+#define LINUX_TIOCGSOFTCAR 0x5419
+#define LINUX_TIOCSSOFTCAR 0x541A
+
+#define LINUX_FIONREAD 0x541B
+
+#define LINUX_TIOCINQ FIONREAD
+#define LINUX_TIOCLINUX 0x541C
+#define LINUX_TIOCCONS 0x541D
+#define LINUX_TIOCGSERIAL 0x541E
+#define LINUX_TIOCSSERIAL 0x541F
+#define LINUX_TIOCPKT 0x5420
+
+#define LINUX_FIONBIO 0x5421
+
+#define LINUX_TIOCNOTTY 0x5422
+#define LINUX_TIOCSETD 0x5423
+#define LINUX_TIOCGETD 0x5424
+#define LINUX_TCSBRKP 0x5425
+#define LINUX_TIOCTTYGSTRUCT 0x5426
+
+#define LINUX_TIOCSBRK 0x5427
+#define LINUX_TIOCCBRK 0x5428
+
+#define LINUX_TIOCGPTN 0x5430
+#define LINUX_TIOCSPTLCK 0x5431
+
+#define LINUX_FIONCLEX 0x5450
+#define LINUX_FIOCLEX 0x5451
+#define LINUX_FIOASYNC 0x5452
+
+#define LINUX_TIOCSERCONFIG 0x5453
+#define LINUX_TIOCSERGWILD 0x5454
+#define LINUX_TIOCSERSWILD 0x5455
+#define LINUX_TIOCGLCKTRMIOS 0x5456
+#define LINUX_TIOCSLCKTRMIOS 0x5457
+
+#define LINUX_IOCTL_TERMIO_MIN LINUX_TCGETS
+#define LINUX_IOCTL_TERMIO_MAX LINUX_TIOCSLCKTRMIOS
+
+/* arguments for tcflow() and LINUX_TCXONC */
+#define LINUX_TCOOFF 0
+#define LINUX_TCOON 1
+#define LINUX_TCIOFF 2
+#define LINUX_TCION 3
+
+/* arguments for tcflush() and LINUX_TCFLSH */
+#define LINUX_TCIFLUSH 0
+#define LINUX_TCOFLUSH 1
+#define LINUX_TCIOFLUSH 2
+
+/* line disciplines */
+#define LINUX_N_TTY 0
+#define LINUX_N_SLIP 1
+#define LINUX_N_MOUSE 2
+#define LINUX_N_PPP 3
+
+/* Linux termio c_cc values */
+#define LINUX_VINTR 0
+#define LINUX_VQUIT 1
+#define LINUX_VERASE 2
+#define LINUX_VKILL 3
+#define LINUX_VEOF 4
+#define LINUX_VTIME 5
+#define LINUX_VMIN 6
+#define LINUX_VSWTC 7
+#define LINUX_NCC 8
+
+/* Linux termios c_cc values */
+/* In addition to the termio values */
+#define LINUX_VSTART 8
+#define LINUX_VSTOP 9
+#define LINUX_VSUSP 10
+#define LINUX_VEOL 11
+#define LINUX_VREPRINT 12
+#define LINUX_VDISCARD 13
+#define LINUX_VWERASE 14
+#define LINUX_VLNEXT 15
+#define LINUX_VEOL2 16
+#define LINUX_NCCS 19
+
+#define LINUX_POSIX_VDISABLE '\0'
+
+/* Linux c_iflag masks */
+#define LINUX_IGNBRK 0x0000001
+#define LINUX_BRKINT 0x0000002
+#define LINUX_IGNPAR 0x0000004
+#define LINUX_PARMRK 0x0000008
+#define LINUX_INPCK 0x0000010
+#define LINUX_ISTRIP 0x0000020
+#define LINUX_INLCR 0x0000040
+#define LINUX_IGNCR 0x0000080
+#define LINUX_ICRNL 0x0000100
+
+#define LINUX_IUCLC 0x0000200
+#define LINUX_IXON 0x0000400
+#define LINUX_IXANY 0x0000800
+#define LINUX_IXOFF 0x0001000
+
+#define LINUX_IMAXBEL 0x0002000
+
+/* Linux c_oflag masks */
+#define LINUX_OPOST 0x0000001
+
+#define LINUX_OLCUC 0x0000002
+#define LINUX_ONLCR 0x0000004
+
+#define LINUX_OCRNL 0x0000008
+#define LINUX_ONOCR 0x0000010
+#define LINUX_ONLRET 0x0000020
+#define LINUX_OFILL 0x0000040
+#define LINUX_OFDEL 0x0000080
+
+#define LINUX_NLDLY 0x0000100
+#define LINUX_NL0 0x0000000
+#define LINUX_NL1 0x0000100
+#define LINUX_CRDLY 0x0000600
+#define LINUX_CR0 0x0000000
+#define LINUX_CR1 0x0000200
+#define LINUX_CR2 0x0000400
+#define LINUX_CR3 0x0000600
+#define LINUX_TABDLY 0x0001800
+#define LINUX_TAB0 0x0000000
+#define LINUX_TAB1 0x0000800
+#define LINUX_TAB2 0x0001000
+#define LINUX_TAB3 0x0001800
+#define LINUX_XTABS 0x0001800
+#define LINUX_BSDLY 0x0002000
+#define LINUX_BS0 0x0000000
+#define LINUX_BS1 0x0002000
+#define LINUX_VTDLY 0x0004000
+#define LINUX_VT0 0x0000000
+#define LINUX_VT1 0x0004000
+#define LINUX_FFDLY 0x0008000
+#define LINUX_FF0 0x0000000
+#define LINUX_FF1 0x0008000
+
+#define LINUX_CBAUD 0x0000100f
+
+#define LINUX_B0 0x00000000
+#define LINUX_B50 0x00000001
+#define LINUX_B75 0x00000002
+#define LINUX_B110 0x00000003
+#define LINUX_B134 0x00000004
+#define LINUX_B150 0x00000005
+#define LINUX_B200 0x00000006
+#define LINUX_B300 0x00000007
+#define LINUX_B600 0x00000008
+#define LINUX_B1200 0x00000009
+#define LINUX_B1800 0x0000000a
+#define LINUX_B2400 0x0000000b
+#define LINUX_B4800 0x0000000c
+#define LINUX_B9600 0x0000000d
+#define LINUX_B19200 0x0000000e
+#define LINUX_B38400 0x0000000f
+#define LINUX_EXTA LINUX_B19200
+#define LINUX_EXTB LINUX_B38400
+
+#define LINUX_CBAUDEX 0x00001000
+#define LINUX_B57600 0x00001001
+#define LINUX_B115200 0x00001002
+
+#define LINUX_CSIZE 0x00000030
+#define LINUX_CS5 0x00000000
+#define LINUX_CS6 0x00000010
+#define LINUX_CS7 0x00000020
+#define LINUX_CS8 0x00000030
+#define LINUX_CSTOPB 0x00000040
+#define LINUX_CREAD 0x00000080
+#define LINUX_PARENB 0x00000100
+#define LINUX_PARODD 0x00000200
+#define LINUX_HUPCL 0x00000400
+#define LINUX_CLOCAL 0x00000800
+
+#define LINUX_CRTSCTS 0x80000000
+
+/* Linux c_lflag masks */
+#define LINUX_ISIG 0x00000001
+#define LINUX_ICANON 0x00000002
+#define LINUX_XCASE 0x00000004
+#define LINUX_ECHO 0x00000008
+#define LINUX_ECHOE 0x00000010
+#define LINUX_ECHOK 0x00000020
+#define LINUX_ECHONL 0x00000040
+#define LINUX_NOFLSH 0x00000080
+#define LINUX_TOSTOP 0x00000100
+#define LINUX_ECHOCTL 0x00000200
+#define LINUX_ECHOPRT 0x00000400
+#define LINUX_ECHOKE 0x00000800
+#define LINUX_FLUSHO 0x00001000
+#define LINUX_PENDIN 0x00002000
+#define LINUX_IEXTEN 0x00008000
+
+/* serial_struct values for TIOC[GS]SERIAL ioctls */
+#define LINUX_ASYNC_CLOSING_WAIT_INF 0
+#define LINUX_ASYNC_CLOSING_WAIT_NONE 65535
+
+#define LINUX_PORT_UNKNOWN 0
+#define LINUX_PORT_8250 1
+#define LINUX_PORT_16450 2
+#define LINUX_PORT_16550 3
+#define LINUX_PORT_16550A 4
+#define LINUX_PORT_CIRRUS 5
+#define LINUX_PORT_16650 6
+
+#define LINUX_PORT_MAX 6
+
+#define LINUX_ASYNC_HUP_NOTIFY 0x0001
+#define LINUX_ASYNC_FOURPORT 0x0002
+#define LINUX_ASYNC_SAK 0x0004
+#define LINUX_ASYNC_SPLIT_TERMIOS 0x0008
+#define LINUX_ASYNC_SPD_MASK 0x0030
+#define LINUX_ASYNC_SPD_HI 0x0010
+#define LINUX_ASYNC_SPD_VHI 0x0020
+#define LINUX_ASYNC_SPD_CUST 0x0030
+#define LINUX_ASYNC_SKIP_TEST 0x0040
+#define LINUX_ASYNC_AUTO_IRQ 0x0080
+#define LINUX_ASYNC_SESSION_LOCKOUT 0x0100
+#define LINUX_ASYNC_PGRP_LOCKOUT 0x0200
+#define LINUX_ASYNC_CALLOUT_NOHUP 0x0400
+#define LINUX_ASYNC_FLAGS 0x0FFF
+
+#define LINUX_IOCTL_DRM_MIN 0x6400
+#define LINUX_IOCTL_DRM_MAX 0x64ff
+
+/*
+ * This doesn't really belong here, but I can't think of a better
+ * place to put it.
+ */
+struct ifnet;
+int linux_ifname(struct ifnet *, char *, size_t);
+
+/*
+ * video
+ */
+#define LINUX_VIDIOCGCAP 0x7601
+#define LINUX_VIDIOCGCHAN 0x7602
+#define LINUX_VIDIOCSCHAN 0x7603
+#define LINUX_VIDIOCGTUNER 0x7604
+#define LINUX_VIDIOCSTUNER 0x7605
+#define LINUX_VIDIOCGPICT 0x7606
+#define LINUX_VIDIOCSPICT 0x7607
+#define LINUX_VIDIOCCAPTURE 0x7608
+#define LINUX_VIDIOCGWIN 0x7609
+#define LINUX_VIDIOCSWIN 0x760a
+#define LINUX_VIDIOCGFBUF 0x760b
+#define LINUX_VIDIOCSFBUF 0x760c
+#define LINUX_VIDIOCKEY 0x760d
+#define LINUX_VIDIOCGFREQ 0x760e
+#define LINUX_VIDIOCSFREQ 0x760f
+#define LINUX_VIDIOCGAUDIO 0x7610
+#define LINUX_VIDIOCSAUDIO 0x7611
+#define LINUX_VIDIOCSYNC 0x7623
+#define LINUX_VIDIOCMCAPTURE 0x7613
+#define LINUX_VIDIOCGMBUF 0x7614
+#define LINUX_VIDIOCGUNIT 0x7615
+#define LINUX_VIDIOCGCAPTURE 0x7616
+#define LINUX_VIDIOCSCAPTURE 0x7617
+#define LINUX_VIDIOCSPLAYMODE 0x7618
+#define LINUX_VIDIOCSWRITEMODE 0x7619
+#define LINUX_VIDIOCGPLAYINFO 0x761a
+#define LINUX_VIDIOCSMICROCODE 0x761b
+#define LINUX_VIDIOCGVBIFMT 0x761c
+#define LINUX_VIDIOCSVBIFMT 0x761d
+
+#define LINUX_IOCTL_VIDEO_MIN LINUX_VIDIOCGCAP
+#define LINUX_IOCTL_VIDEO_MAX LINUX_VIDIOCSVBIFMT
+
+/* videodev2 aka V4L2 */
+
+#define LINUX_VIDIOC_QUERYCAP 0x5600 /* 0x80685600 */
+#define LINUX_VIDIOC_RESERVED 0x5601 /* 0x00005601 */
+#define LINUX_VIDIOC_ENUM_FMT 0x5602 /* 0xc0405602 */
+#define LINUX_VIDIOC_G_FMT 0x5604 /* 0xc0cc5604 */
+#define LINUX_VIDIOC_S_FMT 0x5605 /* 0xc0cc5605 */
+#define LINUX_VIDIOC_REQBUFS 0x5608 /* 0xc0145608 */
+#define LINUX_VIDIOC_QUERYBUF 0x5609 /* 0xc0445609 */
+#define LINUX_VIDIOC_G_FBUF 0x560a /* 0x802c560a */
+#define LINUX_VIDIOC_S_FBUF 0x560b /* 0x402c560b */
+#define LINUX_VIDIOC_OVERLAY 0x560e /* 0x4004560e */
+#define LINUX_VIDIOC_QBUF 0x560f /* 0xc044560f */
+#define LINUX_VIDIOC_DQBUF 0x5611 /* 0xc0445611 */
+#define LINUX_VIDIOC_STREAMON 0x5612 /* 0x40045612 */
+#define LINUX_VIDIOC_STREAMOFF 0x5613 /* 0x40045613 */
+#define LINUX_VIDIOC_G_PARM 0x5615 /* 0xc0cc5615 */
+#define LINUX_VIDIOC_S_PARM 0x5616 /* 0xc0cc5616 */
+#define LINUX_VIDIOC_G_STD 0x5617 /* 0x80085617 */
+#define LINUX_VIDIOC_S_STD 0x5618 /* 0x40085618 */
+#define LINUX_VIDIOC_ENUMSTD 0x5619 /* 0xc0405619 */
+#define LINUX_VIDIOC_ENUMINPUT 0x561a /* 0xc04c561a */
+#define LINUX_VIDIOC_G_CTRL 0x561b /* 0xc008561b */
+#define LINUX_VIDIOC_S_CTRL 0x561c /* 0xc008561c */
+#define LINUX_VIDIOC_G_TUNER 0x561d /* 0xc054561d */
+#define LINUX_VIDIOC_S_TUNER 0x561e /* 0x4054561e */
+#define LINUX_VIDIOC_G_AUDIO 0x5621 /* 0x80345621 */
+#define LINUX_VIDIOC_S_AUDIO 0x5622 /* 0x40345622 */
+#define LINUX_VIDIOC_QUERYCTRL 0x5624 /* 0xc0445624 */
+#define LINUX_VIDIOC_QUERYMENU 0x5625 /* 0xc02c5625 */
+#define LINUX_VIDIOC_G_INPUT 0x5626 /* 0x80045626 */
+#define LINUX_VIDIOC_S_INPUT 0x5627 /* 0xc0045627 */
+#define LINUX_VIDIOC_G_OUTPUT 0x562e /* 0x8004562e */
+#define LINUX_VIDIOC_S_OUTPUT 0x562f /* 0xc004562f */
+#define LINUX_VIDIOC_ENUMOUTPUT 0x5630 /* 0xc0485630 */
+#define LINUX_VIDIOC_G_AUDOUT 0x5631 /* 0x80345631 */
+#define LINUX_VIDIOC_S_AUDOUT 0x5632 /* 0x40345632 */
+#define LINUX_VIDIOC_G_MODULATOR 0x5636 /* 0xc0445636 */
+#define LINUX_VIDIOC_S_MODULATOR 0x5637 /* 0x40445637 */
+#define LINUX_VIDIOC_G_FREQUENCY 0x5638 /* 0xc02c5638 */
+#define LINUX_VIDIOC_S_FREQUENCY 0x5639 /* 0x402c5639 */
+#define LINUX_VIDIOC_CROPCAP 0x563a /* 0xc02c563a */
+#define LINUX_VIDIOC_G_CROP 0x563b /* 0xc014563b */
+#define LINUX_VIDIOC_S_CROP 0x563c /* 0x4014563c */
+#define LINUX_VIDIOC_G_JPEGCOMP 0x563d /* 0x808c563d */
+#define LINUX_VIDIOC_S_JPEGCOMP 0x563e /* 0x408c563e */
+#define LINUX_VIDIOC_QUERYSTD 0x563f /* 0x8008563f */
+#define LINUX_VIDIOC_TRY_FMT 0x5640 /* 0xc0cc5640 */
+#define LINUX_VIDIOC_ENUMAUDIO 0x5641 /* 0xc0345641 */
+#define LINUX_VIDIOC_ENUMAUDOUT 0x5642 /* 0xc0345642 */
+#define LINUX_VIDIOC_G_PRIORITY 0x5643 /* 0x80045643 */
+#define LINUX_VIDIOC_S_PRIORITY 0x5644 /* 0x40045644 */
+#define LINUX_VIDIOC_G_SLICED_VBI_CAP 0x5645 /* 0xc0745645 */
+#define LINUX_VIDIOC_LOG_STATUS 0x5646 /* 0x00005646 */
+#define LINUX_VIDIOC_G_EXT_CTRLS 0x5647 /* 0xc0185647 */
+#define LINUX_VIDIOC_S_EXT_CTRLS 0x5648 /* 0xc0185648 */
+#define LINUX_VIDIOC_TRY_EXT_CTRLS 0x5649 /* 0xc0185649 */
+#define LINUX_VIDIOC_ENUM_FRAMESIZES 0x564a /* 0xc02c564a */
+#define LINUX_VIDIOC_ENUM_FRAMEINTERVALS 0x564b /* 0xc034564b */
+#define LINUX_VIDIOC_G_ENC_INDEX 0x564c /* 0x8818564c */
+#define LINUX_VIDIOC_ENCODER_CMD 0x564d /* 0xc028564d */
+#define LINUX_VIDIOC_TRY_ENCODER_CMD 0x564e /* 0xc028564e */
+#define LINUX_VIDIOC_DBG_S_REGISTER 0x564f /* 0x4038564f */
+#define LINUX_VIDIOC_DBG_G_REGISTER 0x5650 /* 0xc0385650 */
+#define LINUX_VIDIOC_DBG_G_CHIP_IDENT 0x5651 /* 0xc02c5651 */
+#define LINUX_VIDIOC_S_HW_FREQ_SEEK 0x5652 /* 0x40305652 */
+#define LINUX_VIDIOC_ENUM_DV_PRESETS 0x5653 /* 0xc0405653 */
+#define LINUX_VIDIOC_S_DV_PRESET 0x5654 /* 0xc0145654 */
+#define LINUX_VIDIOC_G_DV_PRESET 0x5655 /* 0xc0145655 */
+#define LINUX_VIDIOC_QUERY_DV_PRESET 0x5656 /* 0x80145656 */
+#define LINUX_VIDIOC_S_DV_TIMINGS 0x5657 /* 0xc0845657 */
+#define LINUX_VIDIOC_G_DV_TIMINGS 0x5658 /* 0xc0845658 */
+#define LINUX_VIDIOC_DQEVENT 0x5659 /* 0x80785659 */
+#define LINUX_VIDIOC_SUBSCRIBE_EVENT 0x565a /* 0x4020565a */
+#define LINUX_VIDIOC_UNSUBSCRIBE_EVENT 0x565b /* 0x4020565b */
+
+#define LINUX_VIDIOC_OVERLAY_OLD 0x560e /* 0xc004560e */
+#define LINUX_VIDIOC_S_PARM_OLD 0x5616 /* 0x40cc5616 */
+#define LINUX_VIDIOC_S_CTRL_OLD 0x561c /* 0x4008561c */
+#define LINUX_VIDIOC_G_AUDIO_OLD 0x5621 /* 0xc0345621 */
+#define LINUX_VIDIOC_G_AUDOUT_OLD 0x5631 /* 0xc0345631 */
+#define LINUX_VIDIOC_CROPCAP_OLD 0x563a /* 0x802c563a */
+
+#define LINUX_IOCTL_VIDEO2_MIN LINUX_VIDIOC_QUERYCAP
+#define LINUX_IOCTL_VIDEO2_MAX LINUX_VIDIOC_UNSUBSCRIBE_EVENT
+
+/*
+ * Our libusb(8) calls emulated within linux(4).
+ */
+#define FBSD_LUSB_DEVICEENUMERATE 0xffff
+#define FBSD_LUSB_DEV_QUIRK_ADD 0xfffe
+#define FBSD_LUSB_DEV_QUIRK_GET 0xfffd
+#define FBSD_LUSB_DEV_QUIRK_REMOVE 0xfffc
+#define FBSD_LUSB_DO_REQUEST 0xfffb
+#define FBSD_LUSB_FS_CLEAR_STALL_SYNC 0xfffa
+#define FBSD_LUSB_FS_CLOSE 0xfff9
+#define FBSD_LUSB_FS_COMPLETE 0xfff8
+#define FBSD_LUSB_FS_INIT 0xfff7
+#define FBSD_LUSB_FS_OPEN 0xfff6
+#define FBSD_LUSB_FS_START 0xfff5
+#define FBSD_LUSB_FS_STOP 0xfff4
+#define FBSD_LUSB_FS_UNINIT 0xfff3
+#define FBSD_LUSB_GET_CONFIG 0xfff2
+#define FBSD_LUSB_GET_DEVICEINFO 0xfff1
+#define FBSD_LUSB_GET_DEVICE_DESC 0xfff0
+#define FBSD_LUSB_GET_FULL_DESC 0xffef
+#define FBSD_LUSB_GET_IFACE_DRIVER 0xffee
+#define FBSD_LUSB_GET_PLUGTIME 0xffed
+#define FBSD_LUSB_GET_POWER_MODE 0xffec
+#define FBSD_LUSB_GET_REPORT_DESC 0xffeb
+#define FBSD_LUSB_GET_REPORT_ID 0xffea
+#define FBSD_LUSB_GET_TEMPLATE 0xffe9
+#define FBSD_LUSB_IFACE_DRIVER_ACTIVE 0xffe8
+#define FBSD_LUSB_IFACE_DRIVER_DETACH 0xffe7
+#define FBSD_LUSB_QUIRK_NAME_GET 0xffe6
+#define FBSD_LUSB_READ_DIR 0xffe5
+#define FBSD_LUSB_SET_ALTINTERFACE 0xffe4
+#define FBSD_LUSB_SET_CONFIG 0xffe3
+#define FBSD_LUSB_SET_IMMED 0xffe2
+#define FBSD_LUSB_SET_POWER_MODE 0xffe1
+#define FBSD_LUSB_SET_TEMPLATE 0xffe0
+
+#define FBSD_LUSB_MAX 0xffff
+#define FBSD_LUSB_MIN 0xffe0
+
+/*
+ * Pluggable ioctl handlers
+ */
+struct linux_ioctl_args;
+struct thread;
+
+typedef int linux_ioctl_function_t(struct thread *, struct linux_ioctl_args *);
+
+struct linux_ioctl_handler {
+ linux_ioctl_function_t *func;
+ int low, high;
+};
+
+int linux_ioctl_register_handler(struct linux_ioctl_handler *h);
+int linux_ioctl_unregister_handler(struct linux_ioctl_handler *h);
+
+#endif /* !_LINUX_IOCTL_H_ */
diff --git a/sys/compat/linux/linux_ipc.c b/sys/compat/linux/linux_ipc.c
new file mode 100644
index 0000000..1237edc
--- /dev/null
+++ b/sys/compat/linux/linux_ipc.c
@@ -0,0 +1,899 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysproto.h>
+#include <sys/proc.h>
+#include <sys/limits.h>
+#include <sys/msg.h>
+#include <sys/sem.h>
+#include <sys/shm.h>
+
+#include "opt_compat.h"
+
+#ifdef COMPAT_LINUX32
+#include <machine/../linux32/linux.h>
+#include <machine/../linux32/linux32_proto.h>
+#include <machine/../linux32/linux32_ipc64.h>
+#else
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#include <machine/../linux/linux_ipc64.h>
+#endif
+#include <compat/linux/linux_ipc.h>
+#include <compat/linux/linux_util.h>
+
+struct l_seminfo {
+ l_int semmap;
+ l_int semmni;
+ l_int semmns;
+ l_int semmnu;
+ l_int semmsl;
+ l_int semopm;
+ l_int semume;
+ l_int semusz;
+ l_int semvmx;
+ l_int semaem;
+};
+
+struct l_shminfo {
+ l_int shmmax;
+ l_int shmmin;
+ l_int shmmni;
+ l_int shmseg;
+ l_int shmall;
+};
+
+struct l_shm_info {
+ l_int used_ids;
+ l_ulong shm_tot; /* total allocated shm */
+ l_ulong shm_rss; /* total resident shm */
+ l_ulong shm_swp; /* total swapped shm */
+ l_ulong swap_attempts;
+ l_ulong swap_successes;
+};
+
+struct l_msginfo {
+ l_int msgpool;
+ l_int msgmap;
+ l_int msgmax;
+ l_int msgmnb;
+ l_int msgmni;
+ l_int msgssz;
+ l_int msgtql;
+ l_ushort msgseg;
+};
+
+static void
+bsd_to_linux_shminfo( struct shminfo *bpp, struct l_shminfo *lpp)
+{
+
+ lpp->shmmax = bpp->shmmax;
+ lpp->shmmin = bpp->shmmin;
+ lpp->shmmni = bpp->shmmni;
+ lpp->shmseg = bpp->shmseg;
+ lpp->shmall = bpp->shmall;
+}
+
+static void
+bsd_to_linux_shm_info( struct shm_info *bpp, struct l_shm_info *lpp)
+{
+
+ lpp->used_ids = bpp->used_ids ;
+ lpp->shm_tot = bpp->shm_tot ;
+ lpp->shm_rss = bpp->shm_rss ;
+ lpp->shm_swp = bpp->shm_swp ;
+ lpp->swap_attempts = bpp->swap_attempts ;
+ lpp->swap_successes = bpp->swap_successes ;
+}
+
+struct l_ipc_perm {
+ l_key_t key;
+ l_uid16_t uid;
+ l_gid16_t gid;
+ l_uid16_t cuid;
+ l_gid16_t cgid;
+ l_ushort mode;
+ l_ushort seq;
+};
+
+static void
+linux_to_bsd_ipc_perm(struct l_ipc_perm *lpp, struct ipc_perm *bpp)
+{
+
+ bpp->key = lpp->key;
+ bpp->uid = lpp->uid;
+ bpp->gid = lpp->gid;
+ bpp->cuid = lpp->cuid;
+ bpp->cgid = lpp->cgid;
+ bpp->mode = lpp->mode;
+ bpp->seq = lpp->seq;
+}
+
+
+static void
+bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct l_ipc_perm *lpp)
+{
+
+ lpp->key = bpp->key;
+ lpp->uid = bpp->uid;
+ lpp->gid = bpp->gid;
+ lpp->cuid = bpp->cuid;
+ lpp->cgid = bpp->cgid;
+ lpp->mode = bpp->mode;
+ lpp->seq = bpp->seq;
+}
+
+struct l_msqid_ds {
+ struct l_ipc_perm msg_perm;
+ l_uintptr_t msg_first; /* first message on queue,unused */
+ l_uintptr_t msg_last; /* last message in queue,unused */
+ l_time_t msg_stime; /* last msgsnd time */
+ l_time_t msg_rtime; /* last msgrcv time */
+ l_time_t msg_ctime; /* last change time */
+ l_ulong msg_lcbytes; /* Reuse junk fields for 32 bit */
+ l_ulong msg_lqbytes; /* ditto */
+ l_ushort msg_cbytes; /* current number of bytes on queue */
+ l_ushort msg_qnum; /* number of messages in queue */
+ l_ushort msg_qbytes; /* max number of bytes on queue */
+ l_pid_t msg_lspid; /* pid of last msgsnd */
+ l_pid_t msg_lrpid; /* last receive pid */
+}
+#if defined(__amd64__) && defined(COMPAT_LINUX32)
+__packed
+#endif
+;
+
+struct l_semid_ds {
+ struct l_ipc_perm sem_perm;
+ l_time_t sem_otime;
+ l_time_t sem_ctime;
+ l_uintptr_t sem_base;
+ l_uintptr_t sem_pending;
+ l_uintptr_t sem_pending_last;
+ l_uintptr_t undo;
+ l_ushort sem_nsems;
+}
+#if defined(__amd64__) && defined(COMPAT_LINUX32)
+__packed
+#endif
+;
+
+struct l_shmid_ds {
+ struct l_ipc_perm shm_perm;
+ l_int shm_segsz;
+ l_time_t shm_atime;
+ l_time_t shm_dtime;
+ l_time_t shm_ctime;
+ l_ushort shm_cpid;
+ l_ushort shm_lpid;
+ l_short shm_nattch;
+ l_ushort private1;
+ l_uintptr_t private2;
+ l_uintptr_t private3;
+};
+
+static void
+linux_to_bsd_semid_ds(struct l_semid_ds *lsp, struct semid_ds *bsp)
+{
+
+ linux_to_bsd_ipc_perm(&lsp->sem_perm, &bsp->sem_perm);
+ bsp->sem_otime = lsp->sem_otime;
+ bsp->sem_ctime = lsp->sem_ctime;
+ bsp->sem_nsems = lsp->sem_nsems;
+ bsp->sem_base = PTRIN(lsp->sem_base);
+}
+
+static void
+bsd_to_linux_semid_ds(struct semid_ds *bsp, struct l_semid_ds *lsp)
+{
+
+ bsd_to_linux_ipc_perm(&bsp->sem_perm, &lsp->sem_perm);
+ lsp->sem_otime = bsp->sem_otime;
+ lsp->sem_ctime = bsp->sem_ctime;
+ lsp->sem_nsems = bsp->sem_nsems;
+ lsp->sem_base = PTROUT(bsp->sem_base);
+}
+
+static void
+linux_to_bsd_shmid_ds(struct l_shmid_ds *lsp, struct shmid_ds *bsp)
+{
+
+ linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm);
+ bsp->shm_segsz = lsp->shm_segsz;
+ bsp->shm_lpid = lsp->shm_lpid;
+ bsp->shm_cpid = lsp->shm_cpid;
+ bsp->shm_nattch = lsp->shm_nattch;
+ bsp->shm_atime = lsp->shm_atime;
+ bsp->shm_dtime = lsp->shm_dtime;
+ bsp->shm_ctime = lsp->shm_ctime;
+}
+
+static void
+bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct l_shmid_ds *lsp)
+{
+
+ bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm);
+ if (bsp->shm_segsz > INT_MAX)
+ lsp->shm_segsz = INT_MAX;
+ else
+ lsp->shm_segsz = bsp->shm_segsz;
+ lsp->shm_lpid = bsp->shm_lpid;
+ lsp->shm_cpid = bsp->shm_cpid;
+ if (bsp->shm_nattch > SHRT_MAX)
+ lsp->shm_nattch = SHRT_MAX;
+ else
+ lsp->shm_nattch = bsp->shm_nattch;
+ lsp->shm_atime = bsp->shm_atime;
+ lsp->shm_dtime = bsp->shm_dtime;
+ lsp->shm_ctime = bsp->shm_ctime;
+ lsp->private3 = 0;
+}
+
+static void
+linux_to_bsd_msqid_ds(struct l_msqid_ds *lsp, struct msqid_ds *bsp)
+{
+
+ linux_to_bsd_ipc_perm(&lsp->msg_perm, &bsp->msg_perm);
+ bsp->msg_cbytes = lsp->msg_cbytes;
+ bsp->msg_qnum = lsp->msg_qnum;
+ bsp->msg_qbytes = lsp->msg_qbytes;
+ bsp->msg_lspid = lsp->msg_lspid;
+ bsp->msg_lrpid = lsp->msg_lrpid;
+ bsp->msg_stime = lsp->msg_stime;
+ bsp->msg_rtime = lsp->msg_rtime;
+ bsp->msg_ctime = lsp->msg_ctime;
+}
+
+static void
+bsd_to_linux_msqid_ds(struct msqid_ds *bsp, struct l_msqid_ds *lsp)
+{
+
+ bsd_to_linux_ipc_perm(&bsp->msg_perm, &lsp->msg_perm);
+ lsp->msg_cbytes = bsp->msg_cbytes;
+ lsp->msg_qnum = bsp->msg_qnum;
+ lsp->msg_qbytes = bsp->msg_qbytes;
+ lsp->msg_lspid = bsp->msg_lspid;
+ lsp->msg_lrpid = bsp->msg_lrpid;
+ lsp->msg_stime = bsp->msg_stime;
+ lsp->msg_rtime = bsp->msg_rtime;
+ lsp->msg_ctime = bsp->msg_ctime;
+}
+
+static void
+linux_ipc_perm_to_ipc64_perm(struct l_ipc_perm *in, struct l_ipc64_perm *out)
+{
+
+ /* XXX: do we really need to do something here? */
+ out->key = in->key;
+ out->uid = in->uid;
+ out->gid = in->gid;
+ out->cuid = in->cuid;
+ out->cgid = in->cgid;
+ out->mode = in->mode;
+ out->seq = in->seq;
+}
+
+static int
+linux_msqid_pullup(l_int ver, struct l_msqid_ds *linux_msqid, caddr_t uaddr)
+{
+ struct l_msqid64_ds linux_msqid64;
+ int error;
+
+ if (ver == LINUX_IPC_64) {
+ error = copyin(uaddr, &linux_msqid64, sizeof(linux_msqid64));
+ if (error != 0)
+ return (error);
+
+ bzero(linux_msqid, sizeof(*linux_msqid));
+
+ linux_msqid->msg_perm.uid = linux_msqid64.msg_perm.uid;
+ linux_msqid->msg_perm.gid = linux_msqid64.msg_perm.gid;
+ linux_msqid->msg_perm.mode = linux_msqid64.msg_perm.mode;
+
+ if (linux_msqid64.msg_qbytes > USHRT_MAX)
+ linux_msqid->msg_lqbytes = linux_msqid64.msg_qbytes;
+ else
+ linux_msqid->msg_qbytes = linux_msqid64.msg_qbytes;
+ } else
+ error = copyin(uaddr, linux_msqid, sizeof(*linux_msqid));
+
+ return (error);
+}
+
+static int
+linux_msqid_pushdown(l_int ver, struct l_msqid_ds *linux_msqid, caddr_t uaddr)
+{
+ struct l_msqid64_ds linux_msqid64;
+
+ if (ver == LINUX_IPC_64) {
+ bzero(&linux_msqid64, sizeof(linux_msqid64));
+
+ linux_ipc_perm_to_ipc64_perm(&linux_msqid->msg_perm,
+ &linux_msqid64.msg_perm);
+
+ linux_msqid64.msg_stime = linux_msqid->msg_stime;
+ linux_msqid64.msg_rtime = linux_msqid->msg_rtime;
+ linux_msqid64.msg_ctime = linux_msqid->msg_ctime;
+
+ if (linux_msqid->msg_cbytes == 0)
+ linux_msqid64.msg_cbytes = linux_msqid->msg_lcbytes;
+ else
+ linux_msqid64.msg_cbytes = linux_msqid->msg_cbytes;
+
+ linux_msqid64.msg_qnum = linux_msqid->msg_qnum;
+
+ if (linux_msqid->msg_qbytes == 0)
+ linux_msqid64.msg_qbytes = linux_msqid->msg_lqbytes;
+ else
+ linux_msqid64.msg_qbytes = linux_msqid->msg_qbytes;
+
+ linux_msqid64.msg_lspid = linux_msqid->msg_lspid;
+ linux_msqid64.msg_lrpid = linux_msqid->msg_lrpid;
+
+ return (copyout(&linux_msqid64, uaddr, sizeof(linux_msqid64)));
+ } else
+ return (copyout(linux_msqid, uaddr, sizeof(*linux_msqid)));
+}
+
+static int
+linux_semid_pullup(l_int ver, struct l_semid_ds *linux_semid, caddr_t uaddr)
+{
+ struct l_semid64_ds linux_semid64;
+ int error;
+
+ if (ver == LINUX_IPC_64) {
+ error = copyin(uaddr, &linux_semid64, sizeof(linux_semid64));
+ if (error != 0)
+ return (error);
+
+ bzero(linux_semid, sizeof(*linux_semid));
+
+ linux_semid->sem_perm.uid = linux_semid64.sem_perm.uid;
+ linux_semid->sem_perm.gid = linux_semid64.sem_perm.gid;
+ linux_semid->sem_perm.mode = linux_semid64.sem_perm.mode;
+ } else
+ error = copyin(uaddr, linux_semid, sizeof(*linux_semid));
+
+ return (error);
+}
+
+static int
+linux_semid_pushdown(l_int ver, struct l_semid_ds *linux_semid, caddr_t uaddr)
+{
+ struct l_semid64_ds linux_semid64;
+
+ if (ver == LINUX_IPC_64) {
+ bzero(&linux_semid64, sizeof(linux_semid64));
+
+ linux_ipc_perm_to_ipc64_perm(&linux_semid->sem_perm,
+ &linux_semid64.sem_perm);
+
+ linux_semid64.sem_otime = linux_semid->sem_otime;
+ linux_semid64.sem_ctime = linux_semid->sem_ctime;
+ linux_semid64.sem_nsems = linux_semid->sem_nsems;
+
+ return (copyout(&linux_semid64, uaddr, sizeof(linux_semid64)));
+ } else
+ return (copyout(linux_semid, uaddr, sizeof(*linux_semid)));
+}
+
+static int
+linux_shmid_pullup(l_int ver, struct l_shmid_ds *linux_shmid, caddr_t uaddr)
+{
+ struct l_shmid64_ds linux_shmid64;
+ int error;
+
+ if (ver == LINUX_IPC_64) {
+ error = copyin(uaddr, &linux_shmid64, sizeof(linux_shmid64));
+ if (error != 0)
+ return (error);
+
+ bzero(linux_shmid, sizeof(*linux_shmid));
+
+ linux_shmid->shm_perm.uid = linux_shmid64.shm_perm.uid;
+ linux_shmid->shm_perm.gid = linux_shmid64.shm_perm.gid;
+ linux_shmid->shm_perm.mode = linux_shmid64.shm_perm.mode;
+ } else
+ error = copyin(uaddr, linux_shmid, sizeof(*linux_shmid));
+
+ return (error);
+}
+
+static int
+linux_shmid_pushdown(l_int ver, struct l_shmid_ds *linux_shmid, caddr_t uaddr)
+{
+ struct l_shmid64_ds linux_shmid64;
+
+ /*
+ * XXX: This is backwards and loses information in shm_nattch
+ * and shm_segsz. We should probably either expose the BSD
+ * shmid structure directly and convert it to either the
+ * non-64 or 64 variant directly or the code should always
+ * convert to the 64 variant and then truncate values into the
+ * non-64 variant if needed since the 64 variant has more
+ * precision.
+ */
+ if (ver == LINUX_IPC_64) {
+ bzero(&linux_shmid64, sizeof(linux_shmid64));
+
+ linux_ipc_perm_to_ipc64_perm(&linux_shmid->shm_perm,
+ &linux_shmid64.shm_perm);
+
+ linux_shmid64.shm_segsz = linux_shmid->shm_segsz;
+ linux_shmid64.shm_atime = linux_shmid->shm_atime;
+ linux_shmid64.shm_dtime = linux_shmid->shm_dtime;
+ linux_shmid64.shm_ctime = linux_shmid->shm_ctime;
+ linux_shmid64.shm_cpid = linux_shmid->shm_cpid;
+ linux_shmid64.shm_lpid = linux_shmid->shm_lpid;
+ linux_shmid64.shm_nattch = linux_shmid->shm_nattch;
+
+ return (copyout(&linux_shmid64, uaddr, sizeof(linux_shmid64)));
+ } else
+ return (copyout(linux_shmid, uaddr, sizeof(*linux_shmid)));
+}
+
+static int
+linux_shminfo_pushdown(l_int ver, struct l_shminfo *linux_shminfo,
+ caddr_t uaddr)
+{
+ struct l_shminfo64 linux_shminfo64;
+
+ if (ver == LINUX_IPC_64) {
+ bzero(&linux_shminfo64, sizeof(linux_shminfo64));
+
+ linux_shminfo64.shmmax = linux_shminfo->shmmax;
+ linux_shminfo64.shmmin = linux_shminfo->shmmin;
+ linux_shminfo64.shmmni = linux_shminfo->shmmni;
+ linux_shminfo64.shmseg = linux_shminfo->shmseg;
+ linux_shminfo64.shmall = linux_shminfo->shmall;
+
+ return (copyout(&linux_shminfo64, uaddr,
+ sizeof(linux_shminfo64)));
+ } else
+ return (copyout(linux_shminfo, uaddr, sizeof(*linux_shminfo)));
+}
+
+int
+linux_semop(struct thread *td, struct linux_semop_args *args)
+{
+ struct semop_args /* {
+ int semid;
+ struct sembuf *sops;
+ int nsops;
+ } */ bsd_args;
+
+ bsd_args.semid = args->semid;
+ bsd_args.sops = PTRIN(args->tsops);
+ bsd_args.nsops = args->nsops;
+ return (sys_semop(td, &bsd_args));
+}
+
+int
+linux_semget(struct thread *td, struct linux_semget_args *args)
+{
+ struct semget_args /* {
+ key_t key;
+ int nsems;
+ int semflg;
+ } */ bsd_args;
+
+ if (args->nsems < 0)
+ return (EINVAL);
+ bsd_args.key = args->key;
+ bsd_args.nsems = args->nsems;
+ bsd_args.semflg = args->semflg;
+ return (sys_semget(td, &bsd_args));
+}
+
+int
+linux_semctl(struct thread *td, struct linux_semctl_args *args)
+{
+ struct l_semid_ds linux_semid;
+ struct l_seminfo linux_seminfo;
+ struct semid_ds semid;
+ union semun semun;
+ register_t rval;
+ int cmd, error;
+
+ switch (args->cmd & ~LINUX_IPC_64) {
+ case LINUX_IPC_RMID:
+ cmd = IPC_RMID;
+ break;
+ case LINUX_GETNCNT:
+ cmd = GETNCNT;
+ break;
+ case LINUX_GETPID:
+ cmd = GETPID;
+ break;
+ case LINUX_GETVAL:
+ cmd = GETVAL;
+ break;
+ case LINUX_GETZCNT:
+ cmd = GETZCNT;
+ break;
+ case LINUX_SETVAL:
+ cmd = SETVAL;
+ semun.val = args->arg.val;
+ break;
+ case LINUX_IPC_SET:
+ cmd = IPC_SET;
+ error = linux_semid_pullup(args->cmd & LINUX_IPC_64,
+ &linux_semid, PTRIN(args->arg.buf));
+ if (error)
+ return (error);
+ linux_to_bsd_semid_ds(&linux_semid, &semid);
+ semun.buf = &semid;
+ return (kern_semctl(td, args->semid, args->semnum, cmd, &semun,
+ td->td_retval));
+ case LINUX_IPC_STAT:
+ case LINUX_SEM_STAT:
+ if ((args->cmd & ~LINUX_IPC_64) == LINUX_IPC_STAT)
+ cmd = IPC_STAT;
+ else
+ cmd = SEM_STAT;
+ semun.buf = &semid;
+ error = kern_semctl(td, args->semid, args->semnum, cmd, &semun,
+ &rval);
+ if (error)
+ return (error);
+ bsd_to_linux_semid_ds(&semid, &linux_semid);
+ error = linux_semid_pushdown(args->cmd & LINUX_IPC_64,
+ &linux_semid, PTRIN(args->arg.buf));
+ if (error == 0)
+ td->td_retval[0] = (cmd == SEM_STAT) ? rval : 0;
+ return (error);
+ case LINUX_IPC_INFO:
+ case LINUX_SEM_INFO:
+ bcopy(&seminfo, &linux_seminfo.semmni, sizeof(linux_seminfo) -
+ sizeof(linux_seminfo.semmap) );
+ /*
+ * Linux does not use the semmap field but populates it with
+ * the defined value from SEMMAP, which really is redefined to
+ * SEMMNS, which they define as SEMMNI * SEMMSL. Try to
+ * simulate this returning our dynamic semmns value.
+ */
+ linux_seminfo.semmap = linux_seminfo.semmns;
+/* XXX BSD equivalent?
+#define used_semids 10
+#define used_sems 10
+ linux_seminfo.semusz = used_semids;
+ linux_seminfo.semaem = used_sems;
+*/
+ error = copyout(&linux_seminfo,
+ PTRIN(args->arg.buf), sizeof(linux_seminfo));
+ if (error)
+ return (error);
+ td->td_retval[0] = seminfo.semmni;
+ return (0); /* No need for __semctl call */
+ case LINUX_GETALL:
+ cmd = GETALL;
+ semun.val = args->arg.val;
+ break;
+ case LINUX_SETALL:
+ cmd = SETALL;
+ semun.val = args->arg.val;
+ break;
+ default:
+ linux_msg(td, "ipc type %d is not implemented",
+ args->cmd & ~LINUX_IPC_64);
+ return (EINVAL);
+ }
+ return (kern_semctl(td, args->semid, args->semnum, cmd, &semun,
+ td->td_retval));
+}
+
+int
+linux_msgsnd(struct thread *td, struct linux_msgsnd_args *args)
+{
+ const void *msgp;
+ long mtype;
+ l_long lmtype;
+ int error;
+
+ if ((l_long)args->msgsz < 0 || args->msgsz > (l_long)msginfo.msgmax)
+ return (EINVAL);
+ msgp = PTRIN(args->msgp);
+ if ((error = copyin(msgp, &lmtype, sizeof(lmtype))) != 0)
+ return (error);
+ mtype = (long)lmtype;
+ return (kern_msgsnd(td, args->msqid,
+ (const char *)msgp + sizeof(lmtype),
+ args->msgsz, args->msgflg, mtype));
+}
+
+int
+linux_msgrcv(struct thread *td, struct linux_msgrcv_args *args)
+{
+ void *msgp;
+ long mtype;
+ l_long lmtype;
+ int error;
+
+ if ((l_long)args->msgsz < 0 || args->msgsz > (l_long)msginfo.msgmax)
+ return (EINVAL);
+ msgp = PTRIN(args->msgp);
+ if ((error = kern_msgrcv(td, args->msqid,
+ (char *)msgp + sizeof(lmtype), args->msgsz,
+ args->msgtyp, args->msgflg, &mtype)) != 0)
+ return (error);
+ lmtype = (l_long)mtype;
+ return (copyout(&lmtype, msgp, sizeof(lmtype)));
+}
+
+int
+linux_msgget(struct thread *td, struct linux_msgget_args *args)
+{
+ struct msgget_args /* {
+ key_t key;
+ int msgflg;
+ } */ bsd_args;
+
+ bsd_args.key = args->key;
+ bsd_args.msgflg = args->msgflg;
+ return (sys_msgget(td, &bsd_args));
+}
+
+int
+linux_msgctl(struct thread *td, struct linux_msgctl_args *args)
+{
+ int error, bsd_cmd;
+ struct l_msqid_ds linux_msqid;
+ struct msqid_ds bsd_msqid;
+
+ bsd_cmd = args->cmd & ~LINUX_IPC_64;
+ switch (bsd_cmd) {
+ case LINUX_IPC_INFO:
+ case LINUX_MSG_INFO: {
+ struct l_msginfo linux_msginfo;
+
+ /*
+ * XXX MSG_INFO uses the same data structure but returns different
+ * dynamic counters in msgpool, msgmap, and msgtql fields.
+ */
+ linux_msginfo.msgpool = (long)msginfo.msgmni *
+ (long)msginfo.msgmnb / 1024L; /* XXX MSG_INFO. */
+ linux_msginfo.msgmap = msginfo.msgmnb; /* XXX MSG_INFO. */
+ linux_msginfo.msgmax = msginfo.msgmax;
+ linux_msginfo.msgmnb = msginfo.msgmnb;
+ linux_msginfo.msgmni = msginfo.msgmni;
+ linux_msginfo.msgssz = msginfo.msgssz;
+ linux_msginfo.msgtql = msginfo.msgtql; /* XXX MSG_INFO. */
+ linux_msginfo.msgseg = msginfo.msgseg;
+ error = copyout(&linux_msginfo, PTRIN(args->buf),
+ sizeof(linux_msginfo));
+ if (error == 0)
+ td->td_retval[0] = msginfo.msgmni; /* XXX */
+
+ return (error);
+ }
+
+ /*
+ * TODO: implement this
+ * case LINUX_MSG_STAT:
+ */
+ case LINUX_IPC_STAT:
+ /* NOTHING */
+ break;
+
+ case LINUX_IPC_SET:
+ error = linux_msqid_pullup(args->cmd & LINUX_IPC_64,
+ &linux_msqid, PTRIN(args->buf));
+ if (error)
+ return (error);
+ linux_to_bsd_msqid_ds(&linux_msqid, &bsd_msqid);
+ break;
+
+ case LINUX_IPC_RMID:
+ /* NOTHING */
+ break;
+
+ default:
+ return (EINVAL);
+ break;
+ }
+
+ error = kern_msgctl(td, args->msqid, bsd_cmd, &bsd_msqid);
+ if (error != 0)
+ if (bsd_cmd != LINUX_IPC_RMID || error != EINVAL)
+ return (error);
+
+ if (bsd_cmd == LINUX_IPC_STAT) {
+ bsd_to_linux_msqid_ds(&bsd_msqid, &linux_msqid);
+ return (linux_msqid_pushdown(args->cmd & LINUX_IPC_64,
+ &linux_msqid, PTRIN(args->buf)));
+ }
+
+ return (0);
+}
+
+int
+linux_shmat(struct thread *td, struct linux_shmat_args *args)
+{
+ struct shmat_args /* {
+ int shmid;
+ void *shmaddr;
+ int shmflg;
+ } */ bsd_args;
+ int error;
+#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
+ l_uintptr_t addr;
+#endif
+
+ bsd_args.shmid = args->shmid;
+ bsd_args.shmaddr = PTRIN(args->shmaddr);
+ bsd_args.shmflg = args->shmflg;
+ if ((error = sys_shmat(td, &bsd_args)))
+ return (error);
+#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
+ addr = td->td_retval[0];
+ if ((error = copyout(&addr, PTRIN(args->raddr), sizeof(addr))))
+ return (error);
+ td->td_retval[0] = 0;
+#endif
+ return (0);
+}
+
+int
+linux_shmdt(struct thread *td, struct linux_shmdt_args *args)
+{
+ struct shmdt_args /* {
+ void *shmaddr;
+ } */ bsd_args;
+
+ bsd_args.shmaddr = PTRIN(args->shmaddr);
+ return (sys_shmdt(td, &bsd_args));
+}
+
+int
+linux_shmget(struct thread *td, struct linux_shmget_args *args)
+{
+ struct shmget_args /* {
+ key_t key;
+ int size;
+ int shmflg;
+ } */ bsd_args;
+
+ bsd_args.key = args->key;
+ bsd_args.size = args->size;
+ bsd_args.shmflg = args->shmflg;
+ return (sys_shmget(td, &bsd_args));
+}
+
+int
+linux_shmctl(struct thread *td, struct linux_shmctl_args *args)
+{
+ struct l_shmid_ds linux_shmid;
+ struct l_shminfo linux_shminfo;
+ struct l_shm_info linux_shm_info;
+ struct shmid_ds bsd_shmid;
+ int error;
+
+ switch (args->cmd & ~LINUX_IPC_64) {
+
+ case LINUX_IPC_INFO: {
+ struct shminfo bsd_shminfo;
+
+ /* Perform shmctl wanting removed segments lookup */
+ error = kern_shmctl(td, args->shmid, IPC_INFO,
+ (void *)&bsd_shminfo, NULL);
+ if (error)
+ return (error);
+
+ bsd_to_linux_shminfo(&bsd_shminfo, &linux_shminfo);
+
+ return (linux_shminfo_pushdown(args->cmd & LINUX_IPC_64,
+ &linux_shminfo, PTRIN(args->buf)));
+ }
+
+ case LINUX_SHM_INFO: {
+ struct shm_info bsd_shm_info;
+
+ /* Perform shmctl wanting removed segments lookup */
+ error = kern_shmctl(td, args->shmid, SHM_INFO,
+ (void *)&bsd_shm_info, NULL);
+ if (error)
+ return (error);
+
+ bsd_to_linux_shm_info(&bsd_shm_info, &linux_shm_info);
+
+ return (copyout(&linux_shm_info, PTRIN(args->buf),
+ sizeof(struct l_shm_info)));
+ }
+
+ case LINUX_IPC_STAT:
+ /* Perform shmctl wanting removed segments lookup */
+ error = kern_shmctl(td, args->shmid, IPC_STAT,
+ (void *)&bsd_shmid, NULL);
+ if (error)
+ return (error);
+
+ bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid);
+
+ return (linux_shmid_pushdown(args->cmd & LINUX_IPC_64,
+ &linux_shmid, PTRIN(args->buf)));
+
+ case LINUX_SHM_STAT:
+ /* Perform shmctl wanting removed segments lookup */
+ error = kern_shmctl(td, args->shmid, IPC_STAT,
+ (void *)&bsd_shmid, NULL);
+ if (error)
+ return (error);
+
+ bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid);
+
+ return (linux_shmid_pushdown(args->cmd & LINUX_IPC_64,
+ &linux_shmid, PTRIN(args->buf)));
+
+ case LINUX_IPC_SET:
+ error = linux_shmid_pullup(args->cmd & LINUX_IPC_64,
+ &linux_shmid, PTRIN(args->buf));
+ if (error)
+ return (error);
+
+ linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
+
+ /* Perform shmctl wanting removed segments lookup */
+ return (kern_shmctl(td, args->shmid, IPC_SET,
+ (void *)&bsd_shmid, NULL));
+
+ case LINUX_IPC_RMID: {
+ void *buf;
+
+ if (args->buf == 0)
+ buf = NULL;
+ else {
+ error = linux_shmid_pullup(args->cmd & LINUX_IPC_64,
+ &linux_shmid, PTRIN(args->buf));
+ if (error)
+ return (error);
+ linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
+ buf = (void *)&bsd_shmid;
+ }
+ return (kern_shmctl(td, args->shmid, IPC_RMID, buf, NULL));
+ }
+
+ case LINUX_SHM_LOCK:
+ /* FALLTHROUGH */
+ case LINUX_SHM_UNLOCK:
+ /* FALLTHROUGH */
+ default:
+ linux_msg(td, "ipc type %d not implemented",
+ args->cmd & ~LINUX_IPC_64);
+ return (EINVAL);
+ }
+}
+
+MODULE_DEPEND(linux, sysvmsg, 1, 1, 1);
+MODULE_DEPEND(linux, sysvsem, 1, 1, 1);
+MODULE_DEPEND(linux, sysvshm, 1, 1, 1);
diff --git a/sys/compat/linux/linux_ipc.h b/sys/compat/linux/linux_ipc.h
new file mode 100644
index 0000000..f1531ba
--- /dev/null
+++ b/sys/compat/linux/linux_ipc.h
@@ -0,0 +1,182 @@
+/*-
+ * Copyright (c) 2000 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LINUX_IPC_H_
+#define _LINUX_IPC_H_
+
+/*
+ * SystemV IPC defines
+ */
+#define LINUX_SEMOP 1
+#define LINUX_SEMGET 2
+#define LINUX_SEMCTL 3
+#define LINUX_MSGSND 11
+#define LINUX_MSGRCV 12
+#define LINUX_MSGGET 13
+#define LINUX_MSGCTL 14
+#define LINUX_SHMAT 21
+#define LINUX_SHMDT 22
+#define LINUX_SHMGET 23
+#define LINUX_SHMCTL 24
+
+#define LINUX_IPC_RMID 0
+#define LINUX_IPC_SET 1
+#define LINUX_IPC_STAT 2
+#define LINUX_IPC_INFO 3
+
+#define LINUX_MSG_INFO 12
+
+#define LINUX_SHM_LOCK 11
+#define LINUX_SHM_UNLOCK 12
+#define LINUX_SHM_STAT 13
+#define LINUX_SHM_INFO 14
+
+#define LINUX_SHM_RDONLY 0x1000
+#define LINUX_SHM_RND 0x2000
+#define LINUX_SHM_REMAP 0x4000
+
+/* semctl commands */
+#define LINUX_GETPID 11
+#define LINUX_GETVAL 12
+#define LINUX_GETALL 13
+#define LINUX_GETNCNT 14
+#define LINUX_GETZCNT 15
+#define LINUX_SETVAL 16
+#define LINUX_SETALL 17
+#define LINUX_SEM_STAT 18
+#define LINUX_SEM_INFO 19
+
+/*
+ * Version flags for semctl, msgctl, and shmctl commands
+ * These are passed as bitflags or-ed with the actual command
+ */
+#define LINUX_IPC_OLD 0 /* Old version (no 32-bit UID support on many
+ architectures) */
+#define LINUX_IPC_64 0x0100 /* New version (support 32-bit UIDs, bigger
+ message sizes, etc. */
+
+#if defined(__i386__) || defined(__amd64__)
+
+struct linux_msgctl_args
+{
+ l_int msqid;
+ l_int cmd;
+ struct l_msqid_ds *buf;
+};
+
+struct linux_msgget_args
+{
+ l_key_t key;
+ l_int msgflg;
+};
+
+struct linux_msgrcv_args
+{
+ l_int msqid;
+ struct l_msgbuf *msgp;
+ l_size_t msgsz;
+ l_long msgtyp;
+ l_int msgflg;
+};
+
+struct linux_msgsnd_args
+{
+ l_int msqid;
+ struct l_msgbuf *msgp;
+ l_size_t msgsz;
+ l_int msgflg;
+};
+
+struct linux_semctl_args
+{
+ l_int semid;
+ l_int semnum;
+ l_int cmd;
+ union l_semun arg;
+};
+
+struct linux_semget_args
+{
+ l_key_t key;
+ l_int nsems;
+ l_int semflg;
+};
+
+struct linux_semop_args
+{
+ l_int semid;
+ struct l_sembuf *tsops;
+ l_uint nsops;
+};
+
+struct linux_shmat_args
+{
+ l_int shmid;
+ char *shmaddr;
+ l_int shmflg;
+ l_ulong *raddr;
+};
+
+struct linux_shmctl_args
+{
+ l_int shmid;
+ l_int cmd;
+ struct l_shmid_ds *buf;
+};
+
+struct linux_shmdt_args
+{
+ char *shmaddr;
+};
+
+struct linux_shmget_args
+{
+ l_key_t key;
+ l_size_t size;
+ l_int shmflg;
+};
+
+int linux_msgctl(struct thread *, struct linux_msgctl_args *);
+int linux_msgget(struct thread *, struct linux_msgget_args *);
+int linux_msgrcv(struct thread *, struct linux_msgrcv_args *);
+int linux_msgsnd(struct thread *, struct linux_msgsnd_args *);
+
+int linux_semctl(struct thread *, struct linux_semctl_args *);
+int linux_semget(struct thread *, struct linux_semget_args *);
+int linux_semop(struct thread *, struct linux_semop_args *);
+
+int linux_shmat(struct thread *, struct linux_shmat_args *);
+int linux_shmctl(struct thread *, struct linux_shmctl_args *);
+int linux_shmdt(struct thread *, struct linux_shmdt_args *);
+int linux_shmget(struct thread *, struct linux_shmget_args *);
+
+#endif /* __i386__ || __amd64__ */
+
+#endif /* _LINUX_IPC_H_ */
diff --git a/sys/compat/linux/linux_mib.c b/sys/compat/linux/linux_mib.c
new file mode 100644
index 0000000..323a38f
--- /dev/null
+++ b/sys/compat/linux/linux_mib.c
@@ -0,0 +1,858 @@
+/*-
+ * Copyright (c) 1999 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_compat.h"
+#include "opt_kdtrace.h"
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/sdt.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/jail.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sx.h>
+
+#ifdef COMPAT_LINUX32
+#include <machine/../linux32/linux.h>
+#else
+#include <machine/../linux/linux.h>
+#endif
+#include <compat/linux/linux_dtrace.h>
+#include <compat/linux/linux_mib.h>
+#include <compat/linux/linux_misc.h>
+
+/* DTrace init */
+LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
+
+/**
+ * DTrace probes in this module.
+ */
+LIN_SDT_PROBE_DEFINE0(mib, linux_sysctl_osname, entry);
+LIN_SDT_PROBE_DEFINE1(mib, linux_sysctl_osname, sysctl_string_error, "int");
+LIN_SDT_PROBE_DEFINE1(mib, linux_sysctl_osname, return, "int");
+
+LIN_SDT_PROBE_DEFINE0(mib, linux_sysctl_osrelease, entry);
+LIN_SDT_PROBE_DEFINE1(mib, linux_sysctl_osrelease, sysctl_string_error, "int");
+LIN_SDT_PROBE_DEFINE1(mib, linux_sysctl_osrelease, return, "int");
+LIN_SDT_PROBE_DEFINE0(mib, linux_sysctl_oss_version, entry);
+LIN_SDT_PROBE_DEFINE1(mib, linux_sysctl_oss_version, sysctl_string_error,
+ "int");
+LIN_SDT_PROBE_DEFINE1(mib, linux_sysctl_oss_version, return, "int");
+LIN_SDT_PROBE_DEFINE2(mib, linux_map_osrel, entry, "char *", "int *");
+LIN_SDT_PROBE_DEFINE1(mib, linux_map_osrel, return, "int");
+LIN_SDT_PROBE_DEFINE2(mib, linux_get_prison, entry, "struct prison *",
+ "struct prison **");
+LIN_SDT_PROBE_DEFINE1(mib, linux_get_prison, return, "struct linux_prison *");
+LIN_SDT_PROBE_DEFINE2(mib, linux_alloc_prison, entry, "struct prison *",
+ "struct linux_prison **");
+LIN_SDT_PROBE_DEFINE1(mib, linux_alloc_prison, return, "int");
+LIN_SDT_PROBE_DEFINE2(mib, linux_prison_create, entry, "void *", "void *");
+LIN_SDT_PROBE_DEFINE1(mib, linux_prison_create, vfs_copyopt_error, "int");
+LIN_SDT_PROBE_DEFINE1(mib, linux_prison_create, return, "int");
+LIN_SDT_PROBE_DEFINE2(mib, linux_prison_check, entry, "void *", "void *");
+LIN_SDT_PROBE_DEFINE1(mib, linux_prison_check, vfs_copyopt_error, "int");
+LIN_SDT_PROBE_DEFINE1(mib, linux_prison_check, vfs_getopt_error, "int");
+LIN_SDT_PROBE_DEFINE1(mib, linux_prison_check, return, "int");
+LIN_SDT_PROBE_DEFINE2(mib, linux_prison_set, entry, "void *", "void *");
+LIN_SDT_PROBE_DEFINE1(mib, linux_prison_set, vfs_copyopt_error, "int");
+LIN_SDT_PROBE_DEFINE1(mib, linux_prison_set, vfs_getopt_error, "int");
+LIN_SDT_PROBE_DEFINE1(mib, linux_prison_set, return, "int");
+LIN_SDT_PROBE_DEFINE2(mib, linux_prison_get, entry, "void *", "void *");
+LIN_SDT_PROBE_DEFINE1(mib, linux_prison_get, vfs_setopt_error, "int");
+LIN_SDT_PROBE_DEFINE1(mib, linux_prison_get, vfs_setopts_error, "int");
+LIN_SDT_PROBE_DEFINE1(mib, linux_prison_get, return, "int");
+LIN_SDT_PROBE_DEFINE1(mib, linux_prison_destructor, entry, "void *");
+LIN_SDT_PROBE_DEFINE0(mib, linux_prison_destructor, return);
+LIN_SDT_PROBE_DEFINE0(mib, linux_osd_jail_register, entry);
+LIN_SDT_PROBE_DEFINE0(mib, linux_osd_jail_register, return);
+LIN_SDT_PROBE_DEFINE0(mib, linux_osd_jail_deregister, entry);
+LIN_SDT_PROBE_DEFINE0(mib, linux_osd_jail_deregister, return);
+LIN_SDT_PROBE_DEFINE2(mib, linux_get_osname, entry, "struct thread *",
+ "char *");
+LIN_SDT_PROBE_DEFINE0(mib, linux_get_osname, return);
+LIN_SDT_PROBE_DEFINE2(mib, linux_set_osname, entry, "struct thread *",
+ "char *");
+LIN_SDT_PROBE_DEFINE1(mib, linux_set_osname, return, "int");
+LIN_SDT_PROBE_DEFINE2(mib, linux_get_osrelease, entry, "struct thread *",
+ "char *");
+LIN_SDT_PROBE_DEFINE0(mib, linux_get_osrelease, return);
+LIN_SDT_PROBE_DEFINE1(mib, linux_kernver, entry, "struct thread *");
+LIN_SDT_PROBE_DEFINE1(mib, linux_kernver, return, "int");
+LIN_SDT_PROBE_DEFINE2(mib, linux_set_osrelease, entry, "struct thread *",
+ "char *");
+LIN_SDT_PROBE_DEFINE1(mib, linux_set_osrelease, return, "int");
+LIN_SDT_PROBE_DEFINE1(mib, linux_get_oss_version, entry, "struct thread *");
+LIN_SDT_PROBE_DEFINE1(mib, linux_get_oss_version, return, "int");
+
+LIN_SDT_PROBE_DEFINE2(mib, linux_set_oss_version, entry, "struct thread *",
+ "int");
+LIN_SDT_PROBE_DEFINE1(mib, linux_set_oss_version, return, "int");
+
+struct linux_prison {
+ char pr_osname[LINUX_MAX_UTSNAME];
+ char pr_osrelease[LINUX_MAX_UTSNAME];
+ int pr_oss_version;
+ int pr_osrel;
+};
+
+static struct linux_prison lprison0 = {
+ .pr_osname = "Linux",
+ .pr_osrelease = "2.6.16",
+ .pr_oss_version = 0x030600,
+ .pr_osrel = 2006016
+};
+
+static unsigned linux_osd_jail_slot;
+
+static SYSCTL_NODE(_compat, OID_AUTO, linux, CTLFLAG_RW, 0,
+ "Linux mode");
+
+static int linux_set_osname(struct thread *td, char *osname);
+static int linux_set_osrelease(struct thread *td, char *osrelease);
+static int linux_set_oss_version(struct thread *td, int oss_version);
+
+static int
+linux_sysctl_osname(SYSCTL_HANDLER_ARGS)
+{
+ char osname[LINUX_MAX_UTSNAME];
+ int error;
+
+ LIN_SDT_PROBE0(mib, linux_sysctl_osname, entry);
+
+ linux_get_osname(req->td, osname);
+ error = sysctl_handle_string(oidp, osname, LINUX_MAX_UTSNAME, req);
+ if (error != 0 || req->newptr == NULL) {
+ LIN_SDT_PROBE1(mib, linux_sysctl_osname, sysctl_string_error,
+ error);
+ LIN_SDT_PROBE1(mib, linux_sysctl_osname, return, error);
+ return (error);
+ }
+ error = linux_set_osname(req->td, osname);
+
+ LIN_SDT_PROBE1(mib, linux_sysctl_osname, return, error);
+ return (error);
+}
+
+SYSCTL_PROC(_compat_linux, OID_AUTO, osname,
+ CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE,
+ 0, 0, linux_sysctl_osname, "A",
+ "Linux kernel OS name");
+
+static int
+linux_sysctl_osrelease(SYSCTL_HANDLER_ARGS)
+{
+ char osrelease[LINUX_MAX_UTSNAME];
+ int error;
+
+ LIN_SDT_PROBE0(mib, linux_sysctl_osrelease, entry);
+
+ linux_get_osrelease(req->td, osrelease);
+ error = sysctl_handle_string(oidp, osrelease, LINUX_MAX_UTSNAME, req);
+ if (error != 0 || req->newptr == NULL) {
+ LIN_SDT_PROBE1(mib, linux_sysctl_osrelease, sysctl_string_error,
+ error);
+ LIN_SDT_PROBE1(mib, linux_sysctl_osrelease, return, error);
+ return (error);
+ }
+ error = linux_set_osrelease(req->td, osrelease);
+
+ LIN_SDT_PROBE1(mib, linux_sysctl_osrelease, return, error);
+ return (error);
+}
+
+SYSCTL_PROC(_compat_linux, OID_AUTO, osrelease,
+ CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE,
+ 0, 0, linux_sysctl_osrelease, "A",
+ "Linux kernel OS release");
+
+static int
+linux_sysctl_oss_version(SYSCTL_HANDLER_ARGS)
+{
+ int oss_version;
+ int error;
+
+ LIN_SDT_PROBE0(mib, linux_sysctl_oss_version, entry);
+
+ oss_version = linux_get_oss_version(req->td);
+ error = sysctl_handle_int(oidp, &oss_version, 0, req);
+ if (error != 0 || req->newptr == NULL) {
+ LIN_SDT_PROBE1(mib, linux_sysctl_oss_version,
+ sysctl_string_error, error);
+ LIN_SDT_PROBE1(mib, linux_sysctl_oss_version, return, error);
+ return (error);
+ }
+ error = linux_set_oss_version(req->td, oss_version);
+
+ LIN_SDT_PROBE1(mib, linux_sysctl_oss_version, return, error);
+ return (error);
+}
+
+SYSCTL_PROC(_compat_linux, OID_AUTO, oss_version,
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE,
+ 0, 0, linux_sysctl_oss_version, "I",
+ "Linux OSS version");
+
+/*
+ * Map the osrelease into integer
+ */
+static int
+linux_map_osrel(char *osrelease, int *osrel)
+{
+ char *sep, *eosrelease;
+ int len, v0, v1, v2, v;
+
+ LIN_SDT_PROBE2(mib, linux_map_osrel, entry, osrelease, osrel);
+
+ len = strlen(osrelease);
+ eosrelease = osrelease + len;
+ v0 = strtol(osrelease, &sep, 10);
+ if (osrelease == sep || sep + 1 >= eosrelease || *sep != '.') {
+ LIN_SDT_PROBE1(mib, linux_map_osrel, return, EINVAL);
+ return (EINVAL);
+ }
+ osrelease = sep + 1;
+ v1 = strtol(osrelease, &sep, 10);
+ if (osrelease == sep || sep + 1 >= eosrelease || *sep != '.') {
+ LIN_SDT_PROBE1(mib, linux_map_osrel, return, EINVAL);
+ return (EINVAL);
+ }
+ osrelease = sep + 1;
+ v2 = strtol(osrelease, &sep, 10);
+ if (osrelease == sep || sep != eosrelease) {
+ LIN_SDT_PROBE1(mib, linux_map_osrel, return, EINVAL);
+ return (EINVAL);
+ }
+
+ v = v0 * 1000000 + v1 * 1000 + v2;
+ if (v < 1000000) {
+ LIN_SDT_PROBE1(mib, linux_map_osrel, return, EINVAL);
+ return (EINVAL);
+ }
+
+ *osrel = v;
+
+ LIN_SDT_PROBE1(mib, linux_map_osrel, return, 0);
+ return (0);
+}
+
+/*
+ * Find a prison with Linux info.
+ * Return the Linux info and the (locked) prison.
+ */
+static struct linux_prison *
+linux_find_prison(struct prison *spr, struct prison **prp)
+{
+ struct prison *pr;
+ struct linux_prison *lpr;
+
+ LIN_SDT_PROBE2(mib, linux_get_prison, entry, spr, prp);
+
+ if (!linux_osd_jail_slot)
+ /* In case osd_register failed. */
+ spr = &prison0;
+ for (pr = spr;; pr = pr->pr_parent) {
+ mtx_lock(&pr->pr_mtx);
+ lpr = (pr == &prison0)
+ ? &lprison0
+ : osd_jail_get(pr, linux_osd_jail_slot);
+ if (lpr != NULL)
+ break;
+ mtx_unlock(&pr->pr_mtx);
+ }
+ *prp = pr;
+
+ LIN_SDT_PROBE1(mib, linux_get_prison, return, lpr);
+ return (lpr);
+}
+
+/*
+ * Ensure a prison has its own Linux info. If lprp is non-null, point it to
+ * the Linux info and lock the prison.
+ */
+static int
+linux_alloc_prison(struct prison *pr, struct linux_prison **lprp)
+{
+ struct prison *ppr;
+ struct linux_prison *lpr, *nlpr;
+ int error;
+
+ LIN_SDT_PROBE2(mib, linux_alloc_prison, entry, pr, lprp);
+
+ /* If this prison already has Linux info, return that. */
+ error = 0;
+ lpr = linux_find_prison(pr, &ppr);
+ if (ppr == pr)
+ goto done;
+ /*
+ * Allocate a new info record. Then check again, in case something
+ * changed during the allocation.
+ */
+ mtx_unlock(&ppr->pr_mtx);
+ nlpr = malloc(sizeof(struct linux_prison), M_PRISON, M_WAITOK);
+ lpr = linux_find_prison(pr, &ppr);
+ if (ppr == pr) {
+ free(nlpr, M_PRISON);
+ goto done;
+ }
+ /* Inherit the initial values from the ancestor. */
+ mtx_lock(&pr->pr_mtx);
+ error = osd_jail_set(pr, linux_osd_jail_slot, nlpr);
+ if (error == 0) {
+ bcopy(lpr, nlpr, sizeof(*lpr));
+ lpr = nlpr;
+ } else {
+ free(nlpr, M_PRISON);
+ lpr = NULL;
+ }
+ mtx_unlock(&ppr->pr_mtx);
+ done:
+ if (lprp != NULL)
+ *lprp = lpr;
+ else
+ mtx_unlock(&pr->pr_mtx);
+
+ LIN_SDT_PROBE1(mib, linux_alloc_prison, return, error);
+ return (error);
+}
+
+/*
+ * Jail OSD methods for Linux prison data.
+ */
+static int
+linux_prison_create(void *obj, void *data)
+{
+ struct prison *pr = obj;
+ struct vfsoptlist *opts = data;
+ int jsys, error;
+
+ LIN_SDT_PROBE2(mib, linux_prison_create, entry, obj, data);
+
+ error = vfs_copyopt(opts, "linux", &jsys, sizeof(jsys));
+ if (error != 0) {
+ LIN_SDT_PROBE1(mib, linux_prison_create, vfs_copyopt_error,
+ error);
+ } else if (jsys == JAIL_SYS_INHERIT) {
+ LIN_SDT_PROBE1(mib, linux_prison_create, return, 0);
+ return (0);
+ }
+ /*
+ * Inherit a prison's initial values from its parent
+ * (different from JAIL_SYS_INHERIT which also inherits changes).
+ */
+ error = linux_alloc_prison(pr, NULL);
+
+ LIN_SDT_PROBE1(mib, linux_prison_create, return, error);
+ return (error);
+}
+
+static int
+linux_prison_check(void *obj __unused, void *data)
+{
+ struct vfsoptlist *opts = data;
+ char *osname, *osrelease;
+ int error, jsys, len, osrel, oss_version;
+
+ LIN_SDT_PROBE2(mib, linux_prison_check, entry, obj, data);
+
+ /* Check that the parameters are correct. */
+ error = vfs_copyopt(opts, "linux", &jsys, sizeof(jsys));
+ if (error != 0) {
+ LIN_SDT_PROBE1(mib, linux_prison_check, vfs_copyopt_error,
+ error);
+ }
+ if (error != ENOENT) {
+ if (error != 0) {
+ LIN_SDT_PROBE1(mib, linux_prison_check, return, error);
+ return (error);
+ }
+ if (jsys != JAIL_SYS_NEW && jsys != JAIL_SYS_INHERIT) {
+ LIN_SDT_PROBE1(mib, linux_prison_check, return, EINVAL);
+ return (EINVAL);
+ }
+ }
+ error = vfs_getopt(opts, "linux.osname", (void **)&osname, &len);
+ if (error != 0) {
+ LIN_SDT_PROBE1(mib, linux_prison_check, vfs_getopt_error,
+ error);
+ }
+ if (error != ENOENT) {
+ if (error != 0) {
+ LIN_SDT_PROBE1(mib, linux_prison_check, return, error);
+ return (error);
+ }
+ if (len == 0 || osname[len - 1] != '\0') {
+ LIN_SDT_PROBE1(mib, linux_prison_check, return, EINVAL);
+ return (EINVAL);
+ }
+ if (len > LINUX_MAX_UTSNAME) {
+ vfs_opterror(opts, "linux.osname too long");
+ LIN_SDT_PROBE1(mib, linux_prison_check, return,
+ ENAMETOOLONG);
+ return (ENAMETOOLONG);
+ }
+ }
+ error = vfs_getopt(opts, "linux.osrelease", (void **)&osrelease, &len);
+ if (error != 0) {
+ LIN_SDT_PROBE1(mib, linux_prison_check, vfs_getopt_error,
+ error);
+ }
+ if (error != ENOENT) {
+ if (error != 0) {
+ LIN_SDT_PROBE1(mib, linux_prison_check, return, error);
+ return (error);
+ }
+ if (len == 0 || osrelease[len - 1] != '\0') {
+ LIN_SDT_PROBE1(mib, linux_prison_check, return, EINVAL);
+ return (EINVAL);
+ }
+ if (len > LINUX_MAX_UTSNAME) {
+ vfs_opterror(opts, "linux.osrelease too long");
+ LIN_SDT_PROBE1(mib, linux_prison_check, return,
+ ENAMETOOLONG);
+ return (ENAMETOOLONG);
+ }
+ error = linux_map_osrel(osrelease, &osrel);
+ if (error != 0) {
+ vfs_opterror(opts, "linux.osrelease format error");
+ LIN_SDT_PROBE1(mib, linux_prison_check, return, error);
+ return (error);
+ }
+ }
+ error = vfs_copyopt(opts, "linux.oss_version", &oss_version,
+ sizeof(oss_version));
+ if (error != 0)
+ LIN_SDT_PROBE1(mib, linux_prison_check, vfs_copyopt_error, error);
+
+ if (error == ENOENT)
+ error = 0;
+ LIN_SDT_PROBE1(mib, linux_prison_check, return, error);
+ return (error);
+}
+
+static int
+linux_prison_set(void *obj, void *data)
+{
+ struct linux_prison *lpr;
+ struct prison *pr = obj;
+ struct vfsoptlist *opts = data;
+ char *osname, *osrelease;
+ int error, gotversion, jsys, len, oss_version;
+
+ LIN_SDT_PROBE2(mib, linux_prison_set, entry, obj, data);
+
+ /* Set the parameters, which should be correct. */
+ error = vfs_copyopt(opts, "linux", &jsys, sizeof(jsys));
+ if (error != 0)
+ LIN_SDT_PROBE1(mib, linux_prison_set, vfs_copyopt_error, error);
+ if (error == ENOENT)
+ jsys = -1;
+ error = vfs_getopt(opts, "linux.osname", (void **)&osname, &len);
+ if (error != 0)
+ LIN_SDT_PROBE1(mib, linux_prison_set, vfs_getopt_error, error);
+ if (error == ENOENT)
+ osname = NULL;
+ else
+ jsys = JAIL_SYS_NEW;
+ error = vfs_getopt(opts, "linux.osrelease", (void **)&osrelease, &len);
+ if (error != 0)
+ LIN_SDT_PROBE1(mib, linux_prison_set, vfs_getopt_error, error);
+ if (error == ENOENT)
+ osrelease = NULL;
+ else
+ jsys = JAIL_SYS_NEW;
+ error = vfs_copyopt(opts, "linux.oss_version", &oss_version,
+ sizeof(oss_version));
+ if (error != 0)
+ LIN_SDT_PROBE1(mib, linux_prison_set, vfs_copyopt_error, error);
+ if (error == ENOENT)
+ gotversion = 0;
+ else {
+ gotversion = 1;
+ jsys = JAIL_SYS_NEW;
+ }
+ switch (jsys) {
+ case JAIL_SYS_INHERIT:
+ /* "linux=inherit": inherit the parent's Linux info. */
+ mtx_lock(&pr->pr_mtx);
+ osd_jail_del(pr, linux_osd_jail_slot);
+ mtx_unlock(&pr->pr_mtx);
+ break;
+ case JAIL_SYS_NEW:
+ /*
+ * "linux=new" or "linux.*":
+ * the prison gets its own Linux info.
+ */
+ error = linux_alloc_prison(pr, &lpr);
+ if (error) {
+ mtx_unlock(&pr->pr_mtx);
+ LIN_SDT_PROBE1(mib, linux_prison_set, return, error);
+ return (error);
+ }
+ if (osrelease) {
+ error = linux_map_osrel(osrelease, &lpr->pr_osrel);
+ if (error) {
+ mtx_unlock(&pr->pr_mtx);
+ LIN_SDT_PROBE1(mib, linux_prison_set, return,
+ error);
+ return (error);
+ }
+ strlcpy(lpr->pr_osrelease, osrelease,
+ LINUX_MAX_UTSNAME);
+ }
+ if (osname)
+ strlcpy(lpr->pr_osname, osname, LINUX_MAX_UTSNAME);
+ if (gotversion)
+ lpr->pr_oss_version = oss_version;
+ mtx_unlock(&pr->pr_mtx);
+ }
+
+ LIN_SDT_PROBE1(mib, linux_prison_set, return, 0);
+ return (0);
+}
+
+SYSCTL_JAIL_PARAM_SYS_NODE(linux, CTLFLAG_RW, "Jail Linux parameters");
+SYSCTL_JAIL_PARAM_STRING(_linux, osname, CTLFLAG_RW, LINUX_MAX_UTSNAME,
+ "Jail Linux kernel OS name");
+SYSCTL_JAIL_PARAM_STRING(_linux, osrelease, CTLFLAG_RW, LINUX_MAX_UTSNAME,
+ "Jail Linux kernel OS release");
+SYSCTL_JAIL_PARAM(_linux, oss_version, CTLTYPE_INT | CTLFLAG_RW,
+ "I", "Jail Linux OSS version");
+
+static int
+linux_prison_get(void *obj, void *data)
+{
+ struct linux_prison *lpr;
+ struct prison *ppr;
+ struct prison *pr = obj;
+ struct vfsoptlist *opts = data;
+ int error, i;
+
+ static int version0;
+
+ LIN_SDT_PROBE2(mib, linux_prison_get, entry, obj, data);
+
+ /* See if this prison is the one with the Linux info. */
+ lpr = linux_find_prison(pr, &ppr);
+ i = (ppr == pr) ? JAIL_SYS_NEW : JAIL_SYS_INHERIT;
+ error = vfs_setopt(opts, "linux", &i, sizeof(i));
+ if (error != 0) {
+ LIN_SDT_PROBE1(mib, linux_prison_get, vfs_setopt_error, error);
+ if (error != ENOENT)
+ goto done;
+ }
+ if (i) {
+ error = vfs_setopts(opts, "linux.osname", lpr->pr_osname);
+ if (error != 0) {
+ LIN_SDT_PROBE1(mib, linux_prison_get, vfs_setopts_error,
+ error);
+ if (error != ENOENT)
+ goto done;
+ }
+ error = vfs_setopts(opts, "linux.osrelease", lpr->pr_osrelease);
+ if (error != 0) {
+ LIN_SDT_PROBE1(mib, linux_prison_get, vfs_setopts_error,
+ error);
+ if (error != ENOENT)
+ goto done;
+ }
+ error = vfs_setopt(opts, "linux.oss_version",
+ &lpr->pr_oss_version, sizeof(lpr->pr_oss_version));
+ if (error != 0) {
+ LIN_SDT_PROBE1(mib, linux_prison_get, vfs_setopt_error,
+ error);
+ if(error != ENOENT)
+ goto done;
+ }
+ } else {
+ /*
+ * If this prison is inheriting its Linux info, report
+ * empty/zero parameters.
+ */
+ error = vfs_setopts(opts, "linux.osname", "");
+ if (error != 0) {
+ LIN_SDT_PROBE1(mib, linux_prison_get, vfs_setopts_error,
+ error);
+ if(error != ENOENT)
+ goto done;
+ }
+ error = vfs_setopts(opts, "linux.osrelease", "");
+ if (error != 0) {
+ LIN_SDT_PROBE1(mib, linux_prison_get, vfs_setopts_error,
+ error);
+ if(error != ENOENT)
+ goto done;
+ }
+ error = vfs_setopt(opts, "linux.oss_version", &version0,
+ sizeof(lpr->pr_oss_version));
+ if (error != 0) {
+ LIN_SDT_PROBE1(mib, linux_prison_get, vfs_setopt_error,
+ error);
+ if(error != ENOENT)
+ goto done;
+ }
+ }
+ error = 0;
+
+ done:
+ mtx_unlock(&ppr->pr_mtx);
+
+ LIN_SDT_PROBE1(mib, linux_prison_get, return, error);
+ return (error);
+}
+
+static void
+linux_prison_destructor(void *data)
+{
+
+ LIN_SDT_PROBE1(mib, linux_prison_destructor, entry, data);
+ free(data, M_PRISON);
+ LIN_SDT_PROBE0(mib, linux_prison_destructor, return);
+}
+
+void
+linux_osd_jail_register(void)
+{
+ struct prison *pr;
+ osd_method_t methods[PR_MAXMETHOD] = {
+ [PR_METHOD_CREATE] = linux_prison_create,
+ [PR_METHOD_GET] = linux_prison_get,
+ [PR_METHOD_SET] = linux_prison_set,
+ [PR_METHOD_CHECK] = linux_prison_check
+ };
+
+ LIN_SDT_PROBE0(mib, linux_osd_jail_register, entry);
+
+ linux_osd_jail_slot =
+ osd_jail_register(linux_prison_destructor, methods);
+ if (linux_osd_jail_slot > 0) {
+ /* Copy the system linux info to any current prisons. */
+ sx_xlock(&allprison_lock);
+ TAILQ_FOREACH(pr, &allprison, pr_list)
+ (void)linux_alloc_prison(pr, NULL);
+ sx_xunlock(&allprison_lock);
+ }
+
+ LIN_SDT_PROBE0(mib, linux_osd_jail_register, return);
+}
+
+void
+linux_osd_jail_deregister(void)
+{
+
+ LIN_SDT_PROBE0(mib, linux_osd_jail_register, entry);
+
+ if (linux_osd_jail_slot)
+ osd_jail_deregister(linux_osd_jail_slot);
+
+ LIN_SDT_PROBE0(mib, linux_osd_jail_register, return);
+}
+
+void
+linux_get_osname(struct thread *td, char *dst)
+{
+ struct prison *pr;
+ struct linux_prison *lpr;
+
+ LIN_SDT_PROBE2(mib, linux_get_osname, entry, td, dst);
+
+ lpr = linux_find_prison(td->td_ucred->cr_prison, &pr);
+ bcopy(lpr->pr_osname, dst, LINUX_MAX_UTSNAME);
+ mtx_unlock(&pr->pr_mtx);
+
+ LIN_SDT_PROBE0(mib, linux_get_osname, return);
+}
+
+static int
+linux_set_osname(struct thread *td, char *osname)
+{
+ struct prison *pr;
+ struct linux_prison *lpr;
+
+ LIN_SDT_PROBE2(mib, linux_set_osname, entry, td, osname);
+
+ lpr = linux_find_prison(td->td_ucred->cr_prison, &pr);
+ strlcpy(lpr->pr_osname, osname, LINUX_MAX_UTSNAME);
+ mtx_unlock(&pr->pr_mtx);
+
+ LIN_SDT_PROBE1(mib, linux_set_osname, return, 0);
+ return (0);
+}
+
+void
+linux_get_osrelease(struct thread *td, char *dst)
+{
+ struct prison *pr;
+ struct linux_prison *lpr;
+
+ LIN_SDT_PROBE2(mib, linux_get_osrelease, entry, td, dst);
+
+ lpr = linux_find_prison(td->td_ucred->cr_prison, &pr);
+ bcopy(lpr->pr_osrelease, dst, LINUX_MAX_UTSNAME);
+ mtx_unlock(&pr->pr_mtx);
+
+ LIN_SDT_PROBE0(mib, linux_get_osrelease, return);
+}
+
+int
+linux_kernver(struct thread *td)
+{
+ struct prison *pr;
+ struct linux_prison *lpr;
+ int osrel;
+
+ LIN_SDT_PROBE1(mib, linux_kernver, entry, td);
+
+ lpr = linux_find_prison(td->td_ucred->cr_prison, &pr);
+ osrel = lpr->pr_osrel;
+ mtx_unlock(&pr->pr_mtx);
+
+ LIN_SDT_PROBE1(mib, linux_kernver, return, osrel);
+ return (osrel);
+}
+
+static int
+linux_set_osrelease(struct thread *td, char *osrelease)
+{
+ struct prison *pr;
+ struct linux_prison *lpr;
+ int error;
+
+ LIN_SDT_PROBE2(mib, linux_set_osrelease, entry, td, osrelease);
+
+ lpr = linux_find_prison(td->td_ucred->cr_prison, &pr);
+ error = linux_map_osrel(osrelease, &lpr->pr_osrel);
+ if (error == 0)
+ strlcpy(lpr->pr_osrelease, osrelease, LINUX_MAX_UTSNAME);
+ mtx_unlock(&pr->pr_mtx);
+
+ LIN_SDT_PROBE1(mib, linux_set_osrelease, return, error);
+ return (error);
+}
+
+int
+linux_get_oss_version(struct thread *td)
+{
+ struct prison *pr;
+ struct linux_prison *lpr;
+ int version;
+
+ LIN_SDT_PROBE1(mib, linux_get_oss_version, entry, td);
+
+ lpr = linux_find_prison(td->td_ucred->cr_prison, &pr);
+ version = lpr->pr_oss_version;
+ mtx_unlock(&pr->pr_mtx);
+
+ LIN_SDT_PROBE1(mib, linux_get_oss_version, return, version);
+ return (version);
+}
+
+static int
+linux_set_oss_version(struct thread *td, int oss_version)
+{
+ struct prison *pr;
+ struct linux_prison *lpr;
+
+ LIN_SDT_PROBE2(mib, linux_set_oss_version, entry, td, oss_version);
+
+ lpr = linux_find_prison(td->td_ucred->cr_prison, &pr);
+ lpr->pr_oss_version = oss_version;
+ mtx_unlock(&pr->pr_mtx);
+
+ LIN_SDT_PROBE1(mib, linux_set_oss_version, return, 0);
+ return (0);
+}
+
+#if defined(DEBUG) || defined(KTR)
+/* XXX: can be removed when every ldebug(...) and KTR stuff are removed. */
+
+u_char linux_debug_map[howmany(LINUX_SYS_MAXSYSCALL, sizeof(u_char))];
+
+static int
+linux_debug(int syscall, int toggle, int global)
+{
+
+ if (global) {
+ char c = toggle ? 0 : 0xff;
+
+ memset(linux_debug_map, c, sizeof(linux_debug_map));
+ return (0);
+ }
+ if (syscall < 0 || syscall >= LINUX_SYS_MAXSYSCALL)
+ return (EINVAL);
+ if (toggle)
+ clrbit(linux_debug_map, syscall);
+ else
+ setbit(linux_debug_map, syscall);
+ return (0);
+}
+
+/*
+ * Usage: sysctl linux.debug=<syscall_nr>.<0/1>
+ *
+ * E.g.: sysctl linux.debug=21.0
+ *
+ * As a special case, syscall "all" will apply to all syscalls globally.
+ */
+#define LINUX_MAX_DEBUGSTR 16
+static int
+linux_sysctl_debug(SYSCTL_HANDLER_ARGS)
+{
+ char value[LINUX_MAX_DEBUGSTR], *p;
+ int error, sysc, toggle;
+ int global = 0;
+
+ value[0] = '\0';
+ error = sysctl_handle_string(oidp, value, LINUX_MAX_DEBUGSTR, req);
+ if (error || req->newptr == NULL)
+ return (error);
+ for (p = value; *p != '\0' && *p != '.'; p++);
+ if (*p == '\0')
+ return (EINVAL);
+ *p++ = '\0';
+ sysc = strtol(value, NULL, 0);
+ toggle = strtol(p, NULL, 0);
+ if (strcmp(value, "all") == 0)
+ global = 1;
+ error = linux_debug(sysc, toggle, global);
+ return (error);
+}
+
+SYSCTL_PROC(_compat_linux, OID_AUTO, debug,
+ CTLTYPE_STRING | CTLFLAG_RW,
+ 0, 0, linux_sysctl_debug, "A",
+ "Linux debugging control");
+
+#endif /* DEBUG || KTR */
diff --git a/sys/compat/linux/linux_mib.h b/sys/compat/linux/linux_mib.h
new file mode 100644
index 0000000..e8eedf9
--- /dev/null
+++ b/sys/compat/linux/linux_mib.h
@@ -0,0 +1,50 @@
+/*-
+ * Copyright (c) 1999 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LINUX_MIB_H_
+#define _LINUX_MIB_H_
+
+void linux_osd_jail_register(void);
+void linux_osd_jail_deregister(void);
+
+void linux_get_osname(struct thread *td, char *dst);
+
+void linux_get_osrelease(struct thread *td, char *dst);
+
+int linux_get_oss_version(struct thread *td);
+
+int linux_kernver(struct thread *td);
+
+#define LINUX_KERNVER_2004000 2004000
+#define LINUX_KERNVER_2006000 2006000
+
+#define linux_use26(t) (linux_kernver(t) >= LINUX_KERNVER_2006000)
+
+#endif /* _LINUX_MIB_H_ */
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
new file mode 100644
index 0000000..7587272
--- /dev/null
+++ b/sys/compat/linux/linux_misc.c
@@ -0,0 +1,1927 @@
+/*-
+ * Copyright (c) 2002 Doug Rabson
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_compat.h"
+#include "opt_kdtrace.h"
+
+#include <sys/param.h>
+#include <sys/blist.h>
+#include <sys/fcntl.h>
+#if defined(__i386__)
+#include <sys/imgact_aout.h>
+#endif
+#include <sys/jail.h>
+#include <sys/kernel.h>
+#include <sys/limits.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mman.h>
+#include <sys/mount.h>
+#include <sys/mutex.h>
+#include <sys/namei.h>
+#include <sys/priv.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <sys/racct.h>
+#include <sys/resourcevar.h>
+#include <sys/sched.h>
+#include <sys/sdt.h>
+#include <sys/signalvar.h>
+#include <sys/stat.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysctl.h>
+#include <sys/sysproto.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+#include <sys/vmmeter.h>
+#include <sys/vnode.h>
+#include <sys/wait.h>
+#include <sys/cpuset.h>
+
+#include <security/mac/mac_framework.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_map.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_object.h>
+#include <vm/swap_pager.h>
+
+#ifdef COMPAT_LINUX32
+#include <machine/../linux32/linux.h>
+#include <machine/../linux32/linux32_proto.h>
+#else
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#endif
+
+#include <compat/linux/linux_dtrace.h>
+#include <compat/linux/linux_file.h>
+#include <compat/linux/linux_mib.h>
+#include <compat/linux/linux_signal.h>
+#include <compat/linux/linux_util.h>
+#include <compat/linux/linux_sysproto.h>
+#include <compat/linux/linux_emul.h>
+#include <compat/linux/linux_misc.h>
+
+/* DTrace init */
+LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
+
+/* Linuxulator-global DTrace probes */
+LIN_SDT_PROBE_DECLARE(locks, emul_lock, locked);
+LIN_SDT_PROBE_DECLARE(locks, emul_lock, unlock);
+LIN_SDT_PROBE_DECLARE(locks, emul_shared_rlock, locked);
+LIN_SDT_PROBE_DECLARE(locks, emul_shared_rlock, unlock);
+LIN_SDT_PROBE_DECLARE(locks, emul_shared_wlock, locked);
+LIN_SDT_PROBE_DECLARE(locks, emul_shared_wlock, unlock);
+
+int stclohz; /* Statistics clock frequency */
+
+static unsigned int linux_to_bsd_resource[LINUX_RLIM_NLIMITS] = {
+ RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK,
+ RLIMIT_CORE, RLIMIT_RSS, RLIMIT_NPROC, RLIMIT_NOFILE,
+ RLIMIT_MEMLOCK, RLIMIT_AS
+};
+
+struct l_sysinfo {
+ l_long uptime; /* Seconds since boot */
+ l_ulong loads[3]; /* 1, 5, and 15 minute load averages */
+#define LINUX_SYSINFO_LOADS_SCALE 65536
+ l_ulong totalram; /* Total usable main memory size */
+ l_ulong freeram; /* Available memory size */
+ l_ulong sharedram; /* Amount of shared memory */
+ l_ulong bufferram; /* Memory used by buffers */
+ l_ulong totalswap; /* Total swap space size */
+ l_ulong freeswap; /* swap space still available */
+ l_ushort procs; /* Number of current processes */
+ l_ushort pads;
+ l_ulong totalbig;
+ l_ulong freebig;
+ l_uint mem_unit;
+ char _f[20-2*sizeof(l_long)-sizeof(l_int)]; /* padding */
+};
+int
+linux_sysinfo(struct thread *td, struct linux_sysinfo_args *args)
+{
+ struct l_sysinfo sysinfo;
+ vm_object_t object;
+ int i, j;
+ struct timespec ts;
+
+ getnanouptime(&ts);
+ if (ts.tv_nsec != 0)
+ ts.tv_sec++;
+ sysinfo.uptime = ts.tv_sec;
+
+ /* Use the information from the mib to get our load averages */
+ for (i = 0; i < 3; i++)
+ sysinfo.loads[i] = averunnable.ldavg[i] *
+ LINUX_SYSINFO_LOADS_SCALE / averunnable.fscale;
+
+ sysinfo.totalram = physmem * PAGE_SIZE;
+ sysinfo.freeram = sysinfo.totalram - cnt.v_wire_count * PAGE_SIZE;
+
+ sysinfo.sharedram = 0;
+ mtx_lock(&vm_object_list_mtx);
+ TAILQ_FOREACH(object, &vm_object_list, object_list)
+ if (object->shadow_count > 1)
+ sysinfo.sharedram += object->resident_page_count;
+ mtx_unlock(&vm_object_list_mtx);
+
+ sysinfo.sharedram *= PAGE_SIZE;
+ sysinfo.bufferram = 0;
+
+ swap_pager_status(&i, &j);
+ sysinfo.totalswap = i * PAGE_SIZE;
+ sysinfo.freeswap = (i - j) * PAGE_SIZE;
+
+ sysinfo.procs = nprocs;
+
+ /* The following are only present in newer Linux kernels. */
+ sysinfo.totalbig = 0;
+ sysinfo.freebig = 0;
+ sysinfo.mem_unit = 1;
+
+ return (copyout(&sysinfo, args->info, sizeof(sysinfo)));
+}
+
+int
+linux_alarm(struct thread *td, struct linux_alarm_args *args)
+{
+ struct itimerval it, old_it;
+ u_int secs;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(alarm))
+ printf(ARGS(alarm, "%u"), args->secs);
+#endif
+
+ secs = args->secs;
+
+ if (secs > INT_MAX)
+ secs = INT_MAX;
+
+ it.it_value.tv_sec = (long) secs;
+ it.it_value.tv_usec = 0;
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_usec = 0;
+ error = kern_setitimer(td, ITIMER_REAL, &it, &old_it);
+ if (error)
+ return (error);
+ if (timevalisset(&old_it.it_value)) {
+ if (old_it.it_value.tv_usec != 0)
+ old_it.it_value.tv_sec++;
+ td->td_retval[0] = old_it.it_value.tv_sec;
+ }
+ return (0);
+}
+
+int
+linux_brk(struct thread *td, struct linux_brk_args *args)
+{
+ struct vmspace *vm = td->td_proc->p_vmspace;
+ vm_offset_t new, old;
+ struct obreak_args /* {
+ char * nsize;
+ } */ tmp;
+
+#ifdef DEBUG
+ if (ldebug(brk))
+ printf(ARGS(brk, "%p"), (void *)(uintptr_t)args->dsend);
+#endif
+ old = (vm_offset_t)vm->vm_daddr + ctob(vm->vm_dsize);
+ new = (vm_offset_t)args->dsend;
+ tmp.nsize = (char *)new;
+ if (((caddr_t)new > vm->vm_daddr) && !sys_obreak(td, &tmp))
+ td->td_retval[0] = (long)new;
+ else
+ td->td_retval[0] = (long)old;
+
+ return (0);
+}
+
+#if defined(__i386__)
+/* XXX: what about amd64/linux32? */
+
+int
+linux_uselib(struct thread *td, struct linux_uselib_args *args)
+{
+ struct nameidata ni;
+ struct vnode *vp;
+ struct exec *a_out;
+ struct vattr attr;
+ vm_offset_t vmaddr;
+ unsigned long file_offset;
+ unsigned long bss_size;
+ char *library;
+ ssize_t aresid;
+ int error, locked, writecount;
+
+ LCONVPATHEXIST(td, args->library, &library);
+
+#ifdef DEBUG
+ if (ldebug(uselib))
+ printf(ARGS(uselib, "%s"), library);
+#endif
+
+ a_out = NULL;
+ locked = 0;
+ vp = NULL;
+
+ NDINIT(&ni, LOOKUP, ISOPEN | FOLLOW | LOCKLEAF | AUDITVNODE1,
+ UIO_SYSSPACE, library, td);
+ error = namei(&ni);
+ LFREEPATH(library);
+ if (error)
+ goto cleanup;
+
+ vp = ni.ni_vp;
+ NDFREE(&ni, NDF_ONLY_PNBUF);
+
+ /*
+ * From here on down, we have a locked vnode that must be unlocked.
+ * XXX: The code below largely duplicates exec_check_permissions().
+ */
+ locked = 1;
+
+ /* Writable? */
+ error = VOP_GET_WRITECOUNT(vp, &writecount);
+ if (error != 0)
+ goto cleanup;
+ if (writecount != 0) {
+ error = ETXTBSY;
+ goto cleanup;
+ }
+
+ /* Executable? */
+ error = VOP_GETATTR(vp, &attr, td->td_ucred);
+ if (error)
+ goto cleanup;
+
+ if ((vp->v_mount->mnt_flag & MNT_NOEXEC) ||
+ ((attr.va_mode & 0111) == 0) || (attr.va_type != VREG)) {
+ /* EACCESS is what exec(2) returns. */
+ error = ENOEXEC;
+ goto cleanup;
+ }
+
+ /* Sensible size? */
+ if (attr.va_size == 0) {
+ error = ENOEXEC;
+ goto cleanup;
+ }
+
+ /* Can we access it? */
+ error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
+ if (error)
+ goto cleanup;
+
+ /*
+ * XXX: This should use vn_open() so that it is properly authorized,
+ * and to reduce code redundancy all over the place here.
+ * XXX: Not really, it duplicates far more of exec_check_permissions()
+ * than vn_open().
+ */
+#ifdef MAC
+ error = mac_vnode_check_open(td->td_ucred, vp, VREAD);
+ if (error)
+ goto cleanup;
+#endif
+ error = VOP_OPEN(vp, FREAD, td->td_ucred, td, NULL);
+ if (error)
+ goto cleanup;
+
+ /* Pull in executable header into exec_map */
+ error = vm_mmap(exec_map, (vm_offset_t *)&a_out, PAGE_SIZE,
+ VM_PROT_READ, VM_PROT_READ, 0, OBJT_VNODE, vp, 0);
+ if (error)
+ goto cleanup;
+
+ /* Is it a Linux binary ? */
+ if (((a_out->a_magic >> 16) & 0xff) != 0x64) {
+ error = ENOEXEC;
+ goto cleanup;
+ }
+
+ /*
+ * While we are here, we should REALLY do some more checks
+ */
+
+ /* Set file/virtual offset based on a.out variant. */
+ switch ((int)(a_out->a_magic & 0xffff)) {
+ case 0413: /* ZMAGIC */
+ file_offset = 1024;
+ break;
+ case 0314: /* QMAGIC */
+ file_offset = 0;
+ break;
+ default:
+ error = ENOEXEC;
+ goto cleanup;
+ }
+
+ bss_size = round_page(a_out->a_bss);
+
+ /* Check various fields in header for validity/bounds. */
+ if (a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) {
+ error = ENOEXEC;
+ goto cleanup;
+ }
+
+ /* text + data can't exceed file size */
+ if (a_out->a_data + a_out->a_text > attr.va_size) {
+ error = EFAULT;
+ goto cleanup;
+ }
+
+ /*
+ * text/data/bss must not exceed limits
+ * XXX - this is not complete. it should check current usage PLUS
+ * the resources needed by this library.
+ */
+ PROC_LOCK(td->td_proc);
+ if (a_out->a_text > maxtsiz ||
+ a_out->a_data + bss_size > lim_cur(td->td_proc, RLIMIT_DATA) ||
+ racct_set(td->td_proc, RACCT_DATA, a_out->a_data +
+ bss_size) != 0) {
+ PROC_UNLOCK(td->td_proc);
+ error = ENOMEM;
+ goto cleanup;
+ }
+ PROC_UNLOCK(td->td_proc);
+
+ /*
+ * Prevent more writers.
+ * XXX: Note that if any of the VM operations fail below we don't
+ * clear this flag.
+ */
+ VOP_SET_TEXT(vp);
+
+ /*
+ * Lock no longer needed
+ */
+ locked = 0;
+ VOP_UNLOCK(vp, 0);
+
+ /*
+ * Check if file_offset page aligned. Currently we cannot handle
+ * misalinged file offsets, and so we read in the entire image
+ * (what a waste).
+ */
+ if (file_offset & PAGE_MASK) {
+#ifdef DEBUG
+ printf("uselib: Non page aligned binary %lu\n", file_offset);
+#endif
+ /* Map text+data read/write/execute */
+
+ /* a_entry is the load address and is page aligned */
+ vmaddr = trunc_page(a_out->a_entry);
+
+ /* get anon user mapping, read+write+execute */
+ error = vm_map_find(&td->td_proc->p_vmspace->vm_map, NULL, 0,
+ &vmaddr, a_out->a_text + a_out->a_data, FALSE, VM_PROT_ALL,
+ VM_PROT_ALL, 0);
+ if (error)
+ goto cleanup;
+
+ error = vn_rdwr(UIO_READ, vp, (void *)vmaddr, file_offset,
+ a_out->a_text + a_out->a_data, UIO_USERSPACE, 0,
+ td->td_ucred, NOCRED, &aresid, td);
+ if (error != 0)
+ goto cleanup;
+ if (aresid != 0) {
+ error = ENOEXEC;
+ goto cleanup;
+ }
+ } else {
+#ifdef DEBUG
+ printf("uselib: Page aligned binary %lu\n", file_offset);
+#endif
+ /*
+ * for QMAGIC, a_entry is 20 bytes beyond the load address
+ * to skip the executable header
+ */
+ vmaddr = trunc_page(a_out->a_entry);
+
+ /*
+ * Map it all into the process's space as a single
+ * copy-on-write "data" segment.
+ */
+ error = vm_mmap(&td->td_proc->p_vmspace->vm_map, &vmaddr,
+ a_out->a_text + a_out->a_data, VM_PROT_ALL, VM_PROT_ALL,
+ MAP_PRIVATE | MAP_FIXED, OBJT_VNODE, vp, file_offset);
+ if (error)
+ goto cleanup;
+ }
+#ifdef DEBUG
+ printf("mem=%08lx = %08lx %08lx\n", (long)vmaddr, ((long *)vmaddr)[0],
+ ((long *)vmaddr)[1]);
+#endif
+ if (bss_size != 0) {
+ /* Calculate BSS start address */
+ vmaddr = trunc_page(a_out->a_entry) + a_out->a_text +
+ a_out->a_data;
+
+ /* allocate some 'anon' space */
+ error = vm_map_find(&td->td_proc->p_vmspace->vm_map, NULL, 0,
+ &vmaddr, bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0);
+ if (error)
+ goto cleanup;
+ }
+
+cleanup:
+ /* Unlock vnode if needed */
+ if (locked)
+ VOP_UNLOCK(vp, 0);
+
+ /* Release the temporary mapping. */
+ if (a_out)
+ kmem_free_wakeup(exec_map, (vm_offset_t)a_out, PAGE_SIZE);
+
+ return (error);
+}
+
+#endif /* __i386__ */
+
+int
+linux_select(struct thread *td, struct linux_select_args *args)
+{
+ l_timeval ltv;
+ struct timeval tv0, tv1, utv, *tvp;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(select))
+ printf(ARGS(select, "%d, %p, %p, %p, %p"), args->nfds,
+ (void *)args->readfds, (void *)args->writefds,
+ (void *)args->exceptfds, (void *)args->timeout);
+#endif
+
+ /*
+ * Store current time for computation of the amount of
+ * time left.
+ */
+ if (args->timeout) {
+ if ((error = copyin(args->timeout, &ltv, sizeof(ltv))))
+ goto select_out;
+ utv.tv_sec = ltv.tv_sec;
+ utv.tv_usec = ltv.tv_usec;
+#ifdef DEBUG
+ if (ldebug(select))
+ printf(LMSG("incoming timeout (%jd/%ld)"),
+ (intmax_t)utv.tv_sec, utv.tv_usec);
+#endif
+
+ if (itimerfix(&utv)) {
+ /*
+ * The timeval was invalid. Convert it to something
+ * valid that will act as it does under Linux.
+ */
+ utv.tv_sec += utv.tv_usec / 1000000;
+ utv.tv_usec %= 1000000;
+ if (utv.tv_usec < 0) {
+ utv.tv_sec -= 1;
+ utv.tv_usec += 1000000;
+ }
+ if (utv.tv_sec < 0)
+ timevalclear(&utv);
+ }
+ microtime(&tv0);
+ tvp = &utv;
+ } else
+ tvp = NULL;
+
+ error = kern_select(td, args->nfds, args->readfds, args->writefds,
+ args->exceptfds, tvp, sizeof(l_int) * 8);
+
+#ifdef DEBUG
+ if (ldebug(select))
+ printf(LMSG("real select returns %d"), error);
+#endif
+ if (error)
+ goto select_out;
+
+ if (args->timeout) {
+ if (td->td_retval[0]) {
+ /*
+ * Compute how much time was left of the timeout,
+ * by subtracting the current time and the time
+ * before we started the call, and subtracting
+ * that result from the user-supplied value.
+ */
+ microtime(&tv1);
+ timevalsub(&tv1, &tv0);
+ timevalsub(&utv, &tv1);
+ if (utv.tv_sec < 0)
+ timevalclear(&utv);
+ } else
+ timevalclear(&utv);
+#ifdef DEBUG
+ if (ldebug(select))
+ printf(LMSG("outgoing timeout (%jd/%ld)"),
+ (intmax_t)utv.tv_sec, utv.tv_usec);
+#endif
+ ltv.tv_sec = utv.tv_sec;
+ ltv.tv_usec = utv.tv_usec;
+ if ((error = copyout(&ltv, args->timeout, sizeof(ltv))))
+ goto select_out;
+ }
+
+select_out:
+#ifdef DEBUG
+ if (ldebug(select))
+ printf(LMSG("select_out -> %d"), error);
+#endif
+ return (error);
+}
+
+int
+linux_mremap(struct thread *td, struct linux_mremap_args *args)
+{
+ struct munmap_args /* {
+ void *addr;
+ size_t len;
+ } */ bsd_args;
+ int error = 0;
+
+#ifdef DEBUG
+ if (ldebug(mremap))
+ printf(ARGS(mremap, "%p, %08lx, %08lx, %08lx"),
+ (void *)(uintptr_t)args->addr,
+ (unsigned long)args->old_len,
+ (unsigned long)args->new_len,
+ (unsigned long)args->flags);
+#endif
+
+ if (args->flags & ~(LINUX_MREMAP_FIXED | LINUX_MREMAP_MAYMOVE)) {
+ td->td_retval[0] = 0;
+ return (EINVAL);
+ }
+
+ /*
+ * Check for the page alignment.
+ * Linux defines PAGE_MASK to be FreeBSD ~PAGE_MASK.
+ */
+ if (args->addr & PAGE_MASK) {
+ td->td_retval[0] = 0;
+ return (EINVAL);
+ }
+
+ args->new_len = round_page(args->new_len);
+ args->old_len = round_page(args->old_len);
+
+ if (args->new_len > args->old_len) {
+ td->td_retval[0] = 0;
+ return (ENOMEM);
+ }
+
+ if (args->new_len < args->old_len) {
+ bsd_args.addr =
+ (caddr_t)((uintptr_t)args->addr + args->new_len);
+ bsd_args.len = args->old_len - args->new_len;
+ error = sys_munmap(td, &bsd_args);
+ }
+
+ td->td_retval[0] = error ? 0 : (uintptr_t)args->addr;
+ return (error);
+}
+
+#define LINUX_MS_ASYNC 0x0001
+#define LINUX_MS_INVALIDATE 0x0002
+#define LINUX_MS_SYNC 0x0004
+
+int
+linux_msync(struct thread *td, struct linux_msync_args *args)
+{
+ struct msync_args bsd_args;
+
+ bsd_args.addr = (caddr_t)(uintptr_t)args->addr;
+ bsd_args.len = (uintptr_t)args->len;
+ bsd_args.flags = args->fl & ~LINUX_MS_SYNC;
+
+ return (sys_msync(td, &bsd_args));
+}
+
+int
+linux_time(struct thread *td, struct linux_time_args *args)
+{
+ struct timeval tv;
+ l_time_t tm;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(time))
+ printf(ARGS(time, "*"));
+#endif
+
+ microtime(&tv);
+ tm = tv.tv_sec;
+ if (args->tm && (error = copyout(&tm, args->tm, sizeof(tm))))
+ return (error);
+ td->td_retval[0] = tm;
+ return (0);
+}
+
+struct l_times_argv {
+ l_clock_t tms_utime;
+ l_clock_t tms_stime;
+ l_clock_t tms_cutime;
+ l_clock_t tms_cstime;
+};
+
+
+/*
+ * Glibc versions prior to 2.2.1 always use hard-coded CLK_TCK value.
+ * Since 2.2.1 Glibc uses value exported from kernel via AT_CLKTCK
+ * auxiliary vector entry.
+ */
+#define CLK_TCK 100
+
+#define CONVOTCK(r) (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK))
+#define CONVNTCK(r) (r.tv_sec * stclohz + r.tv_usec / (1000000 / stclohz))
+
+#define CONVTCK(r) (linux_kernver(td) >= LINUX_KERNVER_2004000 ? \
+ CONVNTCK(r) : CONVOTCK(r))
+
+int
+linux_times(struct thread *td, struct linux_times_args *args)
+{
+ struct timeval tv, utime, stime, cutime, cstime;
+ struct l_times_argv tms;
+ struct proc *p;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(times))
+ printf(ARGS(times, "*"));
+#endif
+
+ if (args->buf != NULL) {
+ p = td->td_proc;
+ PROC_LOCK(p);
+ PROC_SLOCK(p);
+ calcru(p, &utime, &stime);
+ PROC_SUNLOCK(p);
+ calccru(p, &cutime, &cstime);
+ PROC_UNLOCK(p);
+
+ tms.tms_utime = CONVTCK(utime);
+ tms.tms_stime = CONVTCK(stime);
+
+ tms.tms_cutime = CONVTCK(cutime);
+ tms.tms_cstime = CONVTCK(cstime);
+
+ if ((error = copyout(&tms, args->buf, sizeof(tms))))
+ return (error);
+ }
+
+ microuptime(&tv);
+ td->td_retval[0] = (int)CONVTCK(tv);
+ return (0);
+}
+
+int
+linux_newuname(struct thread *td, struct linux_newuname_args *args)
+{
+ struct l_new_utsname utsname;
+ char osname[LINUX_MAX_UTSNAME];
+ char osrelease[LINUX_MAX_UTSNAME];
+ char *p;
+
+#ifdef DEBUG
+ if (ldebug(newuname))
+ printf(ARGS(newuname, "*"));
+#endif
+
+ linux_get_osname(td, osname);
+ linux_get_osrelease(td, osrelease);
+
+ bzero(&utsname, sizeof(utsname));
+ strlcpy(utsname.sysname, osname, LINUX_MAX_UTSNAME);
+ getcredhostname(td->td_ucred, utsname.nodename, LINUX_MAX_UTSNAME);
+ getcreddomainname(td->td_ucred, utsname.domainname, LINUX_MAX_UTSNAME);
+ strlcpy(utsname.release, osrelease, LINUX_MAX_UTSNAME);
+ strlcpy(utsname.version, version, LINUX_MAX_UTSNAME);
+ for (p = utsname.version; *p != '\0'; ++p)
+ if (*p == '\n') {
+ *p = '\0';
+ break;
+ }
+ strlcpy(utsname.machine, linux_platform, LINUX_MAX_UTSNAME);
+
+ return (copyout(&utsname, args->buf, sizeof(utsname)));
+}
+
+#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
+struct l_utimbuf {
+ l_time_t l_actime;
+ l_time_t l_modtime;
+};
+
+int
+linux_utime(struct thread *td, struct linux_utime_args *args)
+{
+ struct timeval tv[2], *tvp;
+ struct l_utimbuf lut;
+ char *fname;
+ int error;
+
+ LCONVPATHEXIST(td, args->fname, &fname);
+
+#ifdef DEBUG
+ if (ldebug(utime))
+ printf(ARGS(utime, "%s, *"), fname);
+#endif
+
+ if (args->times) {
+ if ((error = copyin(args->times, &lut, sizeof lut))) {
+ LFREEPATH(fname);
+ return (error);
+ }
+ tv[0].tv_sec = lut.l_actime;
+ tv[0].tv_usec = 0;
+ tv[1].tv_sec = lut.l_modtime;
+ tv[1].tv_usec = 0;
+ tvp = tv;
+ } else
+ tvp = NULL;
+
+ error = kern_utimes(td, fname, UIO_SYSSPACE, tvp, UIO_SYSSPACE);
+ LFREEPATH(fname);
+ return (error);
+}
+
+int
+linux_utimes(struct thread *td, struct linux_utimes_args *args)
+{
+ l_timeval ltv[2];
+ struct timeval tv[2], *tvp = NULL;
+ char *fname;
+ int error;
+
+ LCONVPATHEXIST(td, args->fname, &fname);
+
+#ifdef DEBUG
+ if (ldebug(utimes))
+ printf(ARGS(utimes, "%s, *"), fname);
+#endif
+
+ if (args->tptr != NULL) {
+ if ((error = copyin(args->tptr, ltv, sizeof ltv))) {
+ LFREEPATH(fname);
+ return (error);
+ }
+ tv[0].tv_sec = ltv[0].tv_sec;
+ tv[0].tv_usec = ltv[0].tv_usec;
+ tv[1].tv_sec = ltv[1].tv_sec;
+ tv[1].tv_usec = ltv[1].tv_usec;
+ tvp = tv;
+ }
+
+ error = kern_utimes(td, fname, UIO_SYSSPACE, tvp, UIO_SYSSPACE);
+ LFREEPATH(fname);
+ return (error);
+}
+
+int
+linux_futimesat(struct thread *td, struct linux_futimesat_args *args)
+{
+ l_timeval ltv[2];
+ struct timeval tv[2], *tvp = NULL;
+ char *fname;
+ int error, dfd;
+
+ dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
+ LCONVPATHEXIST_AT(td, args->filename, &fname, dfd);
+
+#ifdef DEBUG
+ if (ldebug(futimesat))
+ printf(ARGS(futimesat, "%s, *"), fname);
+#endif
+
+ if (args->utimes != NULL) {
+ if ((error = copyin(args->utimes, ltv, sizeof ltv))) {
+ LFREEPATH(fname);
+ return (error);
+ }
+ tv[0].tv_sec = ltv[0].tv_sec;
+ tv[0].tv_usec = ltv[0].tv_usec;
+ tv[1].tv_sec = ltv[1].tv_sec;
+ tv[1].tv_usec = ltv[1].tv_usec;
+ tvp = tv;
+ }
+
+ error = kern_utimesat(td, dfd, fname, UIO_SYSSPACE, tvp, UIO_SYSSPACE);
+ LFREEPATH(fname);
+ return (error);
+}
+#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
+
+int
+linux_common_wait(struct thread *td, int pid, int *status,
+ int options, struct rusage *ru)
+{
+ int error, tmpstat;
+
+ error = kern_wait(td, pid, &tmpstat, options, ru);
+ if (error)
+ return (error);
+
+ if (status) {
+ tmpstat &= 0xffff;
+ if (WIFSIGNALED(tmpstat))
+ tmpstat = (tmpstat & 0xffffff80) |
+ BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat));
+ else if (WIFSTOPPED(tmpstat))
+ tmpstat = (tmpstat & 0xffff00ff) |
+ (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8);
+ error = copyout(&tmpstat, status, sizeof(int));
+ }
+
+ return (error);
+}
+
+int
+linux_waitpid(struct thread *td, struct linux_waitpid_args *args)
+{
+ int options;
+
+#ifdef DEBUG
+ if (ldebug(waitpid))
+ printf(ARGS(waitpid, "%d, %p, %d"),
+ args->pid, (void *)args->status, args->options);
+#endif
+ /*
+ * this is necessary because the test in kern_wait doesn't work
+ * because we mess with the options here
+ */
+ if (args->options & ~(WUNTRACED | WNOHANG | WCONTINUED | __WCLONE))
+ return (EINVAL);
+
+ options = (args->options & (WNOHANG | WUNTRACED));
+ /* WLINUXCLONE should be equal to __WCLONE, but we make sure */
+ if (args->options & __WCLONE)
+ options |= WLINUXCLONE;
+
+ return (linux_common_wait(td, args->pid, args->status, options, NULL));
+}
+
+
+int
+linux_mknod(struct thread *td, struct linux_mknod_args *args)
+{
+ char *path;
+ int error;
+
+ LCONVPATHCREAT(td, args->path, &path);
+
+#ifdef DEBUG
+ if (ldebug(mknod))
+ printf(ARGS(mknod, "%s, %d, %d"), path, args->mode, args->dev);
+#endif
+
+ switch (args->mode & S_IFMT) {
+ case S_IFIFO:
+ case S_IFSOCK:
+ error = kern_mkfifo(td, path, UIO_SYSSPACE, args->mode);
+ break;
+
+ case S_IFCHR:
+ case S_IFBLK:
+ error = kern_mknod(td, path, UIO_SYSSPACE, args->mode,
+ args->dev);
+ break;
+
+ case S_IFDIR:
+ error = EPERM;
+ break;
+
+ case 0:
+ args->mode |= S_IFREG;
+ /* FALLTHROUGH */
+ case S_IFREG:
+ error = kern_open(td, path, UIO_SYSSPACE,
+ O_WRONLY | O_CREAT | O_TRUNC, args->mode);
+ if (error == 0)
+ kern_close(td, td->td_retval[0]);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+ LFREEPATH(path);
+ return (error);
+}
+
+int
+linux_mknodat(struct thread *td, struct linux_mknodat_args *args)
+{
+ char *path;
+ int error, dfd;
+
+ dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
+ LCONVPATHCREAT_AT(td, args->filename, &path, dfd);
+
+#ifdef DEBUG
+ if (ldebug(mknodat))
+ printf(ARGS(mknodat, "%s, %d, %d"), path, args->mode, args->dev);
+#endif
+
+ switch (args->mode & S_IFMT) {
+ case S_IFIFO:
+ case S_IFSOCK:
+ error = kern_mkfifoat(td, dfd, path, UIO_SYSSPACE, args->mode);
+ break;
+
+ case S_IFCHR:
+ case S_IFBLK:
+ error = kern_mknodat(td, dfd, path, UIO_SYSSPACE, args->mode,
+ args->dev);
+ break;
+
+ case S_IFDIR:
+ error = EPERM;
+ break;
+
+ case 0:
+ args->mode |= S_IFREG;
+ /* FALLTHROUGH */
+ case S_IFREG:
+ error = kern_openat(td, dfd, path, UIO_SYSSPACE,
+ O_WRONLY | O_CREAT | O_TRUNC, args->mode);
+ if (error == 0)
+ kern_close(td, td->td_retval[0]);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+ LFREEPATH(path);
+ return (error);
+}
+
+/*
+ * UGH! This is just about the dumbest idea I've ever heard!!
+ */
+int
+linux_personality(struct thread *td, struct linux_personality_args *args)
+{
+#ifdef DEBUG
+ if (ldebug(personality))
+ printf(ARGS(personality, "%lu"), (unsigned long)args->per);
+#endif
+ if (args->per != 0)
+ return (EINVAL);
+
+ /* Yes Jim, it's still a Linux... */
+ td->td_retval[0] = 0;
+ return (0);
+}
+
+struct l_itimerval {
+ l_timeval it_interval;
+ l_timeval it_value;
+};
+
+#define B2L_ITIMERVAL(bip, lip) \
+ (bip)->it_interval.tv_sec = (lip)->it_interval.tv_sec; \
+ (bip)->it_interval.tv_usec = (lip)->it_interval.tv_usec; \
+ (bip)->it_value.tv_sec = (lip)->it_value.tv_sec; \
+ (bip)->it_value.tv_usec = (lip)->it_value.tv_usec;
+
+int
+linux_setitimer(struct thread *td, struct linux_setitimer_args *uap)
+{
+ int error;
+ struct l_itimerval ls;
+ struct itimerval aitv, oitv;
+
+#ifdef DEBUG
+ if (ldebug(setitimer))
+ printf(ARGS(setitimer, "%p, %p"),
+ (void *)uap->itv, (void *)uap->oitv);
+#endif
+
+ if (uap->itv == NULL) {
+ uap->itv = uap->oitv;
+ return (linux_getitimer(td, (struct linux_getitimer_args *)uap));
+ }
+
+ error = copyin(uap->itv, &ls, sizeof(ls));
+ if (error != 0)
+ return (error);
+ B2L_ITIMERVAL(&aitv, &ls);
+#ifdef DEBUG
+ if (ldebug(setitimer)) {
+ printf("setitimer: value: sec: %jd, usec: %ld\n",
+ (intmax_t)aitv.it_value.tv_sec, aitv.it_value.tv_usec);
+ printf("setitimer: interval: sec: %jd, usec: %ld\n",
+ (intmax_t)aitv.it_interval.tv_sec, aitv.it_interval.tv_usec);
+ }
+#endif
+ error = kern_setitimer(td, uap->which, &aitv, &oitv);
+ if (error != 0 || uap->oitv == NULL)
+ return (error);
+ B2L_ITIMERVAL(&ls, &oitv);
+
+ return (copyout(&ls, uap->oitv, sizeof(ls)));
+}
+
+int
+linux_getitimer(struct thread *td, struct linux_getitimer_args *uap)
+{
+ int error;
+ struct l_itimerval ls;
+ struct itimerval aitv;
+
+#ifdef DEBUG
+ if (ldebug(getitimer))
+ printf(ARGS(getitimer, "%p"), (void *)uap->itv);
+#endif
+ error = kern_getitimer(td, uap->which, &aitv);
+ if (error != 0)
+ return (error);
+ B2L_ITIMERVAL(&ls, &aitv);
+ return (copyout(&ls, uap->itv, sizeof(ls)));
+}
+
+int
+linux_nice(struct thread *td, struct linux_nice_args *args)
+{
+ struct setpriority_args bsd_args;
+
+ bsd_args.which = PRIO_PROCESS;
+ bsd_args.who = 0; /* current process */
+ bsd_args.prio = args->inc;
+ return (sys_setpriority(td, &bsd_args));
+}
+
+int
+linux_setgroups(struct thread *td, struct linux_setgroups_args *args)
+{
+ struct ucred *newcred, *oldcred;
+ l_gid_t *linux_gidset;
+ gid_t *bsd_gidset;
+ int ngrp, error;
+ struct proc *p;
+
+ ngrp = args->gidsetsize;
+ if (ngrp < 0 || ngrp >= ngroups_max + 1)
+ return (EINVAL);
+ linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_TEMP, M_WAITOK);
+ error = copyin(args->grouplist, linux_gidset, ngrp * sizeof(l_gid_t));
+ if (error)
+ goto out;
+ newcred = crget();
+ p = td->td_proc;
+ PROC_LOCK(p);
+ oldcred = crcopysafe(p, newcred);
+
+ /*
+ * cr_groups[0] holds egid. Setting the whole set from
+ * the supplied set will cause egid to be changed too.
+ * Keep cr_groups[0] unchanged to prevent that.
+ */
+
+ if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS, 0)) != 0) {
+ PROC_UNLOCK(p);
+ crfree(newcred);
+ goto out;
+ }
+
+ if (ngrp > 0) {
+ newcred->cr_ngroups = ngrp + 1;
+
+ bsd_gidset = newcred->cr_groups;
+ ngrp--;
+ while (ngrp >= 0) {
+ bsd_gidset[ngrp + 1] = linux_gidset[ngrp];
+ ngrp--;
+ }
+ } else
+ newcred->cr_ngroups = 1;
+
+ setsugid(p);
+ p->p_ucred = newcred;
+ PROC_UNLOCK(p);
+ crfree(oldcred);
+ error = 0;
+out:
+ free(linux_gidset, M_TEMP);
+ return (error);
+}
+
+int
+linux_getgroups(struct thread *td, struct linux_getgroups_args *args)
+{
+ struct ucred *cred;
+ l_gid_t *linux_gidset;
+ gid_t *bsd_gidset;
+ int bsd_gidsetsz, ngrp, error;
+
+ cred = td->td_ucred;
+ bsd_gidset = cred->cr_groups;
+ bsd_gidsetsz = cred->cr_ngroups - 1;
+
+ /*
+ * cr_groups[0] holds egid. Returning the whole set
+ * here will cause a duplicate. Exclude cr_groups[0]
+ * to prevent that.
+ */
+
+ if ((ngrp = args->gidsetsize) == 0) {
+ td->td_retval[0] = bsd_gidsetsz;
+ return (0);
+ }
+
+ if (ngrp < bsd_gidsetsz)
+ return (EINVAL);
+
+ ngrp = 0;
+ linux_gidset = malloc(bsd_gidsetsz * sizeof(*linux_gidset),
+ M_TEMP, M_WAITOK);
+ while (ngrp < bsd_gidsetsz) {
+ linux_gidset[ngrp] = bsd_gidset[ngrp + 1];
+ ngrp++;
+ }
+
+ error = copyout(linux_gidset, args->grouplist, ngrp * sizeof(l_gid_t));
+ free(linux_gidset, M_TEMP);
+ if (error)
+ return (error);
+
+ td->td_retval[0] = ngrp;
+ return (0);
+}
+
+int
+linux_setrlimit(struct thread *td, struct linux_setrlimit_args *args)
+{
+ struct rlimit bsd_rlim;
+ struct l_rlimit rlim;
+ u_int which;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(setrlimit))
+ printf(ARGS(setrlimit, "%d, %p"),
+ args->resource, (void *)args->rlim);
+#endif
+
+ if (args->resource >= LINUX_RLIM_NLIMITS)
+ return (EINVAL);
+
+ which = linux_to_bsd_resource[args->resource];
+ if (which == -1)
+ return (EINVAL);
+
+ error = copyin(args->rlim, &rlim, sizeof(rlim));
+ if (error)
+ return (error);
+
+ bsd_rlim.rlim_cur = (rlim_t)rlim.rlim_cur;
+ bsd_rlim.rlim_max = (rlim_t)rlim.rlim_max;
+ return (kern_setrlimit(td, which, &bsd_rlim));
+}
+
+int
+linux_old_getrlimit(struct thread *td, struct linux_old_getrlimit_args *args)
+{
+ struct l_rlimit rlim;
+ struct proc *p = td->td_proc;
+ struct rlimit bsd_rlim;
+ u_int which;
+
+#ifdef DEBUG
+ if (ldebug(old_getrlimit))
+ printf(ARGS(old_getrlimit, "%d, %p"),
+ args->resource, (void *)args->rlim);
+#endif
+
+ if (args->resource >= LINUX_RLIM_NLIMITS)
+ return (EINVAL);
+
+ which = linux_to_bsd_resource[args->resource];
+ if (which == -1)
+ return (EINVAL);
+
+ PROC_LOCK(p);
+ lim_rlimit(p, which, &bsd_rlim);
+ PROC_UNLOCK(p);
+
+#ifdef COMPAT_LINUX32
+ rlim.rlim_cur = (unsigned int)bsd_rlim.rlim_cur;
+ if (rlim.rlim_cur == UINT_MAX)
+ rlim.rlim_cur = INT_MAX;
+ rlim.rlim_max = (unsigned int)bsd_rlim.rlim_max;
+ if (rlim.rlim_max == UINT_MAX)
+ rlim.rlim_max = INT_MAX;
+#else
+ rlim.rlim_cur = (unsigned long)bsd_rlim.rlim_cur;
+ if (rlim.rlim_cur == ULONG_MAX)
+ rlim.rlim_cur = LONG_MAX;
+ rlim.rlim_max = (unsigned long)bsd_rlim.rlim_max;
+ if (rlim.rlim_max == ULONG_MAX)
+ rlim.rlim_max = LONG_MAX;
+#endif
+ return (copyout(&rlim, args->rlim, sizeof(rlim)));
+}
+
+int
+linux_getrlimit(struct thread *td, struct linux_getrlimit_args *args)
+{
+ struct l_rlimit rlim;
+ struct proc *p = td->td_proc;
+ struct rlimit bsd_rlim;
+ u_int which;
+
+#ifdef DEBUG
+ if (ldebug(getrlimit))
+ printf(ARGS(getrlimit, "%d, %p"),
+ args->resource, (void *)args->rlim);
+#endif
+
+ if (args->resource >= LINUX_RLIM_NLIMITS)
+ return (EINVAL);
+
+ which = linux_to_bsd_resource[args->resource];
+ if (which == -1)
+ return (EINVAL);
+
+ PROC_LOCK(p);
+ lim_rlimit(p, which, &bsd_rlim);
+ PROC_UNLOCK(p);
+
+ rlim.rlim_cur = (l_ulong)bsd_rlim.rlim_cur;
+ rlim.rlim_max = (l_ulong)bsd_rlim.rlim_max;
+ return (copyout(&rlim, args->rlim, sizeof(rlim)));
+}
+
+int
+linux_sched_setscheduler(struct thread *td,
+ struct linux_sched_setscheduler_args *args)
+{
+ struct sched_setscheduler_args bsd;
+
+#ifdef DEBUG
+ if (ldebug(sched_setscheduler))
+ printf(ARGS(sched_setscheduler, "%d, %d, %p"),
+ args->pid, args->policy, (const void *)args->param);
+#endif
+
+ switch (args->policy) {
+ case LINUX_SCHED_OTHER:
+ bsd.policy = SCHED_OTHER;
+ break;
+ case LINUX_SCHED_FIFO:
+ bsd.policy = SCHED_FIFO;
+ break;
+ case LINUX_SCHED_RR:
+ bsd.policy = SCHED_RR;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ bsd.pid = args->pid;
+ bsd.param = (struct sched_param *)args->param;
+ return (sys_sched_setscheduler(td, &bsd));
+}
+
+int
+linux_sched_getscheduler(struct thread *td,
+ struct linux_sched_getscheduler_args *args)
+{
+ struct sched_getscheduler_args bsd;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(sched_getscheduler))
+ printf(ARGS(sched_getscheduler, "%d"), args->pid);
+#endif
+
+ bsd.pid = args->pid;
+ error = sys_sched_getscheduler(td, &bsd);
+
+ switch (td->td_retval[0]) {
+ case SCHED_OTHER:
+ td->td_retval[0] = LINUX_SCHED_OTHER;
+ break;
+ case SCHED_FIFO:
+ td->td_retval[0] = LINUX_SCHED_FIFO;
+ break;
+ case SCHED_RR:
+ td->td_retval[0] = LINUX_SCHED_RR;
+ break;
+ }
+
+ return (error);
+}
+
+int
+linux_sched_get_priority_max(struct thread *td,
+ struct linux_sched_get_priority_max_args *args)
+{
+ struct sched_get_priority_max_args bsd;
+
+#ifdef DEBUG
+ if (ldebug(sched_get_priority_max))
+ printf(ARGS(sched_get_priority_max, "%d"), args->policy);
+#endif
+
+ switch (args->policy) {
+ case LINUX_SCHED_OTHER:
+ bsd.policy = SCHED_OTHER;
+ break;
+ case LINUX_SCHED_FIFO:
+ bsd.policy = SCHED_FIFO;
+ break;
+ case LINUX_SCHED_RR:
+ bsd.policy = SCHED_RR;
+ break;
+ default:
+ return (EINVAL);
+ }
+ return (sys_sched_get_priority_max(td, &bsd));
+}
+
+int
+linux_sched_get_priority_min(struct thread *td,
+ struct linux_sched_get_priority_min_args *args)
+{
+ struct sched_get_priority_min_args bsd;
+
+#ifdef DEBUG
+ if (ldebug(sched_get_priority_min))
+ printf(ARGS(sched_get_priority_min, "%d"), args->policy);
+#endif
+
+ switch (args->policy) {
+ case LINUX_SCHED_OTHER:
+ bsd.policy = SCHED_OTHER;
+ break;
+ case LINUX_SCHED_FIFO:
+ bsd.policy = SCHED_FIFO;
+ break;
+ case LINUX_SCHED_RR:
+ bsd.policy = SCHED_RR;
+ break;
+ default:
+ return (EINVAL);
+ }
+ return (sys_sched_get_priority_min(td, &bsd));
+}
+
+#define REBOOT_CAD_ON 0x89abcdef
+#define REBOOT_CAD_OFF 0
+#define REBOOT_HALT 0xcdef0123
+#define REBOOT_RESTART 0x01234567
+#define REBOOT_RESTART2 0xA1B2C3D4
+#define REBOOT_POWEROFF 0x4321FEDC
+#define REBOOT_MAGIC1 0xfee1dead
+#define REBOOT_MAGIC2 0x28121969
+#define REBOOT_MAGIC2A 0x05121996
+#define REBOOT_MAGIC2B 0x16041998
+
+int
+linux_reboot(struct thread *td, struct linux_reboot_args *args)
+{
+ struct reboot_args bsd_args;
+
+#ifdef DEBUG
+ if (ldebug(reboot))
+ printf(ARGS(reboot, "0x%x"), args->cmd);
+#endif
+
+ if (args->magic1 != REBOOT_MAGIC1)
+ return (EINVAL);
+
+ switch (args->magic2) {
+ case REBOOT_MAGIC2:
+ case REBOOT_MAGIC2A:
+ case REBOOT_MAGIC2B:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ switch (args->cmd) {
+ case REBOOT_CAD_ON:
+ case REBOOT_CAD_OFF:
+ return (priv_check(td, PRIV_REBOOT));
+ case REBOOT_HALT:
+ bsd_args.opt = RB_HALT;
+ break;
+ case REBOOT_RESTART:
+ case REBOOT_RESTART2:
+ bsd_args.opt = 0;
+ break;
+ case REBOOT_POWEROFF:
+ bsd_args.opt = RB_POWEROFF;
+ break;
+ default:
+ return (EINVAL);
+ }
+ return (sys_reboot(td, &bsd_args));
+}
+
+
+/*
+ * The FreeBSD native getpid(2), getgid(2) and getuid(2) also modify
+ * td->td_retval[1] when COMPAT_43 is defined. This clobbers registers that
+ * are assumed to be preserved. The following lightweight syscalls fixes
+ * this. See also linux_getgid16() and linux_getuid16() in linux_uid16.c
+ *
+ * linux_getpid() - MP SAFE
+ * linux_getgid() - MP SAFE
+ * linux_getuid() - MP SAFE
+ */
+
+int
+linux_getpid(struct thread *td, struct linux_getpid_args *args)
+{
+ struct linux_emuldata *em;
+
+#ifdef DEBUG
+ if (ldebug(getpid))
+ printf(ARGS(getpid, ""));
+#endif
+
+ if (linux_use26(td)) {
+ em = em_find(td->td_proc, EMUL_DONTLOCK);
+ KASSERT(em != NULL, ("getpid: emuldata not found.\n"));
+ td->td_retval[0] = em->shared->group_pid;
+ } else {
+ td->td_retval[0] = td->td_proc->p_pid;
+ }
+
+ return (0);
+}
+
+int
+linux_gettid(struct thread *td, struct linux_gettid_args *args)
+{
+
+#ifdef DEBUG
+ if (ldebug(gettid))
+ printf(ARGS(gettid, ""));
+#endif
+
+ td->td_retval[0] = td->td_proc->p_pid;
+ return (0);
+}
+
+
+int
+linux_getppid(struct thread *td, struct linux_getppid_args *args)
+{
+ struct linux_emuldata *em;
+ struct proc *p, *pp;
+
+#ifdef DEBUG
+ if (ldebug(getppid))
+ printf(ARGS(getppid, ""));
+#endif
+
+ if (!linux_use26(td)) {
+ PROC_LOCK(td->td_proc);
+ td->td_retval[0] = td->td_proc->p_pptr->p_pid;
+ PROC_UNLOCK(td->td_proc);
+ return (0);
+ }
+
+ em = em_find(td->td_proc, EMUL_DONTLOCK);
+
+ KASSERT(em != NULL, ("getppid: process emuldata not found.\n"));
+
+ /* find the group leader */
+ p = pfind(em->shared->group_pid);
+
+ if (p == NULL) {
+#ifdef DEBUG
+ printf(LMSG("parent process not found.\n"));
+#endif
+ return (0);
+ }
+
+ pp = p->p_pptr; /* switch to parent */
+ PROC_LOCK(pp);
+ PROC_UNLOCK(p);
+
+ /* if its also linux process */
+ if (pp->p_sysent == &elf_linux_sysvec) {
+ em = em_find(pp, EMUL_DONTLOCK);
+ KASSERT(em != NULL, ("getppid: parent emuldata not found.\n"));
+
+ td->td_retval[0] = em->shared->group_pid;
+ } else
+ td->td_retval[0] = pp->p_pid;
+
+ PROC_UNLOCK(pp);
+
+ return (0);
+}
+
+int
+linux_getgid(struct thread *td, struct linux_getgid_args *args)
+{
+
+#ifdef DEBUG
+ if (ldebug(getgid))
+ printf(ARGS(getgid, ""));
+#endif
+
+ td->td_retval[0] = td->td_ucred->cr_rgid;
+ return (0);
+}
+
+int
+linux_getuid(struct thread *td, struct linux_getuid_args *args)
+{
+
+#ifdef DEBUG
+ if (ldebug(getuid))
+ printf(ARGS(getuid, ""));
+#endif
+
+ td->td_retval[0] = td->td_ucred->cr_ruid;
+ return (0);
+}
+
+
+int
+linux_getsid(struct thread *td, struct linux_getsid_args *args)
+{
+ struct getsid_args bsd;
+
+#ifdef DEBUG
+ if (ldebug(getsid))
+ printf(ARGS(getsid, "%i"), args->pid);
+#endif
+
+ bsd.pid = args->pid;
+ return (sys_getsid(td, &bsd));
+}
+
+int
+linux_nosys(struct thread *td, struct nosys_args *ignore)
+{
+
+ return (ENOSYS);
+}
+
+int
+linux_getpriority(struct thread *td, struct linux_getpriority_args *args)
+{
+ struct getpriority_args bsd_args;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(getpriority))
+ printf(ARGS(getpriority, "%i, %i"), args->which, args->who);
+#endif
+
+ bsd_args.which = args->which;
+ bsd_args.who = args->who;
+ error = sys_getpriority(td, &bsd_args);
+ td->td_retval[0] = 20 - td->td_retval[0];
+ return (error);
+}
+
+int
+linux_sethostname(struct thread *td, struct linux_sethostname_args *args)
+{
+ int name[2];
+
+#ifdef DEBUG
+ if (ldebug(sethostname))
+ printf(ARGS(sethostname, "*, %i"), args->len);
+#endif
+
+ name[0] = CTL_KERN;
+ name[1] = KERN_HOSTNAME;
+ return (userland_sysctl(td, name, 2, 0, 0, 0, args->hostname,
+ args->len, 0, 0));
+}
+
+int
+linux_setdomainname(struct thread *td, struct linux_setdomainname_args *args)
+{
+ int name[2];
+
+#ifdef DEBUG
+ if (ldebug(setdomainname))
+ printf(ARGS(setdomainname, "*, %i"), args->len);
+#endif
+
+ name[0] = CTL_KERN;
+ name[1] = KERN_NISDOMAINNAME;
+ return (userland_sysctl(td, name, 2, 0, 0, 0, args->name,
+ args->len, 0, 0));
+}
+
+int
+linux_exit_group(struct thread *td, struct linux_exit_group_args *args)
+{
+ struct linux_emuldata *em;
+
+#ifdef DEBUG
+ if (ldebug(exit_group))
+ printf(ARGS(exit_group, "%i"), args->error_code);
+#endif
+
+ em = em_find(td->td_proc, EMUL_DONTLOCK);
+ if (em->shared->refs > 1) {
+ EMUL_SHARED_WLOCK(&emul_shared_lock);
+ em->shared->flags |= EMUL_SHARED_HASXSTAT;
+ em->shared->xstat = W_EXITCODE(args->error_code, 0);
+ EMUL_SHARED_WUNLOCK(&emul_shared_lock);
+ if (linux_use26(td))
+ linux_kill_threads(td, SIGKILL);
+ }
+
+ /*
+ * XXX: we should send a signal to the parent if
+ * SIGNAL_EXIT_GROUP is set. We ignore that (temporarily?)
+ * as it doesnt occur often.
+ */
+ exit1(td, W_EXITCODE(args->error_code, 0));
+
+ return (0);
+}
+
+#define _LINUX_CAPABILITY_VERSION 0x19980330
+
+struct l_user_cap_header {
+ l_int version;
+ l_int pid;
+};
+
+struct l_user_cap_data {
+ l_int effective;
+ l_int permitted;
+ l_int inheritable;
+};
+
+int
+linux_capget(struct thread *td, struct linux_capget_args *args)
+{
+ struct l_user_cap_header luch;
+ struct l_user_cap_data lucd;
+ int error;
+
+ if (args->hdrp == NULL)
+ return (EFAULT);
+
+ error = copyin(args->hdrp, &luch, sizeof(luch));
+ if (error != 0)
+ return (error);
+
+ if (luch.version != _LINUX_CAPABILITY_VERSION) {
+ luch.version = _LINUX_CAPABILITY_VERSION;
+ error = copyout(&luch, args->hdrp, sizeof(luch));
+ if (error)
+ return (error);
+ return (EINVAL);
+ }
+
+ if (luch.pid)
+ return (EPERM);
+
+ if (args->datap) {
+ /*
+ * The current implementation doesn't support setting
+ * a capability (it's essentially a stub) so indicate
+ * that no capabilities are currently set or available
+ * to request.
+ */
+ bzero (&lucd, sizeof(lucd));
+ error = copyout(&lucd, args->datap, sizeof(lucd));
+ }
+
+ return (error);
+}
+
+int
+linux_capset(struct thread *td, struct linux_capset_args *args)
+{
+ struct l_user_cap_header luch;
+ struct l_user_cap_data lucd;
+ int error;
+
+ if (args->hdrp == NULL || args->datap == NULL)
+ return (EFAULT);
+
+ error = copyin(args->hdrp, &luch, sizeof(luch));
+ if (error != 0)
+ return (error);
+
+ if (luch.version != _LINUX_CAPABILITY_VERSION) {
+ luch.version = _LINUX_CAPABILITY_VERSION;
+ error = copyout(&luch, args->hdrp, sizeof(luch));
+ if (error)
+ return (error);
+ return (EINVAL);
+ }
+
+ if (luch.pid)
+ return (EPERM);
+
+ error = copyin(args->datap, &lucd, sizeof(lucd));
+ if (error != 0)
+ return (error);
+
+ /* We currently don't support setting any capabilities. */
+ if (lucd.effective || lucd.permitted || lucd.inheritable) {
+ linux_msg(td,
+ "capset effective=0x%x, permitted=0x%x, "
+ "inheritable=0x%x is not implemented",
+ (int)lucd.effective, (int)lucd.permitted,
+ (int)lucd.inheritable);
+ return (EPERM);
+ }
+
+ return (0);
+}
+
+int
+linux_prctl(struct thread *td, struct linux_prctl_args *args)
+{
+ int error = 0, max_size;
+ struct proc *p = td->td_proc;
+ char comm[LINUX_MAX_COMM_LEN];
+ struct linux_emuldata *em;
+ int pdeath_signal;
+
+#ifdef DEBUG
+ if (ldebug(prctl))
+ printf(ARGS(prctl, "%d, %d, %d, %d, %d"), args->option,
+ args->arg2, args->arg3, args->arg4, args->arg5);
+#endif
+
+ switch (args->option) {
+ case LINUX_PR_SET_PDEATHSIG:
+ if (!LINUX_SIG_VALID(args->arg2))
+ return (EINVAL);
+ em = em_find(p, EMUL_DOLOCK);
+ KASSERT(em != NULL, ("prctl: emuldata not found.\n"));
+ em->pdeath_signal = args->arg2;
+ EMUL_UNLOCK(&emul_lock);
+ break;
+ case LINUX_PR_GET_PDEATHSIG:
+ em = em_find(p, EMUL_DOLOCK);
+ KASSERT(em != NULL, ("prctl: emuldata not found.\n"));
+ pdeath_signal = em->pdeath_signal;
+ EMUL_UNLOCK(&emul_lock);
+ error = copyout(&pdeath_signal,
+ (void *)(register_t)args->arg2,
+ sizeof(pdeath_signal));
+ break;
+ case LINUX_PR_GET_KEEPCAPS:
+ /*
+ * Indicate that we always clear the effective and
+ * permitted capability sets when the user id becomes
+ * non-zero (actually the capability sets are simply
+ * always zero in the current implementation).
+ */
+ td->td_retval[0] = 0;
+ break;
+ case LINUX_PR_SET_KEEPCAPS:
+ /*
+ * Ignore requests to keep the effective and permitted
+ * capability sets when the user id becomes non-zero.
+ */
+ break;
+ case LINUX_PR_SET_NAME:
+ /*
+ * To be on the safe side we need to make sure to not
+ * overflow the size a linux program expects. We already
+ * do this here in the copyin, so that we don't need to
+ * check on copyout.
+ */
+ max_size = MIN(sizeof(comm), sizeof(p->p_comm));
+ error = copyinstr((void *)(register_t)args->arg2, comm,
+ max_size, NULL);
+
+ /* Linux silently truncates the name if it is too long. */
+ if (error == ENAMETOOLONG) {
+ /*
+ * XXX: copyinstr() isn't documented to populate the
+ * array completely, so do a copyin() to be on the
+ * safe side. This should be changed in case
+ * copyinstr() is changed to guarantee this.
+ */
+ error = copyin((void *)(register_t)args->arg2, comm,
+ max_size - 1);
+ comm[max_size - 1] = '\0';
+ }
+ if (error)
+ return (error);
+
+ PROC_LOCK(p);
+ strlcpy(p->p_comm, comm, sizeof(p->p_comm));
+ PROC_UNLOCK(p);
+ break;
+ case LINUX_PR_GET_NAME:
+ PROC_LOCK(p);
+ strlcpy(comm, p->p_comm, sizeof(comm));
+ PROC_UNLOCK(p);
+ error = copyout(comm, (void *)(register_t)args->arg2,
+ strlen(comm) + 1);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return (error);
+}
+
+/*
+ * Get affinity of a process.
+ */
+int
+linux_sched_getaffinity(struct thread *td,
+ struct linux_sched_getaffinity_args *args)
+{
+ int error;
+ struct cpuset_getaffinity_args cga;
+
+#ifdef DEBUG
+ if (ldebug(sched_getaffinity))
+ printf(ARGS(sched_getaffinity, "%d, %d, *"), args->pid,
+ args->len);
+#endif
+ if (args->len < sizeof(cpuset_t))
+ return (EINVAL);
+
+ cga.level = CPU_LEVEL_WHICH;
+ cga.which = CPU_WHICH_PID;
+ cga.id = args->pid;
+ cga.cpusetsize = sizeof(cpuset_t);
+ cga.mask = (cpuset_t *) args->user_mask_ptr;
+
+ if ((error = sys_cpuset_getaffinity(td, &cga)) == 0)
+ td->td_retval[0] = sizeof(cpuset_t);
+
+ return (error);
+}
+
+/*
+ * Set affinity of a process.
+ */
+int
+linux_sched_setaffinity(struct thread *td,
+ struct linux_sched_setaffinity_args *args)
+{
+ struct cpuset_setaffinity_args csa;
+
+#ifdef DEBUG
+ if (ldebug(sched_setaffinity))
+ printf(ARGS(sched_setaffinity, "%d, %d, *"), args->pid,
+ args->len);
+#endif
+ if (args->len < sizeof(cpuset_t))
+ return (EINVAL);
+
+ csa.level = CPU_LEVEL_WHICH;
+ csa.which = CPU_WHICH_PID;
+ csa.id = args->pid;
+ csa.cpusetsize = sizeof(cpuset_t);
+ csa.mask = (cpuset_t *) args->user_mask_ptr;
+
+ return (sys_cpuset_setaffinity(td, &csa));
+}
diff --git a/sys/compat/linux/linux_misc.h b/sys/compat/linux/linux_misc.h
new file mode 100644
index 0000000..154d78f
--- /dev/null
+++ b/sys/compat/linux/linux_misc.h
@@ -0,0 +1,125 @@
+/*-
+ * Copyright (c) 2006 Roman Divacky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LINUX_MISC_H_
+#define _LINUX_MISC_H_
+
+/*
+ * Miscellaneous
+ */
+#define LINUX_NAME_MAX 255
+#define LINUX_MAX_UTSNAME 65
+
+#define LINUX_CTL_MAXNAME 10
+
+/* defines for prctl */
+#define LINUX_PR_SET_PDEATHSIG 1 /* Second arg is a signal. */
+#define LINUX_PR_GET_PDEATHSIG 2 /*
+ * Second arg is a ptr to return the
+ * signal.
+ */
+#define LINUX_PR_GET_KEEPCAPS 7 /* Get drop capabilities on setuid */
+#define LINUX_PR_SET_KEEPCAPS 8 /* Set drop capabilities on setuid */
+#define LINUX_PR_SET_NAME 15 /* Set process name. */
+#define LINUX_PR_GET_NAME 16 /* Get process name. */
+
+#define LINUX_MAX_COMM_LEN 16 /* Maximum length of the process name. */
+
+#define LINUX_MREMAP_MAYMOVE 1
+#define LINUX_MREMAP_FIXED 2
+
+extern const char *linux_platform;
+
+/*
+ * Non-standard aux entry types used in Linux ELF binaries.
+ */
+
+#define LINUX_AT_PLATFORM 15 /* String identifying CPU */
+#define LINUX_AT_HWCAP 16 /* CPU capabilities */
+#define LINUX_AT_CLKTCK 17 /* frequency at which times() increments */
+#define LINUX_AT_SECURE 23 /* secure mode boolean */
+#define LINUX_AT_BASE_PLATFORM 24 /* string identifying real platform, may
+ * differ from AT_PLATFORM.
+ */
+#define LINUX_AT_EXECFN 31 /* filename of program */
+
+/* Linux sets the i387 to extended precision. */
+#if defined(__i386__) || defined(__amd64__)
+#define __LINUX_NPXCW__ 0x37f
+#endif
+
+#define LINUX_CLONE_VM 0x00000100
+#define LINUX_CLONE_FS 0x00000200
+#define LINUX_CLONE_FILES 0x00000400
+#define LINUX_CLONE_SIGHAND 0x00000800
+#define LINUX_CLONE_PID 0x00001000 /* No longer exist in Linux */
+#define LINUX_CLONE_VFORK 0x00004000
+#define LINUX_CLONE_PARENT 0x00008000
+#define LINUX_CLONE_THREAD 0x00010000
+#define LINUX_CLONE_SETTLS 0x00080000
+#define LINUX_CLONE_PARENT_SETTID 0x00100000
+#define LINUX_CLONE_CHILD_CLEARTID 0x00200000
+#define LINUX_CLONE_CHILD_SETTID 0x01000000
+
+#define LINUX_THREADING_FLAGS \
+ (LINUX_CLONE_VM | LINUX_CLONE_FS | LINUX_CLONE_FILES | \
+ LINUX_CLONE_SIGHAND | LINUX_CLONE_THREAD)
+
+/* Scheduling policies */
+#define LINUX_SCHED_OTHER 0
+#define LINUX_SCHED_FIFO 1
+#define LINUX_SCHED_RR 2
+
+struct l_new_utsname {
+ char sysname[LINUX_MAX_UTSNAME];
+ char nodename[LINUX_MAX_UTSNAME];
+ char release[LINUX_MAX_UTSNAME];
+ char version[LINUX_MAX_UTSNAME];
+ char machine[LINUX_MAX_UTSNAME];
+ char domainname[LINUX_MAX_UTSNAME];
+};
+
+#define LINUX_CLOCK_REALTIME 0
+#define LINUX_CLOCK_MONOTONIC 1
+#define LINUX_CLOCK_PROCESS_CPUTIME_ID 2
+#define LINUX_CLOCK_THREAD_CPUTIME_ID 3
+#define LINUX_CLOCK_REALTIME_HR 4
+#define LINUX_CLOCK_MONOTONIC_HR 5
+
+extern int stclohz;
+
+#define __WCLONE 0x80000000
+
+int linux_common_wait(struct thread *td, int pid, int *status,
+ int options, struct rusage *ru);
+int linux_set_upcall_kse(struct thread *td, register_t stack);
+int linux_set_cloned_tls(struct thread *td, void *desc);
+
+#endif /* _LINUX_MISC_H_ */
diff --git a/sys/compat/linux/linux_signal.c b/sys/compat/linux/linux_signal.c
new file mode 100644
index 0000000..1c778f9
--- /dev/null
+++ b/sys/compat/linux/linux_signal.c
@@ -0,0 +1,656 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sx.h>
+#include <sys/proc.h>
+#include <sys/signalvar.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysproto.h>
+
+#include <security/audit/audit.h>
+
+#include "opt_compat.h"
+
+#ifdef COMPAT_LINUX32
+#include <machine/../linux32/linux.h>
+#include <machine/../linux32/linux32_proto.h>
+#else
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#endif
+#include <compat/linux/linux_signal.h>
+#include <compat/linux/linux_util.h>
+#include <compat/linux/linux_emul.h>
+
+void
+linux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss)
+{
+ int b, l;
+
+ SIGEMPTYSET(*bss);
+ bss->__bits[0] = lss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1);
+ bss->__bits[1] = lss->__bits[1];
+ for (l = 1; l <= LINUX_SIGTBLSZ; l++) {
+ if (LINUX_SIGISMEMBER(*lss, l)) {
+ b = linux_to_bsd_signal[_SIG_IDX(l)];
+ if (b)
+ SIGADDSET(*bss, b);
+ }
+ }
+}
+
+void
+bsd_to_linux_sigset(sigset_t *bss, l_sigset_t *lss)
+{
+ int b, l;
+
+ LINUX_SIGEMPTYSET(*lss);
+ lss->__bits[0] = bss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1);
+ lss->__bits[1] = bss->__bits[1];
+ for (b = 1; b <= LINUX_SIGTBLSZ; b++) {
+ if (SIGISMEMBER(*bss, b)) {
+ l = bsd_to_linux_signal[_SIG_IDX(b)];
+ if (l)
+ LINUX_SIGADDSET(*lss, l);
+ }
+ }
+}
+
+static void
+linux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa)
+{
+
+ linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask);
+ bsa->sa_handler = PTRIN(lsa->lsa_handler);
+ bsa->sa_flags = 0;
+ if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP)
+ bsa->sa_flags |= SA_NOCLDSTOP;
+ if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT)
+ bsa->sa_flags |= SA_NOCLDWAIT;
+ if (lsa->lsa_flags & LINUX_SA_SIGINFO)
+ bsa->sa_flags |= SA_SIGINFO;
+ if (lsa->lsa_flags & LINUX_SA_ONSTACK)
+ bsa->sa_flags |= SA_ONSTACK;
+ if (lsa->lsa_flags & LINUX_SA_RESTART)
+ bsa->sa_flags |= SA_RESTART;
+ if (lsa->lsa_flags & LINUX_SA_ONESHOT)
+ bsa->sa_flags |= SA_RESETHAND;
+ if (lsa->lsa_flags & LINUX_SA_NOMASK)
+ bsa->sa_flags |= SA_NODEFER;
+}
+
+static void
+bsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa)
+{
+
+ bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask);
+#ifdef COMPAT_LINUX32
+ lsa->lsa_handler = (uintptr_t)bsa->sa_handler;
+#else
+ lsa->lsa_handler = bsa->sa_handler;
+#endif
+ lsa->lsa_restorer = 0; /* unsupported */
+ lsa->lsa_flags = 0;
+ if (bsa->sa_flags & SA_NOCLDSTOP)
+ lsa->lsa_flags |= LINUX_SA_NOCLDSTOP;
+ if (bsa->sa_flags & SA_NOCLDWAIT)
+ lsa->lsa_flags |= LINUX_SA_NOCLDWAIT;
+ if (bsa->sa_flags & SA_SIGINFO)
+ lsa->lsa_flags |= LINUX_SA_SIGINFO;
+ if (bsa->sa_flags & SA_ONSTACK)
+ lsa->lsa_flags |= LINUX_SA_ONSTACK;
+ if (bsa->sa_flags & SA_RESTART)
+ lsa->lsa_flags |= LINUX_SA_RESTART;
+ if (bsa->sa_flags & SA_RESETHAND)
+ lsa->lsa_flags |= LINUX_SA_ONESHOT;
+ if (bsa->sa_flags & SA_NODEFER)
+ lsa->lsa_flags |= LINUX_SA_NOMASK;
+}
+
+int
+linux_do_sigaction(struct thread *td, int linux_sig, l_sigaction_t *linux_nsa,
+ l_sigaction_t *linux_osa)
+{
+ struct sigaction act, oact, *nsa, *osa;
+ int error, sig;
+
+ if (!LINUX_SIG_VALID(linux_sig))
+ return (EINVAL);
+
+ osa = (linux_osa != NULL) ? &oact : NULL;
+ if (linux_nsa != NULL) {
+ nsa = &act;
+ linux_to_bsd_sigaction(linux_nsa, nsa);
+ } else
+ nsa = NULL;
+
+ if (linux_sig <= LINUX_SIGTBLSZ)
+ sig = linux_to_bsd_signal[_SIG_IDX(linux_sig)];
+ else
+ sig = linux_sig;
+
+ error = kern_sigaction(td, sig, nsa, osa, 0);
+ if (error)
+ return (error);
+
+ if (linux_osa != NULL)
+ bsd_to_linux_sigaction(osa, linux_osa);
+
+ return (0);
+}
+
+
+int
+linux_signal(struct thread *td, struct linux_signal_args *args)
+{
+ l_sigaction_t nsa, osa;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(signal))
+ printf(ARGS(signal, "%d, %p"),
+ args->sig, (void *)(uintptr_t)args->handler);
+#endif
+
+ nsa.lsa_handler = args->handler;
+ nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK;
+ LINUX_SIGEMPTYSET(nsa.lsa_mask);
+
+ error = linux_do_sigaction(td, args->sig, &nsa, &osa);
+ td->td_retval[0] = (int)(intptr_t)osa.lsa_handler;
+
+ return (error);
+}
+
+int
+linux_rt_sigaction(struct thread *td, struct linux_rt_sigaction_args *args)
+{
+ l_sigaction_t nsa, osa;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(rt_sigaction))
+ printf(ARGS(rt_sigaction, "%ld, %p, %p, %ld"),
+ (long)args->sig, (void *)args->act,
+ (void *)args->oact, (long)args->sigsetsize);
+#endif
+
+ if (args->sigsetsize != sizeof(l_sigset_t))
+ return (EINVAL);
+
+ if (args->act != NULL) {
+ error = copyin(args->act, &nsa, sizeof(l_sigaction_t));
+ if (error)
+ return (error);
+ }
+
+ error = linux_do_sigaction(td, args->sig,
+ args->act ? &nsa : NULL,
+ args->oact ? &osa : NULL);
+
+ if (args->oact != NULL && !error) {
+ error = copyout(&osa, args->oact, sizeof(l_sigaction_t));
+ }
+
+ return (error);
+}
+
+static int
+linux_do_sigprocmask(struct thread *td, int how, l_sigset_t *new,
+ l_sigset_t *old)
+{
+ sigset_t omask, nmask;
+ sigset_t *nmaskp;
+ int error;
+
+ td->td_retval[0] = 0;
+
+ switch (how) {
+ case LINUX_SIG_BLOCK:
+ how = SIG_BLOCK;
+ break;
+ case LINUX_SIG_UNBLOCK:
+ how = SIG_UNBLOCK;
+ break;
+ case LINUX_SIG_SETMASK:
+ how = SIG_SETMASK;
+ break;
+ default:
+ return (EINVAL);
+ }
+ if (new != NULL) {
+ linux_to_bsd_sigset(new, &nmask);
+ nmaskp = &nmask;
+ } else
+ nmaskp = NULL;
+ error = kern_sigprocmask(td, how, nmaskp, &omask, 0);
+ if (error == 0 && old != NULL)
+ bsd_to_linux_sigset(&omask, old);
+
+ return (error);
+}
+
+int
+linux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args)
+{
+ l_osigset_t mask;
+ l_sigset_t set, oset;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(sigprocmask))
+ printf(ARGS(sigprocmask, "%d, *, *"), args->how);
+#endif
+
+ if (args->mask != NULL) {
+ error = copyin(args->mask, &mask, sizeof(l_osigset_t));
+ if (error)
+ return (error);
+ LINUX_SIGEMPTYSET(set);
+ set.__bits[0] = mask;
+ }
+
+ error = linux_do_sigprocmask(td, args->how,
+ args->mask ? &set : NULL,
+ args->omask ? &oset : NULL);
+
+ if (args->omask != NULL && !error) {
+ mask = oset.__bits[0];
+ error = copyout(&mask, args->omask, sizeof(l_osigset_t));
+ }
+
+ return (error);
+}
+
+int
+linux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args)
+{
+ l_sigset_t set, oset;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(rt_sigprocmask))
+ printf(ARGS(rt_sigprocmask, "%d, %p, %p, %ld"),
+ args->how, (void *)args->mask,
+ (void *)args->omask, (long)args->sigsetsize);
+#endif
+
+ if (args->sigsetsize != sizeof(l_sigset_t))
+ return EINVAL;
+
+ if (args->mask != NULL) {
+ error = copyin(args->mask, &set, sizeof(l_sigset_t));
+ if (error)
+ return (error);
+ }
+
+ error = linux_do_sigprocmask(td, args->how,
+ args->mask ? &set : NULL,
+ args->omask ? &oset : NULL);
+
+ if (args->omask != NULL && !error) {
+ error = copyout(&oset, args->omask, sizeof(l_sigset_t));
+ }
+
+ return (error);
+}
+
+int
+linux_sgetmask(struct thread *td, struct linux_sgetmask_args *args)
+{
+ struct proc *p = td->td_proc;
+ l_sigset_t mask;
+
+#ifdef DEBUG
+ if (ldebug(sgetmask))
+ printf(ARGS(sgetmask, ""));
+#endif
+
+ PROC_LOCK(p);
+ bsd_to_linux_sigset(&td->td_sigmask, &mask);
+ PROC_UNLOCK(p);
+ td->td_retval[0] = mask.__bits[0];
+ return (0);
+}
+
+int
+linux_ssetmask(struct thread *td, struct linux_ssetmask_args *args)
+{
+ struct proc *p = td->td_proc;
+ l_sigset_t lset;
+ sigset_t bset;
+
+#ifdef DEBUG
+ if (ldebug(ssetmask))
+ printf(ARGS(ssetmask, "%08lx"), (unsigned long)args->mask);
+#endif
+
+ PROC_LOCK(p);
+ bsd_to_linux_sigset(&td->td_sigmask, &lset);
+ td->td_retval[0] = lset.__bits[0];
+ LINUX_SIGEMPTYSET(lset);
+ lset.__bits[0] = args->mask;
+ linux_to_bsd_sigset(&lset, &bset);
+ td->td_sigmask = bset;
+ SIG_CANTMASK(td->td_sigmask);
+ signotify(td);
+ PROC_UNLOCK(p);
+ return (0);
+}
+
+/*
+ * MPSAFE
+ */
+int
+linux_sigpending(struct thread *td, struct linux_sigpending_args *args)
+{
+ struct proc *p = td->td_proc;
+ sigset_t bset;
+ l_sigset_t lset;
+ l_osigset_t mask;
+
+#ifdef DEBUG
+ if (ldebug(sigpending))
+ printf(ARGS(sigpending, "*"));
+#endif
+
+ PROC_LOCK(p);
+ bset = p->p_siglist;
+ SIGSETOR(bset, td->td_siglist);
+ SIGSETAND(bset, td->td_sigmask);
+ PROC_UNLOCK(p);
+ bsd_to_linux_sigset(&bset, &lset);
+ mask = lset.__bits[0];
+ return (copyout(&mask, args->mask, sizeof(mask)));
+}
+
+/*
+ * MPSAFE
+ */
+int
+linux_rt_sigpending(struct thread *td, struct linux_rt_sigpending_args *args)
+{
+ struct proc *p = td->td_proc;
+ sigset_t bset;
+ l_sigset_t lset;
+
+ if (args->sigsetsize > sizeof(lset))
+ return EINVAL;
+ /* NOT REACHED */
+
+#ifdef DEBUG
+ if (ldebug(rt_sigpending))
+ printf(ARGS(rt_sigpending, "*"));
+#endif
+
+ PROC_LOCK(p);
+ bset = p->p_siglist;
+ SIGSETOR(bset, td->td_siglist);
+ SIGSETAND(bset, td->td_sigmask);
+ PROC_UNLOCK(p);
+ bsd_to_linux_sigset(&bset, &lset);
+ return (copyout(&lset, args->set, args->sigsetsize));
+}
+
+/*
+ * MPSAFE
+ */
+int
+linux_rt_sigtimedwait(struct thread *td,
+ struct linux_rt_sigtimedwait_args *args)
+{
+ int error, sig;
+ l_timeval ltv;
+ struct timeval tv;
+ struct timespec ts, *tsa;
+ l_sigset_t lset;
+ sigset_t bset;
+ l_siginfo_t linfo;
+ ksiginfo_t info;
+
+#ifdef DEBUG
+ if (ldebug(rt_sigtimedwait))
+ printf(ARGS(rt_sigtimedwait, "*"));
+#endif
+ if (args->sigsetsize != sizeof(l_sigset_t))
+ return (EINVAL);
+
+ if ((error = copyin(args->mask, &lset, sizeof(lset))))
+ return (error);
+ linux_to_bsd_sigset(&lset, &bset);
+
+ tsa = NULL;
+ if (args->timeout) {
+ if ((error = copyin(args->timeout, &ltv, sizeof(ltv))))
+ return (error);
+#ifdef DEBUG
+ if (ldebug(rt_sigtimedwait))
+ printf(LMSG("linux_rt_sigtimedwait: "
+ "incoming timeout (%d/%d)\n"),
+ ltv.tv_sec, ltv.tv_usec);
+#endif
+ tv.tv_sec = (long)ltv.tv_sec;
+ tv.tv_usec = (suseconds_t)ltv.tv_usec;
+ if (itimerfix(&tv)) {
+ /*
+ * The timeout was invalid. Convert it to something
+ * valid that will act as it does under Linux.
+ */
+ tv.tv_sec += tv.tv_usec / 1000000;
+ tv.tv_usec %= 1000000;
+ if (tv.tv_usec < 0) {
+ tv.tv_sec -= 1;
+ tv.tv_usec += 1000000;
+ }
+ if (tv.tv_sec < 0)
+ timevalclear(&tv);
+#ifdef DEBUG
+ if (ldebug(rt_sigtimedwait))
+ printf(LMSG("linux_rt_sigtimedwait: "
+ "converted timeout (%jd/%ld)\n"),
+ (intmax_t)tv.tv_sec, tv.tv_usec);
+#endif
+ }
+ TIMEVAL_TO_TIMESPEC(&tv, &ts);
+ tsa = &ts;
+ }
+ error = kern_sigtimedwait(td, bset, &info, tsa);
+#ifdef DEBUG
+ if (ldebug(rt_sigtimedwait))
+ printf(LMSG("linux_rt_sigtimedwait: "
+ "sigtimedwait returning (%d)\n"), error);
+#endif
+ if (error)
+ return (error);
+
+ sig = BSD_TO_LINUX_SIGNAL(info.ksi_signo);
+
+ if (args->ptr) {
+ memset(&linfo, 0, sizeof(linfo));
+ ksiginfo_to_lsiginfo(&info, &linfo, sig);
+ error = copyout(&linfo, args->ptr, sizeof(linfo));
+ }
+ if (error == 0)
+ td->td_retval[0] = sig;
+
+ return (error);
+}
+
+int
+linux_kill(struct thread *td, struct linux_kill_args *args)
+{
+ struct kill_args /* {
+ int pid;
+ int signum;
+ } */ tmp;
+
+#ifdef DEBUG
+ if (ldebug(kill))
+ printf(ARGS(kill, "%d, %d"), args->pid, args->signum);
+#endif
+
+ /*
+ * Allow signal 0 as a means to check for privileges
+ */
+ if (!LINUX_SIG_VALID(args->signum) && args->signum != 0)
+ return (EINVAL);
+
+ if (args->signum > 0 && args->signum <= LINUX_SIGTBLSZ)
+ tmp.signum = linux_to_bsd_signal[_SIG_IDX(args->signum)];
+ else
+ tmp.signum = args->signum;
+
+ tmp.pid = args->pid;
+ return (sys_kill(td, &tmp));
+}
+
+static int
+linux_do_tkill(struct thread *td, l_int tgid, l_int pid, l_int signum)
+{
+ struct proc *proc = td->td_proc;
+ struct linux_emuldata *em;
+ struct proc *p;
+ ksiginfo_t ksi;
+ int error;
+
+ AUDIT_ARG_SIGNUM(signum);
+ AUDIT_ARG_PID(pid);
+
+ /*
+ * Allow signal 0 as a means to check for privileges
+ */
+ if (!LINUX_SIG_VALID(signum) && signum != 0)
+ return (EINVAL);
+
+ if (signum > 0 && signum <= LINUX_SIGTBLSZ)
+ signum = linux_to_bsd_signal[_SIG_IDX(signum)];
+
+ if ((p = pfind(pid)) == NULL) {
+ if ((p = zpfind(pid)) == NULL)
+ return (ESRCH);
+ }
+
+ AUDIT_ARG_PROCESS(p);
+ error = p_cansignal(td, p, signum);
+ if (error != 0 || signum == 0)
+ goto out;
+
+ error = ESRCH;
+ em = em_find(p, EMUL_DONTLOCK);
+
+ if (em == NULL) {
+#ifdef DEBUG
+ printf("emuldata not found in do_tkill.\n");
+#endif
+ goto out;
+ }
+ if (tgid > 0 && em->shared->group_pid != tgid)
+ goto out;
+
+ ksiginfo_init(&ksi);
+ ksi.ksi_signo = signum;
+ ksi.ksi_code = LINUX_SI_TKILL;
+ ksi.ksi_errno = 0;
+ ksi.ksi_pid = proc->p_pid;
+ ksi.ksi_uid = proc->p_ucred->cr_ruid;
+
+ error = pksignal(p, ksi.ksi_signo, &ksi);
+
+out:
+ PROC_UNLOCK(p);
+ return (error);
+}
+
+int
+linux_tgkill(struct thread *td, struct linux_tgkill_args *args)
+{
+
+#ifdef DEBUG
+ if (ldebug(tgkill))
+ printf(ARGS(tgkill, "%d, %d, %d"), args->tgid, args->pid, args->sig);
+#endif
+ if (args->pid <= 0 || args->tgid <=0)
+ return (EINVAL);
+
+ return (linux_do_tkill(td, args->tgid, args->pid, args->sig));
+}
+
+int
+linux_tkill(struct thread *td, struct linux_tkill_args *args)
+{
+#ifdef DEBUG
+ if (ldebug(tkill))
+ printf(ARGS(tkill, "%i, %i"), args->tid, args->sig);
+#endif
+ if (args->tid <= 0)
+ return (EINVAL);
+
+ return (linux_do_tkill(td, 0, args->tid, args->sig));
+}
+
+void
+ksiginfo_to_lsiginfo(ksiginfo_t *ksi, l_siginfo_t *lsi, l_int sig)
+{
+
+ lsi->lsi_signo = sig;
+ lsi->lsi_code = ksi->ksi_code;
+
+ switch (sig) {
+ case LINUX_SIGPOLL:
+ /* XXX si_fd? */
+ lsi->lsi_band = ksi->ksi_band;
+ break;
+ case LINUX_SIGCHLD:
+ lsi->lsi_pid = ksi->ksi_pid;
+ lsi->lsi_uid = ksi->ksi_uid;
+ lsi->lsi_status = ksi->ksi_status;
+ break;
+ case LINUX_SIGBUS:
+ case LINUX_SIGILL:
+ case LINUX_SIGFPE:
+ case LINUX_SIGSEGV:
+ lsi->lsi_addr = PTROUT(ksi->ksi_addr);
+ break;
+ default:
+ /* XXX SI_TIMER etc... */
+ lsi->lsi_pid = ksi->ksi_pid;
+ lsi->lsi_uid = ksi->ksi_uid;
+ break;
+ }
+ if (sig >= LINUX_SIGRTMIN) {
+ lsi->lsi_int = ksi->ksi_info.si_value.sival_int;
+ lsi->lsi_ptr = PTROUT(ksi->ksi_info.si_value.sival_ptr);
+ }
+}
diff --git a/sys/compat/linux/linux_signal.h b/sys/compat/linux/linux_signal.h
new file mode 100644
index 0000000..426cf43
--- /dev/null
+++ b/sys/compat/linux/linux_signal.h
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2000 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LINUX_SIGNAL_H_
+#define _LINUX_SIGNAL_H_
+
+#define LINUX_SI_TKILL -6;
+
+extern int bsd_to_linux_signal[];
+extern int linux_to_bsd_signal[];
+
+void linux_to_bsd_sigset(l_sigset_t *, sigset_t *);
+void bsd_to_linux_sigset(sigset_t *, l_sigset_t *);
+int linux_do_sigaction(struct thread *, int, l_sigaction_t *, l_sigaction_t *);
+void ksiginfo_to_lsiginfo(ksiginfo_t *ksi, l_siginfo_t *lsi, l_int sig);
+
+#define LINUX_SIG_VALID(sig) ((sig) <= LINUX_NSIG && (sig) > 0)
+
+#define BSD_TO_LINUX_SIGNAL(sig) \
+ (((sig) <= LINUX_SIGTBLSZ) ? bsd_to_linux_signal[_SIG_IDX(sig)] : sig)
+
+#endif /* _LINUX_SIGNAL_H_ */
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
new file mode 100644
index 0000000..36b23ac
--- /dev/null
+++ b/sys/compat/linux/linux_socket.c
@@ -0,0 +1,1709 @@
+/*-
+ * Copyright (c) 1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/* XXX we use functions that might not exist. */
+#include "opt_compat.h"
+#include "opt_inet6.h"
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/sysproto.h>
+#include <sys/capability.h>
+#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <sys/limits.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/syscallsubr.h>
+#include <sys/uio.h>
+#include <sys/syslog.h>
+#include <sys/un.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#ifdef INET6
+#include <netinet/ip6.h>
+#include <netinet6/ip6_var.h>
+#include <netinet6/in6_var.h>
+#endif
+
+#ifdef COMPAT_LINUX32
+#include <machine/../linux32/linux.h>
+#include <machine/../linux32/linux32_proto.h>
+#else
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#endif
+#include <compat/linux/linux_socket.h>
+#include <compat/linux/linux_util.h>
+
+static int linux_to_bsd_domain(int);
+
+/*
+ * Reads a linux sockaddr and does any necessary translation.
+ * Linux sockaddrs don't have a length field, only a family.
+ * Copy the osockaddr structure pointed to by osa to kernel, adjust
+ * family and convert to sockaddr.
+ */
+static int
+linux_getsockaddr(struct sockaddr **sap, const struct osockaddr *osa, int salen)
+{
+ struct sockaddr *sa;
+ struct osockaddr *kosa;
+#ifdef INET6
+ struct sockaddr_in6 *sin6;
+ int oldv6size;
+#endif
+ char *name;
+ int bdom, error, hdrlen, namelen;
+
+ if (salen < 2 || salen > UCHAR_MAX || !osa)
+ return (EINVAL);
+
+#ifdef INET6
+ oldv6size = 0;
+ /*
+ * Check for old (pre-RFC2553) sockaddr_in6. We may accept it
+ * if it's a v4-mapped address, so reserve the proper space
+ * for it.
+ */
+ if (salen == sizeof(struct sockaddr_in6) - sizeof(uint32_t)) {
+ salen += sizeof(uint32_t);
+ oldv6size = 1;
+ }
+#endif
+
+ kosa = malloc(salen, M_SONAME, M_WAITOK);
+
+ if ((error = copyin(osa, kosa, salen)))
+ goto out;
+
+ bdom = linux_to_bsd_domain(kosa->sa_family);
+ if (bdom == -1) {
+ error = EAFNOSUPPORT;
+ goto out;
+ }
+
+#ifdef INET6
+ /*
+ * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6,
+ * which lacks the scope id compared with RFC2553 one. If we detect
+ * the situation, reject the address and write a message to system log.
+ *
+ * Still accept addresses for which the scope id is not used.
+ */
+ if (oldv6size) {
+ if (bdom == AF_INET6) {
+ sin6 = (struct sockaddr_in6 *)kosa;
+ if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ||
+ (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) &&
+ !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) &&
+ !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) &&
+ !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
+ !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) {
+ sin6->sin6_scope_id = 0;
+ } else {
+ log(LOG_DEBUG,
+ "obsolete pre-RFC2553 sockaddr_in6 rejected\n");
+ error = EINVAL;
+ goto out;
+ }
+ } else
+ salen -= sizeof(uint32_t);
+ }
+#endif
+ if (bdom == AF_INET) {
+ if (salen < sizeof(struct sockaddr_in)) {
+ error = EINVAL;
+ goto out;
+ }
+ salen = sizeof(struct sockaddr_in);
+ }
+
+ if (bdom == AF_LOCAL && salen > sizeof(struct sockaddr_un)) {
+ hdrlen = offsetof(struct sockaddr_un, sun_path);
+ name = ((struct sockaddr_un *)kosa)->sun_path;
+ if (*name == '\0') {
+ /*
+ * Linux abstract namespace starts with a NULL byte.
+ * XXX We do not support abstract namespace yet.
+ */
+ namelen = strnlen(name + 1, salen - hdrlen - 1) + 1;
+ } else
+ namelen = strnlen(name, salen - hdrlen);
+ salen = hdrlen + namelen;
+ if (salen > sizeof(struct sockaddr_un)) {
+ error = ENAMETOOLONG;
+ goto out;
+ }
+ }
+
+ sa = (struct sockaddr *)kosa;
+ sa->sa_family = bdom;
+ sa->sa_len = salen;
+
+ *sap = sa;
+ return (0);
+
+out:
+ free(kosa, M_SONAME);
+ return (error);
+}
+
+static int
+linux_to_bsd_domain(int domain)
+{
+
+ switch (domain) {
+ case LINUX_AF_UNSPEC:
+ return (AF_UNSPEC);
+ case LINUX_AF_UNIX:
+ return (AF_LOCAL);
+ case LINUX_AF_INET:
+ return (AF_INET);
+ case LINUX_AF_INET6:
+ return (AF_INET6);
+ case LINUX_AF_AX25:
+ return (AF_CCITT);
+ case LINUX_AF_IPX:
+ return (AF_IPX);
+ case LINUX_AF_APPLETALK:
+ return (AF_APPLETALK);
+ }
+ return (-1);
+}
+
+static int
+bsd_to_linux_domain(int domain)
+{
+
+ switch (domain) {
+ case AF_UNSPEC:
+ return (LINUX_AF_UNSPEC);
+ case AF_LOCAL:
+ return (LINUX_AF_UNIX);
+ case AF_INET:
+ return (LINUX_AF_INET);
+ case AF_INET6:
+ return (LINUX_AF_INET6);
+ case AF_CCITT:
+ return (LINUX_AF_AX25);
+ case AF_IPX:
+ return (LINUX_AF_IPX);
+ case AF_APPLETALK:
+ return (LINUX_AF_APPLETALK);
+ }
+ return (-1);
+}
+
+static int
+linux_to_bsd_sockopt_level(int level)
+{
+
+ switch (level) {
+ case LINUX_SOL_SOCKET:
+ return (SOL_SOCKET);
+ }
+ return (level);
+}
+
+static int
+bsd_to_linux_sockopt_level(int level)
+{
+
+ switch (level) {
+ case SOL_SOCKET:
+ return (LINUX_SOL_SOCKET);
+ }
+ return (level);
+}
+
+static int
+linux_to_bsd_ip_sockopt(int opt)
+{
+
+ switch (opt) {
+ case LINUX_IP_TOS:
+ return (IP_TOS);
+ case LINUX_IP_TTL:
+ return (IP_TTL);
+ case LINUX_IP_OPTIONS:
+ return (IP_OPTIONS);
+ case LINUX_IP_MULTICAST_IF:
+ return (IP_MULTICAST_IF);
+ case LINUX_IP_MULTICAST_TTL:
+ return (IP_MULTICAST_TTL);
+ case LINUX_IP_MULTICAST_LOOP:
+ return (IP_MULTICAST_LOOP);
+ case LINUX_IP_ADD_MEMBERSHIP:
+ return (IP_ADD_MEMBERSHIP);
+ case LINUX_IP_DROP_MEMBERSHIP:
+ return (IP_DROP_MEMBERSHIP);
+ case LINUX_IP_HDRINCL:
+ return (IP_HDRINCL);
+ }
+ return (-1);
+}
+
+static int
+linux_to_bsd_so_sockopt(int opt)
+{
+
+ switch (opt) {
+ case LINUX_SO_DEBUG:
+ return (SO_DEBUG);
+ case LINUX_SO_REUSEADDR:
+ return (SO_REUSEADDR);
+ case LINUX_SO_TYPE:
+ return (SO_TYPE);
+ case LINUX_SO_ERROR:
+ return (SO_ERROR);
+ case LINUX_SO_DONTROUTE:
+ return (SO_DONTROUTE);
+ case LINUX_SO_BROADCAST:
+ return (SO_BROADCAST);
+ case LINUX_SO_SNDBUF:
+ return (SO_SNDBUF);
+ case LINUX_SO_RCVBUF:
+ return (SO_RCVBUF);
+ case LINUX_SO_KEEPALIVE:
+ return (SO_KEEPALIVE);
+ case LINUX_SO_OOBINLINE:
+ return (SO_OOBINLINE);
+ case LINUX_SO_LINGER:
+ return (SO_LINGER);
+ case LINUX_SO_PEERCRED:
+ return (LOCAL_PEERCRED);
+ case LINUX_SO_RCVLOWAT:
+ return (SO_RCVLOWAT);
+ case LINUX_SO_SNDLOWAT:
+ return (SO_SNDLOWAT);
+ case LINUX_SO_RCVTIMEO:
+ return (SO_RCVTIMEO);
+ case LINUX_SO_SNDTIMEO:
+ return (SO_SNDTIMEO);
+ case LINUX_SO_TIMESTAMP:
+ return (SO_TIMESTAMP);
+ case LINUX_SO_ACCEPTCONN:
+ return (SO_ACCEPTCONN);
+ }
+ return (-1);
+}
+
+static int
+linux_to_bsd_tcp_sockopt(int opt)
+{
+
+ switch (opt) {
+ case LINUX_TCP_NODELAY:
+ return (TCP_NODELAY);
+ case LINUX_TCP_MAXSEG:
+ return (TCP_MAXSEG);
+ case LINUX_TCP_KEEPIDLE:
+ return (TCP_KEEPIDLE);
+ case LINUX_TCP_KEEPINTVL:
+ return (TCP_KEEPINTVL);
+ case LINUX_TCP_KEEPCNT:
+ return (TCP_KEEPCNT);
+ case LINUX_TCP_MD5SIG:
+ return (TCP_MD5SIG);
+ }
+ return (-1);
+}
+
+static int
+linux_to_bsd_msg_flags(int flags)
+{
+ int ret_flags = 0;
+
+ if (flags & LINUX_MSG_OOB)
+ ret_flags |= MSG_OOB;
+ if (flags & LINUX_MSG_PEEK)
+ ret_flags |= MSG_PEEK;
+ if (flags & LINUX_MSG_DONTROUTE)
+ ret_flags |= MSG_DONTROUTE;
+ if (flags & LINUX_MSG_CTRUNC)
+ ret_flags |= MSG_CTRUNC;
+ if (flags & LINUX_MSG_TRUNC)
+ ret_flags |= MSG_TRUNC;
+ if (flags & LINUX_MSG_DONTWAIT)
+ ret_flags |= MSG_DONTWAIT;
+ if (flags & LINUX_MSG_EOR)
+ ret_flags |= MSG_EOR;
+ if (flags & LINUX_MSG_WAITALL)
+ ret_flags |= MSG_WAITALL;
+ if (flags & LINUX_MSG_NOSIGNAL)
+ ret_flags |= MSG_NOSIGNAL;
+#if 0 /* not handled */
+ if (flags & LINUX_MSG_PROXY)
+ ;
+ if (flags & LINUX_MSG_FIN)
+ ;
+ if (flags & LINUX_MSG_SYN)
+ ;
+ if (flags & LINUX_MSG_CONFIRM)
+ ;
+ if (flags & LINUX_MSG_RST)
+ ;
+ if (flags & LINUX_MSG_ERRQUEUE)
+ ;
+#endif
+ return ret_flags;
+}
+
+/*
+* If bsd_to_linux_sockaddr() or linux_to_bsd_sockaddr() faults, then the
+* native syscall will fault. Thus, we don't really need to check the
+* return values for these functions.
+*/
+
+static int
+bsd_to_linux_sockaddr(struct sockaddr *arg)
+{
+ struct sockaddr sa;
+ size_t sa_len = sizeof(struct sockaddr);
+ int error;
+
+ if ((error = copyin(arg, &sa, sa_len)))
+ return (error);
+
+ *(u_short *)&sa = sa.sa_family;
+
+ error = copyout(&sa, arg, sa_len);
+
+ return (error);
+}
+
+static int
+linux_to_bsd_sockaddr(struct sockaddr *arg, int len)
+{
+ struct sockaddr sa;
+ size_t sa_len = sizeof(struct sockaddr);
+ int error;
+
+ if ((error = copyin(arg, &sa, sa_len)))
+ return (error);
+
+ sa.sa_family = *(sa_family_t *)&sa;
+ sa.sa_len = len;
+
+ error = copyout(&sa, arg, sa_len);
+
+ return (error);
+}
+
+
+static int
+linux_sa_put(struct osockaddr *osa)
+{
+ struct osockaddr sa;
+ int error, bdom;
+
+ /*
+ * Only read/write the osockaddr family part, the rest is
+ * not changed.
+ */
+ error = copyin(osa, &sa, sizeof(sa.sa_family));
+ if (error)
+ return (error);
+
+ bdom = bsd_to_linux_domain(sa.sa_family);
+ if (bdom == -1)
+ return (EINVAL);
+
+ sa.sa_family = bdom;
+ error = copyout(&sa, osa, sizeof(sa.sa_family));
+ if (error)
+ return (error);
+
+ return (0);
+}
+
+static int
+linux_to_bsd_cmsg_type(int cmsg_type)
+{
+
+ switch (cmsg_type) {
+ case LINUX_SCM_RIGHTS:
+ return (SCM_RIGHTS);
+ case LINUX_SCM_CREDENTIALS:
+ return (SCM_CREDS);
+ }
+ return (-1);
+}
+
+static int
+bsd_to_linux_cmsg_type(int cmsg_type)
+{
+
+ switch (cmsg_type) {
+ case SCM_RIGHTS:
+ return (LINUX_SCM_RIGHTS);
+ case SCM_CREDS:
+ return (LINUX_SCM_CREDENTIALS);
+ }
+ return (-1);
+}
+
+static int
+linux_to_bsd_msghdr(struct msghdr *bhdr, const struct l_msghdr *lhdr)
+{
+ if (lhdr->msg_controllen > INT_MAX)
+ return (ENOBUFS);
+
+ bhdr->msg_name = PTRIN(lhdr->msg_name);
+ bhdr->msg_namelen = lhdr->msg_namelen;
+ bhdr->msg_iov = PTRIN(lhdr->msg_iov);
+ bhdr->msg_iovlen = lhdr->msg_iovlen;
+ bhdr->msg_control = PTRIN(lhdr->msg_control);
+
+ /*
+ * msg_controllen is skipped since BSD and LINUX control messages
+ * are potentially different sizes (e.g. the cred structure used
+ * by SCM_CREDS is different between the two operating system).
+ *
+ * The caller can set it (if necessary) after converting all the
+ * control messages.
+ */
+
+ bhdr->msg_flags = linux_to_bsd_msg_flags(lhdr->msg_flags);
+ return (0);
+}
+
+static int
+bsd_to_linux_msghdr(const struct msghdr *bhdr, struct l_msghdr *lhdr)
+{
+ lhdr->msg_name = PTROUT(bhdr->msg_name);
+ lhdr->msg_namelen = bhdr->msg_namelen;
+ lhdr->msg_iov = PTROUT(bhdr->msg_iov);
+ lhdr->msg_iovlen = bhdr->msg_iovlen;
+ lhdr->msg_control = PTROUT(bhdr->msg_control);
+
+ /*
+ * msg_controllen is skipped since BSD and LINUX control messages
+ * are potentially different sizes (e.g. the cred structure used
+ * by SCM_CREDS is different between the two operating system).
+ *
+ * The caller can set it (if necessary) after converting all the
+ * control messages.
+ */
+
+ /* msg_flags skipped */
+ return (0);
+}
+
+static int
+linux_set_socket_flags(struct thread *td, int s, int flags)
+{
+ int error;
+
+ if (flags & LINUX_SOCK_NONBLOCK) {
+ error = kern_fcntl(td, s, F_SETFL, O_NONBLOCK);
+ if (error)
+ return (error);
+ }
+ if (flags & LINUX_SOCK_CLOEXEC) {
+ error = kern_fcntl(td, s, F_SETFD, FD_CLOEXEC);
+ if (error)
+ return (error);
+ }
+ return (0);
+}
+
+static int
+linux_sendit(struct thread *td, int s, struct msghdr *mp, int flags,
+ struct mbuf *control, enum uio_seg segflg)
+{
+ struct sockaddr *to;
+ int error;
+
+ if (mp->msg_name != NULL) {
+ error = linux_getsockaddr(&to, mp->msg_name, mp->msg_namelen);
+ if (error)
+ return (error);
+ mp->msg_name = to;
+ } else
+ to = NULL;
+
+ error = kern_sendit(td, s, mp, linux_to_bsd_msg_flags(flags), control,
+ segflg);
+
+ if (to)
+ free(to, M_SONAME);
+ return (error);
+}
+
+/* Return 0 if IP_HDRINCL is set for the given socket. */
+static int
+linux_check_hdrincl(struct thread *td, int s)
+{
+ int error, optval, size_val;
+
+ size_val = sizeof(optval);
+ error = kern_getsockopt(td, s, IPPROTO_IP, IP_HDRINCL,
+ &optval, UIO_SYSSPACE, &size_val);
+ if (error)
+ return (error);
+
+ return (optval == 0);
+}
+
+struct linux_sendto_args {
+ int s;
+ l_uintptr_t msg;
+ int len;
+ int flags;
+ l_uintptr_t to;
+ int tolen;
+};
+
+/*
+ * Updated sendto() when IP_HDRINCL is set:
+ * tweak endian-dependent fields in the IP packet.
+ */
+static int
+linux_sendto_hdrincl(struct thread *td, struct linux_sendto_args *linux_args)
+{
+/*
+ * linux_ip_copysize defines how many bytes we should copy
+ * from the beginning of the IP packet before we customize it for BSD.
+ * It should include all the fields we modify (ip_len and ip_off).
+ */
+#define linux_ip_copysize 8
+
+ struct ip *packet;
+ struct msghdr msg;
+ struct iovec aiov[1];
+ int error;
+
+ /* Check that the packet isn't too big or too small. */
+ if (linux_args->len < linux_ip_copysize ||
+ linux_args->len > IP_MAXPACKET)
+ return (EINVAL);
+
+ packet = (struct ip *)malloc(linux_args->len, M_TEMP, M_WAITOK);
+
+ /* Make kernel copy of the packet to be sent */
+ if ((error = copyin(PTRIN(linux_args->msg), packet,
+ linux_args->len)))
+ goto goout;
+
+ /* Convert fields from Linux to BSD raw IP socket format */
+ packet->ip_len = linux_args->len;
+ packet->ip_off = ntohs(packet->ip_off);
+
+ /* Prepare the msghdr and iovec structures describing the new packet */
+ msg.msg_name = PTRIN(linux_args->to);
+ msg.msg_namelen = linux_args->tolen;
+ msg.msg_iov = aiov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = NULL;
+ msg.msg_flags = 0;
+ aiov[0].iov_base = (char *)packet;
+ aiov[0].iov_len = linux_args->len;
+ error = linux_sendit(td, linux_args->s, &msg, linux_args->flags,
+ NULL, UIO_SYSSPACE);
+goout:
+ free(packet, M_TEMP);
+ return (error);
+}
+
+struct linux_socket_args {
+ int domain;
+ int type;
+ int protocol;
+};
+
+static int
+linux_socket(struct thread *td, struct linux_socket_args *args)
+{
+ struct socket_args /* {
+ int domain;
+ int type;
+ int protocol;
+ } */ bsd_args;
+ int retval_socket, socket_flags;
+
+ bsd_args.protocol = args->protocol;
+ socket_flags = args->type & ~LINUX_SOCK_TYPE_MASK;
+ if (socket_flags & ~(LINUX_SOCK_CLOEXEC | LINUX_SOCK_NONBLOCK))
+ return (EINVAL);
+ bsd_args.type = args->type & LINUX_SOCK_TYPE_MASK;
+ if (bsd_args.type < 0 || bsd_args.type > LINUX_SOCK_MAX)
+ return (EINVAL);
+ bsd_args.domain = linux_to_bsd_domain(args->domain);
+ if (bsd_args.domain == -1)
+ return (EAFNOSUPPORT);
+
+ retval_socket = sys_socket(td, &bsd_args);
+ if (retval_socket)
+ return (retval_socket);
+
+ retval_socket = linux_set_socket_flags(td, td->td_retval[0],
+ socket_flags);
+ if (retval_socket) {
+ (void)kern_close(td, td->td_retval[0]);
+ goto out;
+ }
+
+ if (bsd_args.type == SOCK_RAW
+ && (bsd_args.protocol == IPPROTO_RAW || bsd_args.protocol == 0)
+ && bsd_args.domain == PF_INET) {
+ /* It's a raw IP socket: set the IP_HDRINCL option. */
+ int hdrincl;
+
+ hdrincl = 1;
+ /* We ignore any error returned by kern_setsockopt() */
+ kern_setsockopt(td, td->td_retval[0], IPPROTO_IP, IP_HDRINCL,
+ &hdrincl, UIO_SYSSPACE, sizeof(hdrincl));
+ }
+#ifdef INET6
+ /*
+ * Linux AF_INET6 socket has IPV6_V6ONLY setsockopt set to 0 by default
+ * and some apps depend on this. So, set V6ONLY to 0 for Linux apps.
+ * For simplicity we do this unconditionally of the net.inet6.ip6.v6only
+ * sysctl value.
+ */
+ if (bsd_args.domain == PF_INET6) {
+ int v6only;
+
+ v6only = 0;
+ /* We ignore any error returned by setsockopt() */
+ kern_setsockopt(td, td->td_retval[0], IPPROTO_IPV6, IPV6_V6ONLY,
+ &v6only, UIO_SYSSPACE, sizeof(v6only));
+ }
+#endif
+
+out:
+ return (retval_socket);
+}
+
+struct linux_bind_args {
+ int s;
+ l_uintptr_t name;
+ int namelen;
+};
+
+static int
+linux_bind(struct thread *td, struct linux_bind_args *args)
+{
+ struct sockaddr *sa;
+ int error;
+
+ error = linux_getsockaddr(&sa, PTRIN(args->name),
+ args->namelen);
+ if (error)
+ return (error);
+
+ error = kern_bind(td, args->s, sa);
+ free(sa, M_SONAME);
+ if (error == EADDRNOTAVAIL && args->namelen != sizeof(struct sockaddr_in))
+ return (EINVAL);
+ return (error);
+}
+
+struct linux_connect_args {
+ int s;
+ l_uintptr_t name;
+ int namelen;
+};
+int linux_connect(struct thread *, struct linux_connect_args *);
+
+int
+linux_connect(struct thread *td, struct linux_connect_args *args)
+{
+ struct socket *so;
+ struct sockaddr *sa;
+ u_int fflag;
+ int error;
+
+ error = linux_getsockaddr(&sa, (struct osockaddr *)PTRIN(args->name),
+ args->namelen);
+ if (error)
+ return (error);
+
+ error = kern_connect(td, args->s, sa);
+ free(sa, M_SONAME);
+ if (error != EISCONN)
+ return (error);
+
+ /*
+ * Linux doesn't return EISCONN the first time it occurs,
+ * when on a non-blocking socket. Instead it returns the
+ * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD.
+ *
+ * XXXRW: Instead of using fgetsock(), check that it is a
+ * socket and use the file descriptor reference instead of
+ * creating a new one.
+ */
+ error = fgetsock(td, args->s, CAP_CONNECT, &so, &fflag);
+ if (error == 0) {
+ error = EISCONN;
+ if (fflag & FNONBLOCK) {
+ SOCK_LOCK(so);
+ if (so->so_emuldata == 0)
+ error = so->so_error;
+ so->so_emuldata = (void *)1;
+ SOCK_UNLOCK(so);
+ }
+ fputsock(so);
+ }
+ return (error);
+}
+
+struct linux_listen_args {
+ int s;
+ int backlog;
+};
+
+static int
+linux_listen(struct thread *td, struct linux_listen_args *args)
+{
+ struct listen_args /* {
+ int s;
+ int backlog;
+ } */ bsd_args;
+
+ bsd_args.s = args->s;
+ bsd_args.backlog = args->backlog;
+ return (sys_listen(td, &bsd_args));
+}
+
+static int
+linux_accept_common(struct thread *td, int s, l_uintptr_t addr,
+ l_uintptr_t namelen, int flags)
+{
+ struct accept_args /* {
+ int s;
+ struct sockaddr * __restrict name;
+ socklen_t * __restrict anamelen;
+ } */ bsd_args;
+ int error;
+
+ if (flags & ~(LINUX_SOCK_CLOEXEC | LINUX_SOCK_NONBLOCK))
+ return (EINVAL);
+
+ bsd_args.s = s;
+ /* XXX: */
+ bsd_args.name = (struct sockaddr * __restrict)PTRIN(addr);
+ bsd_args.anamelen = PTRIN(namelen);/* XXX */
+ error = sys_accept(td, &bsd_args);
+ bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.name);
+ if (error) {
+ if (error == EFAULT && namelen != sizeof(struct sockaddr_in))
+ return (EINVAL);
+ return (error);
+ }
+
+ /*
+ * linux appears not to copy flags from the parent socket to the
+ * accepted one, so we must clear the flags in the new descriptor
+ * and apply the requested flags.
+ */
+ error = kern_fcntl(td, td->td_retval[0], F_SETFL, 0);
+ if (error)
+ goto out;
+ error = linux_set_socket_flags(td, td->td_retval[0], flags);
+ if (error)
+ goto out;
+ if (addr)
+ error = linux_sa_put(PTRIN(addr));
+
+out:
+ if (error) {
+ (void)kern_close(td, td->td_retval[0]);
+ td->td_retval[0] = 0;
+ }
+ return (error);
+}
+
+struct linux_accept_args {
+ int s;
+ l_uintptr_t addr;
+ l_uintptr_t namelen;
+};
+
+static int
+linux_accept(struct thread *td, struct linux_accept_args *args)
+{
+
+ return (linux_accept_common(td, args->s, args->addr,
+ args->namelen, 0));
+}
+
+struct linux_accept4_args {
+ int s;
+ l_uintptr_t addr;
+ l_uintptr_t namelen;
+ int flags;
+};
+
+static int
+linux_accept4(struct thread *td, struct linux_accept4_args *args)
+{
+
+ return (linux_accept_common(td, args->s, args->addr,
+ args->namelen, args->flags));
+}
+
+struct linux_getsockname_args {
+ int s;
+ l_uintptr_t addr;
+ l_uintptr_t namelen;
+};
+
+static int
+linux_getsockname(struct thread *td, struct linux_getsockname_args *args)
+{
+ struct getsockname_args /* {
+ int fdes;
+ struct sockaddr * __restrict asa;
+ socklen_t * __restrict alen;
+ } */ bsd_args;
+ int error;
+
+ bsd_args.fdes = args->s;
+ /* XXX: */
+ bsd_args.asa = (struct sockaddr * __restrict)PTRIN(args->addr);
+ bsd_args.alen = PTRIN(args->namelen); /* XXX */
+ error = sys_getsockname(td, &bsd_args);
+ bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.asa);
+ if (error)
+ return (error);
+ error = linux_sa_put(PTRIN(args->addr));
+ if (error)
+ return (error);
+ return (0);
+}
+
+struct linux_getpeername_args {
+ int s;
+ l_uintptr_t addr;
+ l_uintptr_t namelen;
+};
+
+static int
+linux_getpeername(struct thread *td, struct linux_getpeername_args *args)
+{
+ struct getpeername_args /* {
+ int fdes;
+ caddr_t asa;
+ int *alen;
+ } */ bsd_args;
+ int error;
+
+ bsd_args.fdes = args->s;
+ bsd_args.asa = (struct sockaddr *)PTRIN(args->addr);
+ bsd_args.alen = (int *)PTRIN(args->namelen);
+ error = sys_getpeername(td, &bsd_args);
+ bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.asa);
+ if (error)
+ return (error);
+ error = linux_sa_put(PTRIN(args->addr));
+ if (error)
+ return (error);
+ return (0);
+}
+
+struct linux_socketpair_args {
+ int domain;
+ int type;
+ int protocol;
+ l_uintptr_t rsv;
+};
+
+static int
+linux_socketpair(struct thread *td, struct linux_socketpair_args *args)
+{
+ struct socketpair_args /* {
+ int domain;
+ int type;
+ int protocol;
+ int *rsv;
+ } */ bsd_args;
+ int error, socket_flags;
+ int sv[2];
+
+ bsd_args.domain = linux_to_bsd_domain(args->domain);
+ if (bsd_args.domain != PF_LOCAL)
+ return (EAFNOSUPPORT);
+
+ socket_flags = args->type & ~LINUX_SOCK_TYPE_MASK;
+ if (socket_flags & ~(LINUX_SOCK_CLOEXEC | LINUX_SOCK_NONBLOCK))
+ return (EINVAL);
+ bsd_args.type = args->type & LINUX_SOCK_TYPE_MASK;
+ if (bsd_args.type < 0 || bsd_args.type > LINUX_SOCK_MAX)
+ return (EINVAL);
+
+ if (args->protocol != 0 && args->protocol != PF_UNIX)
+
+ /*
+ * Use of PF_UNIX as protocol argument is not right,
+ * but Linux does it.
+ * Do not map PF_UNIX as its Linux value is identical
+ * to FreeBSD one.
+ */
+ return (EPROTONOSUPPORT);
+ else
+ bsd_args.protocol = 0;
+ bsd_args.rsv = (int *)PTRIN(args->rsv);
+ error = kern_socketpair(td, bsd_args.domain, bsd_args.type,
+ bsd_args.protocol, sv);
+ if (error)
+ return (error);
+ error = linux_set_socket_flags(td, sv[0], socket_flags);
+ if (error)
+ goto out;
+ error = linux_set_socket_flags(td, sv[1], socket_flags);
+ if (error)
+ goto out;
+
+ error = copyout(sv, bsd_args.rsv, 2 * sizeof(int));
+
+out:
+ if (error) {
+ (void)kern_close(td, sv[0]);
+ (void)kern_close(td, sv[1]);
+ }
+ return (error);
+}
+
+struct linux_send_args {
+ int s;
+ l_uintptr_t msg;
+ int len;
+ int flags;
+};
+
+static int
+linux_send(struct thread *td, struct linux_send_args *args)
+{
+ struct sendto_args /* {
+ int s;
+ caddr_t buf;
+ int len;
+ int flags;
+ caddr_t to;
+ int tolen;
+ } */ bsd_args;
+
+ bsd_args.s = args->s;
+ bsd_args.buf = (caddr_t)PTRIN(args->msg);
+ bsd_args.len = args->len;
+ bsd_args.flags = args->flags;
+ bsd_args.to = NULL;
+ bsd_args.tolen = 0;
+ return sys_sendto(td, &bsd_args);
+}
+
+struct linux_recv_args {
+ int s;
+ l_uintptr_t msg;
+ int len;
+ int flags;
+};
+
+static int
+linux_recv(struct thread *td, struct linux_recv_args *args)
+{
+ struct recvfrom_args /* {
+ int s;
+ caddr_t buf;
+ int len;
+ int flags;
+ struct sockaddr *from;
+ socklen_t fromlenaddr;
+ } */ bsd_args;
+
+ bsd_args.s = args->s;
+ bsd_args.buf = (caddr_t)PTRIN(args->msg);
+ bsd_args.len = args->len;
+ bsd_args.flags = linux_to_bsd_msg_flags(args->flags);
+ bsd_args.from = NULL;
+ bsd_args.fromlenaddr = 0;
+ return (sys_recvfrom(td, &bsd_args));
+}
+
+static int
+linux_sendto(struct thread *td, struct linux_sendto_args *args)
+{
+ struct msghdr msg;
+ struct iovec aiov;
+ int error;
+
+ if (linux_check_hdrincl(td, args->s) == 0)
+ /* IP_HDRINCL set, tweak the packet before sending */
+ return (linux_sendto_hdrincl(td, args));
+
+ msg.msg_name = PTRIN(args->to);
+ msg.msg_namelen = args->tolen;
+ msg.msg_iov = &aiov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = NULL;
+ msg.msg_flags = 0;
+ aiov.iov_base = PTRIN(args->msg);
+ aiov.iov_len = args->len;
+ error = linux_sendit(td, args->s, &msg, args->flags, NULL,
+ UIO_USERSPACE);
+ return (error);
+}
+
+struct linux_recvfrom_args {
+ int s;
+ l_uintptr_t buf;
+ int len;
+ int flags;
+ l_uintptr_t from;
+ l_uintptr_t fromlen;
+};
+
+static int
+linux_recvfrom(struct thread *td, struct linux_recvfrom_args *args)
+{
+ struct recvfrom_args /* {
+ int s;
+ caddr_t buf;
+ size_t len;
+ int flags;
+ struct sockaddr * __restrict from;
+ socklen_t * __restrict fromlenaddr;
+ } */ bsd_args;
+ size_t len;
+ int error;
+
+ if ((error = copyin(PTRIN(args->fromlen), &len, sizeof(size_t))))
+ return (error);
+
+ bsd_args.s = args->s;
+ bsd_args.buf = PTRIN(args->buf);
+ bsd_args.len = args->len;
+ bsd_args.flags = linux_to_bsd_msg_flags(args->flags);
+ /* XXX: */
+ bsd_args.from = (struct sockaddr * __restrict)PTRIN(args->from);
+ bsd_args.fromlenaddr = PTRIN(args->fromlen);/* XXX */
+
+ linux_to_bsd_sockaddr((struct sockaddr *)bsd_args.from, len);
+ error = sys_recvfrom(td, &bsd_args);
+ bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.from);
+
+ if (error)
+ return (error);
+ if (args->from) {
+ error = linux_sa_put((struct osockaddr *)
+ PTRIN(args->from));
+ if (error)
+ return (error);
+ }
+ return (0);
+}
+
+struct linux_sendmsg_args {
+ int s;
+ l_uintptr_t msg;
+ int flags;
+};
+
+static int
+linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
+{
+ struct cmsghdr *cmsg;
+ struct cmsgcred cmcred;
+ struct mbuf *control;
+ struct msghdr msg;
+ struct l_cmsghdr linux_cmsg;
+ struct l_cmsghdr *ptr_cmsg;
+ struct l_msghdr linux_msg;
+ struct iovec *iov;
+ socklen_t datalen;
+ struct sockaddr *sa;
+ sa_family_t sa_family;
+ void *data;
+ int error;
+
+ error = copyin(PTRIN(args->msg), &linux_msg, sizeof(linux_msg));
+ if (error)
+ return (error);
+
+ /*
+ * Some Linux applications (ping) define a non-NULL control data
+ * pointer, but a msg_controllen of 0, which is not allowed in the
+ * FreeBSD system call interface. NULL the msg_control pointer in
+ * order to handle this case. This should be checked, but allows the
+ * Linux ping to work.
+ */
+ if (PTRIN(linux_msg.msg_control) != NULL && linux_msg.msg_controllen == 0)
+ linux_msg.msg_control = PTROUT(NULL);
+
+ error = linux_to_bsd_msghdr(&msg, &linux_msg);
+ if (error)
+ return (error);
+
+#ifdef COMPAT_LINUX32
+ error = linux32_copyiniov(PTRIN(msg.msg_iov), msg.msg_iovlen,
+ &iov, EMSGSIZE);
+#else
+ error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
+#endif
+ if (error)
+ return (error);
+
+ control = NULL;
+ cmsg = NULL;
+
+ if ((ptr_cmsg = LINUX_CMSG_FIRSTHDR(&linux_msg)) != NULL) {
+ error = kern_getsockname(td, args->s, &sa, &datalen);
+ if (error)
+ goto bad;
+ sa_family = sa->sa_family;
+ free(sa, M_SONAME);
+
+ error = ENOBUFS;
+ cmsg = malloc(CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO);
+ control = m_get(M_WAITOK, MT_CONTROL);
+ if (control == NULL)
+ goto bad;
+
+ do {
+ error = copyin(ptr_cmsg, &linux_cmsg,
+ sizeof(struct l_cmsghdr));
+ if (error)
+ goto bad;
+
+ error = EINVAL;
+ if (linux_cmsg.cmsg_len < sizeof(struct l_cmsghdr))
+ goto bad;
+
+ /*
+ * Now we support only SCM_RIGHTS and SCM_CRED,
+ * so return EINVAL in any other cmsg_type
+ */
+ cmsg->cmsg_type =
+ linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type);
+ cmsg->cmsg_level =
+ linux_to_bsd_sockopt_level(linux_cmsg.cmsg_level);
+ if (cmsg->cmsg_type == -1
+ || cmsg->cmsg_level != SOL_SOCKET)
+ goto bad;
+
+ /*
+ * Some applications (e.g. pulseaudio) attempt to
+ * send ancillary data even if the underlying protocol
+ * doesn't support it which is not allowed in the
+ * FreeBSD system call interface.
+ */
+ if (sa_family != AF_UNIX)
+ continue;
+
+ data = LINUX_CMSG_DATA(ptr_cmsg);
+ datalen = linux_cmsg.cmsg_len - L_CMSG_HDRSZ;
+
+ switch (cmsg->cmsg_type)
+ {
+ case SCM_RIGHTS:
+ break;
+
+ case SCM_CREDS:
+ data = &cmcred;
+ datalen = sizeof(cmcred);
+
+ /*
+ * The lower levels will fill in the structure
+ */
+ bzero(data, datalen);
+ break;
+ }
+
+ cmsg->cmsg_len = CMSG_LEN(datalen);
+
+ error = ENOBUFS;
+ if (!m_append(control, CMSG_HDRSZ, (c_caddr_t)cmsg))
+ goto bad;
+ if (!m_append(control, datalen, (c_caddr_t)data))
+ goto bad;
+ } while ((ptr_cmsg = LINUX_CMSG_NXTHDR(&linux_msg, ptr_cmsg)));
+
+ if (m_length(control, NULL) == 0) {
+ m_freem(control);
+ control = NULL;
+ }
+ }
+
+ msg.msg_iov = iov;
+ msg.msg_flags = 0;
+ error = linux_sendit(td, args->s, &msg, args->flags, control,
+ UIO_USERSPACE);
+
+bad:
+ free(iov, M_IOV);
+ if (cmsg)
+ free(cmsg, M_TEMP);
+ return (error);
+}
+
+struct linux_recvmsg_args {
+ int s;
+ l_uintptr_t msg;
+ int flags;
+};
+
+static int
+linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args)
+{
+ struct cmsghdr *cm;
+ struct cmsgcred *cmcred;
+ struct msghdr msg;
+ struct l_cmsghdr *linux_cmsg = NULL;
+ struct l_ucred linux_ucred;
+ socklen_t datalen, outlen;
+ struct l_msghdr linux_msg;
+ struct iovec *iov, *uiov;
+ struct mbuf *control = NULL;
+ struct mbuf **controlp;
+ caddr_t outbuf;
+ void *data;
+ int error, i, fd, fds, *fdp;
+
+ error = copyin(PTRIN(args->msg), &linux_msg, sizeof(linux_msg));
+ if (error)
+ return (error);
+
+ error = linux_to_bsd_msghdr(&msg, &linux_msg);
+ if (error)
+ return (error);
+
+#ifdef COMPAT_LINUX32
+ error = linux32_copyiniov(PTRIN(msg.msg_iov), msg.msg_iovlen,
+ &iov, EMSGSIZE);
+#else
+ error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
+#endif
+ if (error)
+ return (error);
+
+ if (msg.msg_name) {
+ error = linux_to_bsd_sockaddr((struct sockaddr *)msg.msg_name,
+ msg.msg_namelen);
+ if (error)
+ goto bad;
+ }
+
+ uiov = msg.msg_iov;
+ msg.msg_iov = iov;
+ controlp = (msg.msg_control != NULL) ? &control : NULL;
+ error = kern_recvit(td, args->s, &msg, UIO_USERSPACE, controlp);
+ msg.msg_iov = uiov;
+ if (error)
+ goto bad;
+
+ error = bsd_to_linux_msghdr(&msg, &linux_msg);
+ if (error)
+ goto bad;
+
+ if (linux_msg.msg_name) {
+ error = bsd_to_linux_sockaddr((struct sockaddr *)
+ PTRIN(linux_msg.msg_name));
+ if (error)
+ goto bad;
+ }
+ if (linux_msg.msg_name && linux_msg.msg_namelen > 2) {
+ error = linux_sa_put(PTRIN(linux_msg.msg_name));
+ if (error)
+ goto bad;
+ }
+
+ outbuf = PTRIN(linux_msg.msg_control);
+ outlen = 0;
+
+ if (control) {
+ linux_cmsg = malloc(L_CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO);
+
+ msg.msg_control = mtod(control, struct cmsghdr *);
+ msg.msg_controllen = control->m_len;
+
+ cm = CMSG_FIRSTHDR(&msg);
+
+ while (cm != NULL) {
+ linux_cmsg->cmsg_type =
+ bsd_to_linux_cmsg_type(cm->cmsg_type);
+ linux_cmsg->cmsg_level =
+ bsd_to_linux_sockopt_level(cm->cmsg_level);
+ if (linux_cmsg->cmsg_type == -1
+ || cm->cmsg_level != SOL_SOCKET)
+ {
+ error = EINVAL;
+ goto bad;
+ }
+
+ data = CMSG_DATA(cm);
+ datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data;
+
+ switch (cm->cmsg_type)
+ {
+ case SCM_RIGHTS:
+ if (args->flags & LINUX_MSG_CMSG_CLOEXEC) {
+ fds = datalen / sizeof(int);
+ fdp = data;
+ for (i = 0; i < fds; i++) {
+ fd = *fdp++;
+ (void)kern_fcntl(td, fd,
+ F_SETFD, FD_CLOEXEC);
+ }
+ }
+ break;
+
+ case SCM_CREDS:
+ /*
+ * Currently LOCAL_CREDS is never in
+ * effect for Linux so no need to worry
+ * about sockcred
+ */
+ if (datalen != sizeof(*cmcred)) {
+ error = EMSGSIZE;
+ goto bad;
+ }
+ cmcred = (struct cmsgcred *)data;
+ bzero(&linux_ucred, sizeof(linux_ucred));
+ linux_ucred.pid = cmcred->cmcred_pid;
+ linux_ucred.uid = cmcred->cmcred_uid;
+ linux_ucred.gid = cmcred->cmcred_gid;
+ data = &linux_ucred;
+ datalen = sizeof(linux_ucred);
+ break;
+ }
+
+ if (outlen + LINUX_CMSG_LEN(datalen) >
+ linux_msg.msg_controllen) {
+ if (outlen == 0) {
+ error = EMSGSIZE;
+ goto bad;
+ } else {
+ linux_msg.msg_flags |=
+ LINUX_MSG_CTRUNC;
+ goto out;
+ }
+ }
+
+ linux_cmsg->cmsg_len = LINUX_CMSG_LEN(datalen);
+
+ error = copyout(linux_cmsg, outbuf, L_CMSG_HDRSZ);
+ if (error)
+ goto bad;
+ outbuf += L_CMSG_HDRSZ;
+
+ error = copyout(data, outbuf, datalen);
+ if (error)
+ goto bad;
+
+ outbuf += LINUX_CMSG_ALIGN(datalen);
+ outlen += LINUX_CMSG_LEN(datalen);
+
+ cm = CMSG_NXTHDR(&msg, cm);
+ }
+ }
+
+out:
+ linux_msg.msg_controllen = outlen;
+ error = copyout(&linux_msg, PTRIN(args->msg), sizeof(linux_msg));
+
+bad:
+ free(iov, M_IOV);
+ m_freem(control);
+ free(linux_cmsg, M_TEMP);
+
+ return (error);
+}
+
+struct linux_shutdown_args {
+ int s;
+ int how;
+};
+
+static int
+linux_shutdown(struct thread *td, struct linux_shutdown_args *args)
+{
+ struct shutdown_args /* {
+ int s;
+ int how;
+ } */ bsd_args;
+
+ bsd_args.s = args->s;
+ bsd_args.how = args->how;
+ return (sys_shutdown(td, &bsd_args));
+}
+
+struct linux_setsockopt_args {
+ int s;
+ int level;
+ int optname;
+ l_uintptr_t optval;
+ int optlen;
+};
+
+static int
+linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args)
+{
+ struct setsockopt_args /* {
+ int s;
+ int level;
+ int name;
+ caddr_t val;
+ int valsize;
+ } */ bsd_args;
+ l_timeval linux_tv;
+ struct timeval tv;
+ int error, name;
+
+ bsd_args.s = args->s;
+ bsd_args.level = linux_to_bsd_sockopt_level(args->level);
+ switch (bsd_args.level) {
+ case SOL_SOCKET:
+ name = linux_to_bsd_so_sockopt(args->optname);
+ switch (name) {
+ case SO_RCVTIMEO:
+ /* FALLTHROUGH */
+ case SO_SNDTIMEO:
+ error = copyin(PTRIN(args->optval), &linux_tv,
+ sizeof(linux_tv));
+ if (error)
+ return (error);
+ tv.tv_sec = linux_tv.tv_sec;
+ tv.tv_usec = linux_tv.tv_usec;
+ return (kern_setsockopt(td, args->s, bsd_args.level,
+ name, &tv, UIO_SYSSPACE, sizeof(tv)));
+ /* NOTREACHED */
+ break;
+ default:
+ break;
+ }
+ break;
+ case IPPROTO_IP:
+ name = linux_to_bsd_ip_sockopt(args->optname);
+ break;
+ case IPPROTO_TCP:
+ name = linux_to_bsd_tcp_sockopt(args->optname);
+ break;
+ default:
+ name = -1;
+ break;
+ }
+ if (name == -1)
+ return (ENOPROTOOPT);
+
+ bsd_args.name = name;
+ bsd_args.val = PTRIN(args->optval);
+ bsd_args.valsize = args->optlen;
+
+ if (name == IPV6_NEXTHOP) {
+ linux_to_bsd_sockaddr((struct sockaddr *)bsd_args.val,
+ bsd_args.valsize);
+ error = sys_setsockopt(td, &bsd_args);
+ bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.val);
+ } else
+ error = sys_setsockopt(td, &bsd_args);
+
+ return (error);
+}
+
+struct linux_getsockopt_args {
+ int s;
+ int level;
+ int optname;
+ l_uintptr_t optval;
+ l_uintptr_t optlen;
+};
+
+static int
+linux_getsockopt(struct thread *td, struct linux_getsockopt_args *args)
+{
+ struct getsockopt_args /* {
+ int s;
+ int level;
+ int name;
+ caddr_t val;
+ int *avalsize;
+ } */ bsd_args;
+ l_timeval linux_tv;
+ struct timeval tv;
+ socklen_t tv_len, xulen;
+ struct xucred xu;
+ struct l_ucred lxu;
+ int error, name;
+
+ bsd_args.s = args->s;
+ bsd_args.level = linux_to_bsd_sockopt_level(args->level);
+ switch (bsd_args.level) {
+ case SOL_SOCKET:
+ name = linux_to_bsd_so_sockopt(args->optname);
+ switch (name) {
+ case SO_RCVTIMEO:
+ /* FALLTHROUGH */
+ case SO_SNDTIMEO:
+ tv_len = sizeof(tv);
+ error = kern_getsockopt(td, args->s, bsd_args.level,
+ name, &tv, UIO_SYSSPACE, &tv_len);
+ if (error)
+ return (error);
+ linux_tv.tv_sec = tv.tv_sec;
+ linux_tv.tv_usec = tv.tv_usec;
+ return (copyout(&linux_tv, PTRIN(args->optval),
+ sizeof(linux_tv)));
+ /* NOTREACHED */
+ break;
+ case LOCAL_PEERCRED:
+ if (args->optlen != sizeof(lxu))
+ return (EINVAL);
+ xulen = sizeof(xu);
+ error = kern_getsockopt(td, args->s, bsd_args.level,
+ name, &xu, UIO_SYSSPACE, &xulen);
+ if (error)
+ return (error);
+ /*
+ * XXX Use 0 for pid as the FreeBSD does not cache peer pid.
+ */
+ lxu.pid = 0;
+ lxu.uid = xu.cr_uid;
+ lxu.gid = xu.cr_gid;
+ return (copyout(&lxu, PTRIN(args->optval), sizeof(lxu)));
+ /* NOTREACHED */
+ break;
+ default:
+ break;
+ }
+ break;
+ case IPPROTO_IP:
+ name = linux_to_bsd_ip_sockopt(args->optname);
+ break;
+ case IPPROTO_TCP:
+ name = linux_to_bsd_tcp_sockopt(args->optname);
+ break;
+ default:
+ name = -1;
+ break;
+ }
+ if (name == -1)
+ return (EINVAL);
+
+ bsd_args.name = name;
+ bsd_args.val = PTRIN(args->optval);
+ bsd_args.avalsize = PTRIN(args->optlen);
+
+ if (name == IPV6_NEXTHOP) {
+ error = sys_getsockopt(td, &bsd_args);
+ bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.val);
+ } else
+ error = sys_getsockopt(td, &bsd_args);
+
+ return (error);
+}
+
+/* Argument list sizes for linux_socketcall */
+
+#define LINUX_AL(x) ((x) * sizeof(l_ulong))
+
+static const unsigned char lxs_args[] = {
+ LINUX_AL(0) /* unused*/, LINUX_AL(3) /* socket */,
+ LINUX_AL(3) /* bind */, LINUX_AL(3) /* connect */,
+ LINUX_AL(2) /* listen */, LINUX_AL(3) /* accept */,
+ LINUX_AL(3) /* getsockname */, LINUX_AL(3) /* getpeername */,
+ LINUX_AL(4) /* socketpair */, LINUX_AL(4) /* send */,
+ LINUX_AL(4) /* recv */, LINUX_AL(6) /* sendto */,
+ LINUX_AL(6) /* recvfrom */, LINUX_AL(2) /* shutdown */,
+ LINUX_AL(5) /* setsockopt */, LINUX_AL(5) /* getsockopt */,
+ LINUX_AL(3) /* sendmsg */, LINUX_AL(3) /* recvmsg */,
+ LINUX_AL(4) /* accept4 */
+};
+
+#define LINUX_AL_SIZE sizeof(lxs_args) / sizeof(lxs_args[0]) - 1
+
+int
+linux_socketcall(struct thread *td, struct linux_socketcall_args *args)
+{
+ l_ulong a[6];
+ void *arg;
+ int error;
+
+ if (args->what < LINUX_SOCKET || args->what > LINUX_AL_SIZE)
+ return (EINVAL);
+ error = copyin(PTRIN(args->args), a, lxs_args[args->what]);
+ if (error)
+ return (error);
+
+ arg = a;
+ switch (args->what) {
+ case LINUX_SOCKET:
+ return (linux_socket(td, arg));
+ case LINUX_BIND:
+ return (linux_bind(td, arg));
+ case LINUX_CONNECT:
+ return (linux_connect(td, arg));
+ case LINUX_LISTEN:
+ return (linux_listen(td, arg));
+ case LINUX_ACCEPT:
+ return (linux_accept(td, arg));
+ case LINUX_GETSOCKNAME:
+ return (linux_getsockname(td, arg));
+ case LINUX_GETPEERNAME:
+ return (linux_getpeername(td, arg));
+ case LINUX_SOCKETPAIR:
+ return (linux_socketpair(td, arg));
+ case LINUX_SEND:
+ return (linux_send(td, arg));
+ case LINUX_RECV:
+ return (linux_recv(td, arg));
+ case LINUX_SENDTO:
+ return (linux_sendto(td, arg));
+ case LINUX_RECVFROM:
+ return (linux_recvfrom(td, arg));
+ case LINUX_SHUTDOWN:
+ return (linux_shutdown(td, arg));
+ case LINUX_SETSOCKOPT:
+ return (linux_setsockopt(td, arg));
+ case LINUX_GETSOCKOPT:
+ return (linux_getsockopt(td, arg));
+ case LINUX_SENDMSG:
+ return (linux_sendmsg(td, arg));
+ case LINUX_RECVMSG:
+ return (linux_recvmsg(td, arg));
+ case LINUX_ACCEPT4:
+ return (linux_accept4(td, arg));
+ }
+
+ uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what);
+ return (ENOSYS);
+}
diff --git a/sys/compat/linux/linux_socket.h b/sys/compat/linux/linux_socket.h
new file mode 100644
index 0000000..e6efadb
--- /dev/null
+++ b/sys/compat/linux/linux_socket.h
@@ -0,0 +1,159 @@
+/*-
+ * Copyright (c) 2000 Assar Westerlund
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LINUX_SOCKET_H_
+#define _LINUX_SOCKET_H_
+
+/* msg flags in recvfrom/recvmsg */
+
+#define LINUX_MSG_OOB 0x01
+#define LINUX_MSG_PEEK 0x02
+#define LINUX_MSG_DONTROUTE 0x04
+#define LINUX_MSG_CTRUNC 0x08
+#define LINUX_MSG_PROXY 0x10
+#define LINUX_MSG_TRUNC 0x20
+#define LINUX_MSG_DONTWAIT 0x40
+#define LINUX_MSG_EOR 0x80
+#define LINUX_MSG_WAITALL 0x100
+#define LINUX_MSG_FIN 0x200
+#define LINUX_MSG_SYN 0x400
+#define LINUX_MSG_CONFIRM 0x800
+#define LINUX_MSG_RST 0x1000
+#define LINUX_MSG_ERRQUEUE 0x2000
+#define LINUX_MSG_NOSIGNAL 0x4000
+#define LINUX_MSG_CMSG_CLOEXEC 0x40000000
+
+/* Socket-level control message types */
+
+#define LINUX_SCM_RIGHTS 0x01
+#define LINUX_SCM_CREDENTIALS 0x02
+
+/* Ancilliary data object information macros */
+
+#define LINUX_CMSG_ALIGN(len) roundup2(len, sizeof(l_ulong))
+#define LINUX_CMSG_DATA(cmsg) ((void *)((char *)(cmsg) + \
+ LINUX_CMSG_ALIGN(sizeof(struct l_cmsghdr))))
+#define LINUX_CMSG_SPACE(len) (LINUX_CMSG_ALIGN(sizeof(struct l_cmsghdr)) + \
+ LINUX_CMSG_ALIGN(len))
+#define LINUX_CMSG_LEN(len) (LINUX_CMSG_ALIGN(sizeof(struct l_cmsghdr)) + \
+ (len))
+#define LINUX_CMSG_FIRSTHDR(msg) \
+ ((msg)->msg_controllen >= \
+ sizeof(struct l_cmsghdr) ? \
+ (struct l_cmsghdr *) \
+ PTRIN((msg)->msg_control) : \
+ (struct l_cmsghdr *)(NULL))
+#define LINUX_CMSG_NXTHDR(msg, cmsg) \
+ ((((char *)(cmsg) + \
+ LINUX_CMSG_ALIGN((cmsg)->cmsg_len) + \
+ sizeof(*(cmsg))) > \
+ (((char *)PTRIN((msg)->msg_control)) + \
+ (msg)->msg_controllen)) ? \
+ (struct l_cmsghdr *) NULL : \
+ (struct l_cmsghdr *)((char *)(cmsg) + \
+ LINUX_CMSG_ALIGN((cmsg)->cmsg_len)))
+
+#define CMSG_HDRSZ CMSG_LEN(0)
+#define L_CMSG_HDRSZ LINUX_CMSG_LEN(0)
+
+/* Supported address families */
+
+#define LINUX_AF_UNSPEC 0
+#define LINUX_AF_UNIX 1
+#define LINUX_AF_INET 2
+#define LINUX_AF_AX25 3
+#define LINUX_AF_IPX 4
+#define LINUX_AF_APPLETALK 5
+#define LINUX_AF_INET6 10
+
+/* Supported socket types */
+
+#define LINUX_SOCK_STREAM 1
+#define LINUX_SOCK_DGRAM 2
+#define LINUX_SOCK_RAW 3
+#define LINUX_SOCK_RDM 4
+#define LINUX_SOCK_SEQPACKET 5
+
+#define LINUX_SOCK_MAX LINUX_SOCK_SEQPACKET
+
+#define LINUX_SOCK_TYPE_MASK 0xf
+
+/* Flags for socket, socketpair, accept4 */
+
+#define LINUX_SOCK_CLOEXEC LINUX_O_CLOEXEC
+#define LINUX_SOCK_NONBLOCK LINUX_O_NONBLOCK
+
+struct l_ucred {
+ uint32_t pid;
+ uint32_t uid;
+ uint32_t gid;
+};
+
+/* Operations for socketcall */
+
+#define LINUX_SOCKET 1
+#define LINUX_BIND 2
+#define LINUX_CONNECT 3
+#define LINUX_LISTEN 4
+#define LINUX_ACCEPT 5
+#define LINUX_GETSOCKNAME 6
+#define LINUX_GETPEERNAME 7
+#define LINUX_SOCKETPAIR 8
+#define LINUX_SEND 9
+#define LINUX_RECV 10
+#define LINUX_SENDTO 11
+#define LINUX_RECVFROM 12
+#define LINUX_SHUTDOWN 13
+#define LINUX_SETSOCKOPT 14
+#define LINUX_GETSOCKOPT 15
+#define LINUX_SENDMSG 16
+#define LINUX_RECVMSG 17
+#define LINUX_ACCEPT4 18
+
+/* Socket options */
+#define LINUX_IP_TOS 1
+#define LINUX_IP_TTL 2
+#define LINUX_IP_HDRINCL 3
+#define LINUX_IP_OPTIONS 4
+
+#define LINUX_IP_MULTICAST_IF 32
+#define LINUX_IP_MULTICAST_TTL 33
+#define LINUX_IP_MULTICAST_LOOP 34
+#define LINUX_IP_ADD_MEMBERSHIP 35
+#define LINUX_IP_DROP_MEMBERSHIP 36
+
+#define LINUX_TCP_NODELAY 1
+#define LINUX_TCP_MAXSEG 2
+#define LINUX_TCP_KEEPIDLE 4
+#define LINUX_TCP_KEEPINTVL 5
+#define LINUX_TCP_KEEPCNT 6
+#define LINUX_TCP_MD5SIG 14
+
+#endif /* _LINUX_SOCKET_H_ */
diff --git a/sys/compat/linux/linux_stats.c b/sys/compat/linux/linux_stats.c
new file mode 100644
index 0000000..2e05c85
--- /dev/null
+++ b/sys/compat/linux/linux_stats.c
@@ -0,0 +1,627 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_compat.h"
+
+#include <sys/param.h>
+#include <sys/dirent.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/namei.h>
+#include <sys/stat.h>
+#include <sys/syscallsubr.h>
+#include <sys/systm.h>
+#include <sys/tty.h>
+#include <sys/vnode.h>
+#include <sys/conf.h>
+#include <sys/fcntl.h>
+
+#ifdef COMPAT_LINUX32
+#include <machine/../linux32/linux.h>
+#include <machine/../linux32/linux32_proto.h>
+#else
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#endif
+
+#include <compat/linux/linux_util.h>
+#include <compat/linux/linux_file.h>
+
+#define LINUX_SHMFS_MAGIC 0x01021994
+
+static void
+translate_vnhook_major_minor(struct vnode *vp, struct stat *sb)
+{
+ int major, minor;
+
+ if (vp->v_type == VCHR && vp->v_rdev != NULL &&
+ linux_driver_get_major_minor(devtoname(vp->v_rdev),
+ &major, &minor) == 0) {
+ sb->st_rdev = (major << 8 | minor);
+ }
+}
+
+static int
+linux_kern_statat(struct thread *td, int flag, int fd, char *path,
+ enum uio_seg pathseg, struct stat *sbp)
+{
+
+ return (kern_statat_vnhook(td, flag, fd, path, pathseg, sbp,
+ translate_vnhook_major_minor));
+}
+
+static int
+linux_kern_stat(struct thread *td, char *path, enum uio_seg pathseg,
+ struct stat *sbp)
+{
+
+ return (linux_kern_statat(td, 0, AT_FDCWD, path, pathseg, sbp));
+}
+
+static int
+linux_kern_lstat(struct thread *td, char *path, enum uio_seg pathseg,
+ struct stat *sbp)
+{
+
+ return (linux_kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, path,
+ pathseg, sbp));
+}
+
+/*
+ * XXX: This was removed from newstat_copyout(), and almost identical
+ * XXX: code was in stat64_copyout(). findcdev() needs to be replaced
+ * XXX: with something that does lookup and locking properly.
+ * XXX: When somebody fixes this: please try to avoid duplicating it.
+ */
+#if 0
+static void
+disk_foo(struct somestat *tbuf)
+{
+ struct cdevsw *cdevsw;
+ struct cdev *dev;
+
+ /* Lie about disk drives which are character devices
+ * in FreeBSD but block devices under Linux.
+ */
+ if (S_ISCHR(tbuf.st_mode) &&
+ (dev = findcdev(buf->st_rdev)) != NULL) {
+ cdevsw = dev_refthread(dev);
+ if (cdevsw != NULL) {
+ if (cdevsw->d_flags & D_DISK) {
+ tbuf.st_mode &= ~S_IFMT;
+ tbuf.st_mode |= S_IFBLK;
+
+ /* XXX this may not be quite right */
+ /* Map major number to 0 */
+ tbuf.st_dev = minor(buf->st_dev) & 0xf;
+ tbuf.st_rdev = buf->st_rdev & 0xff;
+ }
+ dev_relthread(dev);
+ }
+ }
+
+}
+#endif
+
+static void
+translate_fd_major_minor(struct thread *td, int fd, struct stat *buf)
+{
+ struct file *fp;
+ struct vnode *vp;
+ int major, minor;
+
+ /*
+ * No capability rights required here.
+ */
+ if ((!S_ISCHR(buf->st_mode) && !S_ISBLK(buf->st_mode)) ||
+ fget(td, fd, 0, &fp) != 0)
+ return;
+ vp = fp->f_vnode;
+ if (vp != NULL && vp->v_rdev != NULL &&
+ linux_driver_get_major_minor(devtoname(vp->v_rdev),
+ &major, &minor) == 0) {
+ buf->st_rdev = (major << 8 | minor);
+ } else if (fp->f_type == DTYPE_PTS) {
+ struct tty *tp = fp->f_data;
+
+ /* Convert the numbers for the slave device. */
+ if (linux_driver_get_major_minor(devtoname(tp->t_dev),
+ &major, &minor) == 0) {
+ buf->st_rdev = (major << 8 | minor);
+ }
+ }
+ fdrop(fp, td);
+}
+
+static int
+newstat_copyout(struct stat *buf, void *ubuf)
+{
+ struct l_newstat tbuf;
+
+ bzero(&tbuf, sizeof(tbuf));
+ tbuf.st_dev = minor(buf->st_dev) | (major(buf->st_dev) << 8);
+ tbuf.st_ino = buf->st_ino;
+ tbuf.st_mode = buf->st_mode;
+ tbuf.st_nlink = buf->st_nlink;
+ tbuf.st_uid = buf->st_uid;
+ tbuf.st_gid = buf->st_gid;
+ tbuf.st_rdev = buf->st_rdev;
+ tbuf.st_size = buf->st_size;
+ tbuf.st_atim.tv_sec = buf->st_atim.tv_sec;
+ tbuf.st_atim.tv_nsec = buf->st_atim.tv_nsec;
+ tbuf.st_mtim.tv_sec = buf->st_mtim.tv_sec;
+ tbuf.st_mtim.tv_nsec = buf->st_mtim.tv_nsec;
+ tbuf.st_ctim.tv_sec = buf->st_ctim.tv_sec;
+ tbuf.st_ctim.tv_nsec = buf->st_ctim.tv_nsec;
+ tbuf.st_blksize = buf->st_blksize;
+ tbuf.st_blocks = buf->st_blocks;
+
+ return (copyout(&tbuf, ubuf, sizeof(tbuf)));
+}
+
+int
+linux_newstat(struct thread *td, struct linux_newstat_args *args)
+{
+ struct stat buf;
+ char *path;
+ int error;
+
+ LCONVPATHEXIST(td, args->path, &path);
+
+#ifdef DEBUG
+ if (ldebug(newstat))
+ printf(ARGS(newstat, "%s, *"), path);
+#endif
+
+ error = linux_kern_stat(td, path, UIO_SYSSPACE, &buf);
+ LFREEPATH(path);
+ if (error)
+ return (error);
+ return (newstat_copyout(&buf, args->buf));
+}
+
+int
+linux_newlstat(struct thread *td, struct linux_newlstat_args *args)
+{
+ struct stat sb;
+ char *path;
+ int error;
+
+ LCONVPATHEXIST(td, args->path, &path);
+
+#ifdef DEBUG
+ if (ldebug(newlstat))
+ printf(ARGS(newlstat, "%s, *"), path);
+#endif
+
+ error = linux_kern_lstat(td, path, UIO_SYSSPACE, &sb);
+ LFREEPATH(path);
+ if (error)
+ return (error);
+ return (newstat_copyout(&sb, args->buf));
+}
+
+int
+linux_newfstat(struct thread *td, struct linux_newfstat_args *args)
+{
+ struct stat buf;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(newfstat))
+ printf(ARGS(newfstat, "%d, *"), args->fd);
+#endif
+
+ error = kern_fstat(td, args->fd, &buf);
+ translate_fd_major_minor(td, args->fd, &buf);
+ if (!error)
+ error = newstat_copyout(&buf, args->buf);
+
+ return (error);
+}
+
+static int
+stat_copyout(struct stat *buf, void *ubuf)
+{
+ struct l_stat lbuf;
+
+ bzero(&lbuf, sizeof(lbuf));
+ lbuf.st_dev = buf->st_dev;
+ lbuf.st_ino = buf->st_ino;
+ lbuf.st_mode = buf->st_mode;
+ lbuf.st_nlink = buf->st_nlink;
+ lbuf.st_uid = buf->st_uid;
+ lbuf.st_gid = buf->st_gid;
+ lbuf.st_rdev = buf->st_rdev;
+ if (buf->st_size < (quad_t)1 << 32)
+ lbuf.st_size = buf->st_size;
+ else
+ lbuf.st_size = -2;
+ lbuf.st_atim.tv_sec = buf->st_atim.tv_sec;
+ lbuf.st_atim.tv_nsec = buf->st_atim.tv_nsec;
+ lbuf.st_mtim.tv_sec = buf->st_mtim.tv_sec;
+ lbuf.st_mtim.tv_nsec = buf->st_mtim.tv_nsec;
+ lbuf.st_ctim.tv_sec = buf->st_ctim.tv_sec;
+ lbuf.st_ctim.tv_nsec = buf->st_ctim.tv_nsec;
+ lbuf.st_blksize = buf->st_blksize;
+ lbuf.st_blocks = buf->st_blocks;
+ lbuf.st_flags = buf->st_flags;
+ lbuf.st_gen = buf->st_gen;
+
+ return (copyout(&lbuf, ubuf, sizeof(lbuf)));
+}
+
+int
+linux_stat(struct thread *td, struct linux_stat_args *args)
+{
+ struct stat buf;
+ char *path;
+ int error;
+
+ LCONVPATHEXIST(td, args->path, &path);
+
+#ifdef DEBUG
+ if (ldebug(stat))
+ printf(ARGS(stat, "%s, *"), path);
+#endif
+ error = linux_kern_stat(td, path, UIO_SYSSPACE, &buf);
+ if (error) {
+ LFREEPATH(path);
+ return (error);
+ }
+ LFREEPATH(path);
+ return(stat_copyout(&buf, args->up));
+}
+
+int
+linux_lstat(struct thread *td, struct linux_lstat_args *args)
+{
+ struct stat buf;
+ char *path;
+ int error;
+
+ LCONVPATHEXIST(td, args->path, &path);
+
+#ifdef DEBUG
+ if (ldebug(lstat))
+ printf(ARGS(lstat, "%s, *"), path);
+#endif
+ error = linux_kern_lstat(td, path, UIO_SYSSPACE, &buf);
+ if (error) {
+ LFREEPATH(path);
+ return (error);
+ }
+ LFREEPATH(path);
+ return(stat_copyout(&buf, args->up));
+}
+
+/* XXX - All fields of type l_int are defined as l_long on i386 */
+struct l_statfs {
+ l_int f_type;
+ l_int f_bsize;
+ l_int f_blocks;
+ l_int f_bfree;
+ l_int f_bavail;
+ l_int f_files;
+ l_int f_ffree;
+ l_fsid_t f_fsid;
+ l_int f_namelen;
+ l_int f_spare[6];
+};
+
+#define LINUX_CODA_SUPER_MAGIC 0x73757245L
+#define LINUX_EXT2_SUPER_MAGIC 0xEF53L
+#define LINUX_HPFS_SUPER_MAGIC 0xf995e849L
+#define LINUX_ISOFS_SUPER_MAGIC 0x9660L
+#define LINUX_MSDOS_SUPER_MAGIC 0x4d44L
+#define LINUX_NCP_SUPER_MAGIC 0x564cL
+#define LINUX_NFS_SUPER_MAGIC 0x6969L
+#define LINUX_NTFS_SUPER_MAGIC 0x5346544EL
+#define LINUX_PROC_SUPER_MAGIC 0x9fa0L
+#define LINUX_UFS_SUPER_MAGIC 0x00011954L /* XXX - UFS_MAGIC in Linux */
+#define LINUX_DEVFS_SUPER_MAGIC 0x1373L
+
+static long
+bsd_to_linux_ftype(const char *fstypename)
+{
+ int i;
+ static struct {const char *bsd_name; long linux_type;} b2l_tbl[] = {
+ {"ufs", LINUX_UFS_SUPER_MAGIC},
+ {"cd9660", LINUX_ISOFS_SUPER_MAGIC},
+ {"nfs", LINUX_NFS_SUPER_MAGIC},
+ {"ext2fs", LINUX_EXT2_SUPER_MAGIC},
+ {"procfs", LINUX_PROC_SUPER_MAGIC},
+ {"msdosfs", LINUX_MSDOS_SUPER_MAGIC},
+ {"ntfs", LINUX_NTFS_SUPER_MAGIC},
+ {"nwfs", LINUX_NCP_SUPER_MAGIC},
+ {"hpfs", LINUX_HPFS_SUPER_MAGIC},
+ {"coda", LINUX_CODA_SUPER_MAGIC},
+ {"devfs", LINUX_DEVFS_SUPER_MAGIC},
+ {NULL, 0L}};
+
+ for (i = 0; b2l_tbl[i].bsd_name != NULL; i++)
+ if (strcmp(b2l_tbl[i].bsd_name, fstypename) == 0)
+ return (b2l_tbl[i].linux_type);
+
+ return (0L);
+}
+
+static void
+bsd_to_linux_statfs(struct statfs *bsd_statfs, struct l_statfs *linux_statfs)
+{
+
+ linux_statfs->f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename);
+ linux_statfs->f_bsize = bsd_statfs->f_bsize;
+ linux_statfs->f_blocks = bsd_statfs->f_blocks;
+ linux_statfs->f_bfree = bsd_statfs->f_bfree;
+ linux_statfs->f_bavail = bsd_statfs->f_bavail;
+ linux_statfs->f_ffree = bsd_statfs->f_ffree;
+ linux_statfs->f_files = bsd_statfs->f_files;
+ linux_statfs->f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
+ linux_statfs->f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
+ linux_statfs->f_namelen = MAXNAMLEN;
+}
+
+int
+linux_statfs(struct thread *td, struct linux_statfs_args *args)
+{
+ struct l_statfs linux_statfs;
+ struct statfs bsd_statfs;
+ char *path;
+ int error, dev_shm;
+
+ LCONVPATHEXIST(td, args->path, &path);
+
+#ifdef DEBUG
+ if (ldebug(statfs))
+ printf(ARGS(statfs, "%s, *"), path);
+#endif
+ dev_shm = 0;
+ error = kern_statfs(td, path, UIO_SYSSPACE, &bsd_statfs);
+ if (strncmp(path, "/dev/shm", sizeof("/dev/shm") - 1) == 0)
+ dev_shm = (path[8] == '\0'
+ || (path[8] == '/' && path[9] == '\0'));
+ LFREEPATH(path);
+ if (error)
+ return (error);
+ bsd_to_linux_statfs(&bsd_statfs, &linux_statfs);
+ if (dev_shm)
+ linux_statfs.f_type = LINUX_SHMFS_MAGIC;
+ return copyout(&linux_statfs, args->buf, sizeof(linux_statfs));
+}
+
+static void
+bsd_to_linux_statfs64(struct statfs *bsd_statfs, struct l_statfs64 *linux_statfs)
+{
+
+ linux_statfs->f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename);
+ linux_statfs->f_bsize = bsd_statfs->f_bsize;
+ linux_statfs->f_blocks = bsd_statfs->f_blocks;
+ linux_statfs->f_bfree = bsd_statfs->f_bfree;
+ linux_statfs->f_bavail = bsd_statfs->f_bavail;
+ linux_statfs->f_ffree = bsd_statfs->f_ffree;
+ linux_statfs->f_files = bsd_statfs->f_files;
+ linux_statfs->f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
+ linux_statfs->f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
+ linux_statfs->f_namelen = MAXNAMLEN;
+}
+
+int
+linux_statfs64(struct thread *td, struct linux_statfs64_args *args)
+{
+ struct l_statfs64 linux_statfs;
+ struct statfs bsd_statfs;
+ char *path;
+ int error;
+
+ if (args->bufsize != sizeof(struct l_statfs64))
+ return EINVAL;
+
+ LCONVPATHEXIST(td, args->path, &path);
+
+#ifdef DEBUG
+ if (ldebug(statfs64))
+ printf(ARGS(statfs64, "%s, *"), path);
+#endif
+ error = kern_statfs(td, path, UIO_SYSSPACE, &bsd_statfs);
+ LFREEPATH(path);
+ if (error)
+ return (error);
+ bsd_to_linux_statfs64(&bsd_statfs, &linux_statfs);
+ return copyout(&linux_statfs, args->buf, sizeof(linux_statfs));
+}
+
+int
+linux_fstatfs(struct thread *td, struct linux_fstatfs_args *args)
+{
+ struct l_statfs linux_statfs;
+ struct statfs bsd_statfs;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(fstatfs))
+ printf(ARGS(fstatfs, "%d, *"), args->fd);
+#endif
+ error = kern_fstatfs(td, args->fd, &bsd_statfs);
+ if (error)
+ return error;
+ bsd_to_linux_statfs(&bsd_statfs, &linux_statfs);
+ return copyout(&linux_statfs, args->buf, sizeof(linux_statfs));
+}
+
+struct l_ustat
+{
+ l_daddr_t f_tfree;
+ l_ino_t f_tinode;
+ char f_fname[6];
+ char f_fpack[6];
+};
+
+int
+linux_ustat(struct thread *td, struct linux_ustat_args *args)
+{
+#ifdef DEBUG
+ if (ldebug(ustat))
+ printf(ARGS(ustat, "%d, *"), args->dev);
+#endif
+
+ return (EOPNOTSUPP);
+}
+
+#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
+
+static int
+stat64_copyout(struct stat *buf, void *ubuf)
+{
+ struct l_stat64 lbuf;
+
+ bzero(&lbuf, sizeof(lbuf));
+ lbuf.st_dev = minor(buf->st_dev) | (major(buf->st_dev) << 8);
+ lbuf.st_ino = buf->st_ino;
+ lbuf.st_mode = buf->st_mode;
+ lbuf.st_nlink = buf->st_nlink;
+ lbuf.st_uid = buf->st_uid;
+ lbuf.st_gid = buf->st_gid;
+ lbuf.st_rdev = buf->st_rdev;
+ lbuf.st_size = buf->st_size;
+ lbuf.st_atim.tv_sec = buf->st_atim.tv_sec;
+ lbuf.st_atim.tv_nsec = buf->st_atim.tv_nsec;
+ lbuf.st_mtim.tv_sec = buf->st_mtim.tv_sec;
+ lbuf.st_mtim.tv_nsec = buf->st_mtim.tv_nsec;
+ lbuf.st_ctim.tv_sec = buf->st_ctim.tv_sec;
+ lbuf.st_ctim.tv_nsec = buf->st_ctim.tv_nsec;
+ lbuf.st_blksize = buf->st_blksize;
+ lbuf.st_blocks = buf->st_blocks;
+
+ /*
+ * The __st_ino field makes all the difference. In the Linux kernel
+ * it is conditionally compiled based on STAT64_HAS_BROKEN_ST_INO,
+ * but without the assignment to __st_ino the runtime linker refuses
+ * to mmap(2) any shared libraries. I guess it's broken alright :-)
+ */
+ lbuf.__st_ino = buf->st_ino;
+
+ return (copyout(&lbuf, ubuf, sizeof(lbuf)));
+}
+
+int
+linux_stat64(struct thread *td, struct linux_stat64_args *args)
+{
+ struct stat buf;
+ char *filename;
+ int error;
+
+ LCONVPATHEXIST(td, args->filename, &filename);
+
+#ifdef DEBUG
+ if (ldebug(stat64))
+ printf(ARGS(stat64, "%s, *"), filename);
+#endif
+
+ error = linux_kern_stat(td, filename, UIO_SYSSPACE, &buf);
+ LFREEPATH(filename);
+ if (error)
+ return (error);
+ return (stat64_copyout(&buf, args->statbuf));
+}
+
+int
+linux_lstat64(struct thread *td, struct linux_lstat64_args *args)
+{
+ struct stat sb;
+ char *filename;
+ int error;
+
+ LCONVPATHEXIST(td, args->filename, &filename);
+
+#ifdef DEBUG
+ if (ldebug(lstat64))
+ printf(ARGS(lstat64, "%s, *"), args->filename);
+#endif
+
+ error = linux_kern_lstat(td, filename, UIO_SYSSPACE, &sb);
+ LFREEPATH(filename);
+ if (error)
+ return (error);
+ return (stat64_copyout(&sb, args->statbuf));
+}
+
+int
+linux_fstat64(struct thread *td, struct linux_fstat64_args *args)
+{
+ struct stat buf;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(fstat64))
+ printf(ARGS(fstat64, "%d, *"), args->fd);
+#endif
+
+ error = kern_fstat(td, args->fd, &buf);
+ translate_fd_major_minor(td, args->fd, &buf);
+ if (!error)
+ error = stat64_copyout(&buf, args->statbuf);
+
+ return (error);
+}
+
+int
+linux_fstatat64(struct thread *td, struct linux_fstatat64_args *args)
+{
+ char *path;
+ int error, dfd, flag;
+ struct stat buf;
+
+ if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW)
+ return (EINVAL);
+ flag = (args->flag & LINUX_AT_SYMLINK_NOFOLLOW) ?
+ AT_SYMLINK_NOFOLLOW : 0;
+
+ dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
+ LCONVPATHEXIST_AT(td, args->pathname, &path, dfd);
+
+#ifdef DEBUG
+ if (ldebug(fstatat64))
+ printf(ARGS(fstatat64, "%i, %s, %i"), args->dfd, path, args->flag);
+#endif
+
+ error = linux_kern_statat(td, flag, dfd, path, UIO_SYSSPACE, &buf);
+ if (!error)
+ error = stat64_copyout(&buf, args->statbuf);
+ LFREEPATH(path);
+
+ return (error);
+}
+
+#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
diff --git a/sys/compat/linux/linux_sysctl.c b/sys/compat/linux/linux_sysctl.c
new file mode 100644
index 0000000..decd8f8
--- /dev/null
+++ b/sys/compat/linux/linux_sysctl.c
@@ -0,0 +1,194 @@
+/*-
+ * Copyright (c) 2001 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_compat.h"
+#include "opt_kdtrace.h"
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/sdt.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <sys/sbuf.h>
+
+#ifdef COMPAT_LINUX32
+#include <machine/../linux32/linux.h>
+#include <machine/../linux32/linux32_proto.h>
+#else
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#endif
+
+#include <compat/linux/linux_dtrace.h>
+#include <compat/linux/linux_misc.h>
+#include <compat/linux/linux_util.h>
+
+#define LINUX_CTL_KERN 1
+#define LINUX_CTL_VM 2
+#define LINUX_CTL_NET 3
+#define LINUX_CTL_PROC 4
+#define LINUX_CTL_FS 5
+#define LINUX_CTL_DEBUG 6
+#define LINUX_CTL_DEV 7
+#define LINUX_CTL_BUS 8
+
+/* CTL_KERN names */
+#define LINUX_KERN_OSTYPE 1
+#define LINUX_KERN_OSRELEASE 2
+#define LINUX_KERN_OSREV 3
+#define LINUX_KERN_VERSION 4
+
+/* DTrace init */
+LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
+
+/**
+ * DTrace probes in this module.
+ */
+LIN_SDT_PROBE_DEFINE2(sysctl, handle_string, entry, "struct l___sysctl_args *",
+ "char *");
+LIN_SDT_PROBE_DEFINE1(sysctl, handle_string, copyout_error, "int");
+LIN_SDT_PROBE_DEFINE1(sysctl, handle_string, return, "int");
+LIN_SDT_PROBE_DEFINE2(sysctl, linux_sysctl, entry, "struct l___sysctl_args *",
+ "struct thread *");
+LIN_SDT_PROBE_DEFINE1(sysctl, linux_sysctl, copyin_error, "int");
+LIN_SDT_PROBE_DEFINE2(sysctl, linux_sysctl, wrong_length, "int", "int");
+LIN_SDT_PROBE_DEFINE1(sysctl, linux_sysctl, unsupported_sysctl, "char *");
+LIN_SDT_PROBE_DEFINE1(sysctl, linux_sysctl, return, "int");
+
+static int
+handle_string(struct l___sysctl_args *la, char *value)
+{
+ int error;
+
+ LIN_SDT_PROBE2(sysctl, handle_string, entry, la, value);
+
+ if (la->oldval != 0) {
+ l_int len = strlen(value);
+ error = copyout(value, PTRIN(la->oldval), len + 1);
+ if (!error && la->oldlenp != 0)
+ error = copyout(&len, PTRIN(la->oldlenp), sizeof(len));
+ if (error) {
+ LIN_SDT_PROBE1(sysctl, handle_string, copyout_error,
+ error);
+ LIN_SDT_PROBE1(sysctl, handle_string, return, error);
+ return (error);
+ }
+ }
+
+ if (la->newval != 0) {
+ LIN_SDT_PROBE1(sysctl, handle_string, return, ENOTDIR);
+ return (ENOTDIR);
+ }
+
+ LIN_SDT_PROBE1(sysctl, handle_string, return, 0);
+ return (0);
+}
+
+int
+linux_sysctl(struct thread *td, struct linux_sysctl_args *args)
+{
+ struct l___sysctl_args la;
+ struct sbuf *sb;
+ l_int *mib;
+ char *sysctl_string;
+ int error, i;
+
+ LIN_SDT_PROBE2(sysctl, linux_sysctl, entry, td, args->args);
+
+ error = copyin(args->args, &la, sizeof(la));
+ if (error) {
+ LIN_SDT_PROBE1(sysctl, linux_sysctl, copyin_error, error);
+ LIN_SDT_PROBE1(sysctl, linux_sysctl, return, error);
+ return (error);
+ }
+
+ if (la.nlen <= 0 || la.nlen > LINUX_CTL_MAXNAME) {
+ LIN_SDT_PROBE2(sysctl, linux_sysctl, wrong_length, la.nlen,
+ LINUX_CTL_MAXNAME);
+ LIN_SDT_PROBE1(sysctl, linux_sysctl, return, ENOTDIR);
+ return (ENOTDIR);
+ }
+
+ mib = malloc(la.nlen * sizeof(l_int), M_TEMP, M_WAITOK);
+ error = copyin(PTRIN(la.name), mib, la.nlen * sizeof(l_int));
+ if (error) {
+ LIN_SDT_PROBE1(sysctl, linux_sysctl, copyin_error, error);
+ LIN_SDT_PROBE1(sysctl, linux_sysctl, return, error);
+ free(mib, M_TEMP);
+ return (error);
+ }
+
+ switch (mib[0]) {
+ case LINUX_CTL_KERN:
+ if (la.nlen < 2)
+ break;
+
+ switch (mib[1]) {
+ case LINUX_KERN_VERSION:
+ error = handle_string(&la, version);
+ free(mib, M_TEMP);
+ LIN_SDT_PROBE1(sysctl, linux_sysctl, return, error);
+ return (error);
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ sb = sbuf_new(NULL, NULL, 20 + la.nlen * 5, SBUF_AUTOEXTEND);
+ if (sb == NULL) {
+ linux_msg(td, "sysctl is not implemented");
+ LIN_SDT_PROBE1(sysctl, linux_sysctl, unsupported_sysctl,
+ "unknown sysctl, ENOMEM during lookup");
+ } else {
+ sbuf_printf(sb, "sysctl ");
+ for (i = 0; i < la.nlen; i++)
+ sbuf_printf(sb, "%c%d", (i) ? ',' : '{', mib[i]);
+ sbuf_printf(sb, "} is not implemented");
+ sbuf_finish(sb);
+ sysctl_string = sbuf_data(sb);
+ linux_msg(td, "%s", sbuf_data(sb));
+ LIN_SDT_PROBE1(sysctl, linux_sysctl, unsupported_sysctl,
+ sysctl_string);
+ sbuf_delete(sb);
+ }
+
+ free(mib, M_TEMP);
+
+ LIN_SDT_PROBE1(sysctl, linux_sysctl, return, ENOTDIR);
+ return (ENOTDIR);
+}
diff --git a/sys/compat/linux/linux_sysproto.h b/sys/compat/linux/linux_sysproto.h
new file mode 100644
index 0000000..69f1577
--- /dev/null
+++ b/sys/compat/linux/linux_sysproto.h
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2005 Travis Poppe
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef LINUX_SYSPROTO
+#define LINUX_SYSPROTO
+
+int linux_nosys(struct thread *, struct nosys_args *);
+
+#endif
diff --git a/sys/compat/linux/linux_time.c b/sys/compat/linux/linux_time.c
new file mode 100644
index 0000000..e03af00
--- /dev/null
+++ b/sys/compat/linux/linux_time.c
@@ -0,0 +1,417 @@
+/* $NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp $ */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Emmanuel Dreyfus.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#if 0
+__KERNEL_RCSID(0, "$NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp $");
+#endif
+
+#include "opt_compat.h"
+#include "opt_kdtrace.h"
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/ucred.h>
+#include <sys/mount.h>
+#include <sys/sdt.h>
+#include <sys/signal.h>
+#include <sys/stdint.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysproto.h>
+#include <sys/time.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+
+#ifdef COMPAT_LINUX32
+#include <machine/../linux32/linux.h>
+#include <machine/../linux32/linux32_proto.h>
+#else
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#endif
+
+#include <compat/linux/linux_dtrace.h>
+#include <compat/linux/linux_misc.h>
+
+/* DTrace init */
+LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
+
+/**
+ * DTrace probes in this module.
+ */
+LIN_SDT_PROBE_DEFINE2(time, native_to_linux_timespec, entry,
+ "struct l_timespec *", "struct timespec *");
+LIN_SDT_PROBE_DEFINE0(time, native_to_linux_timespec, return);
+LIN_SDT_PROBE_DEFINE2(time, linux_to_native_timespec, entry,
+ "struct timespec *", "struct l_timespec *");
+LIN_SDT_PROBE_DEFINE1(time, linux_to_native_timespec, return, "int");
+LIN_SDT_PROBE_DEFINE2(time, linux_to_native_clockid, entry, "clockid_t *",
+ "clockid_t");
+LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unsupported_clockid,
+ "clockid_t");
+LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unknown_clockid,
+ "clockid_t");
+LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, return, "int");
+LIN_SDT_PROBE_DEFINE2(time, linux_clock_gettime, entry, "clockid_t",
+ "struct l_timespec *");
+LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, conversion_error, "int");
+LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, gettime_error, "int");
+LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, copyout_error, "int");
+LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, return, "int");
+LIN_SDT_PROBE_DEFINE2(time, linux_clock_settime, entry, "clockid_t",
+ "struct l_timespec *");
+LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, conversion_error, "int");
+LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, settime_error, "int");
+LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, copyin_error, "int");
+LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, return, "int");
+LIN_SDT_PROBE_DEFINE2(time, linux_clock_getres, entry, "clockid_t",
+ "struct l_timespec *");
+LIN_SDT_PROBE_DEFINE0(time, linux_clock_getres, nullcall);
+LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, conversion_error, "int");
+LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, getres_error, "int");
+LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, copyout_error, "int");
+LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, return, "int");
+LIN_SDT_PROBE_DEFINE2(time, linux_nanosleep, entry, "const struct l_timespec *",
+ "struct l_timespec *");
+LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, conversion_error, "int");
+LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, nanosleep_error, "int");
+LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyout_error, "int");
+LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyin_error, "int");
+LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, return, "int");
+LIN_SDT_PROBE_DEFINE4(time, linux_clock_nanosleep, entry, "clockid_t", "int",
+ "struct l_timespec *", "struct l_timespec *");
+LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, conversion_error, "int");
+LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, nanosleep_error, "int");
+LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyout_error, "int");
+LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyin_error, "int");
+LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_flags, "int");
+LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_clockid, "int");
+LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, return, "int");
+
+static void native_to_linux_timespec(struct l_timespec *,
+ struct timespec *);
+static int linux_to_native_timespec(struct timespec *,
+ struct l_timespec *);
+static int linux_to_native_clockid(clockid_t *, clockid_t);
+
+static void
+native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp)
+{
+
+ LIN_SDT_PROBE2(time, native_to_linux_timespec, entry, ltp, ntp);
+
+ ltp->tv_sec = ntp->tv_sec;
+ ltp->tv_nsec = ntp->tv_nsec;
+
+ LIN_SDT_PROBE0(time, native_to_linux_timespec, return);
+}
+
+static int
+linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp)
+{
+
+ LIN_SDT_PROBE2(time, linux_to_native_timespec, entry, ntp, ltp);
+
+ if (ltp->tv_sec < 0 || ltp->tv_nsec > (l_long)999999999L) {
+ LIN_SDT_PROBE1(time, linux_to_native_timespec, return, EINVAL);
+ return (EINVAL);
+ }
+ ntp->tv_sec = ltp->tv_sec;
+ ntp->tv_nsec = ltp->tv_nsec;
+
+ LIN_SDT_PROBE1(time, linux_to_native_timespec, return, 0);
+ return (0);
+}
+
+static int
+linux_to_native_clockid(clockid_t *n, clockid_t l)
+{
+
+ LIN_SDT_PROBE2(time, linux_to_native_clockid, entry, n, l);
+
+ switch (l) {
+ case LINUX_CLOCK_REALTIME:
+ *n = CLOCK_REALTIME;
+ break;
+ case LINUX_CLOCK_MONOTONIC:
+ *n = CLOCK_MONOTONIC;
+ break;
+ case LINUX_CLOCK_PROCESS_CPUTIME_ID:
+ case LINUX_CLOCK_THREAD_CPUTIME_ID:
+ case LINUX_CLOCK_REALTIME_HR:
+ case LINUX_CLOCK_MONOTONIC_HR:
+ LIN_SDT_PROBE1(time, linux_to_native_clockid,
+ unsupported_clockid, l);
+ LIN_SDT_PROBE1(time, linux_to_native_clockid, return, EINVAL);
+ return (EINVAL);
+ break;
+ default:
+ LIN_SDT_PROBE1(time, linux_to_native_clockid,
+ unknown_clockid, l);
+ LIN_SDT_PROBE1(time, linux_to_native_clockid, return, EINVAL);
+ return (EINVAL);
+ break;
+ }
+
+ LIN_SDT_PROBE1(time, linux_to_native_clockid, return, 0);
+ return (0);
+}
+
+int
+linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args)
+{
+ struct l_timespec lts;
+ int error;
+ clockid_t nwhich = 0; /* XXX: GCC */
+ struct timespec tp;
+
+ LIN_SDT_PROBE2(time, linux_clock_gettime, entry, args->which, args->tp);
+
+ error = linux_to_native_clockid(&nwhich, args->which);
+ if (error != 0) {
+ LIN_SDT_PROBE1(time, linux_clock_gettime, conversion_error,
+ error);
+ LIN_SDT_PROBE1(time, linux_clock_gettime, return, error);
+ return (error);
+ }
+ error = kern_clock_gettime(td, nwhich, &tp);
+ if (error != 0) {
+ LIN_SDT_PROBE1(time, linux_clock_gettime, gettime_error, error);
+ LIN_SDT_PROBE1(time, linux_clock_gettime, return, error);
+ return (error);
+ }
+ native_to_linux_timespec(&lts, &tp);
+
+ error = copyout(&lts, args->tp, sizeof lts);
+ if (error != 0)
+ LIN_SDT_PROBE1(time, linux_clock_gettime, copyout_error, error);
+
+ LIN_SDT_PROBE1(time, linux_clock_gettime, return, error);
+ return (error);
+}
+
+int
+linux_clock_settime(struct thread *td, struct linux_clock_settime_args *args)
+{
+ struct timespec ts;
+ struct l_timespec lts;
+ int error;
+ clockid_t nwhich = 0; /* XXX: GCC */
+
+ LIN_SDT_PROBE2(time, linux_clock_settime, entry, args->which, args->tp);
+
+ error = linux_to_native_clockid(&nwhich, args->which);
+ if (error != 0) {
+ LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error,
+ error);
+ LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
+ return (error);
+ }
+ error = copyin(args->tp, &lts, sizeof lts);
+ if (error != 0) {
+ LIN_SDT_PROBE1(time, linux_clock_settime, copyin_error, error);
+ LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
+ return (error);
+ }
+ error = linux_to_native_timespec(&ts, &lts);
+ if (error != 0) {
+ LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error,
+ error);
+ LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
+ return (error);
+ }
+
+ error = kern_clock_settime(td, nwhich, &ts);
+ if (error != 0)
+ LIN_SDT_PROBE1(time, linux_clock_settime, settime_error, error);
+
+ LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
+ return (error);
+}
+
+int
+linux_clock_getres(struct thread *td, struct linux_clock_getres_args *args)
+{
+ struct timespec ts;
+ struct l_timespec lts;
+ int error;
+ clockid_t nwhich = 0; /* XXX: GCC */
+
+ LIN_SDT_PROBE2(time, linux_clock_getres, entry, args->which, args->tp);
+
+ if (args->tp == NULL) {
+ LIN_SDT_PROBE0(time, linux_clock_getres, nullcall);
+ LIN_SDT_PROBE1(time, linux_clock_getres, return, 0);
+ return (0);
+ }
+
+ error = linux_to_native_clockid(&nwhich, args->which);
+ if (error != 0) {
+ LIN_SDT_PROBE1(time, linux_clock_getres, conversion_error,
+ error);
+ LIN_SDT_PROBE1(time, linux_clock_getres, return, error);
+ return (error);
+ }
+ error = kern_clock_getres(td, nwhich, &ts);
+ if (error != 0) {
+ LIN_SDT_PROBE1(time, linux_clock_getres, getres_error, error);
+ LIN_SDT_PROBE1(time, linux_clock_getres, return, error);
+ return (error);
+ }
+ native_to_linux_timespec(&lts, &ts);
+
+ error = copyout(&lts, args->tp, sizeof lts);
+ if (error != 0)
+ LIN_SDT_PROBE1(time, linux_clock_getres, copyout_error, error);
+
+ LIN_SDT_PROBE1(time, linux_clock_getres, return, error);
+ return (error);
+}
+
+int
+linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args)
+{
+ struct timespec *rmtp;
+ struct l_timespec lrqts, lrmts;
+ struct timespec rqts, rmts;
+ int error;
+
+ LIN_SDT_PROBE2(time, linux_nanosleep, entry, args->rqtp, args->rmtp);
+
+ error = copyin(args->rqtp, &lrqts, sizeof lrqts);
+ if (error != 0) {
+ LIN_SDT_PROBE1(time, linux_nanosleep, copyin_error, error);
+ LIN_SDT_PROBE1(time, linux_nanosleep, return, error);
+ return (error);
+ }
+
+ if (args->rmtp != NULL)
+ rmtp = &rmts;
+ else
+ rmtp = NULL;
+
+ error = linux_to_native_timespec(&rqts, &lrqts);
+ if (error != 0) {
+ LIN_SDT_PROBE1(time, linux_nanosleep, conversion_error, error);
+ LIN_SDT_PROBE1(time, linux_nanosleep, return, error);
+ return (error);
+ }
+ error = kern_nanosleep(td, &rqts, rmtp);
+ if (error != 0) {
+ LIN_SDT_PROBE1(time, linux_nanosleep, nanosleep_error, error);
+ LIN_SDT_PROBE1(time, linux_nanosleep, return, error);
+ return (error);
+ }
+
+ if (args->rmtp != NULL) {
+ native_to_linux_timespec(&lrmts, rmtp);
+ error = copyout(&lrmts, args->rmtp, sizeof(lrmts));
+ if (error != 0) {
+ LIN_SDT_PROBE1(time, linux_nanosleep, copyout_error,
+ error);
+ LIN_SDT_PROBE1(time, linux_nanosleep, return, error);
+ return (error);
+ }
+ }
+
+ LIN_SDT_PROBE1(time, linux_nanosleep, return, 0);
+ return (0);
+}
+
+int
+linux_clock_nanosleep(struct thread *td, struct linux_clock_nanosleep_args *args)
+{
+ struct timespec *rmtp;
+ struct l_timespec lrqts, lrmts;
+ struct timespec rqts, rmts;
+ int error;
+
+ LIN_SDT_PROBE4(time, linux_clock_nanosleep, entry, args->which,
+ args->flags, args->rqtp, args->rmtp);
+
+ if (args->flags != 0) {
+ /* XXX deal with TIMER_ABSTIME */
+ LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_flags,
+ args->flags);
+ LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, EINVAL);
+ return (EINVAL); /* XXX deal with TIMER_ABSTIME */
+ }
+
+ if (args->which != LINUX_CLOCK_REALTIME) {
+ LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_clockid,
+ args->which);
+ LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, EINVAL);
+ return (EINVAL);
+ }
+
+ error = copyin(args->rqtp, &lrqts, sizeof lrqts);
+ if (error != 0) {
+ LIN_SDT_PROBE1(time, linux_clock_nanosleep, copyin_error,
+ error);
+ LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
+ return (error);
+ }
+
+ if (args->rmtp != NULL)
+ rmtp = &rmts;
+ else
+ rmtp = NULL;
+
+ error = linux_to_native_timespec(&rqts, &lrqts);
+ if (error != 0) {
+ LIN_SDT_PROBE1(time, linux_clock_nanosleep, conversion_error,
+ error);
+ LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
+ return (error);
+ }
+ error = kern_nanosleep(td, &rqts, rmtp);
+ if (error != 0) {
+ LIN_SDT_PROBE1(time, linux_clock_nanosleep, nanosleep_error,
+ error);
+ LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
+ return (error);
+ }
+
+ if (args->rmtp != NULL) {
+ native_to_linux_timespec(&lrmts, rmtp);
+ error = copyout(&lrmts, args->rmtp, sizeof lrmts );
+ if (error != 0) {
+ LIN_SDT_PROBE1(time, linux_clock_nanosleep,
+ copyout_error, error);
+ LIN_SDT_PROBE1(time, linux_nanosleep, return, error);
+ return (error);
+ }
+ }
+
+ LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, 0);
+ return (0);
+}
diff --git a/sys/compat/linux/linux_uid16.c b/sys/compat/linux/linux_uid16.c
new file mode 100644
index 0000000..b66fb5c
--- /dev/null
+++ b/sys/compat/linux/linux_uid16.c
@@ -0,0 +1,441 @@
+/*-
+ * Copyright (c) 2001 The FreeBSD Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_compat.h"
+#include "opt_kdtrace.h"
+
+#include <sys/fcntl.h>
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/priv.h>
+#include <sys/proc.h>
+#include <sys/sdt.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysproto.h>
+#include <sys/systm.h>
+
+#ifdef COMPAT_LINUX32
+#include <machine/../linux32/linux.h>
+#include <machine/../linux32/linux32_proto.h>
+#else
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#endif
+
+#include <compat/linux/linux_dtrace.h>
+#include <compat/linux/linux_util.h>
+
+/* DTrace init */
+LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
+
+/**
+ * DTrace probes in this module.
+ */
+LIN_SDT_PROBE_DEFINE3(uid16, linux_chown16, entry, "char *", "l_uid16_t",
+ "l_gid16_t");
+LIN_SDT_PROBE_DEFINE1(uid16, linux_chown16, conv_path, "char *");
+LIN_SDT_PROBE_DEFINE1(uid16, linux_chown16, return, "int");
+LIN_SDT_PROBE_DEFINE3(uid16, linux_lchown16, entry, "char *", "l_uid16_t",
+ "l_gid16_t");
+LIN_SDT_PROBE_DEFINE1(uid16, linux_lchown16, conv_path, "char *");
+LIN_SDT_PROBE_DEFINE1(uid16, linux_lchown16, return, "int");
+LIN_SDT_PROBE_DEFINE2(uid16, linux_setgroups16, entry, "l_uint", "l_gid16_t *");
+LIN_SDT_PROBE_DEFINE1(uid16, linux_setgroups16, copyin_error, "int");
+LIN_SDT_PROBE_DEFINE1(uid16, linux_setgroups16, priv_check_cred_error, "int");
+LIN_SDT_PROBE_DEFINE1(uid16, linux_setgroups16, return, "int");
+LIN_SDT_PROBE_DEFINE2(uid16, linux_getgroups16, entry, "l_uint", "l_gid16_t *");
+LIN_SDT_PROBE_DEFINE1(uid16, linux_getgroups16, copyout_error, "int");
+LIN_SDT_PROBE_DEFINE1(uid16, linux_getgroups16, return, "int");
+LIN_SDT_PROBE_DEFINE0(uid16, linux_getgid16, entry);
+LIN_SDT_PROBE_DEFINE1(uid16, linux_getgid16, return, "int");
+LIN_SDT_PROBE_DEFINE0(uid16, linux_getuid16, entry);
+LIN_SDT_PROBE_DEFINE1(uid16, linux_getuid16, return, "int");
+LIN_SDT_PROBE_DEFINE0(uid16, linux_getegid16, entry);
+LIN_SDT_PROBE_DEFINE1(uid16, linux_getegid16, return, "int");
+LIN_SDT_PROBE_DEFINE0(uid16, linux_geteuid16, entry);
+LIN_SDT_PROBE_DEFINE1(uid16, linux_geteuid16, return, "int");
+LIN_SDT_PROBE_DEFINE1(uid16, linux_setgid16, entry, "l_gid16_t");
+LIN_SDT_PROBE_DEFINE1(uid16, linux_setgid16, return, "int");
+LIN_SDT_PROBE_DEFINE1(uid16, linux_setuid16, entry, "l_uid16_t");
+LIN_SDT_PROBE_DEFINE1(uid16, linux_setuid16, return, "int");
+LIN_SDT_PROBE_DEFINE2(uid16, linux_setregid16, entry, "l_git16_t", "l_git16_t");
+LIN_SDT_PROBE_DEFINE1(uid16, linux_setregid16, return, "int");
+LIN_SDT_PROBE_DEFINE2(uid16, linux_setreuid16, entry, "l_uid16_t", "l_uid16_t");
+LIN_SDT_PROBE_DEFINE1(uid16, linux_setreuid16, return, "int");
+LIN_SDT_PROBE_DEFINE3(uid16, linux_setresgid16, entry, "l_gid16_t", "l_gid16_t",
+ "l_gid16_t");
+LIN_SDT_PROBE_DEFINE1(uid16, linux_setresgid16, return, "int");
+LIN_SDT_PROBE_DEFINE3(uid16, linux_setresuid16, entry, "l_uid16_t", "l_uid16_t",
+ "l_uid16_t");
+LIN_SDT_PROBE_DEFINE1(uid16, linux_setresuid16, return, "int");
+
+DUMMY(setfsuid16);
+DUMMY(setfsgid16);
+DUMMY(getresuid16);
+DUMMY(getresgid16);
+
+#define CAST_NOCHG(x) ((x == 0xFFFF) ? -1 : x)
+
+int
+linux_chown16(struct thread *td, struct linux_chown16_args *args)
+{
+ char *path;
+ int error;
+
+ LCONVPATHEXIST(td, args->path, &path);
+
+ /*
+ * The DTrace probes have to be after the LCONVPATHEXIST, as
+ * LCONVPATHEXIST may return on its own and we do not want to
+ * have a stray entry without the corresponding return.
+ */
+ LIN_SDT_PROBE3(uid16, linux_chown16, entry, args->path, args->uid,
+ args->gid);
+ LIN_SDT_PROBE1(uid16, linux_chown16, conv_path, path);
+
+ error = kern_chown(td, path, UIO_SYSSPACE, CAST_NOCHG(args->uid),
+ CAST_NOCHG(args->gid));
+ LFREEPATH(path);
+
+ LIN_SDT_PROBE1(uid16, linux_chown16, return, error);
+ return (error);
+}
+
+int
+linux_lchown16(struct thread *td, struct linux_lchown16_args *args)
+{
+ char *path;
+ int error;
+
+ LCONVPATHEXIST(td, args->path, &path);
+
+ /*
+ * The DTrace probes have to be after the LCONVPATHEXIST, as
+ * LCONVPATHEXIST may return on its own and we do not want to
+ * have a stray entry without the corresponding return.
+ */
+ LIN_SDT_PROBE3(uid16, linux_lchown16, entry, args->path, args->uid,
+ args->gid);
+ LIN_SDT_PROBE1(uid16, linux_lchown16, conv_path, path);
+
+ error = kern_lchown(td, path, UIO_SYSSPACE, CAST_NOCHG(args->uid),
+ CAST_NOCHG(args->gid));
+ LFREEPATH(path);
+
+ LIN_SDT_PROBE1(uid16, linux_lchown16, return, error);
+ return (error);
+}
+
+int
+linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args)
+{
+ struct ucred *newcred, *oldcred;
+ l_gid16_t *linux_gidset;
+ gid_t *bsd_gidset;
+ int ngrp, error;
+ struct proc *p;
+
+ LIN_SDT_PROBE2(uid16, linux_setgroups16, entry, args->gidsetsize,
+ args->gidset);
+
+ ngrp = args->gidsetsize;
+ if (ngrp < 0 || ngrp >= ngroups_max + 1) {
+ LIN_SDT_PROBE1(uid16, linux_setgroups16, return, EINVAL);
+ return (EINVAL);
+ }
+ linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_TEMP, M_WAITOK);
+ error = copyin(args->gidset, linux_gidset, ngrp * sizeof(l_gid16_t));
+ if (error) {
+ LIN_SDT_PROBE1(uid16, linux_setgroups16, copyin_error, error);
+ LIN_SDT_PROBE1(uid16, linux_setgroups16, return, error);
+ free(linux_gidset, M_TEMP);
+ return (error);
+ }
+ newcred = crget();
+ p = td->td_proc;
+ PROC_LOCK(p);
+ oldcred = crcopysafe(p, newcred);
+
+ /*
+ * cr_groups[0] holds egid. Setting the whole set from
+ * the supplied set will cause egid to be changed too.
+ * Keep cr_groups[0] unchanged to prevent that.
+ */
+
+ if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS, 0)) != 0) {
+ PROC_UNLOCK(p);
+ crfree(newcred);
+
+ LIN_SDT_PROBE1(uid16, linux_setgroups16, priv_check_cred_error,
+ error);
+ goto out;
+ }
+
+ if (ngrp > 0) {
+ newcred->cr_ngroups = ngrp + 1;
+
+ bsd_gidset = newcred->cr_groups;
+ ngrp--;
+ while (ngrp >= 0) {
+ bsd_gidset[ngrp + 1] = linux_gidset[ngrp];
+ ngrp--;
+ }
+ }
+ else
+ newcred->cr_ngroups = 1;
+
+ setsugid(td->td_proc);
+ p->p_ucred = newcred;
+ PROC_UNLOCK(p);
+ crfree(oldcred);
+ error = 0;
+out:
+ free(linux_gidset, M_TEMP);
+
+ LIN_SDT_PROBE1(uid16, linux_setgroups16, return, error);
+ return (error);
+}
+
+int
+linux_getgroups16(struct thread *td, struct linux_getgroups16_args *args)
+{
+ struct ucred *cred;
+ l_gid16_t *linux_gidset;
+ gid_t *bsd_gidset;
+ int bsd_gidsetsz, ngrp, error;
+
+ LIN_SDT_PROBE2(uid16, linux_getgroups16, entry, args->gidsetsize,
+ args->gidset);
+
+ cred = td->td_ucred;
+ bsd_gidset = cred->cr_groups;
+ bsd_gidsetsz = cred->cr_ngroups - 1;
+
+ /*
+ * cr_groups[0] holds egid. Returning the whole set
+ * here will cause a duplicate. Exclude cr_groups[0]
+ * to prevent that.
+ */
+
+ if ((ngrp = args->gidsetsize) == 0) {
+ td->td_retval[0] = bsd_gidsetsz;
+
+ LIN_SDT_PROBE1(uid16, linux_getgroups16, return, 0);
+ return (0);
+ }
+
+ if (ngrp < bsd_gidsetsz) {
+ LIN_SDT_PROBE1(uid16, linux_getgroups16, return, EINVAL);
+ return (EINVAL);
+ }
+
+ ngrp = 0;
+ linux_gidset = malloc(bsd_gidsetsz * sizeof(*linux_gidset),
+ M_TEMP, M_WAITOK);
+ while (ngrp < bsd_gidsetsz) {
+ linux_gidset[ngrp] = bsd_gidset[ngrp + 1];
+ ngrp++;
+ }
+
+ error = copyout(linux_gidset, args->gidset, ngrp * sizeof(l_gid16_t));
+ free(linux_gidset, M_TEMP);
+ if (error) {
+ LIN_SDT_PROBE1(uid16, linux_getgroups16, copyout_error, error);
+ LIN_SDT_PROBE1(uid16, linux_getgroups16, return, error);
+ return (error);
+ }
+
+ td->td_retval[0] = ngrp;
+
+ LIN_SDT_PROBE1(uid16, linux_getgroups16, return, 0);
+ return (0);
+}
+
+/*
+ * The FreeBSD native getgid(2) and getuid(2) also modify td->td_retval[1]
+ * when COMPAT_43 is defined. This clobbers registers that are assumed to
+ * be preserved. The following lightweight syscalls fixes this. See also
+ * linux_getpid(2), linux_getgid(2) and linux_getuid(2) in linux_misc.c
+ *
+ * linux_getgid16() - MP SAFE
+ * linux_getuid16() - MP SAFE
+ */
+
+int
+linux_getgid16(struct thread *td, struct linux_getgid16_args *args)
+{
+
+ LIN_SDT_PROBE0(uid16, linux_getgid16, entry);
+
+ td->td_retval[0] = td->td_ucred->cr_rgid;
+
+ LIN_SDT_PROBE1(uid16, linux_getgid16, return, 0);
+ return (0);
+}
+
+int
+linux_getuid16(struct thread *td, struct linux_getuid16_args *args)
+{
+
+ LIN_SDT_PROBE0(uid16, linux_getuid16, entry);
+
+ td->td_retval[0] = td->td_ucred->cr_ruid;
+
+ LIN_SDT_PROBE1(uid16, linux_getuid16, return, 0);
+ return (0);
+}
+
+int
+linux_getegid16(struct thread *td, struct linux_getegid16_args *args)
+{
+ struct getegid_args bsd;
+ int error;
+
+ LIN_SDT_PROBE0(uid16, linux_getegid16, entry);
+
+ error = sys_getegid(td, &bsd);
+
+ LIN_SDT_PROBE1(uid16, linux_getegid16, return, error);
+ return (error);
+}
+
+int
+linux_geteuid16(struct thread *td, struct linux_geteuid16_args *args)
+{
+ struct geteuid_args bsd;
+ int error;
+
+ LIN_SDT_PROBE0(uid16, linux_geteuid16, entry);
+
+ error = sys_geteuid(td, &bsd);
+
+ LIN_SDT_PROBE1(uid16, linux_geteuid16, return, error);
+ return (error);
+}
+
+int
+linux_setgid16(struct thread *td, struct linux_setgid16_args *args)
+{
+ struct setgid_args bsd;
+ int error;
+
+ LIN_SDT_PROBE1(uid16, linux_setgid16, entry, args->gid);
+
+ bsd.gid = args->gid;
+ error = sys_setgid(td, &bsd);
+
+ LIN_SDT_PROBE1(uid16, linux_setgid16, return, error);
+ return (error);
+}
+
+int
+linux_setuid16(struct thread *td, struct linux_setuid16_args *args)
+{
+ struct setuid_args bsd;
+ int error;
+
+ LIN_SDT_PROBE1(uid16, linux_setuid16, entry, args->uid);
+
+ bsd.uid = args->uid;
+ error = sys_setuid(td, &bsd);
+
+ LIN_SDT_PROBE1(uid16, linux_setuid16, return, error);
+ return (error);
+}
+
+int
+linux_setregid16(struct thread *td, struct linux_setregid16_args *args)
+{
+ struct setregid_args bsd;
+ int error;
+
+ LIN_SDT_PROBE2(uid16, linux_setregid16, entry, args->rgid, args->egid);
+
+ bsd.rgid = CAST_NOCHG(args->rgid);
+ bsd.egid = CAST_NOCHG(args->egid);
+ error = sys_setregid(td, &bsd);
+
+ LIN_SDT_PROBE1(uid16, linux_setregid16, return, error);
+ return (error);
+}
+
+int
+linux_setreuid16(struct thread *td, struct linux_setreuid16_args *args)
+{
+ struct setreuid_args bsd;
+ int error;
+
+ LIN_SDT_PROBE2(uid16, linux_setreuid16, entry, args->ruid, args->euid);
+
+ bsd.ruid = CAST_NOCHG(args->ruid);
+ bsd.euid = CAST_NOCHG(args->euid);
+ error = sys_setreuid(td, &bsd);
+
+ LIN_SDT_PROBE1(uid16, linux_setreuid16, return, error);
+ return (error);
+}
+
+int
+linux_setresgid16(struct thread *td, struct linux_setresgid16_args *args)
+{
+ struct setresgid_args bsd;
+ int error;
+
+ LIN_SDT_PROBE3(uid16, linux_setresgid16, entry, args->rgid, args->egid,
+ args->sgid);
+
+ bsd.rgid = CAST_NOCHG(args->rgid);
+ bsd.egid = CAST_NOCHG(args->egid);
+ bsd.sgid = CAST_NOCHG(args->sgid);
+ error = sys_setresgid(td, &bsd);
+
+ LIN_SDT_PROBE1(uid16, linux_setresgid16, return, error);
+ return (error);
+}
+
+int
+linux_setresuid16(struct thread *td, struct linux_setresuid16_args *args)
+{
+ struct setresuid_args bsd;
+ int error;
+
+ LIN_SDT_PROBE3(uid16, linux_setresuid16, entry, args->ruid, args->euid,
+ args->suid);
+
+ bsd.ruid = CAST_NOCHG(args->ruid);
+ bsd.euid = CAST_NOCHG(args->euid);
+ bsd.suid = CAST_NOCHG(args->suid);
+ error = sys_setresuid(td, &bsd);
+
+ LIN_SDT_PROBE1(uid16, linux_setresuid16, return, error);
+ return (error);
+}
diff --git a/sys/compat/linux/linux_util.c b/sys/compat/linux/linux_util.c
new file mode 100644
index 0000000..76c210c
--- /dev/null
+++ b/sys/compat/linux/linux_util.c
@@ -0,0 +1,333 @@
+/*-
+ * Copyright (c) 1994 Christos Zoulas
+ * Copyright (c) 1995 Frank van der Linden
+ * Copyright (c) 1995 Scott Bartram
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * from: svr4_util.c,v 1.5 1995/01/22 23:44:50 christos Exp
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_compat.h"
+#include "opt_kdtrace.h"
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/fcntl.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/linker_set.h>
+#include <sys/mutex.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/sdt.h>
+#include <sys/syscallsubr.h>
+#include <sys/systm.h>
+#include <sys/vnode.h>
+
+#include <machine/stdarg.h>
+
+#include <compat/linux/linux_util.h>
+#ifdef COMPAT_LINUX32
+#include <machine/../linux32/linux.h>
+#else
+#include <machine/../linux/linux.h>
+#endif
+
+#include <compat/linux/linux_dtrace.h>
+
+const char linux_emul_path[] = "/compat/linux";
+
+/* DTrace init */
+LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
+
+/**
+ * DTrace probes in this module.
+ */
+LIN_SDT_PROBE_DEFINE5(util, linux_emul_convpath, entry, "const char *",
+ "enum uio_seg", "char **", "int", "int");
+LIN_SDT_PROBE_DEFINE1(util, linux_emul_convpath, return, "int");
+LIN_SDT_PROBE_DEFINE1(util, linux_msg, entry, "const char *");
+LIN_SDT_PROBE_DEFINE0(util, linux_msg, return);
+LIN_SDT_PROBE_DEFINE2(util, linux_driver_get_name_dev, entry, "device_t",
+ "const char *");
+LIN_SDT_PROBE_DEFINE0(util, linux_driver_get_name_dev, nullcall);
+LIN_SDT_PROBE_DEFINE1(util, linux_driver_get_name_dev, return, "char *");
+LIN_SDT_PROBE_DEFINE3(util, linux_driver_get_major_minor, entry, "char *",
+ "int *", "int *");
+LIN_SDT_PROBE_DEFINE0(util, linux_driver_get_major_minor, nullcall);
+LIN_SDT_PROBE_DEFINE1(util, linux_driver_get_major_minor, notfound, "char *");
+LIN_SDT_PROBE_DEFINE3(util, linux_driver_get_major_minor, return, "int",
+ "int", "int");
+LIN_SDT_PROBE_DEFINE0(util, linux_get_char_devices, entry);
+LIN_SDT_PROBE_DEFINE1(util, linux_get_char_devices, return, "char *");
+LIN_SDT_PROBE_DEFINE1(util, linux_free_get_char_devices, entry, "char *");
+LIN_SDT_PROBE_DEFINE0(util, linux_free_get_char_devices, return);
+LIN_SDT_PROBE_DEFINE1(util, linux_device_register_handler, entry,
+ "struct linux_device_handler *");
+LIN_SDT_PROBE_DEFINE1(util, linux_device_register_handler, return, "int");
+LIN_SDT_PROBE_DEFINE1(util, linux_device_unregister_handler, entry,
+ "struct linux_device_handler *");
+LIN_SDT_PROBE_DEFINE1(util, linux_device_unregister_handler, return, "int");
+
+/*
+ * Search an alternate path before passing pathname arguments on to
+ * system calls. Useful for keeping a separate 'emulation tree'.
+ *
+ * If cflag is set, we check if an attempt can be made to create the
+ * named file, i.e. we check if the directory it should be in exists.
+ */
+int
+linux_emul_convpath(struct thread *td, const char *path, enum uio_seg pathseg,
+ char **pbuf, int cflag, int dfd)
+{
+ int retval;
+
+ LIN_SDT_PROBE5(util, linux_emul_convpath, entry, path, pathseg, pbuf,
+ cflag, dfd);
+
+ retval = kern_alternate_path(td, linux_emul_path, path, pathseg, pbuf,
+ cflag, dfd);
+
+ LIN_SDT_PROBE1(util, linux_emul_convpath, return, retval);
+ return (retval);
+}
+
+void
+linux_msg(const struct thread *td, const char *fmt, ...)
+{
+ va_list ap;
+ struct proc *p;
+
+ LIN_SDT_PROBE1(util, linux_msg, entry, fmt);
+
+ p = td->td_proc;
+ printf("linux: pid %d (%s): ", (int)p->p_pid, p->p_comm);
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+ printf("\n");
+
+ LIN_SDT_PROBE0(util, linux_msg, return);
+}
+
+struct device_element
+{
+ TAILQ_ENTRY(device_element) list;
+ struct linux_device_handler entry;
+};
+
+static TAILQ_HEAD(, device_element) devices =
+ TAILQ_HEAD_INITIALIZER(devices);
+
+static struct linux_device_handler null_handler =
+ { "mem", "mem", "null", "null", 1, 3, 1};
+
+DATA_SET(linux_device_handler_set, null_handler);
+
+char *
+linux_driver_get_name_dev(device_t dev)
+{
+ struct device_element *de;
+ const char *device_name = device_get_name(dev);
+
+ LIN_SDT_PROBE2(util, linux_driver_get_name_dev, entry, dev,
+ device_name);
+
+ if (device_name == NULL) {
+ LIN_SDT_PROBE0(util, linux_driver_get_name_dev, nullcall);
+ LIN_SDT_PROBE1(util, linux_driver_get_name_dev, return, NULL);
+ return NULL;
+ }
+ TAILQ_FOREACH(de, &devices, list) {
+ if (strcmp(device_name, de->entry.bsd_driver_name) == 0) {
+ LIN_SDT_PROBE1(util, linux_driver_get_name_dev, return,
+ de->entry.linux_driver_name);
+ return (de->entry.linux_driver_name);
+ }
+ }
+
+ LIN_SDT_PROBE1(util, linux_driver_get_name_dev, return, NULL);
+ return NULL;
+}
+
+int
+linux_driver_get_major_minor(const char *node, int *major, int *minor)
+{
+ struct device_element *de;
+
+ LIN_SDT_PROBE3(util, linux_driver_get_major_minor, entry, node, major,
+ minor);
+
+ if (node == NULL || major == NULL || minor == NULL) {
+ LIN_SDT_PROBE0(util, linux_driver_get_major_minor, nullcall);
+ LIN_SDT_PROBE3(util, linux_driver_get_major_minor, return, 1,
+ 0, 0);
+ return 1;
+ }
+
+ if (strlen(node) > strlen("pts/") &&
+ strncmp(node, "pts/", strlen("pts/")) == 0) {
+ unsigned long devno;
+
+ /*
+ * Linux checks major and minors of the slave device
+ * to make sure it's a pty device, so let's make him
+ * believe it is.
+ */
+ devno = strtoul(node + strlen("pts/"), NULL, 10);
+ *major = 136 + (devno / 256);
+ *minor = devno % 256;
+
+ LIN_SDT_PROBE3(util, linux_driver_get_major_minor, return, 0,
+ *major, *minor);
+ return 0;
+ }
+
+ TAILQ_FOREACH(de, &devices, list) {
+ if (strcmp(node, de->entry.bsd_device_name) == 0) {
+ *major = de->entry.linux_major;
+ *minor = de->entry.linux_minor;
+
+ LIN_SDT_PROBE3(util, linux_driver_get_major_minor,
+ return, 0, *major, *minor);
+ return 0;
+ }
+ }
+
+ LIN_SDT_PROBE1(util, linux_driver_get_major_minor, notfound, node);
+ LIN_SDT_PROBE3(util, linux_driver_get_major_minor, return, 1, 0, 0);
+ return 1;
+}
+
+char *
+linux_get_char_devices()
+{
+ struct device_element *de;
+ char *temp, *string, *last;
+ char formated[256];
+ int current_size = 0, string_size = 1024;
+
+ LIN_SDT_PROBE0(util, linux_get_char_devices, entry);
+
+ string = malloc(string_size, M_LINUX, M_WAITOK);
+ string[0] = '\000';
+ last = "";
+ TAILQ_FOREACH(de, &devices, list) {
+ if (!de->entry.linux_char_device)
+ continue;
+ temp = string;
+ if (strcmp(last, de->entry.bsd_driver_name) != 0) {
+ last = de->entry.bsd_driver_name;
+
+ snprintf(formated, sizeof(formated), "%3d %s\n",
+ de->entry.linux_major,
+ de->entry.linux_device_name);
+ if (strlen(formated) + current_size
+ >= string_size) {
+ string_size *= 2;
+ string = malloc(string_size,
+ M_LINUX, M_WAITOK);
+ bcopy(temp, string, current_size);
+ free(temp, M_LINUX);
+ }
+ strcat(string, formated);
+ current_size = strlen(string);
+ }
+ }
+
+ LIN_SDT_PROBE1(util, linux_get_char_devices, return, string);
+ return string;
+}
+
+void
+linux_free_get_char_devices(char *string)
+{
+
+ LIN_SDT_PROBE1(util, linux_get_char_devices, entry, string);
+
+ free(string, M_LINUX);
+
+ LIN_SDT_PROBE0(util, linux_get_char_devices, return);
+}
+
+static int linux_major_starting = 200;
+
+int
+linux_device_register_handler(struct linux_device_handler *d)
+{
+ struct device_element *de;
+
+ LIN_SDT_PROBE1(util, linux_device_register_handler, entry, d);
+
+ if (d == NULL) {
+ LIN_SDT_PROBE1(util, linux_device_register_handler, return,
+ EINVAL);
+ return (EINVAL);
+ }
+
+ de = malloc(sizeof(*de), M_LINUX, M_WAITOK);
+ if (d->linux_major < 0) {
+ d->linux_major = linux_major_starting++;
+ }
+ bcopy(d, &de->entry, sizeof(*d));
+
+ /* Add the element to the list, sorted on span. */
+ TAILQ_INSERT_TAIL(&devices, de, list);
+
+ LIN_SDT_PROBE1(util, linux_device_register_handler, return, 0);
+ return (0);
+}
+
+int
+linux_device_unregister_handler(struct linux_device_handler *d)
+{
+ struct device_element *de;
+
+ LIN_SDT_PROBE1(util, linux_device_unregister_handler, entry, d);
+
+ if (d == NULL) {
+ LIN_SDT_PROBE1(util, linux_device_unregister_handler, return,
+ EINVAL);
+ return (EINVAL);
+ }
+
+ TAILQ_FOREACH(de, &devices, list) {
+ if (bcmp(d, &de->entry, sizeof(*d)) == 0) {
+ TAILQ_REMOVE(&devices, de, list);
+ free(de, M_LINUX);
+
+ LIN_SDT_PROBE1(util, linux_device_unregister_handler,
+ return, 0);
+ return (0);
+ }
+ }
+
+ LIN_SDT_PROBE1(util, linux_device_unregister_handler, return, EINVAL);
+ return (EINVAL);
+}
diff --git a/sys/compat/linux/linux_util.h b/sys/compat/linux/linux_util.h
new file mode 100644
index 0000000..6be0392
--- /dev/null
+++ b/sys/compat/linux/linux_util.h
@@ -0,0 +1,141 @@
+/*-
+ * Copyright (c) 1994 Christos Zoulas
+ * Copyright (c) 1995 Frank van der Linden
+ * Copyright (c) 1995 Scott Bartram
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * from: svr4_util.h,v 1.5 1994/11/18 02:54:31 christos Exp
+ * from: linux_util.h,v 1.2 1995/03/05 23:23:50 fvdl Exp
+ * $FreeBSD$
+ */
+
+#ifndef _LINUX_UTIL_H_
+#define _LINUX_UTIL_H_
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <machine/vmparam.h>
+#include <sys/exec.h>
+#include <sys/sysent.h>
+#include <sys/syslog.h>
+#include <sys/cdefs.h>
+#include <sys/uio.h>
+
+extern const char linux_emul_path[];
+
+int linux_emul_convpath(struct thread *, const char *, enum uio_seg, char **, int, int);
+
+#define LCONVPATH_AT(td, upath, pathp, i, dfd) \
+ do { \
+ int _error; \
+ \
+ _error = linux_emul_convpath(td, upath, UIO_USERSPACE, \
+ pathp, i, dfd); \
+ if (*(pathp) == NULL) \
+ return (_error); \
+ } while (0)
+
+#define LCONVPATH(td, upath, pathp, i) \
+ LCONVPATH_AT(td, upath, pathp, i, AT_FDCWD)
+
+#define LCONVPATHEXIST(td, upath, pathp) LCONVPATH(td, upath, pathp, 0)
+#define LCONVPATHEXIST_AT(td, upath, pathp, dfd) LCONVPATH_AT(td, upath, pathp, 0, dfd)
+#define LCONVPATHCREAT(td, upath, pathp) LCONVPATH(td, upath, pathp, 1)
+#define LCONVPATHCREAT_AT(td, upath, pathp, dfd) LCONVPATH_AT(td, upath, pathp, 1, dfd)
+#define LFREEPATH(path) free(path, M_TEMP)
+
+#define DUMMY(s) \
+LIN_SDT_PROBE_DEFINE0(dummy, s, entry); \
+LIN_SDT_PROBE_DEFINE0(dummy, s, not_implemented); \
+LIN_SDT_PROBE_DEFINE1(dummy, s, return, "int"); \
+int \
+linux_ ## s(struct thread *td, struct linux_ ## s ## _args *args) \
+{ \
+ static pid_t pid; \
+ \
+ LIN_SDT_PROBE0(dummy, s, entry); \
+ \
+ if (pid != td->td_proc->p_pid) { \
+ linux_msg(td, "syscall %s not implemented", #s); \
+ LIN_SDT_PROBE0(dummy, s, not_implemented); \
+ pid = td->td_proc->p_pid; \
+ }; \
+ \
+ LIN_SDT_PROBE1(dummy, s, return, ENOSYS); \
+ return (ENOSYS); \
+} \
+struct __hack
+
+void linux_msg(const struct thread *td, const char *fmt, ...)
+ __printflike(2, 3);
+
+struct linux_device_handler {
+ char *bsd_driver_name;
+ char *linux_driver_name;
+ char *bsd_device_name;
+ char *linux_device_name;
+ int linux_major;
+ int linux_minor;
+ int linux_char_device;
+};
+
+int linux_device_register_handler(struct linux_device_handler *h);
+int linux_device_unregister_handler(struct linux_device_handler *h);
+char *linux_driver_get_name_dev(device_t dev);
+int linux_driver_get_major_minor(const char *node, int *major, int *minor);
+char *linux_get_char_devices(void);
+void linux_free_get_char_devices(char *string);
+
+#if defined(KTR)
+
+#define KTR_LINUX KTR_SUBSYS
+#define LINUX_CTRFMT(nm, fmt) #nm"("fmt")"
+
+#define LINUX_CTR6(f, m, p1, p2, p3, p4, p5, p6) do { \
+ if (ldebug(f)) \
+ CTR6(KTR_LINUX, LINUX_CTRFMT(f, m), \
+ p1, p2, p3, p4, p5, p6); \
+} while (0)
+
+#define LINUX_CTR(f) LINUX_CTR6(f, "", 0, 0, 0, 0, 0, 0)
+#define LINUX_CTR0(f, m) LINUX_CTR6(f, m, 0, 0, 0, 0, 0, 0)
+#define LINUX_CTR1(f, m, p1) LINUX_CTR6(f, m, p1, 0, 0, 0, 0, 0)
+#define LINUX_CTR2(f, m, p1, p2) LINUX_CTR6(f, m, p1, p2, 0, 0, 0, 0)
+#define LINUX_CTR3(f, m, p1, p2, p3) LINUX_CTR6(f, m, p1, p2, p3, 0, 0, 0)
+#define LINUX_CTR4(f, m, p1, p2, p3, p4) LINUX_CTR6(f, m, p1, p2, p3, p4, 0, 0)
+#define LINUX_CTR5(f, m, p1, p2, p3, p4, p5) LINUX_CTR6(f, m, p1, p2, p3, p4, p5, 0)
+#else
+#define LINUX_CTR(f)
+#define LINUX_CTR0(f, m)
+#define LINUX_CTR1(f, m, p1)
+#define LINUX_CTR2(f, m, p1, p2)
+#define LINUX_CTR3(f, m, p1, p2, p3)
+#define LINUX_CTR4(f, m, p1, p2, p3, p4)
+#define LINUX_CTR5(f, m, p1, p2, p3, p4, p5)
+#define LINUX_CTR6(f, m, p1, p2, p3, p4, p5, p6)
+#endif
+
+#endif /* !_LINUX_UTIL_H_ */
diff --git a/sys/compat/linux/linux_videodev2_compat.h b/sys/compat/linux/linux_videodev2_compat.h
new file mode 100644
index 0000000..0d9a3a3
--- /dev/null
+++ b/sys/compat/linux/linux_videodev2_compat.h
@@ -0,0 +1,137 @@
+/*
+ * $FreeBSD$
+ */
+
+/*
+ * This file defines compatibility versions of several video structures
+ * defined in the Linux videodev2.h header (linux_videodev2.h). The
+ * structures defined in this file are the ones that have been determined
+ * to have 32- to 64-bit size dependencies.
+ */
+
+#ifndef _LINUX_VIDEODEV2_COMPAT_H_
+#define _LINUX_VIDEODEV2_COMPAT_H_
+
+struct l_v4l2_buffer {
+ uint32_t index;
+ enum v4l2_buf_type type;
+ uint32_t bytesused;
+ uint32_t flags;
+ enum v4l2_field field;
+ l_timeval timestamp;
+ struct v4l2_timecode timecode;
+ uint32_t sequence;
+
+ /* memory location */
+ enum v4l2_memory memory;
+ union {
+ uint32_t offset;
+ l_ulong userptr;
+ } m;
+ uint32_t length;
+ uint32_t input;
+ uint32_t reserved;
+};
+
+struct l_v4l2_framebuffer {
+ uint32_t capability;
+ uint32_t flags;
+/* FIXME: in theory we should pass something like PCI device + memory
+ * region + offset instead of some physical address */
+ l_uintptr_t base;
+ struct v4l2_pix_format fmt;
+};
+
+struct l_v4l2_clip {
+ struct v4l2_rect c;
+ l_uintptr_t next;
+};
+
+struct l_v4l2_window {
+ struct v4l2_rect w;
+ enum v4l2_field field;
+ uint32_t chromakey;
+ l_uintptr_t clips;
+ uint32_t clipcount;
+ l_uintptr_t bitmap;
+ uint8_t global_alpha;
+};
+
+struct l_v4l2_standard {
+ uint32_t index;
+ v4l2_std_id id;
+ uint8_t name[24];
+ struct v4l2_fract frameperiod; /* Frames, not fields */
+ uint32_t framelines;
+ uint32_t reserved[4];
+}
+#ifdef COMPAT_LINUX32 /* 32bit linuxolator */
+__attribute__ ((packed))
+#endif
+;
+
+struct l_v4l2_ext_control {
+ uint32_t id;
+ uint32_t size;
+ uint32_t reserved2[1];
+ union {
+ int32_t value;
+ int64_t value64;
+ l_uintptr_t string;
+ } u;
+} __attribute__ ((packed));
+
+struct l_v4l2_ext_controls {
+ uint32_t ctrl_class;
+ uint32_t count;
+ uint32_t error_idx;
+ uint32_t reserved[2];
+ l_uintptr_t controls;
+};
+
+struct l_v4l2_format {
+ enum v4l2_buf_type type;
+ union {
+ struct v4l2_pix_format pix; /* V4L2_BUF_TYPE_VIDEO_CAPTURE */
+ struct l_v4l2_window win; /* V4L2_BUF_TYPE_VIDEO_OVERLAY */
+ struct v4l2_vbi_format vbi; /* V4L2_BUF_TYPE_VBI_CAPTURE */
+ struct v4l2_sliced_vbi_format sliced; /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
+ uint8_t raw_data[200]; /* user-defined */
+ } fmt;
+}
+#ifdef COMPAT_LINUX32 /* 32bit linuxolator */
+__attribute__ ((packed))
+#endif
+;
+
+#ifdef VIDIOC_DQEVENT
+struct l_v4l2_event {
+ uint32_t type;
+ union {
+ struct v4l2_event_vsync vsync;
+ uint8_t data[64];
+ } u;
+ uint32_t pending;
+ uint32_t sequence;
+ struct l_timespec timestamp;
+ uint32_t reserved[9];
+};
+#endif
+
+struct l_v4l2_input {
+ uint32_t index; /* Which input */
+ uint8_t name[32]; /* Label */
+ uint32_t type; /* Type of input */
+ uint32_t audioset; /* Associated audios (bitfield) */
+ uint32_t tuner; /* Associated tuner */
+ v4l2_std_id std;
+ uint32_t status;
+ uint32_t capabilities;
+ uint32_t reserved[3];
+}
+#ifdef COMPAT_LINUX32 /* 32bit linuxolator */
+__attribute__ ((packed))
+#endif
+;
+
+#endif /* _LINUX_VIDEODEV2_COMPAT_H_ */
diff --git a/sys/compat/linux/linux_videodev_compat.h b/sys/compat/linux/linux_videodev_compat.h
new file mode 100644
index 0000000..98034bc
--- /dev/null
+++ b/sys/compat/linux/linux_videodev_compat.h
@@ -0,0 +1,59 @@
+/*
+ * $FreeBSD$
+ */
+
+/*
+ * This file defines compatibility versions of several video structures
+ * defined in the Linux videodev.h header (linux_videodev.h). The
+ * structures defined in this file are the ones that have been determined
+ * to have 32- to 64-bit size dependencies.
+ */
+
+#ifndef _LINUX_VIDEODEV_COMPAT_H_
+#define _LINUX_VIDEODEV_COMPAT_H_
+
+struct l_video_tuner
+{
+ l_int tuner;
+#define LINUX_VIDEO_TUNER_NAME_SIZE 32
+ char name[LINUX_VIDEO_TUNER_NAME_SIZE];
+ l_ulong rangelow, rangehigh;
+ uint32_t flags;
+ uint16_t mode;
+ uint16_t signal;
+};
+
+struct l_video_clip
+{
+ int32_t x, y;
+ int32_t width, height;
+ l_uintptr_t next;
+};
+
+struct l_video_window
+{
+ uint32_t x, y;
+ uint32_t width, height;
+ uint32_t chromakey;
+ uint32_t flags;
+ l_uintptr_t clips;
+ l_int clipcount;
+};
+
+struct l_video_buffer
+{
+ l_uintptr_t base;
+ l_int height, width;
+ l_int depth;
+ l_int bytesperline;
+};
+
+struct l_video_code
+{
+#define LINUX_VIDEO_CODE_LOADWHAT_SIZE 16
+ char loadwhat[LINUX_VIDEO_CODE_LOADWHAT_SIZE];
+ l_int datasize;
+ l_uintptr_t data;
+};
+
+#endif /* !_LINUX_VIDEODEV_COMPAT_H_ */
diff --git a/sys/compat/linux/stats_timing.d b/sys/compat/linux/stats_timing.d
new file mode 100644
index 0000000..d0b6f73
--- /dev/null
+++ b/sys/compat/linux/stats_timing.d
@@ -0,0 +1,94 @@
+#!/usr/sbin/dtrace -qs
+
+/*-
+ * Copyright (c) 2008-2012 Alexander Leidinger <netchild@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * Some statistics (all per provider):
+ * - number of calls to a function per executable binary (not per PID!)
+ * - allows to see where an optimization would be beneficial for a given
+ * application
+ * - graph of CPU time spend in functions per executable binary
+ * - together with the number of calls to this function this allows
+ * to determine if a kernel optimization would be beneficial / is
+ * possible for a given application
+ * - graph of longest running (CPU-time!) function in total
+ * - may help finding problem cases in the kernel code
+ * - timing statistics for the emul_lock
+ * - graph of longest held (CPU-time!) locks
+ */
+
+#pragma D option dynvarsize=32m
+
+linuxulator*:::entry
+{
+ self->time[probefunc] = vtimestamp;
+ @calls[probeprov, execname, probefunc] = count();
+}
+
+linuxulator*:::return
+/self->time[probefunc] != 0/
+{
+ this->timediff = self->time[probefunc] - vtimestamp;
+
+ @stats[probeprov, execname, probefunc] = quantize(this->timediff);
+ @longest[probeprov, probefunc] = max(this->timediff);
+
+ self->time[probefunc] = 0;
+}
+
+linuxulator*:::locked
+{
+ self->lock[arg0] = vtimestamp;
+}
+
+linuxulator*:::unlock
+/self->lock[arg0] != 0/
+{
+ this->timediff = self->lock[arg0] - vtimestamp;
+
+ @lockstats[probefunc] = quantize(this->timediff);
+ @longlock[probefunc] = max(this->timediff);
+
+ self->lock[arg0] = 0;
+}
+
+END
+{
+ printf("Number of calls per provider/application/kernel function:");
+ printa(@calls);
+ printf("CPU-timing statistics per provider/application/kernel function (in ns):");
+ printa(@stats);
+ printf("Longest running (CPU-time!) functions per provider (in ns):");
+ printa(@longest);
+ printf("Lock CPU-timing statistics:");
+ printa(@lockstats);
+ printf("Longest running (CPU-time!) locks:");
+ printa(@longlock);
+}
+
diff --git a/sys/compat/linux/trace_futexes.d b/sys/compat/linux/trace_futexes.d
new file mode 100644
index 0000000..bd9dac6
--- /dev/null
+++ b/sys/compat/linux/trace_futexes.d
@@ -0,0 +1,182 @@
+#!/usr/sbin/dtrace -qs
+
+/*-
+ * Copyright (c) 2011-2012 Alexander Leidinger <netchild@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/**
+ * Trace futex operations:
+ * - internal locks
+ * - size of the futex list
+ * - report error conditions (emulation errors, kernel errors,
+ * programming errors)
+ * - execution time (wallclock) of futex related functions
+ */
+
+#pragma D option specsize=32m
+
+/* Error conditions */
+linuxulator*:futex:futex_get:error,
+linuxulator*:futex:futex_sleep:requeue_error,
+linuxulator*:futex:futex_sleep:sleep_error,
+linuxulator*:futex:futex_wait:copyin_error,
+linuxulator*:futex:futex_wait:itimerfix_error,
+linuxulator*:futex:futex_wait:sleep_error,
+linuxulator*:futex:futex_atomic_op:missing_access_check,
+linuxulator*:futex:futex_atomic_op:unimplemented_op,
+linuxulator*:futex:futex_atomic_op:unimplemented_cmp,
+linuxulator*:futex:linux_sys_futex:unimplemented_clockswitch,
+linuxulator*:futex:linux_sys_futex:copyin_error,
+linuxulator*:futex:linux_sys_futex:unhandled_efault,
+linuxulator*:futex:linux_sys_futex:unimplemented_lock_pi,
+linuxulator*:futex:linux_sys_futex:unimplemented_unlock_pi,
+linuxulator*:futex:linux_sys_futex:unimplemented_trylock_pi,
+linuxulator*:futex:linux_sys_futex:unimplemented_wait_requeue_pi,
+linuxulator*:futex:linux_sys_futex:unimplemented_cmp_requeue_pi,
+linuxulator*:futex:linux_sys_futex:unknown_operation,
+linuxulator*:futex:linux_get_robust_list:copyout_error,
+linuxulator*:futex:handle_futex_death:copyin_error,
+linuxulator*:futex:fetch_robust_entry:copyin_error,
+linuxulator*:futex:release_futexes:copyin_error
+{
+ printf("ERROR: %s in %s:%s:%s\n", probename, probeprov, probemod,
+ probefunc);
+ stack();
+ ustack();
+}
+
+linuxulator*:futex:linux_sys_futex:invalid_cmp_requeue_use,
+linuxulator*:futex:linux_sys_futex:deprecated_requeue,
+linuxulator*:futex:linux_set_robust_list:size_error
+{
+ printf("WARNING: %s:%s:%s:%s in application %s, maybe an application error?\n",
+ probename, probeprov, probemod, probefunc, execname);
+ stack();
+ ustack();
+}
+
+
+/* Per futex checks/statistics */
+
+linuxulator*:futex:futex:create
+{
+ ++futex_count;
+ @max_futexes = max(futex_count);
+}
+
+linuxulator*:futex:futex:destroy
+/futex_count == 0/
+{
+ printf("ERROR: Request to destroy a futex which was not created,\n");
+ printf(" or this script was started after some futexes where\n");
+ printf(" created. Stack trace:\n");
+ stack();
+ ustack();
+}
+
+linuxulator*:futex:futex:destroy
+{
+ --futex_count;
+}
+
+
+/* Internal locks */
+
+linuxulator*:locks:futex_mtx:locked
+{
+ ++check[probefunc, arg0];
+ @stats[probefunc] = count();
+
+ ts[probefunc] = timestamp;
+ spec[probefunc] = speculation();
+ printf("Stacktrace of last lock operation of the %s:\n", probefunc);
+ stack();
+}
+
+linuxulator*:locks:futex_mtx:unlock
+/check[probefunc, arg0] == 0/
+{
+ printf("ERROR: unlock attemt of unlocked %s (%p),", probefunc, arg0);
+ printf(" missing SDT probe in kernel, or dtrace program started");
+ printf(" while the %s was already held (race condition).", probefunc);
+ printf(" Stack trace follows:");
+ stack();
+}
+
+linuxulator*:locks:futex_mtx:unlock
+{
+ discard(spec[probefunc]);
+ spec[probefunc] = 0;
+ --check[probefunc, arg0];
+}
+
+/* Timeout handling for internal locks */
+
+tick-10s
+/spec["futex_mtx"] != 0 && timestamp - ts["futex_mtx"] >= 9999999000/
+{
+ commit(spec["futex_mtx"]);
+ spec["futex_mtx"] = 0;
+}
+
+
+/* Timing statistings */
+
+linuxulator*:futex::entry
+{
+ self->time[probefunc] = timestamp;
+ @calls[probeprov, execname, probefunc] = count();
+}
+
+linuxulator*:futex::return
+/self->time[probefunc] != 0/
+{
+ this->timediff = self->time[probefunc] - timestamp;
+
+ @timestats[probeprov, execname, probefunc] = quantize(this->timediff);
+ @longest[probeprov, probefunc] = max(this->timediff);
+
+ self->time[probefunc] = 0;
+}
+
+
+/* Statistics */
+
+END
+{
+ printf("Number of locks per type:");
+ printa(@stats);
+ printf("Number of maximum number of futexes in the futex list:");
+ printa(@max_futexes);
+ printf("Number of futexes still existing: %d", futex_count);
+ printf("Number of calls per provider/application/kernel function:");
+ printa(@calls);
+ printf("Wallclock-timing statistics per provider/application/kernel function (in ns):");
+ printa(@timestats);
+ printf("Longest running (wallclock!) functions per provider (in ns):");
+ printa(@longest);
+}
diff --git a/sys/compat/ndis/cfg_var.h b/sys/compat/ndis/cfg_var.h
new file mode 100644
index 0000000..1fb44ce
--- /dev/null
+++ b/sys/compat/ndis/cfg_var.h
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 2003
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _CFG_VAR_H_
+#define _CFG_VAR_H_
+
+struct ndis_cfg {
+ char *nc_cfgkey;
+ char *nc_cfgdesc;
+ char nc_val[256];
+ int nc_idx;
+};
+
+typedef struct ndis_cfg ndis_cfg;
+
+#endif /* _CFG_VAR_H_ */
diff --git a/sys/compat/ndis/hal_var.h b/sys/compat/ndis/hal_var.h
new file mode 100644
index 0000000..699b01c
--- /dev/null
+++ b/sys/compat/ndis/hal_var.h
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 2003
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _HAL_VAR_H_
+#define _HAL_VAR_H_
+
+#define NDIS_BUS_SPACE_IO X86_BUS_SPACE_IO
+#define NDIS_BUS_SPACE_MEM X86_BUS_SPACE_MEM
+
+extern image_patch_table hal_functbl[];
+
+__BEGIN_DECLS
+extern int hal_libinit(void);
+extern int hal_libfini(void);
+extern uint8_t KfAcquireSpinLock(kspin_lock *);
+extern void KfReleaseSpinLock(kspin_lock *, uint8_t);
+extern uint8_t KfRaiseIrql(uint8_t);
+extern void KfLowerIrql(uint8_t);
+extern uint8_t KeGetCurrentIrql(void);
+__END_DECLS
+
+#endif /* _HAL_VAR_H_ */
diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c
new file mode 100644
index 0000000..71b4b80
--- /dev/null
+++ b/sys/compat/ndis/kern_ndis.c
@@ -0,0 +1,1433 @@
+/*-
+ * Copyright (c) 2003
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/unistd.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/callout.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/conf.h>
+
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/kthread.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_ioctl.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+
+#include <compat/ndis/pe_var.h>
+#include <compat/ndis/cfg_var.h>
+#include <compat/ndis/resource_var.h>
+#include <compat/ndis/ntoskrnl_var.h>
+#include <compat/ndis/ndis_var.h>
+#include <compat/ndis/hal_var.h>
+#include <compat/ndis/usbd_var.h>
+#include <dev/if_ndis/if_ndisvar.h>
+
+#define NDIS_DUMMY_PATH "\\\\some\\bogus\\path"
+
+static void ndis_status_func(ndis_handle, ndis_status, void *, uint32_t);
+static void ndis_statusdone_func(ndis_handle);
+static void ndis_setdone_func(ndis_handle, ndis_status);
+static void ndis_getdone_func(ndis_handle, ndis_status);
+static void ndis_resetdone_func(ndis_handle, ndis_status, uint8_t);
+static void ndis_sendrsrcavail_func(ndis_handle);
+static void ndis_intrsetup(kdpc *, device_object *,
+ irp *, struct ndis_softc *);
+static void ndis_return(device_object *, void *);
+
+static image_patch_table kernndis_functbl[] = {
+ IMPORT_SFUNC(ndis_status_func, 4),
+ IMPORT_SFUNC(ndis_statusdone_func, 1),
+ IMPORT_SFUNC(ndis_setdone_func, 2),
+ IMPORT_SFUNC(ndis_getdone_func, 2),
+ IMPORT_SFUNC(ndis_resetdone_func, 3),
+ IMPORT_SFUNC(ndis_sendrsrcavail_func, 1),
+ IMPORT_SFUNC(ndis_intrsetup, 4),
+ IMPORT_SFUNC(ndis_return, 1),
+
+ { NULL, NULL, NULL }
+};
+
+static struct nd_head ndis_devhead;
+
+/*
+ * This allows us to export our symbols to other modules.
+ * Note that we call ourselves 'ndisapi' to avoid a namespace
+ * collision with if_ndis.ko, which internally calls itself
+ * 'ndis.'
+ *
+ * Note: some of the subsystems depend on each other, so the
+ * order in which they're started is important. The order of
+ * importance is:
+ *
+ * HAL - spinlocks and IRQL manipulation
+ * ntoskrnl - DPC and workitem threads, object waiting
+ * windrv - driver/device registration
+ *
+ * The HAL should also be the last thing shut down, since
+ * the ntoskrnl subsystem will use spinlocks right up until
+ * the DPC and workitem threads are terminated.
+ */
+
+static int
+ndis_modevent(module_t mod, int cmd, void *arg)
+{
+ int error = 0;
+ image_patch_table *patch;
+
+ switch (cmd) {
+ case MOD_LOAD:
+ /* Initialize subsystems */
+ hal_libinit();
+ ntoskrnl_libinit();
+ windrv_libinit();
+ ndis_libinit();
+ usbd_libinit();
+
+ patch = kernndis_functbl;
+ while (patch->ipt_func != NULL) {
+ windrv_wrap((funcptr)patch->ipt_func,
+ (funcptr *)&patch->ipt_wrap,
+ patch->ipt_argcnt, patch->ipt_ftype);
+ patch++;
+ }
+
+ TAILQ_INIT(&ndis_devhead);
+ break;
+ case MOD_SHUTDOWN:
+ if (TAILQ_FIRST(&ndis_devhead) == NULL) {
+ /* Shut down subsystems */
+ ndis_libfini();
+ usbd_libfini();
+ windrv_libfini();
+ ntoskrnl_libfini();
+ hal_libfini();
+
+ patch = kernndis_functbl;
+ while (patch->ipt_func != NULL) {
+ windrv_unwrap(patch->ipt_wrap);
+ patch++;
+ }
+ }
+ break;
+ case MOD_UNLOAD:
+ /* Shut down subsystems */
+ ndis_libfini();
+ usbd_libfini();
+ windrv_libfini();
+ ntoskrnl_libfini();
+ hal_libfini();
+
+ patch = kernndis_functbl;
+ while (patch->ipt_func != NULL) {
+ windrv_unwrap(patch->ipt_wrap);
+ patch++;
+ }
+
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return (error);
+}
+DEV_MODULE(ndisapi, ndis_modevent, NULL);
+MODULE_VERSION(ndisapi, 1);
+
+static void
+ndis_sendrsrcavail_func(adapter)
+ ndis_handle adapter;
+{
+}
+
+static void
+ndis_status_func(adapter, status, sbuf, slen)
+ ndis_handle adapter;
+ ndis_status status;
+ void *sbuf;
+ uint32_t slen;
+{
+ ndis_miniport_block *block;
+ struct ndis_softc *sc;
+ struct ifnet *ifp;
+
+ block = adapter;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+ ifp = sc->ifp;
+ if (ifp->if_flags & IFF_DEBUG)
+ device_printf(sc->ndis_dev, "status: %x\n", status);
+}
+
+static void
+ndis_statusdone_func(adapter)
+ ndis_handle adapter;
+{
+ ndis_miniport_block *block;
+ struct ndis_softc *sc;
+ struct ifnet *ifp;
+
+ block = adapter;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+ ifp = sc->ifp;
+ if (ifp->if_flags & IFF_DEBUG)
+ device_printf(sc->ndis_dev, "status complete\n");
+}
+
+static void
+ndis_setdone_func(adapter, status)
+ ndis_handle adapter;
+ ndis_status status;
+{
+ ndis_miniport_block *block;
+ block = adapter;
+
+ block->nmb_setstat = status;
+ KeSetEvent(&block->nmb_setevent, IO_NO_INCREMENT, FALSE);
+}
+
+static void
+ndis_getdone_func(adapter, status)
+ ndis_handle adapter;
+ ndis_status status;
+{
+ ndis_miniport_block *block;
+ block = adapter;
+
+ block->nmb_getstat = status;
+ KeSetEvent(&block->nmb_getevent, IO_NO_INCREMENT, FALSE);
+}
+
+static void
+ndis_resetdone_func(ndis_handle adapter, ndis_status status,
+ uint8_t addressingreset)
+{
+ ndis_miniport_block *block;
+ struct ndis_softc *sc;
+ struct ifnet *ifp;
+
+ block = adapter;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+ ifp = sc->ifp;
+
+ if (ifp->if_flags & IFF_DEBUG)
+ device_printf(sc->ndis_dev, "reset done...\n");
+ KeSetEvent(&block->nmb_resetevent, IO_NO_INCREMENT, FALSE);
+}
+
+int
+ndis_create_sysctls(arg)
+ void *arg;
+{
+ struct ndis_softc *sc;
+ ndis_cfg *vals;
+ char buf[256];
+ struct sysctl_oid *oidp;
+ struct sysctl_ctx_entry *e;
+
+ if (arg == NULL)
+ return (EINVAL);
+
+ sc = arg;
+ vals = sc->ndis_regvals;
+
+ TAILQ_INIT(&sc->ndis_cfglist_head);
+
+ /* Add the driver-specific registry keys. */
+
+ while(1) {
+ if (vals->nc_cfgkey == NULL)
+ break;
+
+ if (vals->nc_idx != sc->ndis_devidx) {
+ vals++;
+ continue;
+ }
+
+ /* See if we already have a sysctl with this name */
+
+ oidp = NULL;
+ TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) {
+ oidp = e->entry;
+ if (strcasecmp(oidp->oid_name, vals->nc_cfgkey) == 0)
+ break;
+ oidp = NULL;
+ }
+
+ if (oidp != NULL) {
+ vals++;
+ continue;
+ }
+
+ ndis_add_sysctl(sc, vals->nc_cfgkey, vals->nc_cfgdesc,
+ vals->nc_val, CTLFLAG_RW);
+ vals++;
+ }
+
+ /* Now add a couple of builtin keys. */
+
+ /*
+ * Environment can be either Windows (0) or WindowsNT (1).
+ * We qualify as the latter.
+ */
+ ndis_add_sysctl(sc, "Environment",
+ "Windows environment", "1", CTLFLAG_RD);
+
+ /* NDIS version should be 5.1. */
+ ndis_add_sysctl(sc, "NdisVersion",
+ "NDIS API Version", "0x00050001", CTLFLAG_RD);
+
+ /*
+ * Some miniport drivers rely on the existence of the SlotNumber,
+ * NetCfgInstanceId and DriverDesc keys.
+ */
+ ndis_add_sysctl(sc, "SlotNumber", "Slot Numer", "01", CTLFLAG_RD);
+ ndis_add_sysctl(sc, "NetCfgInstanceId", "NetCfgInstanceId",
+ "{12345678-1234-5678-CAFE0-123456789ABC}", CTLFLAG_RD);
+ ndis_add_sysctl(sc, "DriverDesc", "Driver Description",
+ "NDIS Network Adapter", CTLFLAG_RD);
+
+ /* Bus type (PCI, PCMCIA, etc...) */
+ sprintf(buf, "%d", (int)sc->ndis_iftype);
+ ndis_add_sysctl(sc, "BusType", "Bus Type", buf, CTLFLAG_RD);
+
+ if (sc->ndis_res_io != NULL) {
+ sprintf(buf, "0x%lx", rman_get_start(sc->ndis_res_io));
+ ndis_add_sysctl(sc, "IOBaseAddress",
+ "Base I/O Address", buf, CTLFLAG_RD);
+ }
+
+ if (sc->ndis_irq != NULL) {
+ sprintf(buf, "%lu", rman_get_start(sc->ndis_irq));
+ ndis_add_sysctl(sc, "InterruptNumber",
+ "Interrupt Number", buf, CTLFLAG_RD);
+ }
+
+ return (0);
+}
+
+int
+ndis_add_sysctl(arg, key, desc, val, flag)
+ void *arg;
+ char *key;
+ char *desc;
+ char *val;
+ int flag;
+{
+ struct ndis_softc *sc;
+ struct ndis_cfglist *cfg;
+ char descstr[256];
+
+ sc = arg;
+
+ cfg = malloc(sizeof(struct ndis_cfglist), M_DEVBUF, M_NOWAIT|M_ZERO);
+
+ if (cfg == NULL) {
+ printf("failed for %s\n", key);
+ return (ENOMEM);
+ }
+
+ cfg->ndis_cfg.nc_cfgkey = strdup(key, M_DEVBUF);
+ if (desc == NULL) {
+ snprintf(descstr, sizeof(descstr), "%s (dynamic)", key);
+ cfg->ndis_cfg.nc_cfgdesc = strdup(descstr, M_DEVBUF);
+ } else
+ cfg->ndis_cfg.nc_cfgdesc = strdup(desc, M_DEVBUF);
+ strcpy(cfg->ndis_cfg.nc_val, val);
+
+ TAILQ_INSERT_TAIL(&sc->ndis_cfglist_head, cfg, link);
+
+ cfg->ndis_oid =
+ SYSCTL_ADD_STRING(device_get_sysctl_ctx(sc->ndis_dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(sc->ndis_dev)),
+ OID_AUTO, cfg->ndis_cfg.nc_cfgkey, flag,
+ cfg->ndis_cfg.nc_val, sizeof(cfg->ndis_cfg.nc_val),
+ cfg->ndis_cfg.nc_cfgdesc);
+
+ return (0);
+}
+
+/*
+ * Somewhere, somebody decided "hey, let's automatically create
+ * a sysctl tree for each device instance as it's created -- it'll
+ * make life so much easier!" Lies. Why must they turn the kernel
+ * into a house of lies?
+ */
+
+int
+ndis_flush_sysctls(arg)
+ void *arg;
+{
+ struct ndis_softc *sc;
+ struct ndis_cfglist *cfg;
+ struct sysctl_ctx_list *clist;
+
+ sc = arg;
+
+ clist = device_get_sysctl_ctx(sc->ndis_dev);
+
+ while (!TAILQ_EMPTY(&sc->ndis_cfglist_head)) {
+ cfg = TAILQ_FIRST(&sc->ndis_cfglist_head);
+ TAILQ_REMOVE(&sc->ndis_cfglist_head, cfg, link);
+ sysctl_ctx_entry_del(clist, cfg->ndis_oid);
+ sysctl_remove_oid(cfg->ndis_oid, 1, 0);
+ free(cfg->ndis_cfg.nc_cfgkey, M_DEVBUF);
+ free(cfg->ndis_cfg.nc_cfgdesc, M_DEVBUF);
+ free(cfg, M_DEVBUF);
+ }
+
+ return (0);
+}
+
+void *
+ndis_get_routine_address(functbl, name)
+ struct image_patch_table *functbl;
+ char *name;
+{
+ int i;
+
+ for (i = 0; functbl[i].ipt_name != NULL; i++)
+ if (strcmp(name, functbl[i].ipt_name) == 0)
+ return (functbl[i].ipt_wrap);
+ return (NULL);
+}
+
+static void
+ndis_return(dobj, arg)
+ device_object *dobj;
+ void *arg;
+{
+ ndis_miniport_block *block;
+ ndis_miniport_characteristics *ch;
+ ndis_return_handler returnfunc;
+ ndis_handle adapter;
+ ndis_packet *p;
+ uint8_t irql;
+ list_entry *l;
+
+ block = arg;
+ ch = IoGetDriverObjectExtension(dobj->do_drvobj, (void *)1);
+
+ p = arg;
+ adapter = block->nmb_miniportadapterctx;
+
+ if (adapter == NULL)
+ return;
+
+ returnfunc = ch->nmc_return_packet_func;
+
+ KeAcquireSpinLock(&block->nmb_returnlock, &irql);
+ while (!IsListEmpty(&block->nmb_returnlist)) {
+ l = RemoveHeadList((&block->nmb_returnlist));
+ p = CONTAINING_RECORD(l, ndis_packet, np_list);
+ InitializeListHead((&p->np_list));
+ KeReleaseSpinLock(&block->nmb_returnlock, irql);
+ MSCALL2(returnfunc, adapter, p);
+ KeAcquireSpinLock(&block->nmb_returnlock, &irql);
+ }
+ KeReleaseSpinLock(&block->nmb_returnlock, irql);
+}
+
+void
+ndis_return_packet(buf, arg)
+ void *buf; /* not used */
+ void *arg;
+{
+ ndis_packet *p;
+ ndis_miniport_block *block;
+
+ if (arg == NULL)
+ return;
+
+ p = arg;
+
+ /* Decrement refcount. */
+ p->np_refcnt--;
+
+ /* Release packet when refcount hits zero, otherwise return. */
+ if (p->np_refcnt)
+ return;
+
+ block = ((struct ndis_softc *)p->np_softc)->ndis_block;
+
+ KeAcquireSpinLockAtDpcLevel(&block->nmb_returnlock);
+ InitializeListHead((&p->np_list));
+ InsertHeadList((&block->nmb_returnlist), (&p->np_list));
+ KeReleaseSpinLockFromDpcLevel(&block->nmb_returnlock);
+
+ IoQueueWorkItem(block->nmb_returnitem,
+ (io_workitem_func)kernndis_functbl[7].ipt_wrap,
+ WORKQUEUE_CRITICAL, block);
+}
+
+void
+ndis_free_bufs(b0)
+ ndis_buffer *b0;
+{
+ ndis_buffer *next;
+
+ if (b0 == NULL)
+ return;
+
+ while(b0 != NULL) {
+ next = b0->mdl_next;
+ IoFreeMdl(b0);
+ b0 = next;
+ }
+}
+
+void
+ndis_free_packet(p)
+ ndis_packet *p;
+{
+ if (p == NULL)
+ return;
+
+ ndis_free_bufs(p->np_private.npp_head);
+ NdisFreePacket(p);
+}
+
+int
+ndis_convert_res(arg)
+ void *arg;
+{
+ struct ndis_softc *sc;
+ ndis_resource_list *rl = NULL;
+ cm_partial_resource_desc *prd = NULL;
+ ndis_miniport_block *block;
+ device_t dev;
+ struct resource_list *brl;
+ struct resource_list_entry *brle;
+ int error = 0;
+
+ sc = arg;
+ block = sc->ndis_block;
+ dev = sc->ndis_dev;
+
+ rl = malloc(sizeof(ndis_resource_list) +
+ (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1)),
+ M_DEVBUF, M_NOWAIT|M_ZERO);
+
+ if (rl == NULL)
+ return (ENOMEM);
+
+ rl->cprl_version = 5;
+ rl->cprl_revision = 1;
+ rl->cprl_count = sc->ndis_rescnt;
+ prd = rl->cprl_partial_descs;
+
+ brl = BUS_GET_RESOURCE_LIST(dev, dev);
+
+ if (brl != NULL) {
+
+ STAILQ_FOREACH(brle, brl, link) {
+ switch (brle->type) {
+ case SYS_RES_IOPORT:
+ prd->cprd_type = CmResourceTypePort;
+ prd->cprd_flags = CM_RESOURCE_PORT_IO;
+ prd->cprd_sharedisp =
+ CmResourceShareDeviceExclusive;
+ prd->u.cprd_port.cprd_start.np_quad =
+ brle->start;
+ prd->u.cprd_port.cprd_len = brle->count;
+ break;
+ case SYS_RES_MEMORY:
+ prd->cprd_type = CmResourceTypeMemory;
+ prd->cprd_flags =
+ CM_RESOURCE_MEMORY_READ_WRITE;
+ prd->cprd_sharedisp =
+ CmResourceShareDeviceExclusive;
+ prd->u.cprd_mem.cprd_start.np_quad =
+ brle->start;
+ prd->u.cprd_mem.cprd_len = brle->count;
+ break;
+ case SYS_RES_IRQ:
+ prd->cprd_type = CmResourceTypeInterrupt;
+ prd->cprd_flags = 0;
+ /*
+ * Always mark interrupt resources as
+ * shared, since in our implementation,
+ * they will be.
+ */
+ prd->cprd_sharedisp =
+ CmResourceShareShared;
+ prd->u.cprd_intr.cprd_level = brle->start;
+ prd->u.cprd_intr.cprd_vector = brle->start;
+ prd->u.cprd_intr.cprd_affinity = 0;
+ break;
+ default:
+ break;
+ }
+ prd++;
+ }
+ }
+
+ block->nmb_rlist = rl;
+
+ return (error);
+}
+
+/*
+ * Map an NDIS packet to an mbuf list. When an NDIS driver receives a
+ * packet, it will hand it to us in the form of an ndis_packet,
+ * which we need to convert to an mbuf that is then handed off
+ * to the stack. Note: we configure the mbuf list so that it uses
+ * the memory regions specified by the ndis_buffer structures in
+ * the ndis_packet as external storage. In most cases, this will
+ * point to a memory region allocated by the driver (either by
+ * ndis_malloc_withtag() or ndis_alloc_sharedmem()). We expect
+ * the driver to handle free()ing this region for is, so we set up
+ * a dummy no-op free handler for it.
+ */
+
+int
+ndis_ptom(m0, p)
+ struct mbuf **m0;
+ ndis_packet *p;
+{
+ struct mbuf *m = NULL, *prev = NULL;
+ ndis_buffer *buf;
+ ndis_packet_private *priv;
+ uint32_t totlen = 0;
+ struct ifnet *ifp;
+ struct ether_header *eh;
+ int diff;
+
+ if (p == NULL || m0 == NULL)
+ return (EINVAL);
+
+ priv = &p->np_private;
+ buf = priv->npp_head;
+ p->np_refcnt = 0;
+
+ for (buf = priv->npp_head; buf != NULL; buf = buf->mdl_next) {
+ if (buf == priv->npp_head)
+ m = m_gethdr(M_NOWAIT, MT_DATA);
+ else
+ m = m_get(M_NOWAIT, MT_DATA);
+ if (m == NULL) {
+ m_freem(*m0);
+ *m0 = NULL;
+ return (ENOBUFS);
+ }
+ m->m_len = MmGetMdlByteCount(buf);
+ m->m_data = MmGetMdlVirtualAddress(buf);
+ MEXTADD(m, m->m_data, m->m_len, ndis_return_packet,
+ m->m_data, p, 0, EXT_NDIS);
+ p->np_refcnt++;
+
+ totlen += m->m_len;
+ if (m->m_flags & M_PKTHDR)
+ *m0 = m;
+ else
+ prev->m_next = m;
+ prev = m;
+ }
+
+ /*
+ * This is a hack to deal with the Marvell 8335 driver
+ * which, when associated with an AP in WPA-PSK mode,
+ * seems to overpad its frames by 8 bytes. I don't know
+ * that the extra 8 bytes are for, and they're not there
+ * in open mode, so for now clamp the frame size at 1514
+ * until I can figure out how to deal with this properly,
+ * otherwise if_ethersubr() will spank us by discarding
+ * the 'oversize' frames.
+ */
+
+ eh = mtod((*m0), struct ether_header *);
+ ifp = ((struct ndis_softc *)p->np_softc)->ifp;
+ if (totlen > ETHER_MAX_FRAME(ifp, eh->ether_type, FALSE)) {
+ diff = totlen - ETHER_MAX_FRAME(ifp, eh->ether_type, FALSE);
+ totlen -= diff;
+ m->m_len -= diff;
+ }
+ (*m0)->m_pkthdr.len = totlen;
+
+ return (0);
+}
+
+/*
+ * Create an NDIS packet from an mbuf chain.
+ * This is used mainly when transmitting packets, where we need
+ * to turn an mbuf off an interface's send queue and transform it
+ * into an NDIS packet which will be fed into the NDIS driver's
+ * send routine.
+ *
+ * NDIS packets consist of two parts: an ndis_packet structure,
+ * which is vaguely analagous to the pkthdr portion of an mbuf,
+ * and one or more ndis_buffer structures, which define the
+ * actual memory segments in which the packet data resides.
+ * We need to allocate one ndis_buffer for each mbuf in a chain,
+ * plus one ndis_packet as the header.
+ */
+
+int
+ndis_mtop(m0, p)
+ struct mbuf *m0;
+ ndis_packet **p;
+{
+ struct mbuf *m;
+ ndis_buffer *buf = NULL, *prev = NULL;
+ ndis_packet_private *priv;
+
+ if (p == NULL || *p == NULL || m0 == NULL)
+ return (EINVAL);
+
+ priv = &(*p)->np_private;
+ priv->npp_totlen = m0->m_pkthdr.len;
+
+ for (m = m0; m != NULL; m = m->m_next) {
+ if (m->m_len == 0)
+ continue;
+ buf = IoAllocateMdl(m->m_data, m->m_len, FALSE, FALSE, NULL);
+ if (buf == NULL) {
+ ndis_free_packet(*p);
+ *p = NULL;
+ return (ENOMEM);
+ }
+ MmBuildMdlForNonPagedPool(buf);
+
+ if (priv->npp_head == NULL)
+ priv->npp_head = buf;
+ else
+ prev->mdl_next = buf;
+ prev = buf;
+ }
+
+ priv->npp_tail = buf;
+
+ return (0);
+}
+
+int
+ndis_get_supported_oids(arg, oids, oidcnt)
+ void *arg;
+ ndis_oid **oids;
+ int *oidcnt;
+{
+ int len, rval;
+ ndis_oid *o;
+
+ if (arg == NULL || oids == NULL || oidcnt == NULL)
+ return (EINVAL);
+ len = 0;
+ ndis_get_info(arg, OID_GEN_SUPPORTED_LIST, NULL, &len);
+
+ o = malloc(len, M_DEVBUF, M_NOWAIT);
+ if (o == NULL)
+ return (ENOMEM);
+
+ rval = ndis_get_info(arg, OID_GEN_SUPPORTED_LIST, o, &len);
+
+ if (rval) {
+ free(o, M_DEVBUF);
+ return (rval);
+ }
+
+ *oids = o;
+ *oidcnt = len / 4;
+
+ return (0);
+}
+
+int
+ndis_set_info(arg, oid, buf, buflen)
+ void *arg;
+ ndis_oid oid;
+ void *buf;
+ int *buflen;
+{
+ struct ndis_softc *sc;
+ ndis_status rval;
+ ndis_handle adapter;
+ ndis_setinfo_handler setfunc;
+ uint32_t byteswritten = 0, bytesneeded = 0;
+ uint8_t irql;
+ uint64_t duetime;
+
+ /*
+ * According to the NDIS spec, MiniportQueryInformation()
+ * and MiniportSetInformation() requests are handled serially:
+ * once one request has been issued, we must wait for it to
+ * finish before allowing another request to proceed.
+ */
+
+ sc = arg;
+
+ KeResetEvent(&sc->ndis_block->nmb_setevent);
+
+ KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql);
+
+ if (sc->ndis_block->nmb_pendingreq != NULL) {
+ KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
+ panic("ndis_set_info() called while other request pending");
+ } else
+ sc->ndis_block->nmb_pendingreq = (ndis_request *)sc;
+
+ setfunc = sc->ndis_chars->nmc_setinfo_func;
+ adapter = sc->ndis_block->nmb_miniportadapterctx;
+
+ if (adapter == NULL || setfunc == NULL ||
+ sc->ndis_block->nmb_devicectx == NULL) {
+ sc->ndis_block->nmb_pendingreq = NULL;
+ KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
+ return (ENXIO);
+ }
+
+ rval = MSCALL6(setfunc, adapter, oid, buf, *buflen,
+ &byteswritten, &bytesneeded);
+
+ sc->ndis_block->nmb_pendingreq = NULL;
+
+ KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
+
+ if (rval == NDIS_STATUS_PENDING) {
+ /* Wait up to 5 seconds. */
+ duetime = (5 * 1000000) * -10;
+ KeWaitForSingleObject(&sc->ndis_block->nmb_setevent,
+ 0, 0, FALSE, &duetime);
+ rval = sc->ndis_block->nmb_setstat;
+ }
+
+ if (byteswritten)
+ *buflen = byteswritten;
+ if (bytesneeded)
+ *buflen = bytesneeded;
+
+ if (rval == NDIS_STATUS_INVALID_LENGTH)
+ return (ENOSPC);
+
+ if (rval == NDIS_STATUS_INVALID_OID)
+ return (EINVAL);
+
+ if (rval == NDIS_STATUS_NOT_SUPPORTED ||
+ rval == NDIS_STATUS_NOT_ACCEPTED)
+ return (ENOTSUP);
+
+ if (rval != NDIS_STATUS_SUCCESS)
+ return (ENODEV);
+
+ return (0);
+}
+
+typedef void (*ndis_senddone_func)(ndis_handle, ndis_packet *, ndis_status);
+
+int
+ndis_send_packets(arg, packets, cnt)
+ void *arg;
+ ndis_packet **packets;
+ int cnt;
+{
+ struct ndis_softc *sc;
+ ndis_handle adapter;
+ ndis_sendmulti_handler sendfunc;
+ ndis_senddone_func senddonefunc;
+ int i;
+ ndis_packet *p;
+ uint8_t irql = 0;
+
+ sc = arg;
+ adapter = sc->ndis_block->nmb_miniportadapterctx;
+ if (adapter == NULL)
+ return (ENXIO);
+ sendfunc = sc->ndis_chars->nmc_sendmulti_func;
+ senddonefunc = sc->ndis_block->nmb_senddone_func;
+
+ if (NDIS_SERIALIZED(sc->ndis_block))
+ KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql);
+
+ MSCALL3(sendfunc, adapter, packets, cnt);
+
+ for (i = 0; i < cnt; i++) {
+ p = packets[i];
+ /*
+ * Either the driver already handed the packet to
+ * ndis_txeof() due to a failure, or it wants to keep
+ * it and release it asynchronously later. Skip to the
+ * next one.
+ */
+ if (p == NULL || p->np_oob.npo_status == NDIS_STATUS_PENDING)
+ continue;
+ MSCALL3(senddonefunc, sc->ndis_block, p, p->np_oob.npo_status);
+ }
+
+ if (NDIS_SERIALIZED(sc->ndis_block))
+ KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
+
+ return (0);
+}
+
+int
+ndis_send_packet(arg, packet)
+ void *arg;
+ ndis_packet *packet;
+{
+ struct ndis_softc *sc;
+ ndis_handle adapter;
+ ndis_status status;
+ ndis_sendsingle_handler sendfunc;
+ ndis_senddone_func senddonefunc;
+ uint8_t irql = 0;
+
+ sc = arg;
+ adapter = sc->ndis_block->nmb_miniportadapterctx;
+ if (adapter == NULL)
+ return (ENXIO);
+ sendfunc = sc->ndis_chars->nmc_sendsingle_func;
+ senddonefunc = sc->ndis_block->nmb_senddone_func;
+
+ if (NDIS_SERIALIZED(sc->ndis_block))
+ KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql);
+ status = MSCALL3(sendfunc, adapter, packet,
+ packet->np_private.npp_flags);
+
+ if (status == NDIS_STATUS_PENDING) {
+ if (NDIS_SERIALIZED(sc->ndis_block))
+ KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
+ return (0);
+ }
+
+ MSCALL3(senddonefunc, sc->ndis_block, packet, status);
+
+ if (NDIS_SERIALIZED(sc->ndis_block))
+ KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
+
+ return (0);
+}
+
+int
+ndis_init_dma(arg)
+ void *arg;
+{
+ struct ndis_softc *sc;
+ int i, error;
+
+ sc = arg;
+
+ sc->ndis_tmaps = malloc(sizeof(bus_dmamap_t) * sc->ndis_maxpkts,
+ M_DEVBUF, M_NOWAIT|M_ZERO);
+
+ if (sc->ndis_tmaps == NULL)
+ return (ENOMEM);
+
+ for (i = 0; i < sc->ndis_maxpkts; i++) {
+ error = bus_dmamap_create(sc->ndis_ttag, 0,
+ &sc->ndis_tmaps[i]);
+ if (error) {
+ free(sc->ndis_tmaps, M_DEVBUF);
+ return (ENODEV);
+ }
+ }
+
+ return (0);
+}
+
+int
+ndis_destroy_dma(arg)
+ void *arg;
+{
+ struct ndis_softc *sc;
+ struct mbuf *m;
+ ndis_packet *p = NULL;
+ int i;
+
+ sc = arg;
+
+ for (i = 0; i < sc->ndis_maxpkts; i++) {
+ if (sc->ndis_txarray[i] != NULL) {
+ p = sc->ndis_txarray[i];
+ m = (struct mbuf *)p->np_rsvd[1];
+ if (m != NULL)
+ m_freem(m);
+ ndis_free_packet(sc->ndis_txarray[i]);
+ }
+ bus_dmamap_destroy(sc->ndis_ttag, sc->ndis_tmaps[i]);
+ }
+
+ free(sc->ndis_tmaps, M_DEVBUF);
+
+ bus_dma_tag_destroy(sc->ndis_ttag);
+
+ return (0);
+}
+
+int
+ndis_reset_nic(arg)
+ void *arg;
+{
+ struct ndis_softc *sc;
+ ndis_handle adapter;
+ ndis_reset_handler resetfunc;
+ uint8_t addressing_reset;
+ int rval;
+ uint8_t irql = 0;
+
+ sc = arg;
+
+ NDIS_LOCK(sc);
+ adapter = sc->ndis_block->nmb_miniportadapterctx;
+ resetfunc = sc->ndis_chars->nmc_reset_func;
+
+ if (adapter == NULL || resetfunc == NULL ||
+ sc->ndis_block->nmb_devicectx == NULL) {
+ NDIS_UNLOCK(sc);
+ return (EIO);
+ }
+
+ NDIS_UNLOCK(sc);
+
+ KeResetEvent(&sc->ndis_block->nmb_resetevent);
+
+ if (NDIS_SERIALIZED(sc->ndis_block))
+ KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql);
+
+ rval = MSCALL2(resetfunc, &addressing_reset, adapter);
+
+ if (NDIS_SERIALIZED(sc->ndis_block))
+ KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
+
+ if (rval == NDIS_STATUS_PENDING)
+ KeWaitForSingleObject(&sc->ndis_block->nmb_resetevent,
+ 0, 0, FALSE, NULL);
+
+ return (0);
+}
+
+int
+ndis_halt_nic(arg)
+ void *arg;
+{
+ struct ndis_softc *sc;
+ ndis_handle adapter;
+ ndis_halt_handler haltfunc;
+ ndis_miniport_block *block;
+ int empty = 0;
+ uint8_t irql;
+
+ sc = arg;
+ block = sc->ndis_block;
+
+ if (!cold)
+ KeFlushQueuedDpcs();
+
+ /*
+ * Wait for all packets to be returned.
+ */
+
+ while (1) {
+ KeAcquireSpinLock(&block->nmb_returnlock, &irql);
+ empty = IsListEmpty(&block->nmb_returnlist);
+ KeReleaseSpinLock(&block->nmb_returnlock, irql);
+ if (empty)
+ break;
+ NdisMSleep(1000);
+ }
+
+ NDIS_LOCK(sc);
+ adapter = sc->ndis_block->nmb_miniportadapterctx;
+ if (adapter == NULL) {
+ NDIS_UNLOCK(sc);
+ return (EIO);
+ }
+
+ sc->ndis_block->nmb_devicectx = NULL;
+
+ /*
+ * The adapter context is only valid after the init
+ * handler has been called, and is invalid once the
+ * halt handler has been called.
+ */
+
+ haltfunc = sc->ndis_chars->nmc_halt_func;
+ NDIS_UNLOCK(sc);
+
+ MSCALL1(haltfunc, adapter);
+
+ NDIS_LOCK(sc);
+ sc->ndis_block->nmb_miniportadapterctx = NULL;
+ NDIS_UNLOCK(sc);
+
+ return (0);
+}
+
+int
+ndis_shutdown_nic(arg)
+ void *arg;
+{
+ struct ndis_softc *sc;
+ ndis_handle adapter;
+ ndis_shutdown_handler shutdownfunc;
+
+ sc = arg;
+ NDIS_LOCK(sc);
+ adapter = sc->ndis_block->nmb_miniportadapterctx;
+ shutdownfunc = sc->ndis_chars->nmc_shutdown_handler;
+ NDIS_UNLOCK(sc);
+ if (adapter == NULL || shutdownfunc == NULL)
+ return (EIO);
+
+ if (sc->ndis_chars->nmc_rsvd0 == NULL)
+ MSCALL1(shutdownfunc, adapter);
+ else
+ MSCALL1(shutdownfunc, sc->ndis_chars->nmc_rsvd0);
+
+ TAILQ_REMOVE(&ndis_devhead, sc->ndis_block, link);
+
+ return (0);
+}
+
+int
+ndis_pnpevent_nic(arg, type)
+ void *arg;
+ int type;
+{
+ device_t dev;
+ struct ndis_softc *sc;
+ ndis_handle adapter;
+ ndis_pnpevent_handler pnpeventfunc;
+
+ dev = arg;
+ sc = device_get_softc(arg);
+ NDIS_LOCK(sc);
+ adapter = sc->ndis_block->nmb_miniportadapterctx;
+ pnpeventfunc = sc->ndis_chars->nmc_pnpevent_handler;
+ NDIS_UNLOCK(sc);
+ if (adapter == NULL || pnpeventfunc == NULL)
+ return (EIO);
+
+ if (sc->ndis_chars->nmc_rsvd0 == NULL)
+ MSCALL4(pnpeventfunc, adapter, type, NULL, 0);
+ else
+ MSCALL4(pnpeventfunc, sc->ndis_chars->nmc_rsvd0, type, NULL, 0);
+
+ return (0);
+}
+
+int
+ndis_init_nic(arg)
+ void *arg;
+{
+ struct ndis_softc *sc;
+ ndis_miniport_block *block;
+ ndis_init_handler initfunc;
+ ndis_status status, openstatus = 0;
+ ndis_medium mediumarray[NdisMediumMax];
+ uint32_t chosenmedium, i;
+
+ if (arg == NULL)
+ return (EINVAL);
+
+ sc = arg;
+ NDIS_LOCK(sc);
+ block = sc->ndis_block;
+ initfunc = sc->ndis_chars->nmc_init_func;
+ NDIS_UNLOCK(sc);
+
+ sc->ndis_block->nmb_timerlist = NULL;
+
+ for (i = 0; i < NdisMediumMax; i++)
+ mediumarray[i] = i;
+
+ status = MSCALL6(initfunc, &openstatus, &chosenmedium,
+ mediumarray, NdisMediumMax, block, block);
+
+ /*
+ * If the init fails, blow away the other exported routines
+ * we obtained from the driver so we can't call them later.
+ * If the init failed, none of these will work.
+ */
+ if (status != NDIS_STATUS_SUCCESS) {
+ NDIS_LOCK(sc);
+ sc->ndis_block->nmb_miniportadapterctx = NULL;
+ NDIS_UNLOCK(sc);
+ return (ENXIO);
+ }
+
+ /*
+ * This may look really goofy, but apparently it is possible
+ * to halt a miniport too soon after it's been initialized.
+ * After MiniportInitialize() finishes, pause for 1 second
+ * to give the chip a chance to handle any short-lived timers
+ * that were set in motion. If we call MiniportHalt() too soon,
+ * some of the timers may not be cancelled, because the driver
+ * expects them to fire before the halt is called.
+ */
+
+ pause("ndwait", hz);
+
+ NDIS_LOCK(sc);
+ sc->ndis_block->nmb_devicectx = sc;
+ NDIS_UNLOCK(sc);
+
+ return (0);
+}
+
+static void
+ndis_intrsetup(dpc, dobj, ip, sc)
+ kdpc *dpc;
+ device_object *dobj;
+ irp *ip;
+ struct ndis_softc *sc;
+{
+ ndis_miniport_interrupt *intr;
+
+ intr = sc->ndis_block->nmb_interrupt;
+
+ /* Sanity check. */
+
+ if (intr == NULL)
+ return;
+
+ KeAcquireSpinLockAtDpcLevel(&intr->ni_dpccountlock);
+ KeResetEvent(&intr->ni_dpcevt);
+ if (KeInsertQueueDpc(&intr->ni_dpc, NULL, NULL) == TRUE)
+ intr->ni_dpccnt++;
+ KeReleaseSpinLockFromDpcLevel(&intr->ni_dpccountlock);
+}
+
+int
+ndis_get_info(arg, oid, buf, buflen)
+ void *arg;
+ ndis_oid oid;
+ void *buf;
+ int *buflen;
+{
+ struct ndis_softc *sc;
+ ndis_status rval;
+ ndis_handle adapter;
+ ndis_queryinfo_handler queryfunc;
+ uint32_t byteswritten = 0, bytesneeded = 0;
+ uint8_t irql;
+ uint64_t duetime;
+
+ sc = arg;
+
+ KeResetEvent(&sc->ndis_block->nmb_getevent);
+
+ KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql);
+
+ if (sc->ndis_block->nmb_pendingreq != NULL) {
+ KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
+ panic("ndis_get_info() called while other request pending");
+ } else
+ sc->ndis_block->nmb_pendingreq = (ndis_request *)sc;
+
+ queryfunc = sc->ndis_chars->nmc_queryinfo_func;
+ adapter = sc->ndis_block->nmb_miniportadapterctx;
+
+ if (adapter == NULL || queryfunc == NULL ||
+ sc->ndis_block->nmb_devicectx == NULL) {
+ sc->ndis_block->nmb_pendingreq = NULL;
+ KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
+ return (ENXIO);
+ }
+
+ rval = MSCALL6(queryfunc, adapter, oid, buf, *buflen,
+ &byteswritten, &bytesneeded);
+
+ sc->ndis_block->nmb_pendingreq = NULL;
+
+ KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
+
+ /* Wait for requests that block. */
+
+ if (rval == NDIS_STATUS_PENDING) {
+ /* Wait up to 5 seconds. */
+ duetime = (5 * 1000000) * -10;
+ KeWaitForSingleObject(&sc->ndis_block->nmb_getevent,
+ 0, 0, FALSE, &duetime);
+ rval = sc->ndis_block->nmb_getstat;
+ }
+
+ if (byteswritten)
+ *buflen = byteswritten;
+ if (bytesneeded)
+ *buflen = bytesneeded;
+
+ if (rval == NDIS_STATUS_INVALID_LENGTH ||
+ rval == NDIS_STATUS_BUFFER_TOO_SHORT)
+ return (ENOSPC);
+
+ if (rval == NDIS_STATUS_INVALID_OID)
+ return (EINVAL);
+
+ if (rval == NDIS_STATUS_NOT_SUPPORTED ||
+ rval == NDIS_STATUS_NOT_ACCEPTED)
+ return (ENOTSUP);
+
+ if (rval != NDIS_STATUS_SUCCESS)
+ return (ENODEV);
+
+ return (0);
+}
+
+uint32_t
+NdisAddDevice(drv, pdo)
+ driver_object *drv;
+ device_object *pdo;
+{
+ device_object *fdo;
+ ndis_miniport_block *block;
+ struct ndis_softc *sc;
+ uint32_t status;
+ int error;
+
+ sc = device_get_softc(pdo->do_devext);
+
+ if (sc->ndis_iftype == PCMCIABus || sc->ndis_iftype == PCIBus) {
+ error = bus_setup_intr(sc->ndis_dev, sc->ndis_irq,
+ INTR_TYPE_NET | INTR_MPSAFE,
+ NULL, ntoskrnl_intr, NULL, &sc->ndis_intrhand);
+ if (error)
+ return (NDIS_STATUS_FAILURE);
+ }
+
+ status = IoCreateDevice(drv, sizeof(ndis_miniport_block), NULL,
+ FILE_DEVICE_UNKNOWN, 0, FALSE, &fdo);
+
+ if (status != STATUS_SUCCESS)
+ return (status);
+
+ block = fdo->do_devext;
+
+ block->nmb_filterdbs.nf_ethdb = block;
+ block->nmb_deviceobj = fdo;
+ block->nmb_physdeviceobj = pdo;
+ block->nmb_nextdeviceobj = IoAttachDeviceToDeviceStack(fdo, pdo);
+ KeInitializeSpinLock(&block->nmb_lock);
+ KeInitializeSpinLock(&block->nmb_returnlock);
+ KeInitializeEvent(&block->nmb_getevent, EVENT_TYPE_NOTIFY, TRUE);
+ KeInitializeEvent(&block->nmb_setevent, EVENT_TYPE_NOTIFY, TRUE);
+ KeInitializeEvent(&block->nmb_resetevent, EVENT_TYPE_NOTIFY, TRUE);
+ InitializeListHead(&block->nmb_parmlist);
+ InitializeListHead(&block->nmb_returnlist);
+ block->nmb_returnitem = IoAllocateWorkItem(fdo);
+
+ /*
+ * Stash pointers to the miniport block and miniport
+ * characteristics info in the if_ndis softc so the
+ * UNIX wrapper driver can get to them later.
+ */
+ sc->ndis_block = block;
+ sc->ndis_chars = IoGetDriverObjectExtension(drv, (void *)1);
+
+ /*
+ * If the driver has a MiniportTransferData() function,
+ * we should allocate a private RX packet pool.
+ */
+
+ if (sc->ndis_chars->nmc_transferdata_func != NULL) {
+ NdisAllocatePacketPool(&status, &block->nmb_rxpool,
+ 32, PROTOCOL_RESERVED_SIZE_IN_PACKET);
+ if (status != NDIS_STATUS_SUCCESS) {
+ IoDetachDevice(block->nmb_nextdeviceobj);
+ IoDeleteDevice(fdo);
+ return (status);
+ }
+ InitializeListHead((&block->nmb_packetlist));
+ }
+
+ /* Give interrupt handling priority over timers. */
+ IoInitializeDpcRequest(fdo, kernndis_functbl[6].ipt_wrap);
+ KeSetImportanceDpc(&fdo->do_dpc, KDPC_IMPORTANCE_HIGH);
+
+ /* Finish up BSD-specific setup. */
+
+ block->nmb_signature = (void *)0xcafebabe;
+ block->nmb_status_func = kernndis_functbl[0].ipt_wrap;
+ block->nmb_statusdone_func = kernndis_functbl[1].ipt_wrap;
+ block->nmb_setdone_func = kernndis_functbl[2].ipt_wrap;
+ block->nmb_querydone_func = kernndis_functbl[3].ipt_wrap;
+ block->nmb_resetdone_func = kernndis_functbl[4].ipt_wrap;
+ block->nmb_sendrsrc_func = kernndis_functbl[5].ipt_wrap;
+ block->nmb_pendingreq = NULL;
+
+ TAILQ_INSERT_TAIL(&ndis_devhead, block, link);
+
+ return (STATUS_SUCCESS);
+}
+
+int
+ndis_unload_driver(arg)
+ void *arg;
+{
+ struct ndis_softc *sc;
+ device_object *fdo;
+
+ sc = arg;
+
+ if (sc->ndis_intrhand)
+ bus_teardown_intr(sc->ndis_dev,
+ sc->ndis_irq, sc->ndis_intrhand);
+
+ if (sc->ndis_block->nmb_rlist != NULL)
+ free(sc->ndis_block->nmb_rlist, M_DEVBUF);
+
+ ndis_flush_sysctls(sc);
+
+ TAILQ_REMOVE(&ndis_devhead, sc->ndis_block, link);
+
+ if (sc->ndis_chars->nmc_transferdata_func != NULL)
+ NdisFreePacketPool(sc->ndis_block->nmb_rxpool);
+ fdo = sc->ndis_block->nmb_deviceobj;
+ IoFreeWorkItem(sc->ndis_block->nmb_returnitem);
+ IoDetachDevice(sc->ndis_block->nmb_nextdeviceobj);
+ IoDeleteDevice(fdo);
+
+ return (0);
+}
diff --git a/sys/compat/ndis/kern_windrv.c b/sys/compat/ndis/kern_windrv.c
new file mode 100644
index 0000000..5572988
--- /dev/null
+++ b/sys/compat/ndis/kern_windrv.c
@@ -0,0 +1,988 @@
+/*-
+ * Copyright (c) 2005
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/unistd.h>
+#include <sys/types.h>
+
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/module.h>
+#include <sys/conf.h>
+#include <sys/mbuf.h>
+#include <sys/bus.h>
+#include <sys/proc.h>
+#include <sys/sched.h>
+#include <sys/smp.h>
+
+#include <sys/queue.h>
+
+#ifdef __i386__
+#include <machine/segments.h>
+#endif
+
+#include <dev/usb/usb.h>
+
+#include <compat/ndis/pe_var.h>
+#include <compat/ndis/cfg_var.h>
+#include <compat/ndis/resource_var.h>
+#include <compat/ndis/ntoskrnl_var.h>
+#include <compat/ndis/ndis_var.h>
+#include <compat/ndis/hal_var.h>
+#include <compat/ndis/usbd_var.h>
+
+static struct mtx drvdb_mtx;
+static STAILQ_HEAD(drvdb, drvdb_ent) drvdb_head;
+
+static driver_object fake_pci_driver; /* serves both PCI and cardbus */
+static driver_object fake_pccard_driver;
+
+#ifdef __i386__
+static void x86_oldldt(void *);
+static void x86_newldt(void *);
+
+struct tid {
+ void *tid_except_list; /* 0x00 */
+ uint32_t tid_oldfs; /* 0x04 */
+ uint32_t tid_selector; /* 0x08 */
+ struct tid *tid_self; /* 0x0C */
+ int tid_cpu; /* 0x10 */
+};
+
+static struct tid *my_tids;
+#endif /* __i386__ */
+
+#define DUMMY_REGISTRY_PATH "\\\\some\\bogus\\path"
+
+int
+windrv_libinit(void)
+{
+ STAILQ_INIT(&drvdb_head);
+ mtx_init(&drvdb_mtx, "Windows driver DB lock",
+ "Windows internal lock", MTX_DEF);
+
+ /*
+ * PCI and pccard devices don't need to use IRPs to
+ * interact with their bus drivers (usually), so our
+ * emulated PCI and pccard drivers are just stubs.
+ * USB devices, on the other hand, do all their I/O
+ * by exchanging IRPs with the USB bus driver, so
+ * for that we need to provide emulator dispatcher
+ * routines, which are in a separate module.
+ */
+
+ windrv_bus_attach(&fake_pci_driver, "PCI Bus");
+ windrv_bus_attach(&fake_pccard_driver, "PCCARD Bus");
+
+#ifdef __i386__
+
+ /*
+ * In order to properly support SMP machines, we have
+ * to modify the GDT on each CPU, since we never know
+ * on which one we'll end up running.
+ */
+
+ my_tids = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(struct tid) * mp_ncpus, 0);
+ if (my_tids == NULL)
+ panic("failed to allocate thread info blocks");
+ smp_rendezvous(NULL, x86_newldt, NULL, NULL);
+#endif
+ return (0);
+}
+
+int
+windrv_libfini(void)
+{
+ struct drvdb_ent *d;
+
+ mtx_lock(&drvdb_mtx);
+ while(STAILQ_FIRST(&drvdb_head) != NULL) {
+ d = STAILQ_FIRST(&drvdb_head);
+ STAILQ_REMOVE_HEAD(&drvdb_head, link);
+ free(d, M_DEVBUF);
+ }
+ mtx_unlock(&drvdb_mtx);
+
+ RtlFreeUnicodeString(&fake_pci_driver.dro_drivername);
+ RtlFreeUnicodeString(&fake_pccard_driver.dro_drivername);
+
+ mtx_destroy(&drvdb_mtx);
+
+#ifdef __i386__
+ smp_rendezvous(NULL, x86_oldldt, NULL, NULL);
+ ExFreePool(my_tids);
+#endif
+ return (0);
+}
+
+/*
+ * Given the address of a driver image, find its corresponding
+ * driver_object.
+ */
+
+driver_object *
+windrv_lookup(img, name)
+ vm_offset_t img;
+ char *name;
+{
+ struct drvdb_ent *d;
+ unicode_string us;
+ ansi_string as;
+
+ bzero((char *)&us, sizeof(us));
+
+ /* Damn unicode. */
+
+ if (name != NULL) {
+ RtlInitAnsiString(&as, name);
+ if (RtlAnsiStringToUnicodeString(&us, &as, TRUE))
+ return (NULL);
+ }
+
+ mtx_lock(&drvdb_mtx);
+ STAILQ_FOREACH(d, &drvdb_head, link) {
+ if (d->windrv_object->dro_driverstart == (void *)img ||
+ (bcmp((char *)d->windrv_object->dro_drivername.us_buf,
+ (char *)us.us_buf, us.us_len) == 0 && us.us_len)) {
+ mtx_unlock(&drvdb_mtx);
+ if (name != NULL)
+ ExFreePool(us.us_buf);
+ return (d->windrv_object);
+ }
+ }
+ mtx_unlock(&drvdb_mtx);
+
+ if (name != NULL)
+ RtlFreeUnicodeString(&us);
+
+ return (NULL);
+}
+
+struct drvdb_ent *
+windrv_match(matchfunc, ctx)
+ matchfuncptr matchfunc;
+ void *ctx;
+{
+ struct drvdb_ent *d;
+ int match;
+
+ mtx_lock(&drvdb_mtx);
+ STAILQ_FOREACH(d, &drvdb_head, link) {
+ if (d->windrv_devlist == NULL)
+ continue;
+ match = matchfunc(d->windrv_bustype, d->windrv_devlist, ctx);
+ if (match == TRUE) {
+ mtx_unlock(&drvdb_mtx);
+ return (d);
+ }
+ }
+ mtx_unlock(&drvdb_mtx);
+
+ return (NULL);
+}
+
+/*
+ * Remove a driver_object from our datatabase and destroy it. Throw
+ * away any custom driver extension info that may have been added.
+ */
+
+int
+windrv_unload(mod, img, len)
+ module_t mod;
+ vm_offset_t img;
+ int len;
+{
+ struct drvdb_ent *db, *r = NULL;
+ driver_object *drv;
+ device_object *d, *pdo;
+ device_t dev;
+ list_entry *e;
+
+ drv = windrv_lookup(img, NULL);
+
+ /*
+ * When we unload a driver image, we need to force a
+ * detach of any devices that might be using it. We
+ * need the PDOs of all attached devices for this.
+ * Getting at them is a little hard. We basically
+ * have to walk the device lists of all our bus
+ * drivers.
+ */
+
+ mtx_lock(&drvdb_mtx);
+ STAILQ_FOREACH(db, &drvdb_head, link) {
+ /*
+ * Fake bus drivers have no devlist info.
+ * If this driver has devlist info, it's
+ * a loaded Windows driver and has no PDOs,
+ * so skip it.
+ */
+ if (db->windrv_devlist != NULL)
+ continue;
+ pdo = db->windrv_object->dro_devobj;
+ while (pdo != NULL) {
+ d = pdo->do_attacheddev;
+ if (d->do_drvobj != drv) {
+ pdo = pdo->do_nextdev;
+ continue;
+ }
+ dev = pdo->do_devext;
+ pdo = pdo->do_nextdev;
+ mtx_unlock(&drvdb_mtx);
+ device_detach(dev);
+ mtx_lock(&drvdb_mtx);
+ }
+ }
+
+ STAILQ_FOREACH(db, &drvdb_head, link) {
+ if (db->windrv_object->dro_driverstart == (void *)img) {
+ r = db;
+ STAILQ_REMOVE(&drvdb_head, db, drvdb_ent, link);
+ break;
+ }
+ }
+ mtx_unlock(&drvdb_mtx);
+
+ if (r == NULL)
+ return (ENOENT);
+
+ if (drv == NULL)
+ return (ENOENT);
+
+ /*
+ * Destroy any custom extensions that may have been added.
+ */
+ drv = r->windrv_object;
+ while (!IsListEmpty(&drv->dro_driverext->dre_usrext)) {
+ e = RemoveHeadList(&drv->dro_driverext->dre_usrext);
+ ExFreePool(e);
+ }
+
+ /* Free the driver extension */
+ free(drv->dro_driverext, M_DEVBUF);
+
+ /* Free the driver name */
+ RtlFreeUnicodeString(&drv->dro_drivername);
+
+ /* Free driver object */
+ free(drv, M_DEVBUF);
+
+ /* Free our DB handle */
+ free(r, M_DEVBUF);
+
+ return (0);
+}
+
+#define WINDRV_LOADED htonl(0x42534F44)
+
+#ifdef __amd64__
+static void
+patch_user_shared_data_address(vm_offset_t img, size_t len)
+{
+ unsigned long i, n, max_addr, *addr;
+
+ n = len - sizeof(unsigned long);
+ max_addr = KI_USER_SHARED_DATA + sizeof(kuser_shared_data);
+ for (i = 0; i < n; i++) {
+ addr = (unsigned long *)(img + i);
+ if (*addr >= KI_USER_SHARED_DATA && *addr < max_addr) {
+ *addr -= KI_USER_SHARED_DATA;
+ *addr += (unsigned long)&kuser_shared_data;
+ }
+ }
+}
+#endif
+
+/*
+ * Loader routine for actual Windows driver modules, ultimately
+ * calls the driver's DriverEntry() routine.
+ */
+
+int
+windrv_load(mod, img, len, bustype, devlist, regvals)
+ module_t mod;
+ vm_offset_t img;
+ int len;
+ interface_type bustype;
+ void *devlist;
+ ndis_cfg *regvals;
+{
+ image_import_descriptor imp_desc;
+ image_optional_header opt_hdr;
+ driver_entry entry;
+ struct drvdb_ent *new;
+ struct driver_object *drv;
+ int status;
+ uint32_t *ptr;
+ ansi_string as;
+
+ /*
+ * First step: try to relocate and dynalink the executable
+ * driver image.
+ */
+
+ ptr = (uint32_t *)(img + 8);
+ if (*ptr == WINDRV_LOADED)
+ goto skipreloc;
+
+ /* Perform text relocation */
+ if (pe_relocate(img))
+ return (ENOEXEC);
+
+ /* Dynamically link the NDIS.SYS routines -- required. */
+ if (pe_patch_imports(img, "NDIS", ndis_functbl))
+ return (ENOEXEC);
+
+ /* Dynamically link the HAL.dll routines -- optional. */
+ if (pe_get_import_descriptor(img, &imp_desc, "HAL") == 0) {
+ if (pe_patch_imports(img, "HAL", hal_functbl))
+ return (ENOEXEC);
+ }
+
+ /* Dynamically link ntoskrnl.exe -- optional. */
+ if (pe_get_import_descriptor(img, &imp_desc, "ntoskrnl") == 0) {
+ if (pe_patch_imports(img, "ntoskrnl", ntoskrnl_functbl))
+ return (ENOEXEC);
+ }
+
+#ifdef __amd64__
+ patch_user_shared_data_address(img, len);
+#endif
+
+ /* Dynamically link USBD.SYS -- optional */
+ if (pe_get_import_descriptor(img, &imp_desc, "USBD") == 0) {
+ if (pe_patch_imports(img, "USBD", usbd_functbl))
+ return (ENOEXEC);
+ }
+
+ *ptr = WINDRV_LOADED;
+
+skipreloc:
+
+ /* Next step: find the driver entry point. */
+
+ pe_get_optional_header(img, &opt_hdr);
+ entry = (driver_entry)pe_translate_addr(img, opt_hdr.ioh_entryaddr);
+
+ /* Next step: allocate and store a driver object. */
+
+ new = malloc(sizeof(struct drvdb_ent), M_DEVBUF, M_NOWAIT|M_ZERO);
+ if (new == NULL)
+ return (ENOMEM);
+
+ drv = malloc(sizeof(driver_object), M_DEVBUF, M_NOWAIT|M_ZERO);
+ if (drv == NULL) {
+ free (new, M_DEVBUF);
+ return (ENOMEM);
+ }
+
+ /* Allocate a driver extension structure too. */
+
+ drv->dro_driverext = malloc(sizeof(driver_extension),
+ M_DEVBUF, M_NOWAIT|M_ZERO);
+
+ if (drv->dro_driverext == NULL) {
+ free(new, M_DEVBUF);
+ free(drv, M_DEVBUF);
+ return (ENOMEM);
+ }
+
+ InitializeListHead((&drv->dro_driverext->dre_usrext));
+
+ drv->dro_driverstart = (void *)img;
+ drv->dro_driversize = len;
+
+ RtlInitAnsiString(&as, DUMMY_REGISTRY_PATH);
+ if (RtlAnsiStringToUnicodeString(&drv->dro_drivername, &as, TRUE)) {
+ free(new, M_DEVBUF);
+ free(drv, M_DEVBUF);
+ return (ENOMEM);
+ }
+
+ new->windrv_object = drv;
+ new->windrv_regvals = regvals;
+ new->windrv_devlist = devlist;
+ new->windrv_bustype = bustype;
+
+ /* Now call the DriverEntry() function. */
+
+ status = MSCALL2(entry, drv, &drv->dro_drivername);
+
+ if (status != STATUS_SUCCESS) {
+ RtlFreeUnicodeString(&drv->dro_drivername);
+ free(drv, M_DEVBUF);
+ free(new, M_DEVBUF);
+ return (ENODEV);
+ }
+
+ mtx_lock(&drvdb_mtx);
+ STAILQ_INSERT_HEAD(&drvdb_head, new, link);
+ mtx_unlock(&drvdb_mtx);
+
+ return (0);
+}
+
+/*
+ * Make a new Physical Device Object for a device that was
+ * detected/plugged in. For us, the PDO is just a way to
+ * get at the device_t.
+ */
+
+int
+windrv_create_pdo(drv, bsddev)
+ driver_object *drv;
+ device_t bsddev;
+{
+ device_object *dev;
+
+ /*
+ * This is a new physical device object, which technically
+ * is the "top of the stack." Consequently, we don't do
+ * an IoAttachDeviceToDeviceStack() here.
+ */
+
+ mtx_lock(&drvdb_mtx);
+ IoCreateDevice(drv, 0, NULL, FILE_DEVICE_UNKNOWN, 0, FALSE, &dev);
+ mtx_unlock(&drvdb_mtx);
+
+ /* Stash pointer to our BSD device handle. */
+
+ dev->do_devext = bsddev;
+
+ return (STATUS_SUCCESS);
+}
+
+void
+windrv_destroy_pdo(drv, bsddev)
+ driver_object *drv;
+ device_t bsddev;
+{
+ device_object *pdo;
+
+ pdo = windrv_find_pdo(drv, bsddev);
+
+ /* Remove reference to device_t */
+
+ pdo->do_devext = NULL;
+
+ mtx_lock(&drvdb_mtx);
+ IoDeleteDevice(pdo);
+ mtx_unlock(&drvdb_mtx);
+}
+
+/*
+ * Given a device_t, find the corresponding PDO in a driver's
+ * device list.
+ */
+
+device_object *
+windrv_find_pdo(drv, bsddev)
+ driver_object *drv;
+ device_t bsddev;
+{
+ device_object *pdo;
+
+ mtx_lock(&drvdb_mtx);
+ pdo = drv->dro_devobj;
+ while (pdo != NULL) {
+ if (pdo->do_devext == bsddev) {
+ mtx_unlock(&drvdb_mtx);
+ return (pdo);
+ }
+ pdo = pdo->do_nextdev;
+ }
+ mtx_unlock(&drvdb_mtx);
+
+ return (NULL);
+}
+
+/*
+ * Add an internally emulated driver to the database. We need this
+ * to set up an emulated bus driver so that it can receive IRPs.
+ */
+
+int
+windrv_bus_attach(drv, name)
+ driver_object *drv;
+ char *name;
+{
+ struct drvdb_ent *new;
+ ansi_string as;
+
+ new = malloc(sizeof(struct drvdb_ent), M_DEVBUF, M_NOWAIT|M_ZERO);
+ if (new == NULL)
+ return (ENOMEM);
+
+ RtlInitAnsiString(&as, name);
+ if (RtlAnsiStringToUnicodeString(&drv->dro_drivername, &as, TRUE))
+ {
+ free(new, M_DEVBUF);
+ return (ENOMEM);
+ }
+
+ /*
+ * Set up a fake image pointer to avoid false matches
+ * in windrv_lookup().
+ */
+ drv->dro_driverstart = (void *)0xFFFFFFFF;
+
+ new->windrv_object = drv;
+ new->windrv_devlist = NULL;
+ new->windrv_regvals = NULL;
+
+ mtx_lock(&drvdb_mtx);
+ STAILQ_INSERT_HEAD(&drvdb_head, new, link);
+ mtx_unlock(&drvdb_mtx);
+
+ return (0);
+}
+
+#ifdef __amd64__
+
+extern void x86_64_wrap(void);
+extern void x86_64_wrap_call(void);
+extern void x86_64_wrap_end(void);
+
+int
+windrv_wrap(func, wrap, argcnt, ftype)
+ funcptr func;
+ funcptr *wrap;
+ int argcnt;
+ int ftype;
+{
+ funcptr p;
+ vm_offset_t *calladdr;
+ vm_offset_t wrapstart, wrapend, wrapcall;
+
+ wrapstart = (vm_offset_t)&x86_64_wrap;
+ wrapend = (vm_offset_t)&x86_64_wrap_end;
+ wrapcall = (vm_offset_t)&x86_64_wrap_call;
+
+ /* Allocate a new wrapper instance. */
+
+ p = malloc((wrapend - wrapstart), M_DEVBUF, M_NOWAIT);
+ if (p == NULL)
+ return (ENOMEM);
+
+ /* Copy over the code. */
+
+ bcopy((char *)wrapstart, p, (wrapend - wrapstart));
+
+ /* Insert the function address into the new wrapper instance. */
+
+ calladdr = (uint64_t *)((char *)p + (wrapcall - wrapstart) + 2);
+ *calladdr = (vm_offset_t)func;
+
+ *wrap = p;
+
+ return (0);
+}
+#endif /* __amd64__ */
+
+
+#ifdef __i386__
+
+struct x86desc {
+ uint16_t x_lolimit;
+ uint16_t x_base0;
+ uint8_t x_base1;
+ uint8_t x_flags;
+ uint8_t x_hilimit;
+ uint8_t x_base2;
+};
+
+struct gdt {
+ uint16_t limit;
+ void *base;
+} __attribute__((__packed__));
+
+extern uint16_t x86_getfs(void);
+extern void x86_setfs(uint16_t);
+extern void *x86_gettid(void);
+extern void x86_critical_enter(void);
+extern void x86_critical_exit(void);
+extern void x86_getldt(struct gdt *, uint16_t *);
+extern void x86_setldt(struct gdt *, uint16_t);
+
+#define SEL_LDT 4 /* local descriptor table */
+#define SEL_TO_FS(x) (((x) << 3))
+
+/*
+ * FreeBSD 6.0 and later has a special GDT segment reserved
+ * specifically for us, so if GNDIS_SEL is defined, use that.
+ * If not, use GTGATE_SEL, which is uninitialized and infrequently
+ * used.
+ */
+
+#ifdef GNDIS_SEL
+#define FREEBSD_EMPTYSEL GNDIS_SEL
+#else
+#define FREEBSD_EMPTYSEL GTGATE_SEL /* slot 7 */
+#endif
+
+/*
+ * The meanings of various bits in a descriptor vary a little
+ * depending on whether the descriptor will be used as a
+ * code, data or system descriptor. (And that in turn depends
+ * on which segment register selects the descriptor.)
+ * We're only trying to create a data segment, so the definitions
+ * below are the ones that apply to a data descriptor.
+ */
+
+#define SEGFLAGLO_PRESENT 0x80 /* segment is present */
+#define SEGFLAGLO_PRIVLVL 0x60 /* privlevel needed for this seg */
+#define SEGFLAGLO_CD 0x10 /* 1 = code/data, 0 = system */
+#define SEGFLAGLO_MBZ 0x08 /* must be zero */
+#define SEGFLAGLO_EXPANDDOWN 0x04 /* limit expands down */
+#define SEGFLAGLO_WRITEABLE 0x02 /* segment is writeable */
+#define SEGGLAGLO_ACCESSED 0x01 /* segment has been accessed */
+
+#define SEGFLAGHI_GRAN 0x80 /* granularity, 1 = byte, 0 = page */
+#define SEGFLAGHI_BIG 0x40 /* 1 = 32 bit stack, 0 = 16 bit */
+
+/*
+ * Context switch from UNIX to Windows. Save the existing value
+ * of %fs for this processor, then change it to point to our
+ * fake TID. Note that it is also possible to pin ourselves
+ * to our current CPU, though I'm not sure this is really
+ * necessary. It depends on whether or not an interrupt might
+ * preempt us while Windows code is running and we wind up
+ * scheduled onto another CPU as a result. So far, it doesn't
+ * seem like this is what happens.
+ */
+
+void
+ctxsw_utow(void)
+{
+ struct tid *t;
+
+ t = &my_tids[curthread->td_oncpu];
+
+ /*
+ * Ugly hack. During system bootstrap (cold == 1), only CPU 0
+ * is running. So if we were loaded at bootstrap, only CPU 0
+ * will have our special GDT entry. This is a problem for SMP
+ * systems, so to deal with this, we check here to make sure
+ * the TID for this processor has been initialized, and if it
+ * hasn't, we need to do it right now or else things will
+ * explode.
+ */
+
+ if (t->tid_self != t)
+ x86_newldt(NULL);
+
+ x86_critical_enter();
+ t->tid_oldfs = x86_getfs();
+ t->tid_cpu = curthread->td_oncpu;
+ sched_pin();
+ x86_setfs(SEL_TO_FS(t->tid_selector));
+ x86_critical_exit();
+
+ /* Now entering Windows land, population: you. */
+}
+
+/*
+ * Context switch from Windows back to UNIX. Restore %fs to
+ * its previous value. This always occurs after a call to
+ * ctxsw_utow().
+ */
+
+void
+ctxsw_wtou(void)
+{
+ struct tid *t;
+
+ x86_critical_enter();
+ t = x86_gettid();
+ x86_setfs(t->tid_oldfs);
+ sched_unpin();
+ x86_critical_exit();
+
+ /* Welcome back to UNIX land, we missed you. */
+
+#ifdef EXTRA_SANITY
+ if (t->tid_cpu != curthread->td_oncpu)
+ panic("ctxsw GOT MOVED TO OTHER CPU!");
+#endif
+}
+
+static int windrv_wrap_stdcall(funcptr, funcptr *, int);
+static int windrv_wrap_fastcall(funcptr, funcptr *, int);
+static int windrv_wrap_regparm(funcptr, funcptr *);
+
+extern void x86_fastcall_wrap(void);
+extern void x86_fastcall_wrap_call(void);
+extern void x86_fastcall_wrap_arg(void);
+extern void x86_fastcall_wrap_end(void);
+
+static int
+windrv_wrap_fastcall(func, wrap, argcnt)
+ funcptr func;
+ funcptr *wrap;
+ int8_t argcnt;
+{
+ funcptr p;
+ vm_offset_t *calladdr;
+ uint8_t *argaddr;
+ vm_offset_t wrapstart, wrapend, wrapcall, wraparg;
+
+ wrapstart = (vm_offset_t)&x86_fastcall_wrap;
+ wrapend = (vm_offset_t)&x86_fastcall_wrap_end;
+ wrapcall = (vm_offset_t)&x86_fastcall_wrap_call;
+ wraparg = (vm_offset_t)&x86_fastcall_wrap_arg;
+
+ /* Allocate a new wrapper instance. */
+
+ p = malloc((wrapend - wrapstart), M_DEVBUF, M_NOWAIT);
+ if (p == NULL)
+ return (ENOMEM);
+
+ /* Copy over the code. */
+
+ bcopy((char *)wrapstart, p, (wrapend - wrapstart));
+
+ /* Insert the function address into the new wrapper instance. */
+
+ calladdr = (vm_offset_t *)((char *)p + ((wrapcall - wrapstart) + 1));
+ *calladdr = (vm_offset_t)func;
+
+ argcnt -= 2;
+ if (argcnt < 1)
+ argcnt = 0;
+
+ argaddr = (u_int8_t *)((char *)p + ((wraparg - wrapstart) + 1));
+ *argaddr = argcnt * sizeof(uint32_t);
+
+ *wrap = p;
+
+ return (0);
+}
+
+extern void x86_stdcall_wrap(void);
+extern void x86_stdcall_wrap_call(void);
+extern void x86_stdcall_wrap_arg(void);
+extern void x86_stdcall_wrap_end(void);
+
+static int
+windrv_wrap_stdcall(func, wrap, argcnt)
+ funcptr func;
+ funcptr *wrap;
+ uint8_t argcnt;
+{
+ funcptr p;
+ vm_offset_t *calladdr;
+ uint8_t *argaddr;
+ vm_offset_t wrapstart, wrapend, wrapcall, wraparg;
+
+ wrapstart = (vm_offset_t)&x86_stdcall_wrap;
+ wrapend = (vm_offset_t)&x86_stdcall_wrap_end;
+ wrapcall = (vm_offset_t)&x86_stdcall_wrap_call;
+ wraparg = (vm_offset_t)&x86_stdcall_wrap_arg;
+
+ /* Allocate a new wrapper instance. */
+
+ p = malloc((wrapend - wrapstart), M_DEVBUF, M_NOWAIT);
+ if (p == NULL)
+ return (ENOMEM);
+
+ /* Copy over the code. */
+
+ bcopy((char *)wrapstart, p, (wrapend - wrapstart));
+
+ /* Insert the function address into the new wrapper instance. */
+
+ calladdr = (vm_offset_t *)((char *)p + ((wrapcall - wrapstart) + 1));
+ *calladdr = (vm_offset_t)func;
+
+ argaddr = (u_int8_t *)((char *)p + ((wraparg - wrapstart) + 1));
+ *argaddr = argcnt * sizeof(uint32_t);
+
+ *wrap = p;
+
+ return (0);
+}
+
+extern void x86_regparm_wrap(void);
+extern void x86_regparm_wrap_call(void);
+extern void x86_regparm_wrap_end(void);
+
+static int
+windrv_wrap_regparm(func, wrap)
+ funcptr func;
+ funcptr *wrap;
+{
+ funcptr p;
+ vm_offset_t *calladdr;
+ vm_offset_t wrapstart, wrapend, wrapcall;
+
+ wrapstart = (vm_offset_t)&x86_regparm_wrap;
+ wrapend = (vm_offset_t)&x86_regparm_wrap_end;
+ wrapcall = (vm_offset_t)&x86_regparm_wrap_call;
+
+ /* Allocate a new wrapper instance. */
+
+ p = malloc((wrapend - wrapstart), M_DEVBUF, M_NOWAIT);
+ if (p == NULL)
+ return (ENOMEM);
+
+ /* Copy over the code. */
+
+ bcopy(x86_regparm_wrap, p, (wrapend - wrapstart));
+
+ /* Insert the function address into the new wrapper instance. */
+
+ calladdr = (vm_offset_t *)((char *)p + ((wrapcall - wrapstart) + 1));
+ *calladdr = (vm_offset_t)func;
+
+ *wrap = p;
+
+ return (0);
+}
+
+int
+windrv_wrap(func, wrap, argcnt, ftype)
+ funcptr func;
+ funcptr *wrap;
+ int argcnt;
+ int ftype;
+{
+ switch(ftype) {
+ case WINDRV_WRAP_FASTCALL:
+ return (windrv_wrap_fastcall(func, wrap, argcnt));
+ case WINDRV_WRAP_STDCALL:
+ return (windrv_wrap_stdcall(func, wrap, argcnt));
+ case WINDRV_WRAP_REGPARM:
+ return (windrv_wrap_regparm(func, wrap));
+ case WINDRV_WRAP_CDECL:
+ return (windrv_wrap_stdcall(func, wrap, 0));
+ default:
+ break;
+ }
+
+ return (EINVAL);
+}
+
+static void
+x86_oldldt(dummy)
+ void *dummy;
+{
+ struct x86desc *gdt;
+ struct gdt gtable;
+ uint16_t ltable;
+
+ mtx_lock_spin(&dt_lock);
+
+ /* Grab location of existing GDT. */
+
+ x86_getldt(&gtable, &ltable);
+
+ /* Find the slot we updated. */
+
+ gdt = gtable.base;
+ gdt += FREEBSD_EMPTYSEL;
+
+ /* Empty it out. */
+
+ bzero((char *)gdt, sizeof(struct x86desc));
+
+ /* Restore GDT. */
+
+ x86_setldt(&gtable, ltable);
+
+ mtx_unlock_spin(&dt_lock);
+}
+
+static void
+x86_newldt(dummy)
+ void *dummy;
+{
+ struct gdt gtable;
+ uint16_t ltable;
+ struct x86desc *l;
+ struct thread *t;
+
+ t = curthread;
+
+ mtx_lock_spin(&dt_lock);
+
+ /* Grab location of existing GDT. */
+
+ x86_getldt(&gtable, &ltable);
+
+ /* Get pointer to the GDT table. */
+
+ l = gtable.base;
+
+ /* Get pointer to empty slot */
+
+ l += FREEBSD_EMPTYSEL;
+
+ /* Initialize TID for this CPU. */
+
+ my_tids[t->td_oncpu].tid_selector = FREEBSD_EMPTYSEL;
+ my_tids[t->td_oncpu].tid_self = &my_tids[t->td_oncpu];
+
+ /* Set up new GDT entry. */
+
+ l->x_lolimit = sizeof(struct tid);
+ l->x_hilimit = SEGFLAGHI_GRAN|SEGFLAGHI_BIG;
+ l->x_base0 = (vm_offset_t)(&my_tids[t->td_oncpu]) & 0xFFFF;
+ l->x_base1 = ((vm_offset_t)(&my_tids[t->td_oncpu]) >> 16) & 0xFF;
+ l->x_base2 = ((vm_offset_t)(&my_tids[t->td_oncpu]) >> 24) & 0xFF;
+ l->x_flags = SEGFLAGLO_PRESENT|SEGFLAGLO_CD|SEGFLAGLO_WRITEABLE;
+
+ /* Update the GDT. */
+
+ x86_setldt(&gtable, ltable);
+
+ mtx_unlock_spin(&dt_lock);
+
+ /* Whew. */
+}
+
+#endif /* __i386__ */
+
+int
+windrv_unwrap(func)
+ funcptr func;
+{
+ free(func, M_DEVBUF);
+
+ return (0);
+}
diff --git a/sys/compat/ndis/ndis_var.h b/sys/compat/ndis/ndis_var.h
new file mode 100644
index 0000000..2692e54
--- /dev/null
+++ b/sys/compat/ndis/ndis_var.h
@@ -0,0 +1,1767 @@
+/*-
+ * Copyright (c) 2003
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _NDIS_VAR_H_
+#define _NDIS_VAR_H_
+
+/* Forward declarations */
+struct ndis_miniport_block;
+struct ndis_mdriver_block;
+typedef struct ndis_miniport_block ndis_miniport_block;
+typedef struct ndis_mdriver_block ndis_mdriver_block;
+
+/* Base types */
+typedef uint32_t ndis_status;
+typedef void *ndis_handle;
+typedef uint32_t ndis_oid;
+typedef uint32_t ndis_error_code;
+typedef register_t ndis_kspin_lock;
+typedef uint8_t ndis_kirql;
+
+/*
+ * NDIS status codes (there are lots of them). The ones that
+ * don't seem to fit the pattern are actually mapped to generic
+ * NT status codes.
+ */
+
+#define NDIS_STATUS_SUCCESS 0
+#define NDIS_STATUS_PENDING 0x00000103
+#define NDIS_STATUS_NOT_RECOGNIZED 0x00010001
+#define NDIS_STATUS_NOT_COPIED 0x00010002
+#define NDIS_STATUS_NOT_ACCEPTED 0x00010003
+#define NDIS_STATUS_CALL_ACTIVE 0x00010007
+#define NDIS_STATUS_ONLINE 0x40010003
+#define NDIS_STATUS_RESET_START 0x40010004
+#define NDIS_STATUS_RESET_END 0x40010005
+#define NDIS_STATUS_RING_STATUS 0x40010006
+#define NDIS_STATUS_CLOSED 0x40010007
+#define NDIS_STATUS_WAN_LINE_UP 0x40010008
+#define NDIS_STATUS_WAN_LINE_DOWN 0x40010009
+#define NDIS_STATUS_WAN_FRAGMENT 0x4001000A
+#define NDIS_STATUS_MEDIA_CONNECT 0x4001000B
+#define NDIS_STATUS_MEDIA_DISCONNECT 0x4001000C
+#define NDIS_STATUS_HARDWARE_LINE_UP 0x4001000D
+#define NDIS_STATUS_HARDWARE_LINE_DOWN 0x4001000E
+#define NDIS_STATUS_INTERFACE_UP 0x4001000F
+#define NDIS_STATUS_INTERFACE_DOWN 0x40010010
+#define NDIS_STATUS_MEDIA_BUSY 0x40010011
+#define NDIS_STATUS_MEDIA_SPECIFIC_INDICATION 0x40010012
+#define NDIS_STATUS_WW_INDICATION NDIS_STATUS_MEDIA_SPECIFIC_INDICATION
+#define NDIS_STATUS_LINK_SPEED_CHANGE 0x40010013
+#define NDIS_STATUS_WAN_GET_STATS 0x40010014
+#define NDIS_STATUS_WAN_CO_FRAGMENT 0x40010015
+#define NDIS_STATUS_WAN_CO_LINKPARAMS 0x40010016
+#define NDIS_STATUS_NOT_RESETTABLE 0x80010001
+#define NDIS_STATUS_SOFT_ERRORS 0x80010003
+#define NDIS_STATUS_HARD_ERRORS 0x80010004
+#define NDIS_STATUS_BUFFER_OVERFLOW 0x80000005
+#define NDIS_STATUS_FAILURE 0xC0000001
+#define NDIS_STATUS_RESOURCES 0xC000009A
+#define NDIS_STATUS_CLOSING 0xC0010002
+#define NDIS_STATUS_BAD_VERSION 0xC0010004
+#define NDIS_STATUS_BAD_CHARACTERISTICS 0xC0010005
+#define NDIS_STATUS_ADAPTER_NOT_FOUND 0xC0010006
+#define NDIS_STATUS_OPEN_FAILED 0xC0010007
+#define NDIS_STATUS_DEVICE_FAILED 0xC0010008
+#define NDIS_STATUS_MULTICAST_FULL 0xC0010009
+#define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A
+#define NDIS_STATUS_MULTICAST_NOT_FOUND 0xC001000B
+#define NDIS_STATUS_REQUEST_ABORTED 0xC001000C
+#define NDIS_STATUS_RESET_IN_PROGRESS 0xC001000D
+#define NDIS_STATUS_CLOSING_INDICATING 0xC001000E
+#define NDIS_STATUS_NOT_SUPPORTED 0xC00000BB
+#define NDIS_STATUS_INVALID_PACKET 0xC001000F
+#define NDIS_STATUS_OPEN_LIST_FULL 0xC0010010
+#define NDIS_STATUS_ADAPTER_NOT_READY 0xC0010011
+#define NDIS_STATUS_ADAPTER_NOT_OPEN 0xC0010012
+#define NDIS_STATUS_NOT_INDICATING 0xC0010013
+#define NDIS_STATUS_INVALID_LENGTH 0xC0010014
+#define NDIS_STATUS_INVALID_DATA 0xC0010015
+#define NDIS_STATUS_BUFFER_TOO_SHORT 0xC0010016
+#define NDIS_STATUS_INVALID_OID 0xC0010017
+#define NDIS_STATUS_ADAPTER_REMOVED 0xC0010018
+#define NDIS_STATUS_UNSUPPORTED_MEDIA 0xC0010019
+#define NDIS_STATUS_GROUP_ADDRESS_IN_USE 0xC001001A
+#define NDIS_STATUS_FILE_NOT_FOUND 0xC001001B
+#define NDIS_STATUS_ERROR_READING_FILE 0xC001001C
+#define NDIS_STATUS_ALREADY_MAPPED 0xC001001D
+#define NDIS_STATUS_RESOURCE_CONFLICT 0xC001001E
+#define NDIS_STATUS_NO_CABLE 0xC001001F
+#define NDIS_STATUS_INVALID_SAP 0xC0010020
+#define NDIS_STATUS_SAP_IN_USE 0xC0010021
+#define NDIS_STATUS_INVALID_ADDRESS 0xC0010022
+#define NDIS_STATUS_VC_NOT_ACTIVATED 0xC0010023
+#define NDIS_STATUS_DEST_OUT_OF_ORDER 0xC0010024
+#define NDIS_STATUS_VC_NOT_AVAILABLE 0xC0010025
+#define NDIS_STATUS_CELLRATE_NOT_AVAILABLE 0xC0010026
+#define NDIS_STATUS_INCOMPATABLE_QOS 0xC0010027
+#define NDIS_STATUS_AAL_PARAMS_UNSUPPORTED 0xC0010028
+#define NDIS_STATUS_NO_ROUTE_TO_DESTINATION 0xC0010029
+#define NDIS_STATUS_TOKEN_RING_OPEN_ERROR 0xC0011000
+#define NDIS_STATUS_INVALID_DEVICE_REQUEST 0xC0000010
+#define NDIS_STATUS_NETWORK_UNREACHABLE 0xC000023C
+
+/*
+ * NDIS event codes. They are usually reported to NdisWriteErrorLogEntry().
+ */
+
+#define EVENT_NDIS_RESOURCE_CONFLICT 0xC0001388
+#define EVENT_NDIS_OUT_OF_RESOURCE 0xC0001389
+#define EVENT_NDIS_HARDWARE_FAILURE 0xC000138A
+#define EVENT_NDIS_ADAPTER_NOT_FOUND 0xC000138B
+#define EVENT_NDIS_INTERRUPT_CONNECT 0xC000138C
+#define EVENT_NDIS_DRIVER_FAILURE 0xC000138D
+#define EVENT_NDIS_BAD_VERSION 0xC000138E
+#define EVENT_NDIS_TIMEOUT 0x8000138F
+#define EVENT_NDIS_NETWORK_ADDRESS 0xC0001390
+#define EVENT_NDIS_UNSUPPORTED_CONFIGURATION 0xC0001391
+#define EVENT_NDIS_INVALID_VALUE_FROM_ADAPTER 0xC0001392
+#define EVENT_NDIS_MISSING_CONFIGURATION_PARAMETER 0xC0001393
+#define EVENT_NDIS_BAD_IO_BASE_ADDRESS 0xC0001394
+#define EVENT_NDIS_RECEIVE_SPACE_SMALL 0x40001395
+#define EVENT_NDIS_ADAPTER_DISABLED 0x80001396
+#define EVENT_NDIS_IO_PORT_CONFLICT 0x80001397
+#define EVENT_NDIS_PORT_OR_DMA_CONFLICT 0x80001398
+#define EVENT_NDIS_MEMORY_CONFLICT 0x80001399
+#define EVENT_NDIS_INTERRUPT_CONFLICT 0x8000139A
+#define EVENT_NDIS_DMA_CONFLICT 0x8000139B
+#define EVENT_NDIS_INVALID_DOWNLOAD_FILE_ERROR 0xC000139C
+#define EVENT_NDIS_MAXRECEIVES_ERROR 0x8000139D
+#define EVENT_NDIS_MAXTRANSMITS_ERROR 0x8000139E
+#define EVENT_NDIS_MAXFRAMESIZE_ERROR 0x8000139F
+#define EVENT_NDIS_MAXINTERNALBUFS_ERROR 0x800013A0
+#define EVENT_NDIS_MAXMULTICAST_ERROR 0x800013A1
+#define EVENT_NDIS_PRODUCTID_ERROR 0x800013A2
+#define EVENT_NDIS_LOBE_FAILUE_ERROR 0x800013A3
+#define EVENT_NDIS_SIGNAL_LOSS_ERROR 0x800013A4
+#define EVENT_NDIS_REMOVE_RECEIVED_ERROR 0x800013A5
+#define EVENT_NDIS_TOKEN_RING_CORRECTION 0x400013A6
+#define EVENT_NDIS_ADAPTER_CHECK_ERROR 0xC00013A7
+#define EVENT_NDIS_RESET_FAILURE_ERROR 0x800013A8
+#define EVENT_NDIS_CABLE_DISCONNECTED_ERROR 0x800013A9
+#define EVENT_NDIS_RESET_FAILURE_CORRECTION 0x800013AA
+
+/*
+ * NDIS OIDs used by the queryinfo/setinfo routines.
+ * Some are required by all NDIS drivers, some are specific to
+ * a particular type of device, and some are purely optional.
+ * Unfortunately, one of the purely optional OIDs is the one
+ * that lets us set the MAC address of the device.
+ */
+
+/* Required OIDs */
+#define OID_GEN_SUPPORTED_LIST 0x00010101
+#define OID_GEN_HARDWARE_STATUS 0x00010102
+#define OID_GEN_MEDIA_SUPPORTED 0x00010103
+#define OID_GEN_MEDIA_IN_USE 0x00010104
+#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105
+#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106
+#define OID_GEN_LINK_SPEED 0x00010107
+#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108
+#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109
+#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A
+#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B
+#define OID_GEN_VENDOR_ID 0x0001010C
+#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D
+#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E
+#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F
+#define OID_GEN_DRIVER_VERSION 0x00010110
+#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111
+#define OID_GEN_PROTOCOL_OPTIONS 0x00010112
+#define OID_GEN_MAC_OPTIONS 0x00010113
+#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114
+#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115
+#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116
+#define OID_GEN_SUPPORTED_GUIDS 0x00010117
+#define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118 /* Set only */
+#define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119 /* Set only */
+#define OID_GEN_MACHINE_NAME 0x0001021A
+#define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B /* Set only */
+#define OID_GEN_VLAN_ID 0x0001021C
+
+/* Optional OIDs. */
+#define OID_GEN_MEDIA_CAPABILITIES 0x00010201
+#define OID_GEN_PHYSICAL_MEDIUM 0x00010202
+
+/* Required statistics OIDs. */
+#define OID_GEN_XMIT_OK 0x00020101
+#define OID_GEN_RCV_OK 0x00020102
+#define OID_GEN_XMIT_ERROR 0x00020103
+#define OID_GEN_RCV_ERROR 0x00020104
+#define OID_GEN_RCV_NO_BUFFER 0x00020105
+
+/* Optional OID statistics */
+#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201
+#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202
+#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203
+#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204
+#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205
+#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206
+#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207
+#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208
+#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209
+#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A
+#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B
+#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C
+#define OID_GEN_RCV_CRC_ERROR 0x0002020D
+#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E
+#define OID_GEN_GET_TIME_CAPS 0x0002020F
+#define OID_GEN_GET_NETCARD_TIME 0x00020210
+#define OID_GEN_NETCARD_LOAD 0x00020211
+#define OID_GEN_DEVICE_PROFILE 0x00020212
+
+/* 802.3 (ethernet) OIDs */
+#define OID_802_3_PERMANENT_ADDRESS 0x01010101
+#define OID_802_3_CURRENT_ADDRESS 0x01010102
+#define OID_802_3_MULTICAST_LIST 0x01010103
+#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104
+#define OID_802_3_MAC_OPTIONS 0x01010105
+#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001
+#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101
+#define OID_802_3_XMIT_ONE_COLLISION 0x01020102
+#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103
+#define OID_802_3_XMIT_DEFERRED 0x01020201
+#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202
+#define OID_802_3_RCV_OVERRUN 0x01020203
+#define OID_802_3_XMIT_UNDERRUN 0x01020204
+#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205
+#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206
+#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207
+
+/* PnP and power management OIDs */
+#define OID_PNP_CAPABILITIES 0xFD010100
+#define OID_PNP_SET_POWER 0xFD010101
+#define OID_PNP_QUERY_POWER 0xFD010102
+#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103
+#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104
+#define OID_PNP_WAKE_UP_PATTERN_LIST 0xFD010105
+#define OID_PNP_ENABLE_WAKE_UP 0xFD010106
+
+/*
+ * These are the possible power states for
+ * OID_PNP_SET_POWER and OID_PNP_QUERY_POWER.
+ */
+#define NDIS_POWERSTATE_UNSPEC 0
+#define NDIS_POWERSTATE_D0 1
+#define NDIS_POWERSTATE_D1 2
+#define NDIS_POWERSTATE_D2 3
+#define NDIS_POWERSTATE_D3 4
+
+/*
+ * These are used with the MiniportPnpEventNotify() method.
+ */
+
+#define NDIS_POWERPROFILE_BATTERY 0
+#define NDIS_POWERPROFILE_ACONLINE 1
+
+#define NDIS_PNP_EVENT_QUERY_REMOVED 0
+#define NDIS_PNP_EVENT_REMOVED 1
+#define NDIS_PNP_EVENT_SURPRISE_REMOVED 2
+#define NDIS_PNP_EVENT_QUERY_STOPPED 3
+#define NDIS_PNP_EVENT_STOPPED 4
+#define NDIS_PNP_EVENT_PROFILECHANGED 5
+
+
+/* PnP/PM Statistics (Optional). */
+#define OID_PNP_WAKE_UP_OK 0xFD020200
+#define OID_PNP_WAKE_UP_ERROR 0xFD020201
+
+/* The following bits are defined for OID_PNP_ENABLE_WAKE_UP */
+#define NDIS_PNP_WAKE_UP_MAGIC_PACKET 0x00000001
+#define NDIS_PNP_WAKE_UP_PATTERN_MATCH 0x00000002
+#define NDIS_PNP_WAKE_UP_LINK_CHANGE 0x00000004
+
+/* 802.11 OIDs */
+#define OID_802_11_BSSID 0x0D010101
+#define OID_802_11_SSID 0x0D010102
+#define OID_802_11_NETWORK_TYPES_SUPPORTED 0x0D010203
+#define OID_802_11_NETWORK_TYPE_IN_USE 0x0D010204
+#define OID_802_11_TX_POWER_LEVEL 0x0D010205
+#define OID_802_11_RSSI 0x0D010206
+#define OID_802_11_RSSI_TRIGGER 0x0D010207
+#define OID_802_11_INFRASTRUCTURE_MODE 0x0D010108
+#define OID_802_11_FRAGMENTATION_THRESHOLD 0x0D010209
+#define OID_802_11_RTS_THRESHOLD 0x0D01020A
+#define OID_802_11_NUMBER_OF_ANTENNAS 0x0D01020B
+#define OID_802_11_RX_ANTENNA_SELECTED 0x0D01020C
+#define OID_802_11_TX_ANTENNA_SELECTED 0x0D01020D
+#define OID_802_11_SUPPORTED_RATES 0x0D01020E
+#define OID_802_11_DESIRED_RATES 0x0D010210
+#define OID_802_11_CONFIGURATION 0x0D010211
+#define OID_802_11_STATISTICS 0x0D020212
+#define OID_802_11_ADD_WEP 0x0D010113
+#define OID_802_11_REMOVE_WEP 0x0D010114
+#define OID_802_11_DISASSOCIATE 0x0D010115
+#define OID_802_11_POWER_MODE 0x0D010216
+#define OID_802_11_BSSID_LIST 0x0D010217
+#define OID_802_11_AUTHENTICATION_MODE 0x0D010118
+#define OID_802_11_PRIVACY_FILTER 0x0D010119
+#define OID_802_11_BSSID_LIST_SCAN 0x0D01011A
+#define OID_802_11_WEP_STATUS 0x0D01011B
+#define OID_802_11_ENCRYPTION_STATUS OID_802_11_WEP_STATUS
+#define OID_802_11_RELOAD_DEFAULTS 0x0D01011C
+#define OID_802_11_ADD_KEY 0x0D01011D
+#define OID_802_11_REMOVE_KEY 0x0D01011E
+#define OID_802_11_ASSOCIATION_INFORMATION 0x0D01011F
+#define OID_802_11_TEST 0x0D010120
+#define OID_802_11_CAPABILITY 0x0D010122
+#define OID_802_11_PMKID 0x0D010123
+
+/* structures/definitions for 802.11 */
+#define NDIS_80211_NETTYPE_11FH 0x00000000
+#define NDIS_80211_NETTYPE_11DS 0x00000001
+#define NDIS_80211_NETTYPE_11OFDM5 0x00000002
+#define NDIS_80211_NETTYPE_11OFDM24 0x00000003
+#define NDIS_80211_NETTYPE_AUTO 0x00000004
+
+struct ndis_80211_nettype_list {
+ uint32_t ntl_items;
+ uint32_t ntl_type[1];
+};
+
+#define NDIS_80211_POWERMODE_CAM 0x00000000
+#define NDIS_80211_POWERMODE_MAX_PSP 0x00000001
+#define NDIS_80211_POWERMODE_FAST_PSP 0x00000002
+
+typedef uint32_t ndis_80211_power; /* Power in milliwatts */
+typedef uint32_t ndis_80211_rssi; /* Signal strength in dBm */
+
+struct ndis_80211_config_fh {
+ uint32_t ncf_length;
+ uint32_t ncf_hoppatterh;
+ uint32_t ncf_hopset;
+ uint32_t ncf_dwelltime;
+};
+
+typedef struct ndis_80211_config_fh ndis_80211_config_fh;
+
+struct ndis_80211_config {
+ uint32_t nc_length;
+ uint32_t nc_beaconperiod;
+ uint32_t nc_atimwin;
+ uint32_t nc_dsconfig;
+ ndis_80211_config_fh nc_fhconfig;
+};
+
+typedef struct ndis_80211_config ndis_80211_config;
+
+struct ndis_80211_stats {
+ uint32_t ns_length;
+ uint64_t ns_txfragcnt;
+ uint64_t ns_txmcastcnt;
+ uint64_t ns_failedcnt;
+ uint64_t ns_retrycnt;
+ uint64_t ns_multiretrycnt;
+ uint64_t ns_rtssuccesscnt;
+ uint64_t ns_rtsfailcnt;
+ uint64_t ns_ackfailcnt;
+ uint64_t ns_dupeframecnt;
+ uint64_t ns_rxfragcnt;
+ uint64_t ns_rxmcastcnt;
+ uint64_t ns_fcserrcnt;
+};
+
+typedef struct ndis_80211_stats ndis_80211_stats;
+
+typedef uint32_t ndis_80211_key_idx;
+
+struct ndis_80211_wep {
+ uint32_t nw_length;
+ uint32_t nw_keyidx;
+ uint32_t nw_keylen;
+ uint8_t nw_keydata[256];
+};
+
+typedef struct ndis_80211_wep ndis_80211_wep;
+
+#define NDIS_80211_WEPKEY_TX 0x80000000
+#define NDIS_80211_WEPKEY_PERCLIENT 0x40000000
+
+#define NDIS_80211_NET_INFRA_IBSS 0x00000000
+#define NDIS_80211_NET_INFRA_BSS 0x00000001
+#define NDIS_80211_NET_INFRA_AUTO 0x00000002
+
+#define NDIS_80211_AUTHMODE_OPEN 0x00000000
+#define NDIS_80211_AUTHMODE_SHARED 0x00000001
+#define NDIS_80211_AUTHMODE_AUTO 0x00000002
+#define NDIS_80211_AUTHMODE_WPA 0x00000003
+#define NDIS_80211_AUTHMODE_WPAPSK 0x00000004
+#define NDIS_80211_AUTHMODE_WPANONE 0x00000005
+#define NDIS_80211_AUTHMODE_WPA2 0x00000006
+#define NDIS_80211_AUTHMODE_WPA2PSK 0x00000007
+
+typedef uint8_t ndis_80211_rates[8];
+typedef uint8_t ndis_80211_rates_ex[16];
+typedef uint8_t ndis_80211_macaddr[6];
+
+struct ndis_80211_ssid {
+ uint32_t ns_ssidlen;
+ uint8_t ns_ssid[32];
+};
+
+typedef struct ndis_80211_ssid ndis_80211_ssid;
+
+struct ndis_wlan_bssid {
+ uint32_t nwb_length;
+ ndis_80211_macaddr nwb_macaddr;
+ uint8_t nwb_rsvd[2];
+ ndis_80211_ssid nwb_ssid;
+ uint32_t nwb_privacy;
+ ndis_80211_rssi nwb_rssi;
+ uint32_t nwb_nettype;
+ ndis_80211_config nwb_config;
+ uint32_t nwb_netinfra;
+ ndis_80211_rates nwb_supportedrates;
+};
+
+typedef struct ndis_wlan_bssid ndis_wlan_bssid;
+
+struct ndis_80211_bssid_list {
+ uint32_t nbl_items;
+ ndis_wlan_bssid nbl_bssid[1];
+};
+
+typedef struct ndis_80211_bssid_list ndis_80211_bssid_list;
+
+struct ndis_wlan_bssid_ex {
+ uint32_t nwbx_len;
+ ndis_80211_macaddr nwbx_macaddr;
+ uint8_t nwbx_rsvd[2];
+ ndis_80211_ssid nwbx_ssid;
+ uint32_t nwbx_privacy;
+ ndis_80211_rssi nwbx_rssi;
+ uint32_t nwbx_nettype;
+ ndis_80211_config nwbx_config;
+ uint32_t nwbx_netinfra;
+ ndis_80211_rates_ex nwbx_supportedrates;
+ uint32_t nwbx_ielen;
+ uint8_t nwbx_ies[1];
+};
+
+typedef struct ndis_wlan_bssid_ex ndis_wlan_bssid_ex;
+
+struct ndis_80211_bssid_list_ex {
+ uint32_t nblx_items;
+ ndis_wlan_bssid_ex nblx_bssid[1];
+};
+
+typedef struct ndis_80211_bssid_list_ex ndis_80211_bssid_list_ex;
+
+struct ndis_80211_fixed_ies {
+ uint8_t nfi_tstamp[8];
+ uint16_t nfi_beaconint;
+ uint16_t nfi_caps;
+};
+
+struct ndis_80211_variable_ies {
+ uint8_t nvi_elemid;
+ uint8_t nvi_len;
+ uint8_t nvi_data[1];
+};
+
+typedef uint32_t ndis_80211_fragthresh;
+typedef uint32_t ndis_80211_rtsthresh;
+typedef uint32_t ndis_80211_antenna;
+
+#define NDIS_80211_PRIVFILT_ACCEPTALL 0x00000000
+#define NDIS_80211_PRIVFILT_8021XWEP 0x00000001
+
+#define NDIS_80211_WEPSTAT_ENABLED 0x00000000
+#define NDIS_80211_WEPSTAT_ENC1ENABLED NDIS_80211_WEPSTAT_ENABLED
+#define NDIS_80211_WEPSTAT_DISABLED 0x00000001
+#define NDIS_80211_WEPSTAT_ENCDISABLED NDIS_80211_WEPSTAT_DISABLED
+#define NDIS_80211_WEPSTAT_KEYABSENT 0x00000002
+#define NDIS_80211_WEPSTAT_ENC1KEYABSENT NDIS_80211_WEPSTAT_KEYABSENT
+#define NDIS_80211_WEPSTAT_NOTSUPPORTED 0x00000003
+#define NDIS_80211_WEPSTAT_ENCNOTSUPPORTED NDIS_80211_WEPSTAT_NOTSUPPORTED
+#define NDIS_80211_WEPSTAT_ENC2ENABLED 0x00000004
+#define NDIS_80211_WEPSTAT_ENC2KEYABSENT 0x00000005
+#define NDIS_80211_WEPSTAT_ENC3ENABLED 0x00000006
+#define NDIS_80211_WEPSTAT_ENC3KEYABSENT 0x00000007
+
+#define NDIS_80211_RELOADDEFAULT_WEP 0x00000000
+
+#define NDIS_80211_STATUSTYPE_AUTH 0x00000000
+#define NDIS_80211_STATUSTYPE_PMKIDLIST 0x00000001
+
+struct ndis_80211_status_indication {
+ uint32_t nsi_type;
+};
+
+typedef struct ndis_80211_status_indication ndis_80211_status_indication;
+
+#define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01
+#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02
+#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06
+#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E
+
+struct ndis_80211_auth_request {
+ uint32_t nar_len;
+ ndis_80211_macaddr nar_bssid;
+ uint32_t nar_flags;
+};
+
+typedef struct ndis_80211_auth_request ndis_80211_auth_request;
+
+struct ndis_80211_key {
+ uint32_t nk_len;
+ uint32_t nk_keyidx;
+ uint32_t nk_keylen;
+ ndis_80211_macaddr nk_bssid;
+ uint8_t nk_pad[6];
+ uint64_t nk_keyrsc;
+ uint8_t nk_keydata[32];
+};
+
+typedef struct ndis_80211_key ndis_80211_key;
+
+struct ndis_80211_remove_key {
+ uint32_t nk_len;
+ uint32_t nk_keyidx;
+ ndis_80211_macaddr nk_bssid;
+};
+
+typedef struct ndis_80211_remove_key ndis_80211_remove_key;
+
+#define NDIS_80211_AI_REQFI_CAPABILITIES 0x00000001
+#define NDIS_80211_AI_REQFI_LISTENINTERVAL 0x00000002
+#define NDIS_80211_AI_REQFI_CURRENTAPADDRESS 0x00000004
+
+#define NDIS_80211_AI_RESFI_CAPABILITIES 0x00000001
+#define NDIS_80211_AI_RESFI_STATUSCODE 0x00000002
+#define NDIS_80211_AI_RESFI_ASSOCIATIONID 0x00000004
+
+struct ndis_80211_ai_reqfi {
+ uint16_t naq_caps;
+ uint16_t naq_listentint;
+ ndis_80211_macaddr naq_currentapaddr;
+};
+
+typedef struct ndis_80211_ai_reqfi ndis_80211_ai_reqfi;
+
+struct ndis_80211_ai_resfi {
+ uint16_t nas_caps;
+ uint16_t nas_statuscode;
+ uint16_t nas_associd;
+};
+
+typedef struct ndis_80211_ai_resfi ndis_80211_ai_resfi;
+
+struct ndis_80211_assoc_info {
+ uint32_t nai_len;
+ uint16_t nai_avail_req_fixed_ies;
+ ndis_80211_ai_reqfi nai_req_fixed_ies;
+ uint32_t nai_req_ielen;
+ uint32_t nai_offset_req_ies;
+ uint16_t nai_avail_resp_fixed_ies;
+ ndis_80211_ai_resfi nai_resp_fixed_iex;
+ uint32_t nai_resp_ielen;
+ uint32_t nai_offset_resp_ies;
+};
+
+typedef struct ndis_80211_assoc_info ndis_80211_assoc_info;
+
+struct ndis_80211_auth_event {
+ ndis_80211_status_indication nae_status;
+ ndis_80211_auth_request nae_request[1];
+};
+
+typedef struct ndis_80211_auth_event ndis_80211_auth_event;
+
+struct ndis_80211_test {
+ uint32_t nt_len;
+ uint32_t nt_type;
+ union {
+ ndis_80211_auth_event nt_authevent;
+ uint32_t nt_rssitrigger;
+ } u;
+};
+
+typedef struct ndis_80211_test ndis_80211_test;
+
+struct ndis_80211_auth_encrypt {
+ uint32_t ne_authmode;
+ uint32_t ne_cryptstat;
+};
+
+typedef struct ndis_80211_auth_encrypt ndis_80211_auth_encrypt;
+
+struct ndis_80211_caps {
+ uint32_t nc_len;
+ uint32_t nc_ver;
+ uint32_t nc_numpmkids;
+ ndis_80211_auth_encrypt nc_authencs[1];
+};
+
+typedef struct ndis_80211_caps ndis_80211_caps;
+
+struct ndis_80211_bssidinfo {
+ ndis_80211_macaddr nb_bssid;
+ uint8_t nb_pmkid[16];
+};
+
+typedef struct ndis_80211_bssidinfo ndis_80211_bssidinfo;
+
+struct ndis_80211_pmkid {
+ uint32_t np_len;
+ uint32_t np_bssidcnt;
+ ndis_80211_bssidinfo np_bssidinfo[1];
+};
+
+typedef struct ndis_80211_pmkid ndis_80211_pmkid;
+
+struct ndis_80211_pmkid_cand {
+ ndis_80211_macaddr npc_bssid;
+ uint32_t npc_flags;
+};
+
+typedef struct ndis_80211_pmkid_cand ndis_80211_pmkid_cand;
+
+#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED (0x01)
+
+struct ndis_80211_pmkid_candidate_list {
+ uint32_t npcl_version;
+ uint32_t npcl_numcandidates;
+ ndis_80211_pmkid_cand npcl_candidatelist[1];
+};
+
+typedef struct ndis_80211_pmkid_candidate_list ndis_80211_pmkid_candidate_list;
+
+struct ndis_80211_enc_indication {
+ uint32_t nei_statustype;
+ ndis_80211_pmkid_candidate_list nei_pmkidlist;
+};
+
+typedef struct ndis_80211_enc_indication ndis_80211_enc_indication;
+
+/* TCP OIDs. */
+
+#define OID_TCP_TASK_OFFLOAD 0xFC010201
+#define OID_TCP_TASK_IPSEC_ADD_SA 0xFC010202
+#define OID_TCP_TASK_IPSEC_DELETE_SA 0xFC010203
+#define OID_TCP_SAN_SUPPORT 0xFC010204
+
+
+#define NDIS_TASK_OFFLOAD_VERSION 1
+
+#define NDIS_TASK_TCPIP_CSUM 0x00000000
+#define NDIS_TASK_IPSEC 0x00000001
+#define NDIS_TASK_TCP_LARGESEND 0x00000002
+
+#define NDIS_ENCAP_UNSPEC 0x00000000
+#define NDIS_ENCAP_NULL 0x00000001
+#define NDIS_ENCAP_IEEE802_3 0x00000002
+#define NDIS_ENCAP_IEEE802_5 0x00000003
+#define NDIS_ENCAP_SNAP_ROUTED 0x00000004
+#define NDIS_ENCAP_SNAP_BRIDGED 0x00000005
+
+#define NDIS_ENCAPFLAG_FIXEDHDRLEN 0x00000001
+
+struct ndis_encap_fmt {
+ uint32_t nef_encap;
+ uint32_t nef_flags;
+ uint32_t nef_encaphdrlen;
+};
+
+typedef struct ndis_encap_fmt ndis_encap_fmt;
+
+struct ndis_task_offload_hdr {
+ uint32_t ntoh_vers;
+ uint32_t ntoh_len;
+ uint32_t ntoh_rsvd;
+ uint32_t ntoh_offset_firsttask;
+ ndis_encap_fmt ntoh_encapfmt;
+};
+
+typedef struct ndis_task_offload_hdr ndis_task_offload_hdr;
+
+struct ndis_task_offload {
+ uint32_t nto_vers;
+ uint32_t nto_len;
+ uint32_t nto_task;
+ uint32_t nto_offset_nexttask;
+ uint32_t nto_taskbuflen;
+ uint8_t nto_taskbuf[1];
+};
+
+typedef struct ndis_task_offload ndis_task_offload;
+
+#define NDIS_TCPSUM_FLAGS_IP_OPTS 0x00000001
+#define NDIS_TCPSUM_FLAGS_TCP_OPTS 0x00000002
+#define NDIS_TCPSUM_FLAGS_TCP_CSUM 0x00000004
+#define NDIS_TCPSUM_FLAGS_UDP_CSUM 0x00000008
+#define NDIS_TCPSUM_FLAGS_IP_CSUM 0x00000010
+
+struct ndis_task_tcpip_csum {
+ uint32_t nttc_v4tx;
+ uint32_t nttc_v4rx;
+ uint32_t nttc_v6tx;
+ uint32_t nttc_v6rx;
+};
+
+typedef struct ndis_task_tcpip_csum ndis_task_tcpip_csum;
+
+struct ndis_task_tcp_largesend {
+ uint32_t nttl_vers;
+ uint32_t nttl_maxofflen;
+ uint32_t nttl_minsegcnt;
+ uint8_t nttl_tcpopt;
+ uint8_t nttl_ipopt;
+};
+
+typedef struct ndis_task_tcp_largesend ndis_task_tcp_largesend;
+
+#define NDIS_IPSEC_AH_MD5 0x00000001
+#define NDIS_IPSEC_AH_SHA1 0x00000002
+#define NDIS_IPSEC_AH_TRANSPORT 0x00000004
+#define NDIS_IPSEC_AH_TUNNEL 0x00000008
+#define NDIS_IPSEC_AH_SEND 0x00000010
+#define NDIS_IPSEC_AH_RECEIVE 0x00000020
+
+#define NDIS_IPSEC_ESP_DES 0x00000001
+#define NDIS_IPSEC_ESP_RSVD 0x00000002
+#define NDIS_IPSEC_ESP_3DES 0x00000004
+#define NDIS_IPSEC_ESP_NULL 0x00000008
+#define NDIS_IPSEC_ESP_TRANSPORT 0x00000010
+#define NDIS_IPSEC_ESP_TUNNEL 0x00000020
+#define NDIS_IPSEC_ESP_SEND 0x00000040
+#define NDIS_IPSEC_ESP_RECEIVE 0x00000080
+
+struct ndis_task_ipsec {
+ uint32_t nti_ah_esp_combined;
+ uint32_t nti_ah_transport_tunnel_combined;
+ uint32_t nti_v4_options;
+ uint32_t nti_rsvd;
+ uint32_t nti_v4ah;
+ uint32_t nti_v4esp;
+};
+
+typedef struct ndis_task_ipsec ndis_task_ipsec;
+
+/*
+ * Attribures of NDIS drivers. Not all drivers support
+ * all attributes.
+ */
+
+#define NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT 0x00000001
+#define NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT 0x00000002
+#define NDIS_ATTRIBUTE_IGNORE_TOKEN_RING_ERRORS 0x00000004
+#define NDIS_ATTRIBUTE_BUS_MASTER 0x00000008
+#define NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER 0x00000010
+#define NDIS_ATTRIBUTE_DESERIALIZE 0x00000020
+#define NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND 0x00000040
+#define NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK 0x00000080
+#define NDIS_ATTRIBUTE_NOT_CO_NDIS 0x00000100
+#define NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS 0x00000200
+
+#define NDIS_SERIALIZED(block) \
+ (((block)->nmb_flags & NDIS_ATTRIBUTE_DESERIALIZE) == 0)
+
+enum ndis_media_state {
+ nmc_connected,
+ nmc_disconnected
+};
+
+typedef enum ndis_media_state ndis_media_state;
+
+/* Ndis Packet Filter Bits (OID_GEN_CURRENT_PACKET_FILTER). */
+
+#define NDIS_PACKET_TYPE_DIRECTED 0x00000001
+#define NDIS_PACKET_TYPE_MULTICAST 0x00000002
+#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004
+#define NDIS_PACKET_TYPE_BROADCAST 0x00000008
+#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010
+#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020
+#define NDIS_PACKET_TYPE_SMT 0x00000040
+#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080
+#define NDIS_PACKET_TYPE_GROUP 0x00001000
+#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00002000
+#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00004000
+#define NDIS_PACKET_TYPE_MAC_FRAME 0x00008000
+
+
+/* Ndis MAC option bits (OID_GEN_MAC_OPTIONS). */
+
+#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001
+#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002
+#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004
+#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008
+#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010
+#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020
+#define NDIS_MAC_OPTION_8021P_PRIORITY 0x00000040
+#define NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE 0x00000080
+#define NDIS_MAC_OPTION_RECEIVE_AT_DPC 0x00000100
+#define NDIS_MAC_OPTION_8021Q_VLAN 0x00000200
+#define NDIS_MAC_OPTION_RESERVED 0x80000000
+
+#define NDIS_DMA_24BITS 0x00
+#define NDIS_DMA_32BITS 0x01
+#define NDIS_DMA_64BITS 0x02
+
+/*
+struct ndis_physaddr {
+#ifdef __i386__
+ uint64_t np_quad;
+#endif
+#ifdef __amd64__
+ uint32_t np_low;
+ uint32_t np_high;
+#define np_quad np_low
+#endif
+#ifdef notdef
+ uint32_t np_low;
+ uint32_t np_high;
+#endif
+};
+*/
+
+typedef struct physaddr ndis_physaddr;
+
+struct ndis_ansi_string {
+ uint16_t nas_len;
+ uint16_t nas_maxlen;
+ char *nas_buf;
+};
+
+typedef struct ndis_ansi_string ndis_ansi_string;
+
+#ifdef notdef
+/*
+ * nus_buf is really a wchar_t *, but it's inconvenient to include
+ * all the necessary header goop needed to define it, and it's a
+ * pointer anyway, so for now, just make it a uint16_t *.
+ */
+struct ndis_unicode_string {
+ uint16_t nus_len;
+ uint16_t nus_maxlen;
+ uint16_t *nus_buf;
+};
+typedef struct ndis_unicode_string ndis_unicode_string;
+#endif
+
+typedef unicode_string ndis_unicode_string;
+
+enum ndis_parm_type {
+ ndis_parm_int,
+ ndis_parm_hexint,
+ ndis_parm_string,
+ ndis_parm_multistring,
+ ndis_parm_binary
+};
+
+typedef enum ndis_parm_type ndis_parm_type;
+
+struct ndis_binary_data {
+ uint16_t nbd_len;
+ void *nbd_buf;
+};
+
+typedef struct ndis_binary_data ndis_binary_data;
+
+struct ndis_config_parm {
+ ndis_parm_type ncp_type;
+ union {
+ uint32_t ncp_intdata;
+ ndis_unicode_string ncp_stringdata;
+ ndis_binary_data ncp_binarydata;
+ } ncp_parmdata;
+};
+
+/*
+ * Not part of Windows NDIS spec; we uses this to keep a
+ * list of ndis_config_parm structures that we've allocated.
+ */
+
+typedef struct ndis_config_parm ndis_config_parm;
+
+struct ndis_parmlist_entry {
+ list_entry np_list;
+ ndis_config_parm np_parm;
+};
+
+typedef struct ndis_parmlist_entry ndis_parmlist_entry;
+
+#ifdef notdef
+struct ndis_list_entry {
+ struct ndis_list_entry *nle_flink;
+ struct ndis_list_entry *nle_blink;
+};
+
+typedef struct ndis_list_entry ndis_list_entry;
+#endif
+
+struct ndis_bind_paths {
+ uint32_t nbp_number;
+ ndis_unicode_string nbp_paths[1];
+};
+
+typedef struct ndis_bind_paths ndis_bind_paths;
+
+#ifdef notdef
+struct dispatch_header {
+ uint8_t dh_type;
+ uint8_t dh_abs;
+ uint8_t dh_size;
+ uint8_t dh_inserted;
+ uint32_t dh_sigstate;
+ list_entry dh_waitlisthead;
+};
+#endif
+
+#define dispatch_header nt_dispatch_header
+
+struct ndis_ktimer {
+ struct dispatch_header nk_header;
+ uint64_t nk_duetime;
+ list_entry nk_timerlistentry;
+ void *nk_dpc;
+ uint32_t nk_period;
+};
+
+struct ndis_kevent {
+ struct dispatch_header nk_header;
+};
+
+struct ndis_event {
+ struct nt_kevent ne_event;
+};
+
+typedef struct ndis_event ndis_event;
+
+/* Kernel defered procedure call (i.e. timer callback) */
+
+struct ndis_kdpc;
+typedef void (*ndis_kdpc_func)(struct ndis_kdpc *, void *, void *, void *);
+
+struct ndis_kdpc {
+ uint16_t nk_type;
+ uint8_t nk_num;
+ uint8_t nk_importance;
+ list_entry nk_dpclistentry;
+ ndis_kdpc_func nk_deferedfunc;
+ void *nk_deferredctx;
+ void *nk_sysarg1;
+ void *nk_sysarg2;
+ uint32_t *nk_lock;
+};
+
+struct ndis_timer {
+ struct ktimer nt_ktimer;
+ struct kdpc nt_kdpc;
+};
+
+typedef struct ndis_timer ndis_timer;
+
+typedef void (*ndis_timer_function)(void *, void *, void *, void *);
+
+struct ndis_miniport_timer {
+ struct ktimer nmt_ktimer;
+ struct kdpc nmt_kdpc;
+ ndis_timer_function nmt_timerfunc;
+ void *nmt_timerctx;
+ ndis_miniport_block *nmt_block;
+ struct ndis_miniport_timer *nmt_nexttimer;
+};
+
+typedef struct ndis_miniport_timer ndis_miniport_timer;
+
+struct ndis_spin_lock {
+ ndis_kspin_lock nsl_spinlock;
+ ndis_kirql nsl_kirql;
+};
+
+typedef struct ndis_spin_lock ndis_spin_lock;
+
+struct ndis_rw_lock {
+ union {
+ kspin_lock nrl_spinlock;
+ void *nrl_ctx;
+ } u;
+ uint8_t nrl_rsvd[16];
+};
+
+#define nrl_spinlock u.nrl_spinlock
+#define nrl_ctx u.nrl_ctx;
+
+typedef struct ndis_rw_lock ndis_rw_lock;
+
+struct ndis_lock_state {
+ uint16_t nls_lockstate;
+ ndis_kirql nls_oldirql;
+};
+
+typedef struct ndis_lock_state ndis_lock_state;
+
+struct ndis_request {
+ uint8_t nr_macreserved[4*sizeof(void *)];
+ uint32_t nr_requesttype;
+ union _ndis_data {
+ struct _ndis_query_information {
+ ndis_oid nr_oid;
+ void *nr_infobuf;
+ uint32_t nr_infobuflen;
+ uint32_t nr_byteswritten;
+ uint32_t nr_bytesneeded;
+ } ndis_query_information;
+ struct _ndis_set_information {
+ ndis_oid nr_oid;
+ void *nr_infobuf;
+ uint32_t nr_infobuflen;
+ uint32_t nr_byteswritten;
+ uint32_t nr_bytesneeded;
+ } ndis_set_information;
+ } ndis_data;
+ /* NDIS 5.0 extentions */
+ uint8_t nr_ndis_rsvd[9 * sizeof(void *)];
+ union {
+ uint8_t nr_callmgr_rsvd[2 * sizeof(void *)];
+ uint8_t nr_protocol_rsvd[2 * sizeof(void *)];
+ } u;
+ uint8_t nr_miniport_rsvd[2 * sizeof(void *)];
+};
+
+typedef struct ndis_request ndis_request;
+
+/*
+ * Filler, not used.
+ */
+struct ndis_miniport_interrupt {
+ kinterrupt *ni_introbj;
+ ndis_kspin_lock ni_dpccountlock;
+ void *ni_rsvd;
+ void *ni_isrfunc;
+ void *ni_dpcfunc;
+ kdpc ni_dpc;
+ ndis_miniport_block *ni_block;
+ uint8_t ni_dpccnt;
+ uint8_t ni_filler1;
+ struct nt_kevent ni_dpcevt;
+ uint8_t ni_shared;
+ uint8_t ni_isrreq;
+};
+
+typedef struct ndis_miniport_interrupt ndis_miniport_interrupt;
+
+enum ndis_interrupt_mode {
+ nim_level,
+ nim_latched
+};
+
+typedef enum ndis_interrupt_mode ndis_interrupt_mode;
+
+#define NUMBER_OF_SINGLE_WORK_ITEMS 6
+
+struct ndis_work_item;
+
+typedef void (*ndis_proc)(struct ndis_work_item *, void *);
+
+struct ndis_work_item {
+ void *nwi_ctx;
+ ndis_proc nwi_func;
+ uint8_t nwi_wraprsvd[sizeof(void *) * 8];
+};
+
+typedef struct ndis_work_item ndis_work_item;
+
+#define NdisInitializeWorkItem(w, f, c) \
+ do { \
+ (w)->nwi_ctx = c; \
+ (w)->nwi_func = f; \
+ } while (0)
+
+#ifdef notdef
+struct ndis_buffer {
+ struct ndis_buffer *nb_next;
+ uint16_t nb_size;
+ uint16_t nb_flags;
+ void *nb_process;
+ void *nb_mappedsystemva;
+ void *nb_startva;
+ uint32_t nb_bytecount;
+ uint32_t nb_byteoffset;
+};
+
+typedef struct ndis_buffer ndis_buffer;
+#endif
+
+struct ndis_sc_element {
+ ndis_physaddr nse_addr;
+ uint32_t nse_len;
+ uint32_t *nse_rsvd;
+};
+
+typedef struct ndis_sc_element ndis_sc_element;
+
+#define NDIS_MAXSEG 32
+#define NDIS_BUS_SPACE_SHARED_MAXADDR 0x3E7FFFFF
+
+struct ndis_sc_list {
+ uint32_t nsl_frags;
+ uint32_t *nsl_rsvd;
+ ndis_sc_element nsl_elements[NDIS_MAXSEG];
+};
+
+typedef struct ndis_sc_list ndis_sc_list;
+
+struct ndis_tcpip_csum {
+ union {
+ uint32_t ntc_txflags;
+ uint32_t ntc_rxflags;
+ uint32_t ntc_val;
+ } u;
+};
+
+typedef struct ndis_tcpip_csum ndis_tcpip_csum;
+
+#define NDIS_TXCSUM_DO_IPV4 0x00000001
+#define NDIS_TXCSUM_DO_IPV6 0x00000002
+#define NDIS_TXCSUM_DO_TCP 0x00000004
+#define NDIS_TXCSUM_DO_UDP 0x00000008
+#define NDIS_TXCSUM_DO_IP 0x00000010
+
+#define NDIS_RXCSUM_TCP_FAILED 0x00000001
+#define NDIS_RXCSUM_UDP_FAILED 0x00000002
+#define NDIS_RXCSUM_IP_FAILED 0x00000004
+#define NDIS_RXCSUM_TCP_PASSED 0x00000008
+#define NDIS_RXCSUM_UDP_PASSED 0x00000010
+#define NDIS_RXCSUM_IP_PASSED 0x00000020
+#define NDIS_RXCSUM_LOOPBACK 0x00000040
+
+struct ndis_vlan {
+ union {
+ struct {
+ uint32_t nvt_userprio:3;
+ uint32_t nvt_canformatid:1;
+ uint32_t nvt_vlanid:12;
+ uint32_t nvt_rsvd:16;
+ } nv_taghdr;
+ } u;
+};
+
+typedef struct ndis_vlan ndis_vlan;
+
+enum ndis_perpkt_info {
+ ndis_tcpipcsum_info,
+ ndis_ipsec_info,
+ ndis_largesend_info,
+ ndis_classhandle_info,
+ ndis_rsvd,
+ ndis_sclist_info,
+ ndis_ieee8021q_info,
+ ndis_originalpkt_info,
+ ndis_packetcancelid,
+ ndis_maxpkt_info
+};
+
+typedef enum ndis_perpkt_info ndis_perpkt_info;
+
+struct ndis_packet_extension {
+ void *npe_info[ndis_maxpkt_info];
+};
+
+typedef struct ndis_packet_extension ndis_packet_extension;
+
+struct ndis_packet_private {
+ uint32_t npp_physcnt;
+ uint32_t npp_totlen;
+ ndis_buffer *npp_head;
+ ndis_buffer *npp_tail;
+
+ void *npp_pool;
+ uint32_t npp_count;
+ uint32_t npp_flags;
+ uint8_t npp_validcounts;
+ uint8_t npp_ndispktflags;
+ uint16_t npp_packetooboffset;
+};
+
+#define NDIS_FLAGS_PROTOCOL_ID_MASK 0x0000000F
+#define NDIS_FLAGS_MULTICAST_PACKET 0x00000010
+#define NDIS_FLAGS_RESERVED2 0x00000020
+#define NDIS_FLAGS_RESERVED3 0x00000040
+#define NDIS_FLAGS_DONT_LOOPBACK 0x00000080
+#define NDIS_FLAGS_IS_LOOPBACK_PACKET 0x00000100
+#define NDIS_FLAGS_LOOPBACK_ONLY 0x00000200
+#define NDIS_FLAGS_RESERVED4 0x00000400
+#define NDIS_FLAGS_DOUBLE_BUFFERED 0x00000800
+#define NDIS_FLAGS_SENT_AT_DPC 0x00001000
+#define NDIS_FLAGS_USES_SG_BUFFER_LIST 0x00002000
+
+#define NDIS_PACKET_WRAPPER_RESERVED 0x3F
+#define NDIS_PACKET_CONTAINS_MEDIA_SPECIFIC_INFO 0x40
+#define NDIS_PACKET_ALLOCATED_BY_NDIS 0x80
+
+#define NDIS_PROTOCOL_ID_DEFAULT 0x00
+#define NDIS_PROTOCOL_ID_TCP_IP 0x02
+#define NDIS_PROTOCOL_ID_IPX 0x06
+#define NDIS_PROTOCOL_ID_NBF 0x07
+#define NDIS_PROTOCOL_ID_MAX 0x0F
+#define NDIS_PROTOCOL_ID_MASK 0x0F
+
+typedef struct ndis_packet_private ndis_packet_private;
+
+enum ndis_classid {
+ ndis_class_802_3prio,
+ ndis_class_wirelesswan_mbx,
+ ndis_class_irda_packetinfo,
+ ndis_class_atm_aainfo
+};
+
+typedef enum ndis_classid ndis_classid;
+
+struct ndis_mediaspecific_info {
+ uint32_t nmi_nextentoffset;
+ ndis_classid nmi_classid;
+ uint32_t nmi_size;
+ uint8_t nmi_classinfo[1];
+};
+
+typedef struct ndis_mediaspecific_info ndis_mediaspecific_info;
+
+struct ndis_packet_oob {
+ union {
+ uint64_t npo_timetotx;
+ uint64_t npo_timetxed;
+ } u;
+ uint64_t npo_timerxed;
+ uint32_t npo_hdrlen;
+ uint32_t npo_mediaspecific_len;
+ void *npo_mediaspecific;
+ ndis_status npo_status;
+};
+
+typedef struct ndis_packet_oob ndis_packet_oob;
+
+/*
+ * Our protocol private region for handling ethernet.
+ * We need this to stash some of the things returned
+ * by NdisMEthIndicateReceive().
+ */
+
+struct ndis_ethpriv {
+ void *nep_ctx; /* packet context */
+ long nep_offset; /* residual data to transfer */
+ void *nep_pad[2];
+};
+
+typedef struct ndis_ethpriv ndis_ethpriv;
+
+#define PROTOCOL_RESERVED_SIZE_IN_PACKET (4 * sizeof(void *))
+
+struct ndis_packet {
+ ndis_packet_private np_private;
+ union {
+ /* For connectionless miniports. */
+ struct {
+ uint8_t np_miniport_rsvd[2 * sizeof(void *)];
+ uint8_t np_wrapper_rsvd[2 * sizeof(void *)];
+ } np_clrsvd;
+ /* For de-serialized miniports */
+ struct {
+ uint8_t np_miniport_rsvdex[3 * sizeof(void *)];
+ uint8_t np_wrapper_rsvdex[sizeof(void *)];
+ } np_dsrsvd;
+ struct {
+ uint8_t np_mac_rsvd[4 * sizeof(void *)];
+ } np_macrsvd;
+ } u;
+ uint32_t *np_rsvd[2];
+ uint8_t np_protocolreserved[PROTOCOL_RESERVED_SIZE_IN_PACKET];
+
+ /*
+ * This next part is probably wrong, but we need some place
+ * to put the out of band data structure...
+ */
+ ndis_packet_oob np_oob;
+ ndis_packet_extension np_ext;
+ ndis_sc_list np_sclist;
+
+ /* BSD-specific stuff which should be invisible to drivers. */
+
+ uint32_t np_refcnt;
+ void *np_softc;
+ void *np_m0;
+ int np_txidx;
+ list_entry np_list;
+};
+
+typedef struct ndis_packet ndis_packet;
+
+struct ndis_packet_pool {
+ slist_header np_head;
+ int np_dead;
+ nt_kevent np_event;
+ kspin_lock np_lock;
+ int np_cnt;
+ int np_len;
+ int np_protrsvd;
+ void *np_pktmem;
+};
+
+typedef struct ndis_packet_pool ndis_packet_pool;
+
+/* mbuf ext type for NDIS */
+#define EXT_NDIS EXT_NET_DRV
+
+/* mtx type for NDIS */
+#define MTX_NDIS_LOCK "NDIS lock"
+
+struct ndis_filterdbs {
+ union {
+ void *nf_ethdb;
+ void *nf_nulldb;
+ } u;
+ void *nf_trdb;
+ void *nf_fddidb;
+ void *nf_arcdb;
+};
+
+typedef struct ndis_filterdbs ndis_filterdbs;
+
+#define nf_ethdb u.nf_ethdb
+
+enum ndis_medium {
+ NdisMedium802_3,
+ NdisMedium802_5,
+ NdisMediumFddi,
+ NdisMediumWan,
+ NdisMediumLocalTalk,
+ NdisMediumDix, /* defined for convenience, not a real medium */
+ NdisMediumArcnetRaw,
+ NdisMediumArcnet878_2,
+ NdisMediumAtm,
+ NdisMediumWirelessWan,
+ NdisMediumIrda,
+ NdisMediumBpc,
+ NdisMediumCoWan,
+ NdisMedium1394,
+ NdisMediumMax
+};
+
+typedef enum ndis_medium ndis_medium;
+/*
+enum interface_type {
+ InterfaceTypeUndefined = -1,
+ Internal,
+ Isa,
+ Eisa,
+ MicroChannel,
+ TurboChannel,
+ PCIBus,
+ VMEBus,
+ NuBus,
+ PCMCIABus,
+ CBus,
+ MPIBus,
+ MPSABus,
+ ProcessorInternal,
+ InternalPowerBus,
+ PNPISABus,
+ PNPBus,
+ MaximumInterfaceType
+};
+*/
+enum ndis_interface_type {
+ NdisInterfaceInternal = Internal,
+ NdisInterfaceIsa = Isa,
+ NdisInterfaceEisa = Eisa,
+ NdisInterfaceMca = MicroChannel,
+ NdisInterfaceTurboChannel = TurboChannel,
+ NdisInterfacePci = PCIBus,
+ NdisInterfacePcMcia = PCMCIABus
+};
+
+typedef enum ndis_interface_type ndis_interface_type;
+
+struct ndis_paddr_unit {
+ ndis_physaddr npu_physaddr;
+ uint32_t npu_len;
+};
+
+typedef struct ndis_paddr_unit ndis_paddr_unit;
+
+struct ndis_map_arg {
+ ndis_paddr_unit *nma_fraglist;
+ int nma_cnt;
+ int nma_max;
+};
+
+/*
+ * Miniport characteristics were originally defined in the NDIS 3.0
+ * spec and then extended twice, in NDIS 4.0 and 5.0.
+ */
+
+struct ndis_miniport_characteristics {
+
+ /* NDIS 3.0 */
+
+ uint8_t nmc_version_major;
+ uint8_t nmc_version_minor;
+ uint16_t nmc_pad;
+ uint32_t nmc_rsvd;
+ void * nmc_checkhang_func;
+ void * nmc_disable_interrupts_func;
+ void * nmc_enable_interrupts_func;
+ void * nmc_halt_func;
+ void * nmc_interrupt_func;
+ void * nmc_init_func;
+ void * nmc_isr_func;
+ void * nmc_queryinfo_func;
+ void * nmc_reconfig_func;
+ void * nmc_reset_func;
+ void * nmc_sendsingle_func;
+ void * nmc_setinfo_func;
+ void * nmc_transferdata_func;
+
+ /* NDIS 4.0 extentions */
+
+ void * nmc_return_packet_func;
+ void * nmc_sendmulti_func;
+ void * nmc_allocate_complete_func;
+
+ /* NDIS 5.0 extensions */
+
+ void * nmc_cocreatevc_func;
+ void * nmc_codeletevc_func;
+ void * nmc_coactivatevc_func;
+ void * nmc_codeactivatevc_func;
+ void * nmc_comultisend_func;
+ void * nmc_corequest_func;
+
+ /* NDIS 5.1 extentions */
+
+ void * nmc_canceltxpkts_handler;
+ void * nmc_pnpevent_handler;
+ void * nmc_shutdown_handler;
+ void * nmc_rsvd0;
+ void * nmc_rsvd1;
+ void * nmc_rsvd2;
+ void * nmc_rsvd3;
+};
+
+typedef struct ndis_miniport_characteristics ndis_miniport_characteristics;
+
+struct ndis_driver_object {
+ char *ndo_ifname;
+ void *ndo_softc;
+ ndis_miniport_characteristics ndo_chars;
+};
+
+typedef struct ndis_driver_object ndis_driver_object;
+
+struct ndis_reference {
+ ndis_kspin_lock nr_spinlock;
+ uint16_t nr_refcnt;
+ uint8_t nr_closing;
+};
+
+typedef struct ndis_reference ndis_reference;
+
+struct ndis_timer_entry {
+ struct callout nte_ch;
+ ndis_miniport_timer *nte_timer;
+ TAILQ_ENTRY(ndis_timer_entry) link;
+};
+
+TAILQ_HEAD(nte_head, ndis_timer_entry);
+
+#define NDIS_FH_TYPE_VFS 0
+#define NDIS_FH_TYPE_MODULE 1
+
+struct ndis_fh {
+ int nf_type;
+ char *nf_name;
+ void *nf_vp;
+ void *nf_map;
+ uint32_t nf_maplen;
+};
+
+typedef struct ndis_fh ndis_fh;
+
+/*
+ * The miniport block is basically the internal NDIS handle. We need
+ * to define this because, unfortunately, it is not entirely opaque
+ * to NDIS drivers. For one thing, it contains the function pointer
+ * to the NDIS packet receive handler, which is invoked out of the
+ * NDIS block via a macro rather than a function pointer. (The
+ * NdisMIndicateReceivePacket() routine is a macro rather than
+ * a function.) For another, the driver maintains a pointer to the
+ * miniport block and passes it as a handle to various NDIS functions.
+ * (The driver never really knows this because it's hidden behind
+ * an ndis_handle though.)
+ *
+ * The miniport block has two parts: the first part contains fields
+ * that must never change, since they are referenced by driver
+ * binaries through macros. The second part is ignored by the driver,
+ * but contains various things used internaly by NDIS.SYS. In our
+ * case, we define the first 'immutable' part exactly as it appears
+ * in Windows, but don't bother duplicating the Windows definitions
+ * for the second part. Instead, we replace them with a few BSD-specific
+ * things.
+ */
+
+struct ndis_miniport_block {
+ /*
+ * Windows-specific portion -- DO NOT MODIFY OR NDIS
+ * DRIVERS WILL NOT WORK.
+ */
+ void *nmb_signature; /* magic number */
+ ndis_miniport_block *nmb_nextminiport;
+ ndis_mdriver_block *nmb_driverhandle;
+ ndis_handle nmb_miniportadapterctx;
+ ndis_unicode_string nmb_name;
+ ndis_bind_paths *nmb_bindpaths;
+ ndis_handle nmb_openqueue;
+ ndis_reference nmb_ref;
+ ndis_handle nmb_devicectx;
+ uint8_t nmb_padding;
+ uint8_t nmb_lockacquired;
+ uint8_t nmb_pmodeopens;
+ uint8_t nmb_assignedcpu;
+ ndis_kspin_lock nmb_lock;
+ ndis_request *nmb_mediarequest;
+ ndis_miniport_interrupt *nmb_interrupt;
+ uint32_t nmb_flags;
+ uint32_t nmb_pnpflags;
+ list_entry nmb_packetlist;
+ ndis_packet *nmb_firstpendingtxpacket;
+ ndis_packet *nmb_returnpacketqueue;
+ uint32_t nmb_requestbuffer;
+ void *nmb_setmcastbuf;
+ ndis_miniport_block *nmb_primaryminiport;
+ void *nmb_wrapperctx;
+ void *nmb_busdatactx;
+ uint32_t nmb_pnpcaps;
+ cm_resource_list *nmb_resources;
+ ndis_timer nmb_wkupdpctimer;
+ ndis_unicode_string nmb_basename;
+ ndis_unicode_string nmb_symlinkname;
+ uint32_t nmb_checkforhangsecs;
+ uint16_t nmb_cfhticks;
+ uint16_t nmb_cfhcurrticks;
+ ndis_status nmb_resetstatus;
+ ndis_handle nmb_resetopen;
+ ndis_filterdbs nmb_filterdbs;
+ void *nmb_pktind_func;
+ void *nmb_senddone_func;
+ void *nmb_sendrsrc_func;
+ void *nmb_resetdone_func;
+ ndis_medium nmb_medium;
+ uint32_t nmb_busnum;
+ uint32_t nmb_bustype;
+ uint32_t nmb_adaptertype;
+ device_object *nmb_deviceobj; /* Functional device */
+ device_object *nmb_physdeviceobj; /* Physical device */
+ device_object *nmb_nextdeviceobj; /* Next dev in stack */
+ void *nmb_mapreg;
+ void *nmb_callmgraflist;
+ void *nmb_miniportthread;
+ void *nmb_setinfobuf;
+ uint16_t nmb_setinfobuflen;
+ uint16_t nmb_maxsendpkts;
+ ndis_status nmb_fakestatus;
+ void *nmb_lockhandler;
+ ndis_unicode_string *nmb_adapterinstancename;
+ void *nmb_timerqueue;
+ uint32_t nmb_mactoptions;
+ ndis_request *nmb_pendingreq;
+ uint32_t nmb_maxlongaddrs;
+ uint32_t nmb_maxshortaddrs;
+ uint32_t nmb_currlookahead;
+ uint32_t nmb_maxlookahead;
+ void *nmb_interrupt_func;
+ void *nmb_disableintr_func;
+ void *nmb_enableintr_func;
+ void *nmb_sendpkts_func;
+ void *nmb_deferredsend_func;
+ void *nmb_ethrxindicate_func;
+ void *nmb_txrxindicate_func;
+ void *nmb_fddirxindicate_func;
+ void *nmb_ethrxdone_func;
+ void *nmb_txrxdone_func;
+ void *nmb_fddirxcond_func;
+ void *nmb_status_func;
+ void *nmb_statusdone_func;
+ void *nmb_tdcond_func;
+ void *nmb_querydone_func;
+ void *nmb_setdone_func;
+ void *nmb_wantxdone_func;
+ void *nmb_wanrx_func;
+ void *nmb_wanrxdone_func;
+ /*
+ * End of windows-specific portion of miniport block. Everything
+ * below is BSD-specific.
+ */
+ list_entry nmb_parmlist;
+ ndis_resource_list *nmb_rlist;
+ ndis_status nmb_getstat;
+ nt_kevent nmb_getevent;
+ ndis_status nmb_setstat;
+ nt_kevent nmb_setevent;
+ nt_kevent nmb_resetevent;
+ io_workitem *nmb_returnitem;
+ ndis_miniport_timer *nmb_timerlist;
+ ndis_handle nmb_rxpool;
+ list_entry nmb_returnlist;
+ kspin_lock nmb_returnlock;
+ TAILQ_ENTRY(ndis_miniport_block) link;
+};
+
+TAILQ_HEAD(nd_head, ndis_miniport_block);
+
+typedef ndis_status (*ndis_init_handler)(ndis_status *, uint32_t *,
+ ndis_medium *, uint32_t, ndis_handle, ndis_handle);
+typedef ndis_status (*ndis_queryinfo_handler)(ndis_handle, ndis_oid,
+ void *, uint32_t, uint32_t *, uint32_t *);
+typedef ndis_status (*ndis_setinfo_handler)(ndis_handle, ndis_oid,
+ void *, uint32_t, uint32_t *, uint32_t *);
+typedef ndis_status (*ndis_sendsingle_handler)(ndis_handle,
+ ndis_packet *, uint32_t);
+typedef ndis_status (*ndis_sendmulti_handler)(ndis_handle,
+ ndis_packet **, uint32_t);
+typedef void (*ndis_isr_handler)(uint8_t *, uint8_t *, ndis_handle);
+typedef void (*ndis_interrupt_handler)(ndis_handle);
+typedef int (*ndis_reset_handler)(uint8_t *, ndis_handle);
+typedef void (*ndis_halt_handler)(ndis_handle);
+typedef void (*ndis_return_handler)(ndis_handle, ndis_packet *);
+typedef void (*ndis_enable_interrupts_handler)(ndis_handle);
+typedef void (*ndis_disable_interrupts_handler)(ndis_handle);
+typedef void (*ndis_shutdown_handler)(void *);
+typedef void (*ndis_pnpevent_handler)(void *, int, void *, uint32_t);
+typedef void (*ndis_allocdone_handler)(ndis_handle, void *,
+ ndis_physaddr *, uint32_t, void *);
+typedef uint8_t (*ndis_checkforhang_handler)(ndis_handle);
+
+typedef ndis_status (*driver_entry)(void *, unicode_string *);
+
+extern image_patch_table ndis_functbl[];
+
+#define NDIS_TASKQUEUE 1
+#define NDIS_SWI 2
+
+#define NDIS_PSTATE_RUNNING 1
+#define NDIS_PSTATE_SLEEPING 2
+
+#define NdisQueryPacket(p, pbufcnt, bufcnt, firstbuf, plen) \
+ do { \
+ if ((firstbuf) != NULL) { \
+ ndis_buffer **_first; \
+ _first = firstbuf; \
+ *(_first) = (p)->np_private.npp_head; \
+ } \
+ if ((plen) || (bufcnt) || (pbufcnt)) { \
+ if ((p)->np_private.npp_validcounts == FALSE) { \
+ ndis_buffer *tmp; \
+ unsigned int tlen = 0, pcnt = 0; \
+ unsigned int add = 0; \
+ unsigned int pktlen, off; \
+ \
+ tmp = (p)->np_private.npp_head; \
+ while (tmp != NULL) { \
+ off = MmGetMdlByteOffset(tmp); \
+ pktlen = MmGetMdlByteCount(tmp);\
+ tlen += pktlen; \
+ pcnt += \
+ NDIS_BUFFER_TO_SPAN_PAGES(tmp); \
+ add++; \
+ tmp = tmp->mdl_next; \
+ } \
+ (p)->np_private.npp_count = add; \
+ (p)->np_private.npp_totlen = tlen; \
+ (p)->np_private.npp_physcnt = pcnt; \
+ (p)->np_private.npp_validcounts = TRUE; \
+ } \
+ if (pbufcnt) { \
+ unsigned int *_pbufcnt; \
+ _pbufcnt = (pbufcnt); \
+ *(_pbufcnt) = (p)->np_private.npp_physcnt; \
+ } \
+ if (bufcnt) { \
+ unsigned int *_bufcnt; \
+ _bufcnt = (bufcnt); \
+ *(_bufcnt) = (p)->np_private.npp_count; \
+ } \
+ if (plen) { \
+ unsigned int *_plen; \
+ _plen = (plen); \
+ *(_plen) = (p)->np_private.npp_totlen; \
+ } \
+ } \
+ } while (0)
+
+__BEGIN_DECLS
+extern int ndis_libinit(void);
+extern int ndis_libfini(void);
+extern int ndis_load_driver(vm_offset_t, void *);
+extern int ndis_unload_driver(void *);
+extern int ndis_mtop(struct mbuf *, ndis_packet **);
+extern int ndis_ptom(struct mbuf **, ndis_packet *);
+extern int ndis_get_info(void *, ndis_oid, void *, int *);
+extern int ndis_set_info(void *, ndis_oid, void *, int *);
+extern void *ndis_get_routine_address(struct image_patch_table *, char *);
+extern int ndis_get_supported_oids(void *, ndis_oid **, int *);
+extern int ndis_send_packets(void *, ndis_packet **, int);
+extern int ndis_send_packet(void *, ndis_packet *);
+extern int ndis_convert_res(void *);
+extern int ndis_alloc_amem(void *);
+extern void ndis_free_amem(void *);
+extern void ndis_free_packet(ndis_packet *);
+extern void ndis_free_bufs(ndis_buffer *);
+extern int ndis_reset_nic(void *);
+extern int ndis_halt_nic(void *);
+extern int ndis_shutdown_nic(void *);
+extern int ndis_pnpevent_nic(void *, int);
+extern int ndis_init_nic(void *);
+extern void ndis_return_packet(void *, void *);
+extern int ndis_init_dma(void *);
+extern int ndis_destroy_dma(void *);
+extern int ndis_create_sysctls(void *);
+extern int ndis_add_sysctl(void *, char *, char *, char *, int);
+extern int ndis_flush_sysctls(void *);
+
+extern uint32_t NdisAddDevice(driver_object *, device_object *);
+extern void NdisAllocatePacketPool(ndis_status *,
+ ndis_handle *, uint32_t, uint32_t);
+extern void NdisAllocatePacketPoolEx(ndis_status *,
+ ndis_handle *, uint32_t, uint32_t, uint32_t);
+extern uint32_t NdisPacketPoolUsage(ndis_handle);
+extern void NdisFreePacketPool(ndis_handle);
+extern void NdisAllocatePacket(ndis_status *,
+ ndis_packet **, ndis_handle);
+extern void NdisFreePacket(ndis_packet *);
+extern ndis_status NdisScheduleWorkItem(ndis_work_item *);
+extern void NdisMSleep(uint32_t);
+__END_DECLS
+
+#endif /* _NDIS_VAR_H_ */
diff --git a/sys/compat/ndis/ntoskrnl_var.h b/sys/compat/ndis/ntoskrnl_var.h
new file mode 100644
index 0000000..2642626
--- /dev/null
+++ b/sys/compat/ndis/ntoskrnl_var.h
@@ -0,0 +1,1529 @@
+/*-
+ * Copyright (c) 2003
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _NTOSKRNL_VAR_H_
+#define _NTOSKRNL_VAR_H_
+
+#define MTX_NTOSKRNL_SPIN_LOCK "NDIS thread lock"
+
+/*
+ * us_buf is really a wchar_t *, but it's inconvenient to include
+ * all the necessary header goop needed to define it, and it's a
+ * pointer anyway, so for now, just make it a uint16_t *.
+ */
+struct unicode_string {
+ uint16_t us_len;
+ uint16_t us_maxlen;
+ uint16_t *us_buf;
+};
+
+typedef struct unicode_string unicode_string;
+
+struct ansi_string {
+ uint16_t as_len;
+ uint16_t as_maxlen;
+ char *as_buf;
+};
+
+typedef struct ansi_string ansi_string;
+
+/*
+ * Windows memory descriptor list. In Windows, it's possible for
+ * buffers to be passed between user and kernel contexts without
+ * copying. Buffers may also be allocated in either paged or
+ * non-paged memory regions. An MDL describes the pages of memory
+ * used to contain a particular buffer. Note that a single MDL
+ * may describe a buffer that spans multiple pages. An array of
+ * page addresses appears immediately after the MDL structure itself.
+ * MDLs are therefore implicitly variably sized, even though they
+ * don't look it.
+ *
+ * Note that in FreeBSD, we can take many shortcuts in the way
+ * we handle MDLs because:
+ *
+ * - We are only concerned with pages in kernel context. This means
+ * we will only ever use the kernel's memory map, and remapping
+ * of buffers is never needed.
+ *
+ * - Kernel pages can never be paged out, so we don't have to worry
+ * about whether or not a page is actually mapped before going to
+ * touch it.
+ */
+
+struct mdl {
+ struct mdl *mdl_next;
+ uint16_t mdl_size;
+ uint16_t mdl_flags;
+ void *mdl_process;
+ void *mdl_mappedsystemva;
+ void *mdl_startva;
+ uint32_t mdl_bytecount;
+ uint32_t mdl_byteoffset;
+};
+
+typedef struct mdl mdl, ndis_buffer;
+
+/* MDL flags */
+
+#define MDL_MAPPED_TO_SYSTEM_VA 0x0001
+#define MDL_PAGES_LOCKED 0x0002
+#define MDL_SOURCE_IS_NONPAGED_POOL 0x0004
+#define MDL_ALLOCATED_FIXED_SIZE 0x0008
+#define MDL_PARTIAL 0x0010
+#define MDL_PARTIAL_HAS_BEEN_MAPPED 0x0020
+#define MDL_IO_PAGE_READ 0x0040
+#define MDL_WRITE_OPERATION 0x0080
+#define MDL_PARENT_MAPPED_SYSTEM_VA 0x0100
+#define MDL_FREE_EXTRA_PTES 0x0200
+#define MDL_IO_SPACE 0x0800
+#define MDL_NETWORK_HEADER 0x1000
+#define MDL_MAPPING_CAN_FAIL 0x2000
+#define MDL_ALLOCATED_MUST_SUCCEED 0x4000
+#define MDL_ZONE_ALLOCED 0x8000 /* BSD private */
+
+#define MDL_ZONE_PAGES 16
+#define MDL_ZONE_SIZE (sizeof(mdl) + (sizeof(vm_offset_t) * MDL_ZONE_PAGES))
+
+/* Note: assumes x86 page size of 4K. */
+
+#ifndef PAGE_SHIFT
+#if PAGE_SIZE == 4096
+#define PAGE_SHIFT 12
+#elif PAGE_SIZE == 8192
+#define PAGE_SHIFT 13
+#else
+#error PAGE_SHIFT undefined!
+#endif
+#endif
+
+#define SPAN_PAGES(ptr, len) \
+ ((uint32_t)((((uintptr_t)(ptr) & (PAGE_SIZE - 1)) + \
+ (len) + (PAGE_SIZE - 1)) >> PAGE_SHIFT))
+
+#define PAGE_ALIGN(ptr) \
+ ((void *)((uintptr_t)(ptr) & ~(PAGE_SIZE - 1)))
+
+#define BYTE_OFFSET(ptr) \
+ ((uint32_t)((uintptr_t)(ptr) & (PAGE_SIZE - 1)))
+
+#define MDL_PAGES(m) (vm_offset_t *)(m + 1)
+
+#define MmInitializeMdl(b, baseva, len) \
+ (b)->mdl_next = NULL; \
+ (b)->mdl_size = (uint16_t)(sizeof(mdl) + \
+ (sizeof(vm_offset_t) * SPAN_PAGES((baseva), (len)))); \
+ (b)->mdl_flags = 0; \
+ (b)->mdl_startva = (void *)PAGE_ALIGN((baseva)); \
+ (b)->mdl_byteoffset = BYTE_OFFSET((baseva)); \
+ (b)->mdl_bytecount = (uint32_t)(len);
+
+#define MmGetMdlByteOffset(mdl) ((mdl)->mdl_byteoffset)
+#define MmGetMdlByteCount(mdl) ((mdl)->mdl_bytecount)
+#define MmGetMdlVirtualAddress(mdl) \
+ ((void *)((char *)((mdl)->mdl_startva) + (mdl)->mdl_byteoffset))
+#define MmGetMdlStartVa(mdl) ((mdl)->mdl_startva)
+#define MmGetMdlPfnArray(mdl) MDL_PAGES(mdl)
+
+#define WDM_MAJOR 1
+#define WDM_MINOR_WIN98 0x00
+#define WDM_MINOR_WINME 0x05
+#define WDM_MINOR_WIN2000 0x10
+#define WDM_MINOR_WINXP 0x20
+#define WDM_MINOR_WIN2003 0x30
+
+enum nt_caching_type {
+ MmNonCached = 0,
+ MmCached = 1,
+ MmWriteCombined = 2,
+ MmHardwareCoherentCached = 3,
+ MmNonCachedUnordered = 4,
+ MmUSWCCached = 5,
+ MmMaximumCacheType = 6
+};
+
+/*-
+ * The ndis_kspin_lock type is called KSPIN_LOCK in MS-Windows.
+ * According to the Windows DDK header files, KSPIN_LOCK is defined like this:
+ * typedef ULONG_PTR KSPIN_LOCK;
+ *
+ * From basetsd.h (SDK, Feb. 2003):
+ * typedef [public] unsigned __int3264 ULONG_PTR, *PULONG_PTR;
+ * typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
+ * typedef _W64 unsigned long ULONG_PTR, *PULONG_PTR;
+ *
+ * The keyword __int3264 specifies an integral type that has the following
+ * properties:
+ * + It is 32-bit on 32-bit platforms
+ * + It is 64-bit on 64-bit platforms
+ * + It is 32-bit on the wire for backward compatibility.
+ * It gets truncated on the sending side and extended appropriately
+ * (signed or unsigned) on the receiving side.
+ *
+ * Thus register_t seems the proper mapping onto FreeBSD for spin locks.
+ */
+
+typedef register_t kspin_lock;
+
+struct slist_entry {
+ struct slist_entry *sl_next;
+};
+
+typedef struct slist_entry slist_entry;
+
+union slist_header {
+ uint64_t slh_align;
+ struct {
+ struct slist_entry *slh_next;
+ uint16_t slh_depth;
+ uint16_t slh_seq;
+ } slh_list;
+};
+
+typedef union slist_header slist_header;
+
+struct list_entry {
+ struct list_entry *nle_flink;
+ struct list_entry *nle_blink;
+};
+
+typedef struct list_entry list_entry;
+
+#define InitializeListHead(l) \
+ (l)->nle_flink = (l)->nle_blink = (l)
+
+#define IsListEmpty(h) \
+ ((h)->nle_flink == (h))
+
+#define RemoveEntryList(e) \
+ do { \
+ list_entry *b; \
+ list_entry *f; \
+ \
+ f = (e)->nle_flink; \
+ b = (e)->nle_blink; \
+ b->nle_flink = f; \
+ f->nle_blink = b; \
+ } while (0)
+
+/* These two have to be inlined since they return things. */
+
+static __inline__ list_entry *
+RemoveHeadList(list_entry *l)
+{
+ list_entry *f;
+ list_entry *e;
+
+ e = l->nle_flink;
+ f = e->nle_flink;
+ l->nle_flink = f;
+ f->nle_blink = l;
+
+ return (e);
+}
+
+static __inline__ list_entry *
+RemoveTailList(list_entry *l)
+{
+ list_entry *b;
+ list_entry *e;
+
+ e = l->nle_blink;
+ b = e->nle_blink;
+ l->nle_blink = b;
+ b->nle_flink = l;
+
+ return (e);
+}
+
+#define InsertTailList(l, e) \
+ do { \
+ list_entry *b; \
+ \
+ b = l->nle_blink; \
+ e->nle_flink = l; \
+ e->nle_blink = b; \
+ b->nle_flink = (e); \
+ l->nle_blink = (e); \
+ } while (0)
+
+#define InsertHeadList(l, e) \
+ do { \
+ list_entry *f; \
+ \
+ f = l->nle_flink; \
+ e->nle_flink = f; \
+ e->nle_blink = l; \
+ f->nle_blink = e; \
+ l->nle_flink = e; \
+ } while (0)
+
+#define CONTAINING_RECORD(addr, type, field) \
+ ((type *)((vm_offset_t)(addr) - (vm_offset_t)(&((type *)0)->field)))
+
+struct nt_dispatch_header {
+ uint8_t dh_type;
+ uint8_t dh_abs;
+ uint8_t dh_size;
+ uint8_t dh_inserted;
+ int32_t dh_sigstate;
+ list_entry dh_waitlisthead;
+};
+
+typedef struct nt_dispatch_header nt_dispatch_header;
+
+/* Dispatcher object types */
+
+#define DISP_TYPE_NOTIFICATION_EVENT 0 /* KEVENT */
+#define DISP_TYPE_SYNCHRONIZATION_EVENT 1 /* KEVENT */
+#define DISP_TYPE_MUTANT 2 /* KMUTANT/KMUTEX */
+#define DISP_TYPE_PROCESS 3 /* KPROCESS */
+#define DISP_TYPE_QUEUE 4 /* KQUEUE */
+#define DISP_TYPE_SEMAPHORE 5 /* KSEMAPHORE */
+#define DISP_TYPE_THREAD 6 /* KTHREAD */
+#define DISP_TYPE_NOTIFICATION_TIMER 8 /* KTIMER */
+#define DISP_TYPE_SYNCHRONIZATION_TIMER 9 /* KTIMER */
+
+#define OTYPE_EVENT 0
+#define OTYPE_MUTEX 1
+#define OTYPE_THREAD 2
+#define OTYPE_TIMER 3
+
+/* Windows dispatcher levels. */
+
+#define PASSIVE_LEVEL 0
+#define LOW_LEVEL 0
+#define APC_LEVEL 1
+#define DISPATCH_LEVEL 2
+#define DEVICE_LEVEL (DISPATCH_LEVEL + 1)
+#define PROFILE_LEVEL 27
+#define CLOCK1_LEVEL 28
+#define CLOCK2_LEVEL 28
+#define IPI_LEVEL 29
+#define POWER_LEVEL 30
+#define HIGH_LEVEL 31
+
+#define SYNC_LEVEL_UP DISPATCH_LEVEL
+#define SYNC_LEVEL_MP (IPI_LEVEL - 1)
+
+#define AT_PASSIVE_LEVEL(td) \
+ ((td)->td_proc->p_flag & P_KTHREAD == FALSE)
+
+#define AT_DISPATCH_LEVEL(td) \
+ ((td)->td_base_pri == PI_REALTIME)
+
+#define AT_DIRQL_LEVEL(td) \
+ ((td)->td_priority <= PI_NET)
+
+#define AT_HIGH_LEVEL(td) \
+ ((td)->td_critnest != 0)
+
+struct nt_objref {
+ nt_dispatch_header no_dh;
+ void *no_obj;
+ TAILQ_ENTRY(nt_objref) link;
+};
+
+TAILQ_HEAD(nt_objref_head, nt_objref);
+
+typedef struct nt_objref nt_objref;
+
+#define EVENT_TYPE_NOTIFY 0
+#define EVENT_TYPE_SYNC 1
+
+/*
+ * We need to use the timeout()/untimeout() API for ktimers
+ * since timers can be initialized, but not destroyed (so
+ * malloc()ing our own callout structures would mean a leak,
+ * since there'd be no way to free() them). This means we
+ * need to use struct callout_handle, which is really just a
+ * pointer. To make it easier to deal with, we use a union
+ * to overlay the callout_handle over the k_timerlistentry.
+ * The latter is a list_entry, which is two pointers, so
+ * there's enough space available to hide a callout_handle
+ * there.
+ */
+
+struct ktimer {
+ nt_dispatch_header k_header;
+ uint64_t k_duetime;
+ union {
+ list_entry k_timerlistentry;
+ struct callout *k_callout;
+ } u;
+ void *k_dpc;
+ uint32_t k_period;
+};
+
+#define k_timerlistentry u.k_timerlistentry
+#define k_callout u.k_callout
+
+typedef struct ktimer ktimer;
+
+struct nt_kevent {
+ nt_dispatch_header k_header;
+};
+
+typedef struct nt_kevent nt_kevent;
+
+/* Kernel defered procedure call (i.e. timer callback) */
+
+struct kdpc;
+typedef void (*kdpc_func)(struct kdpc *, void *, void *, void *);
+
+struct kdpc {
+ uint16_t k_type;
+ uint8_t k_num; /* CPU number */
+ uint8_t k_importance; /* priority */
+ list_entry k_dpclistentry;
+ void *k_deferedfunc;
+ void *k_deferredctx;
+ void *k_sysarg1;
+ void *k_sysarg2;
+ void *k_lock;
+};
+
+#define KDPC_IMPORTANCE_LOW 0
+#define KDPC_IMPORTANCE_MEDIUM 1
+#define KDPC_IMPORTANCE_HIGH 2
+
+#define KDPC_CPU_DEFAULT 255
+
+typedef struct kdpc kdpc;
+
+/*
+ * Note: the acquisition count is BSD-specific. The Microsoft
+ * documentation says that mutexes can be acquired recursively
+ * by a given thread, but that you must release the mutex as
+ * many times as you acquired it before it will be set to the
+ * signalled state (i.e. before any other threads waiting on
+ * the object will be woken up). However the Windows KMUTANT
+ * structure has no field for keeping track of the number of
+ * acquisitions, so we need to add one ourselves. As long as
+ * driver code treats the mutex as opaque, we should be ok.
+ */
+struct kmutant {
+ nt_dispatch_header km_header;
+ list_entry km_listentry;
+ void *km_ownerthread;
+ uint8_t km_abandoned;
+ uint8_t km_apcdisable;
+};
+
+typedef struct kmutant kmutant;
+
+#define LOOKASIDE_DEPTH 256
+
+struct general_lookaside {
+ slist_header gl_listhead;
+ uint16_t gl_depth;
+ uint16_t gl_maxdepth;
+ uint32_t gl_totallocs;
+ union {
+ uint32_t gl_allocmisses;
+ uint32_t gl_allochits;
+ } u_a;
+ uint32_t gl_totalfrees;
+ union {
+ uint32_t gl_freemisses;
+ uint32_t gl_freehits;
+ } u_m;
+ uint32_t gl_type;
+ uint32_t gl_tag;
+ uint32_t gl_size;
+ void *gl_allocfunc;
+ void *gl_freefunc;
+ list_entry gl_listent;
+ uint32_t gl_lasttotallocs;
+ union {
+ uint32_t gl_lastallocmisses;
+ uint32_t gl_lastallochits;
+ } u_l;
+ uint32_t gl_rsvd[2];
+};
+
+typedef struct general_lookaside general_lookaside;
+
+struct npaged_lookaside_list {
+ general_lookaside nll_l;
+#ifdef __i386__
+ kspin_lock nll_obsoletelock;
+#endif
+};
+
+typedef struct npaged_lookaside_list npaged_lookaside_list;
+typedef struct npaged_lookaside_list paged_lookaside_list;
+
+typedef void * (*lookaside_alloc_func)(uint32_t, size_t, uint32_t);
+typedef void (*lookaside_free_func)(void *);
+
+struct irp;
+
+struct kdevice_qentry {
+ list_entry kqe_devlistent;
+ uint32_t kqe_sortkey;
+ uint8_t kqe_inserted;
+};
+
+typedef struct kdevice_qentry kdevice_qentry;
+
+struct kdevice_queue {
+ uint16_t kq_type;
+ uint16_t kq_size;
+ list_entry kq_devlisthead;
+ kspin_lock kq_lock;
+ uint8_t kq_busy;
+};
+
+typedef struct kdevice_queue kdevice_queue;
+
+struct wait_ctx_block {
+ kdevice_qentry wcb_waitqueue;
+ void *wcb_devfunc;
+ void *wcb_devctx;
+ uint32_t wcb_mapregcnt;
+ void *wcb_devobj;
+ void *wcb_curirp;
+ void *wcb_bufchaindpc;
+};
+
+typedef struct wait_ctx_block wait_ctx_block;
+
+struct wait_block {
+ list_entry wb_waitlist;
+ void *wb_kthread;
+ nt_dispatch_header *wb_object;
+ struct wait_block *wb_next;
+#ifdef notdef
+ uint16_t wb_waitkey;
+ uint16_t wb_waittype;
+#endif
+ uint8_t wb_waitkey;
+ uint8_t wb_waittype;
+ uint8_t wb_awakened;
+ uint8_t wb_oldpri;
+};
+
+typedef struct wait_block wait_block;
+
+#define wb_ext wb_kthread
+
+#define THREAD_WAIT_OBJECTS 3
+#define MAX_WAIT_OBJECTS 64
+
+#define WAITTYPE_ALL 0
+#define WAITTYPE_ANY 1
+
+#define WAITKEY_VALID 0x8000
+
+/* kthread priority */
+#define LOW_PRIORITY 0
+#define LOW_REALTIME_PRIORITY 16
+#define HIGH_PRIORITY 31
+
+struct thread_context {
+ void *tc_thrctx;
+ void *tc_thrfunc;
+};
+
+typedef struct thread_context thread_context;
+
+/* Forward declaration */
+struct driver_object;
+struct devobj_extension;
+
+struct driver_extension {
+ struct driver_object *dre_driverobj;
+ void *dre_adddevicefunc;
+ uint32_t dre_reinitcnt;
+ unicode_string dre_srvname;
+
+ /*
+ * Drivers are allowed to add one or more custom extensions
+ * to the driver object, but there's no special pointer
+ * for them. Hang them off here for now.
+ */
+
+ list_entry dre_usrext;
+};
+
+typedef struct driver_extension driver_extension;
+
+struct custom_extension {
+ list_entry ce_list;
+ void *ce_clid;
+};
+
+typedef struct custom_extension custom_extension;
+
+/*
+ * The KINTERRUPT structure in Windows is opaque to drivers.
+ * We define our own custom version with things we need.
+ */
+
+struct kinterrupt {
+ list_entry ki_list;
+ device_t ki_dev;
+ int ki_rid;
+ void *ki_cookie;
+ struct resource *ki_irq;
+ kspin_lock ki_lock_priv;
+ kspin_lock *ki_lock;
+ void *ki_svcfunc;
+ void *ki_svcctx;
+};
+
+typedef struct kinterrupt kinterrupt;
+
+struct ksystem_time {
+ uint32_t low_part;
+ int32_t high1_time;
+ int32_t high2_time;
+};
+
+enum nt_product_type {
+ NT_PRODUCT_WIN_NT = 1,
+ NT_PRODUCT_LAN_MAN_NT,
+ NT_PRODUCT_SERVER
+};
+
+enum alt_arch_type {
+ STANDARD_DESIGN,
+ NEC98x86,
+ END_ALTERNATIVES
+};
+
+struct kuser_shared_data {
+ uint32_t tick_count;
+ uint32_t tick_count_multiplier;
+ volatile struct ksystem_time interrupt_time;
+ volatile struct ksystem_time system_time;
+ volatile struct ksystem_time time_zone_bias;
+ uint16_t image_number_low;
+ uint16_t image_number_high;
+ int16_t nt_system_root[260];
+ uint32_t max_stack_trace_depth;
+ uint32_t crypto_exponent;
+ uint32_t time_zone_id;
+ uint32_t large_page_min;
+ uint32_t reserved2[7];
+ enum nt_product_type nt_product_type;
+ uint8_t product_type_is_valid;
+ uint32_t nt_major_version;
+ uint32_t nt_minor_version;
+ uint8_t processor_features[64];
+ uint32_t reserved1;
+ uint32_t reserved3;
+ volatile uint32_t time_slip;
+ enum alt_arch_type alt_arch_type;
+ int64_t system_expiration_date;
+ uint32_t suite_mask;
+ uint8_t kdbg_enabled;
+ volatile uint32_t active_console;
+ volatile uint32_t dismount_count;
+ uint32_t com_plus_package;
+ uint32_t last_system_rit_event_tick_count;
+ uint32_t num_phys_pages;
+ uint8_t safe_boot_mode;
+ uint32_t trace_log;
+ uint64_t fill0;
+ uint64_t sys_call[4];
+ union {
+ volatile struct ksystem_time tick_count;
+ volatile uint64_t tick_count_quad;
+ } tick;
+};
+
+/*
+ * In Windows, there are Physical Device Objects (PDOs) and
+ * Functional Device Objects (FDOs). Physical Device Objects are
+ * created and maintained by bus drivers. For example, the PCI
+ * bus driver might detect two PCI ethernet cards on a given
+ * bus. The PCI bus driver will then allocate two device_objects
+ * for its own internal bookeeping purposes. This is analagous
+ * to the device_t that the FreeBSD PCI code allocates and passes
+ * into each PCI driver's probe and attach routines.
+ *
+ * When an ethernet driver claims one of the ethernet cards
+ * on the bus, it will create its own device_object. This is
+ * the Functional Device Object. This object is analagous to the
+ * device-specific softc structure.
+ */
+
+struct device_object {
+ uint16_t do_type;
+ uint16_t do_size;
+ uint32_t do_refcnt;
+ struct driver_object *do_drvobj;
+ struct device_object *do_nextdev;
+ struct device_object *do_attacheddev;
+ struct irp *do_currirp;
+ void *do_iotimer;
+ uint32_t do_flags;
+ uint32_t do_characteristics;
+ void *do_vpb;
+ void *do_devext;
+ uint32_t do_devtype;
+ uint8_t do_stacksize;
+ union {
+ list_entry do_listent;
+ wait_ctx_block do_wcb;
+ } queue;
+ uint32_t do_alignreq;
+ kdevice_queue do_devqueue;
+ struct kdpc do_dpc;
+ uint32_t do_activethreads;
+ void *do_securitydesc;
+ struct nt_kevent do_devlock;
+ uint16_t do_sectorsz;
+ uint16_t do_spare1;
+ struct devobj_extension *do_devobj_ext;
+ void *do_rsvd;
+};
+
+typedef struct device_object device_object;
+
+struct devobj_extension {
+ uint16_t dve_type;
+ uint16_t dve_size;
+ device_object *dve_devobj;
+};
+
+typedef struct devobj_extension devobj_extension;
+
+/* Device object flags */
+
+#define DO_VERIFY_VOLUME 0x00000002
+#define DO_BUFFERED_IO 0x00000004
+#define DO_EXCLUSIVE 0x00000008
+#define DO_DIRECT_IO 0x00000010
+#define DO_MAP_IO_BUFFER 0x00000020
+#define DO_DEVICE_HAS_NAME 0x00000040
+#define DO_DEVICE_INITIALIZING 0x00000080
+#define DO_SYSTEM_BOOT_PARTITION 0x00000100
+#define DO_LONG_TERM_REQUESTS 0x00000200
+#define DO_NEVER_LAST_DEVICE 0x00000400
+#define DO_SHUTDOWN_REGISTERED 0x00000800
+#define DO_BUS_ENUMERATED_DEVICE 0x00001000
+#define DO_POWER_PAGABLE 0x00002000
+#define DO_POWER_INRUSH 0x00004000
+#define DO_LOW_PRIORITY_FILESYSTEM 0x00010000
+
+/* Priority boosts */
+
+#define IO_NO_INCREMENT 0
+#define IO_CD_ROM_INCREMENT 1
+#define IO_DISK_INCREMENT 1
+#define IO_KEYBOARD_INCREMENT 6
+#define IO_MAILSLOT_INCREMENT 2
+#define IO_MOUSE_INCREMENT 6
+#define IO_NAMED_PIPE_INCREMENT 2
+#define IO_NETWORK_INCREMENT 2
+#define IO_PARALLEL_INCREMENT 1
+#define IO_SERIAL_INCREMENT 2
+#define IO_SOUND_INCREMENT 8
+#define IO_VIDEO_INCREMENT 1
+
+/* IRP major codes */
+
+#define IRP_MJ_CREATE 0x00
+#define IRP_MJ_CREATE_NAMED_PIPE 0x01
+#define IRP_MJ_CLOSE 0x02
+#define IRP_MJ_READ 0x03
+#define IRP_MJ_WRITE 0x04
+#define IRP_MJ_QUERY_INFORMATION 0x05
+#define IRP_MJ_SET_INFORMATION 0x06
+#define IRP_MJ_QUERY_EA 0x07
+#define IRP_MJ_SET_EA 0x08
+#define IRP_MJ_FLUSH_BUFFERS 0x09
+#define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a
+#define IRP_MJ_SET_VOLUME_INFORMATION 0x0b
+#define IRP_MJ_DIRECTORY_CONTROL 0x0c
+#define IRP_MJ_FILE_SYSTEM_CONTROL 0x0d
+#define IRP_MJ_DEVICE_CONTROL 0x0e
+#define IRP_MJ_INTERNAL_DEVICE_CONTROL 0x0f
+#define IRP_MJ_SHUTDOWN 0x10
+#define IRP_MJ_LOCK_CONTROL 0x11
+#define IRP_MJ_CLEANUP 0x12
+#define IRP_MJ_CREATE_MAILSLOT 0x13
+#define IRP_MJ_QUERY_SECURITY 0x14
+#define IRP_MJ_SET_SECURITY 0x15
+#define IRP_MJ_POWER 0x16
+#define IRP_MJ_SYSTEM_CONTROL 0x17
+#define IRP_MJ_DEVICE_CHANGE 0x18
+#define IRP_MJ_QUERY_QUOTA 0x19
+#define IRP_MJ_SET_QUOTA 0x1a
+#define IRP_MJ_PNP 0x1b
+#define IRP_MJ_PNP_POWER IRP_MJ_PNP // Obsolete....
+#define IRP_MJ_MAXIMUM_FUNCTION 0x1b
+#define IRP_MJ_SCSI IRP_MJ_INTERNAL_DEVICE_CONTROL
+
+/* IRP minor codes */
+
+#define IRP_MN_QUERY_DIRECTORY 0x01
+#define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x02
+#define IRP_MN_USER_FS_REQUEST 0x00
+
+#define IRP_MN_MOUNT_VOLUME 0x01
+#define IRP_MN_VERIFY_VOLUME 0x02
+#define IRP_MN_LOAD_FILE_SYSTEM 0x03
+#define IRP_MN_TRACK_LINK 0x04
+#define IRP_MN_KERNEL_CALL 0x04
+
+#define IRP_MN_LOCK 0x01
+#define IRP_MN_UNLOCK_SINGLE 0x02
+#define IRP_MN_UNLOCK_ALL 0x03
+#define IRP_MN_UNLOCK_ALL_BY_KEY 0x04
+
+#define IRP_MN_NORMAL 0x00
+#define IRP_MN_DPC 0x01
+#define IRP_MN_MDL 0x02
+#define IRP_MN_COMPLETE 0x04
+#define IRP_MN_COMPRESSED 0x08
+
+#define IRP_MN_MDL_DPC (IRP_MN_MDL | IRP_MN_DPC)
+#define IRP_MN_COMPLETE_MDL (IRP_MN_COMPLETE | IRP_MN_MDL)
+#define IRP_MN_COMPLETE_MDL_DPC (IRP_MN_COMPLETE_MDL | IRP_MN_DPC)
+
+#define IRP_MN_SCSI_CLASS 0x01
+
+#define IRP_MN_START_DEVICE 0x00
+#define IRP_MN_QUERY_REMOVE_DEVICE 0x01
+#define IRP_MN_REMOVE_DEVICE 0x02
+#define IRP_MN_CANCEL_REMOVE_DEVICE 0x03
+#define IRP_MN_STOP_DEVICE 0x04
+#define IRP_MN_QUERY_STOP_DEVICE 0x05
+#define IRP_MN_CANCEL_STOP_DEVICE 0x06
+
+#define IRP_MN_QUERY_DEVICE_RELATIONS 0x07
+#define IRP_MN_QUERY_INTERFACE 0x08
+#define IRP_MN_QUERY_CAPABILITIES 0x09
+#define IRP_MN_QUERY_RESOURCES 0x0A
+#define IRP_MN_QUERY_RESOURCE_REQUIREMENTS 0x0B
+#define IRP_MN_QUERY_DEVICE_TEXT 0x0C
+#define IRP_MN_FILTER_RESOURCE_REQUIREMENTS 0x0D
+
+#define IRP_MN_READ_CONFIG 0x0F
+#define IRP_MN_WRITE_CONFIG 0x10
+#define IRP_MN_EJECT 0x11
+#define IRP_MN_SET_LOCK 0x12
+#define IRP_MN_QUERY_ID 0x13
+#define IRP_MN_QUERY_PNP_DEVICE_STATE 0x14
+#define IRP_MN_QUERY_BUS_INFORMATION 0x15
+#define IRP_MN_DEVICE_USAGE_NOTIFICATION 0x16
+#define IRP_MN_SURPRISE_REMOVAL 0x17
+#define IRP_MN_QUERY_LEGACY_BUS_INFORMATION 0x18
+
+#define IRP_MN_WAIT_WAKE 0x00
+#define IRP_MN_POWER_SEQUENCE 0x01
+#define IRP_MN_SET_POWER 0x02
+#define IRP_MN_QUERY_POWER 0x03
+
+#define IRP_MN_QUERY_ALL_DATA 0x00
+#define IRP_MN_QUERY_SINGLE_INSTANCE 0x01
+#define IRP_MN_CHANGE_SINGLE_INSTANCE 0x02
+#define IRP_MN_CHANGE_SINGLE_ITEM 0x03
+#define IRP_MN_ENABLE_EVENTS 0x04
+#define IRP_MN_DISABLE_EVENTS 0x05
+#define IRP_MN_ENABLE_COLLECTION 0x06
+#define IRP_MN_DISABLE_COLLECTION 0x07
+#define IRP_MN_REGINFO 0x08
+#define IRP_MN_EXECUTE_METHOD 0x09
+#define IRP_MN_REGINFO_EX 0x0b
+
+/* IRP flags */
+
+#define IRP_NOCACHE 0x00000001
+#define IRP_PAGING_IO 0x00000002
+#define IRP_MOUNT_COMPLETION 0x00000002
+#define IRP_SYNCHRONOUS_API 0x00000004
+#define IRP_ASSOCIATED_IRP 0x00000008
+#define IRP_BUFFERED_IO 0x00000010
+#define IRP_DEALLOCATE_BUFFER 0x00000020
+#define IRP_INPUT_OPERATION 0x00000040
+#define IRP_SYNCHRONOUS_PAGING_IO 0x00000040
+#define IRP_CREATE_OPERATION 0x00000080
+#define IRP_READ_OPERATION 0x00000100
+#define IRP_WRITE_OPERATION 0x00000200
+#define IRP_CLOSE_OPERATION 0x00000400
+#define IRP_DEFER_IO_COMPLETION 0x00000800
+#define IRP_OB_QUERY_NAME 0x00001000
+#define IRP_HOLD_DEVICE_QUEUE 0x00002000
+#define IRP_RETRY_IO_COMPLETION 0x00004000
+#define IRP_CLASS_CACHE_OPERATION 0x00008000
+#define IRP_SET_USER_EVENT IRP_CLOSE_OPERATION
+
+/* IRP I/O control flags */
+
+#define IRP_QUOTA_CHARGED 0x01
+#define IRP_ALLOCATED_MUST_SUCCEED 0x02
+#define IRP_ALLOCATED_FIXED_SIZE 0x04
+#define IRP_LOOKASIDE_ALLOCATION 0x08
+
+/* I/O method types */
+
+#define METHOD_BUFFERED 0
+#define METHOD_IN_DIRECT 1
+#define METHOD_OUT_DIRECT 2
+#define METHOD_NEITHER 3
+
+/* File access types */
+
+#define FILE_ANY_ACCESS 0x0000
+#define FILE_SPECIAL_ACCESS FILE_ANY_ACCESS
+#define FILE_READ_ACCESS 0x0001
+#define FILE_WRITE_ACCESS 0x0002
+
+/* Recover I/O access method from IOCTL code. */
+
+#define IO_METHOD(x) ((x) & 0xFFFFFFFC)
+
+/* Recover function code from IOCTL code */
+
+#define IO_FUNC(x) (((x) & 0x7FFC) >> 2)
+
+/* Macro to construct an IOCTL code. */
+
+#define IOCTL_CODE(dev, func, iomethod, acc) \
+ ((dev) << 16) | (acc << 14) | (func << 2) | (iomethod))
+
+
+struct io_status_block {
+ union {
+ uint32_t isb_status;
+ void *isb_ptr;
+ } u;
+ register_t isb_info;
+};
+#define isb_status u.isb_status
+#define isb_ptr u.isb_ptr
+
+typedef struct io_status_block io_status_block;
+
+struct kapc {
+ uint16_t apc_type;
+ uint16_t apc_size;
+ uint32_t apc_spare0;
+ void *apc_thread;
+ list_entry apc_list;
+ void *apc_kernfunc;
+ void *apc_rundownfunc;
+ void *apc_normalfunc;
+ void *apc_normctx;
+ void *apc_sysarg1;
+ void *apc_sysarg2;
+ uint8_t apc_stateidx;
+ uint8_t apc_cpumode;
+ uint8_t apc_inserted;
+};
+
+typedef struct kapc kapc;
+
+typedef uint32_t (*completion_func)(device_object *,
+ struct irp *, void *);
+typedef uint32_t (*cancel_func)(device_object *,
+ struct irp *);
+
+struct io_stack_location {
+ uint8_t isl_major;
+ uint8_t isl_minor;
+ uint8_t isl_flags;
+ uint8_t isl_ctl;
+
+ /*
+ * There's a big-ass union here in the actual Windows
+ * definition of the stucture, but it contains stuff
+ * that doesn't really apply to BSD, and defining it
+ * all properly would require duplicating over a dozen
+ * other structures that we'll never use. Since the
+ * io_stack_location structure is opaque to drivers
+ * anyway, I'm not going to bother with the extra crap.
+ */
+
+ union {
+ struct {
+ uint32_t isl_len;
+ uint32_t *isl_key;
+ uint64_t isl_byteoff;
+ } isl_read;
+ struct {
+ uint32_t isl_len;
+ uint32_t *isl_key;
+ uint64_t isl_byteoff;
+ } isl_write;
+ struct {
+ uint32_t isl_obuflen;
+ uint32_t isl_ibuflen;
+ uint32_t isl_iocode;
+ void *isl_type3ibuf;
+ } isl_ioctl;
+ struct {
+ void *isl_arg1;
+ void *isl_arg2;
+ void *isl_arg3;
+ void *isl_arg4;
+ } isl_others;
+ } isl_parameters __attribute__((packed));
+
+ void *isl_devobj;
+ void *isl_fileobj;
+ completion_func isl_completionfunc;
+ void *isl_completionctx;
+};
+
+typedef struct io_stack_location io_stack_location;
+
+/* Stack location control flags */
+
+#define SL_PENDING_RETURNED 0x01
+#define SL_INVOKE_ON_CANCEL 0x20
+#define SL_INVOKE_ON_SUCCESS 0x40
+#define SL_INVOKE_ON_ERROR 0x80
+
+struct irp {
+ uint16_t irp_type;
+ uint16_t irp_size;
+ mdl *irp_mdl;
+ uint32_t irp_flags;
+ union {
+ struct irp *irp_master;
+ uint32_t irp_irpcnt;
+ void *irp_sysbuf;
+ } irp_assoc;
+ list_entry irp_thlist;
+ io_status_block irp_iostat;
+ uint8_t irp_reqmode;
+ uint8_t irp_pendingreturned;
+ uint8_t irp_stackcnt;
+ uint8_t irp_currentstackloc;
+ uint8_t irp_cancel;
+ uint8_t irp_cancelirql;
+ uint8_t irp_apcenv;
+ uint8_t irp_allocflags;
+ io_status_block *irp_usriostat;
+ nt_kevent *irp_usrevent;
+ union {
+ struct {
+ void *irp_apcfunc;
+ void *irp_apcctx;
+ } irp_asyncparms;
+ uint64_t irp_allocsz;
+ } irp_overlay;
+ cancel_func irp_cancelfunc;
+ void *irp_userbuf;
+
+ /* Windows kernel info */
+
+ union {
+ struct {
+ union {
+ kdevice_qentry irp_dqe;
+ struct {
+ void *irp_drvctx[4];
+ } s1;
+ } u1;
+ void *irp_thread;
+ char *irp_auxbuf;
+ struct {
+ list_entry irp_list;
+ union {
+ io_stack_location *irp_csl;
+ uint32_t irp_pkttype;
+ } u2;
+ } s2;
+ void *irp_fileobj;
+ } irp_overlay;
+ union {
+ kapc irp_apc;
+ struct {
+ void *irp_ep;
+ void *irp_dev;
+ } irp_usb;
+ } irp_misc;
+ void *irp_compkey;
+ } irp_tail;
+};
+
+#define irp_csl s2.u2.irp_csl
+#define irp_pkttype s2.u2.irp_pkttype
+
+#define IRP_NDIS_DEV(irp) (irp)->irp_tail.irp_misc.irp_usb.irp_dev
+#define IRP_NDISUSB_EP(irp) (irp)->irp_tail.irp_misc.irp_usb.irp_ep
+
+typedef struct irp irp;
+
+#define InterlockedExchangePointer(dst, val) \
+ (void *)InterlockedExchange((uint32_t *)(dst), (uintptr_t)(val))
+
+#define IoSizeOfIrp(ssize) \
+ ((uint16_t) (sizeof(irp) + ((ssize) * (sizeof(io_stack_location)))))
+
+#define IoSetCancelRoutine(irp, func) \
+ (cancel_func)InterlockedExchangePointer( \
+ (void *)&(ip)->irp_cancelfunc, (void *)(func))
+
+#define IoSetCancelValue(irp, val) \
+ (u_long)InterlockedExchangePointer( \
+ (void *)&(ip)->irp_cancel, (void *)(val))
+
+#define IoGetCurrentIrpStackLocation(irp) \
+ (irp)->irp_tail.irp_overlay.irp_csl
+
+#define IoGetNextIrpStackLocation(irp) \
+ ((irp)->irp_tail.irp_overlay.irp_csl - 1)
+
+#define IoSetNextIrpStackLocation(irp) \
+ do { \
+ irp->irp_currentstackloc--; \
+ irp->irp_tail.irp_overlay.irp_csl--; \
+ } while(0)
+
+#define IoSetCompletionRoutine(irp, func, ctx, ok, err, cancel) \
+ do { \
+ io_stack_location *s; \
+ s = IoGetNextIrpStackLocation((irp)); \
+ s->isl_completionfunc = (func); \
+ s->isl_completionctx = (ctx); \
+ s->isl_ctl = 0; \
+ if (ok) s->isl_ctl = SL_INVOKE_ON_SUCCESS; \
+ if (err) s->isl_ctl |= SL_INVOKE_ON_ERROR; \
+ if (cancel) s->isl_ctl |= SL_INVOKE_ON_CANCEL; \
+ } while(0)
+
+#define IoMarkIrpPending(irp) \
+ IoGetCurrentIrpStackLocation(irp)->isl_ctl |= SL_PENDING_RETURNED
+#define IoUnmarkIrpPending(irp) \
+ IoGetCurrentIrpStackLocation(irp)->isl_ctl &= ~SL_PENDING_RETURNED
+
+#define IoCopyCurrentIrpStackLocationToNext(irp) \
+ do { \
+ io_stack_location *src, *dst; \
+ src = IoGetCurrentIrpStackLocation(irp); \
+ dst = IoGetNextIrpStackLocation(irp); \
+ bcopy((char *)src, (char *)dst, \
+ offsetof(io_stack_location, isl_completionfunc)); \
+ } while(0)
+
+#define IoSkipCurrentIrpStackLocation(irp) \
+ do { \
+ (irp)->irp_currentstackloc++; \
+ (irp)->irp_tail.irp_overlay.irp_csl++; \
+ } while(0)
+
+#define IoInitializeDpcRequest(dobj, dpcfunc) \
+ KeInitializeDpc(&(dobj)->do_dpc, dpcfunc, dobj)
+
+#define IoRequestDpc(dobj, irp, ctx) \
+ KeInsertQueueDpc(&(dobj)->do_dpc, irp, ctx)
+
+typedef uint32_t (*driver_dispatch)(device_object *, irp *);
+
+/*
+ * The driver_object is allocated once for each driver that's loaded
+ * into the system. A new one is allocated for each driver and
+ * populated a bit via the driver's DriverEntry function.
+ * In general, a Windows DriverEntry() function will provide a pointer
+ * to its AddDevice() method and set up the dispatch table.
+ * For NDIS drivers, this is all done behind the scenes in the
+ * NdisInitializeWrapper() and/or NdisMRegisterMiniport() routines.
+ */
+
+struct driver_object {
+ uint16_t dro_type;
+ uint16_t dro_size;
+ device_object *dro_devobj;
+ uint32_t dro_flags;
+ void *dro_driverstart;
+ uint32_t dro_driversize;
+ void *dro_driversection;
+ driver_extension *dro_driverext;
+ unicode_string dro_drivername;
+ unicode_string *dro_hwdb;
+ void *dro_pfastiodispatch;
+ void *dro_driverinitfunc;
+ void *dro_driverstartiofunc;
+ void *dro_driverunloadfunc;
+ driver_dispatch dro_dispatch[IRP_MJ_MAXIMUM_FUNCTION + 1];
+};
+
+typedef struct driver_object driver_object;
+
+#define DEVPROP_DEVICE_DESCRIPTION 0x00000000
+#define DEVPROP_HARDWARE_ID 0x00000001
+#define DEVPROP_COMPATIBLE_IDS 0x00000002
+#define DEVPROP_BOOTCONF 0x00000003
+#define DEVPROP_BOOTCONF_TRANSLATED 0x00000004
+#define DEVPROP_CLASS_NAME 0x00000005
+#define DEVPROP_CLASS_GUID 0x00000006
+#define DEVPROP_DRIVER_KEYNAME 0x00000007
+#define DEVPROP_MANUFACTURER 0x00000008
+#define DEVPROP_FRIENDLYNAME 0x00000009
+#define DEVPROP_LOCATION_INFO 0x0000000A
+#define DEVPROP_PHYSDEV_NAME 0x0000000B
+#define DEVPROP_BUSTYPE_GUID 0x0000000C
+#define DEVPROP_LEGACY_BUSTYPE 0x0000000D
+#define DEVPROP_BUS_NUMBER 0x0000000E
+#define DEVPROP_ENUMERATOR_NAME 0x0000000F
+#define DEVPROP_ADDRESS 0x00000010
+#define DEVPROP_UINUMBER 0x00000011
+#define DEVPROP_INSTALL_STATE 0x00000012
+#define DEVPROP_REMOVAL_POLICY 0x00000013
+
+/* Various supported device types (used with IoCreateDevice()) */
+
+#define FILE_DEVICE_BEEP 0x00000001
+#define FILE_DEVICE_CD_ROM 0x00000002
+#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
+#define FILE_DEVICE_CONTROLLER 0x00000004
+#define FILE_DEVICE_DATALINK 0x00000005
+#define FILE_DEVICE_DFS 0x00000006
+#define FILE_DEVICE_DISK 0x00000007
+#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
+#define FILE_DEVICE_FILE_SYSTEM 0x00000009
+#define FILE_DEVICE_INPORT_PORT 0x0000000A
+#define FILE_DEVICE_KEYBOARD 0x0000000B
+#define FILE_DEVICE_MAILSLOT 0x0000000C
+#define FILE_DEVICE_MIDI_IN 0x0000000D
+#define FILE_DEVICE_MIDI_OUT 0x0000000E
+#define FILE_DEVICE_MOUSE 0x0000000F
+#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010
+#define FILE_DEVICE_NAMED_PIPE 0x00000011
+#define FILE_DEVICE_NETWORK 0x00000012
+#define FILE_DEVICE_NETWORK_BROWSER 0x00000013
+#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
+#define FILE_DEVICE_NULL 0x00000015
+#define FILE_DEVICE_PARALLEL_PORT 0x00000016
+#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017
+#define FILE_DEVICE_PRINTER 0x00000018
+#define FILE_DEVICE_SCANNER 0x00000019
+#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001A
+#define FILE_DEVICE_SERIAL_PORT 0x0000001B
+#define FILE_DEVICE_SCREEN 0x0000001C
+#define FILE_DEVICE_SOUND 0x0000001D
+#define FILE_DEVICE_STREAMS 0x0000001E
+#define FILE_DEVICE_TAPE 0x0000001F
+#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
+#define FILE_DEVICE_TRANSPORT 0x00000021
+#define FILE_DEVICE_UNKNOWN 0x00000022
+#define FILE_DEVICE_VIDEO 0x00000023
+#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
+#define FILE_DEVICE_WAVE_IN 0x00000025
+#define FILE_DEVICE_WAVE_OUT 0x00000026
+#define FILE_DEVICE_8042_PORT 0x00000027
+#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
+#define FILE_DEVICE_BATTERY 0x00000029
+#define FILE_DEVICE_BUS_EXTENDER 0x0000002A
+#define FILE_DEVICE_MODEM 0x0000002B
+#define FILE_DEVICE_VDM 0x0000002C
+#define FILE_DEVICE_MASS_STORAGE 0x0000002D
+#define FILE_DEVICE_SMB 0x0000002E
+#define FILE_DEVICE_KS 0x0000002F
+#define FILE_DEVICE_CHANGER 0x00000030
+#define FILE_DEVICE_SMARTCARD 0x00000031
+#define FILE_DEVICE_ACPI 0x00000032
+#define FILE_DEVICE_DVD 0x00000033
+#define FILE_DEVICE_FULLSCREEN_VIDEO 0x00000034
+#define FILE_DEVICE_DFS_FILE_SYSTEM 0x00000035
+#define FILE_DEVICE_DFS_VOLUME 0x00000036
+#define FILE_DEVICE_SERENUM 0x00000037
+#define FILE_DEVICE_TERMSRV 0x00000038
+#define FILE_DEVICE_KSEC 0x00000039
+#define FILE_DEVICE_FIPS 0x0000003A
+
+/* Device characteristics */
+
+#define FILE_REMOVABLE_MEDIA 0x00000001
+#define FILE_READ_ONLY_DEVICE 0x00000002
+#define FILE_FLOPPY_DISKETTE 0x00000004
+#define FILE_WRITE_ONCE_MEDIA 0x00000008
+#define FILE_REMOTE_DEVICE 0x00000010
+#define FILE_DEVICE_IS_MOUNTED 0x00000020
+#define FILE_VIRTUAL_VOLUME 0x00000040
+#define FILE_AUTOGENERATED_DEVICE_NAME 0x00000080
+#define FILE_DEVICE_SECURE_OPEN 0x00000100
+
+/* Status codes */
+
+#define STATUS_SUCCESS 0x00000000
+#define STATUS_USER_APC 0x000000C0
+#define STATUS_KERNEL_APC 0x00000100
+#define STATUS_ALERTED 0x00000101
+#define STATUS_TIMEOUT 0x00000102
+#define STATUS_PENDING 0x00000103
+#define STATUS_FAILURE 0xC0000001
+#define STATUS_NOT_IMPLEMENTED 0xC0000002
+#define STATUS_ACCESS_VIOLATION 0xC0000005
+#define STATUS_INVALID_PARAMETER 0xC000000D
+#define STATUS_INVALID_DEVICE_REQUEST 0xC0000010
+#define STATUS_MORE_PROCESSING_REQUIRED 0xC0000016
+#define STATUS_NO_MEMORY 0xC0000017
+#define STATUS_BUFFER_TOO_SMALL 0xC0000023
+#define STATUS_MUTANT_NOT_OWNED 0xC0000046
+#define STATUS_NOT_SUPPORTED 0xC00000BB
+#define STATUS_INVALID_PARAMETER_2 0xC00000F0
+#define STATUS_INSUFFICIENT_RESOURCES 0xC000009A
+#define STATUS_DEVICE_NOT_CONNECTED 0xC000009D
+#define STATUS_CANCELLED 0xC0000120
+#define STATUS_NOT_FOUND 0xC0000225
+#define STATUS_DEVICE_REMOVED 0xC00002B6
+
+#define STATUS_WAIT_0 0x00000000
+
+/* Memory pool types, for ExAllocatePoolWithTag() */
+
+#define NonPagedPool 0x00000000
+#define PagedPool 0x00000001
+#define NonPagedPoolMustSucceed 0x00000002
+#define DontUseThisType 0x00000003
+#define NonPagedPoolCacheAligned 0x00000004
+#define PagedPoolCacheAligned 0x00000005
+#define NonPagedPoolCacheAlignedMustS 0x00000006
+#define MaxPoolType 0x00000007
+
+/*
+ * IO_WORKITEM is an opaque structures that must be allocated
+ * via IoAllocateWorkItem() and released via IoFreeWorkItem().
+ * Consequently, we can define it any way we want.
+ */
+typedef void (*io_workitem_func)(device_object *, void *);
+
+struct io_workitem {
+ io_workitem_func iw_func;
+ void *iw_ctx;
+ list_entry iw_listentry;
+ device_object *iw_dobj;
+ int iw_idx;
+};
+
+typedef struct io_workitem io_workitem;
+
+#define WORKQUEUE_CRITICAL 0
+#define WORKQUEUE_DELAYED 1
+#define WORKQUEUE_HYPERCRITICAL 2
+
+#define WORKITEM_THREADS 4
+#define WORKITEM_LEGACY_THREAD 3
+#define WORKIDX_INC(x) (x) = (x + 1) % WORKITEM_LEGACY_THREAD
+
+/*
+ * Older, deprecated work item API, needed to support NdisQueueWorkItem().
+ */
+
+struct work_queue_item;
+
+typedef void (*work_item_func)(struct work_queue_item *, void *);
+
+struct work_queue_item {
+ list_entry wqi_entry;
+ work_item_func wqi_func;
+ void *wqi_ctx;
+};
+
+typedef struct work_queue_item work_queue_item;
+
+#define ExInitializeWorkItem(w, func, ctx) \
+ do { \
+ (w)->wqi_func = (func); \
+ (w)->wqi_ctx = (ctx); \
+ InitializeListHead(&((w)->wqi_entry)); \
+ } while (0)
+
+/*
+ * FreeBSD's kernel stack is 2 pages in size by default. The
+ * Windows stack is larger, so we need to give our threads more
+ * stack pages. 4 should be enough, we use 8 just to extra safe.
+ */
+#define NDIS_KSTACK_PAGES 8
+
+/*
+ * Different kinds of function wrapping we can do.
+ */
+
+#define WINDRV_WRAP_STDCALL 1
+#define WINDRV_WRAP_FASTCALL 2
+#define WINDRV_WRAP_REGPARM 3
+#define WINDRV_WRAP_CDECL 4
+#define WINDRV_WRAP_AMD64 5
+
+struct drvdb_ent {
+ driver_object *windrv_object;
+ void *windrv_devlist;
+ ndis_cfg *windrv_regvals;
+ interface_type windrv_bustype;
+ STAILQ_ENTRY(drvdb_ent) link;
+};
+
+extern image_patch_table ntoskrnl_functbl[];
+#ifdef __amd64__
+extern struct kuser_shared_data kuser_shared_data;
+#endif
+typedef void (*funcptr)(void);
+typedef int (*matchfuncptr)(interface_type, void *, void *);
+
+__BEGIN_DECLS
+extern int windrv_libinit(void);
+extern int windrv_libfini(void);
+extern driver_object *windrv_lookup(vm_offset_t, char *);
+extern struct drvdb_ent *windrv_match(matchfuncptr, void *);
+extern int windrv_load(module_t, vm_offset_t, int, interface_type,
+ void *, ndis_cfg *);
+extern int windrv_unload(module_t, vm_offset_t, int);
+extern int windrv_create_pdo(driver_object *, device_t);
+extern void windrv_destroy_pdo(driver_object *, device_t);
+extern device_object *windrv_find_pdo(driver_object *, device_t);
+extern int windrv_bus_attach(driver_object *, char *);
+extern int windrv_wrap(funcptr, funcptr *, int, int);
+extern int windrv_unwrap(funcptr);
+extern void ctxsw_utow(void);
+extern void ctxsw_wtou(void);
+
+extern int ntoskrnl_libinit(void);
+extern int ntoskrnl_libfini(void);
+
+extern void ntoskrnl_intr(void *);
+extern void ntoskrnl_time(uint64_t *);
+
+extern uint16_t ExQueryDepthSList(slist_header *);
+extern slist_entry
+ *InterlockedPushEntrySList(slist_header *, slist_entry *);
+extern slist_entry *InterlockedPopEntrySList(slist_header *);
+extern uint32_t RtlUnicodeStringToAnsiString(ansi_string *,
+ unicode_string *, uint8_t);
+extern uint32_t RtlAnsiStringToUnicodeString(unicode_string *,
+ ansi_string *, uint8_t);
+extern void RtlInitAnsiString(ansi_string *, char *);
+extern void RtlInitUnicodeString(unicode_string *,
+ uint16_t *);
+extern void RtlFreeUnicodeString(unicode_string *);
+extern void RtlFreeAnsiString(ansi_string *);
+extern void KeInitializeDpc(kdpc *, void *, void *);
+extern uint8_t KeInsertQueueDpc(kdpc *, void *, void *);
+extern uint8_t KeRemoveQueueDpc(kdpc *);
+extern void KeSetImportanceDpc(kdpc *, uint32_t);
+extern void KeSetTargetProcessorDpc(kdpc *, uint8_t);
+extern void KeFlushQueuedDpcs(void);
+extern uint32_t KeGetCurrentProcessorNumber(void);
+extern void KeInitializeTimer(ktimer *);
+extern void KeInitializeTimerEx(ktimer *, uint32_t);
+extern uint8_t KeSetTimer(ktimer *, int64_t, kdpc *);
+extern uint8_t KeSetTimerEx(ktimer *, int64_t, uint32_t, kdpc *);
+extern uint8_t KeCancelTimer(ktimer *);
+extern uint8_t KeReadStateTimer(ktimer *);
+extern uint32_t KeWaitForSingleObject(void *, uint32_t,
+ uint32_t, uint8_t, int64_t *);
+extern void KeInitializeEvent(nt_kevent *, uint32_t, uint8_t);
+extern void KeClearEvent(nt_kevent *);
+extern uint32_t KeReadStateEvent(nt_kevent *);
+extern uint32_t KeSetEvent(nt_kevent *, uint32_t, uint8_t);
+extern uint32_t KeResetEvent(nt_kevent *);
+#ifdef __i386__
+extern void KefAcquireSpinLockAtDpcLevel(kspin_lock *);
+extern void KefReleaseSpinLockFromDpcLevel(kspin_lock *);
+extern uint8_t KeAcquireSpinLockRaiseToDpc(kspin_lock *);
+#else
+extern void KeAcquireSpinLockAtDpcLevel(kspin_lock *);
+extern void KeReleaseSpinLockFromDpcLevel(kspin_lock *);
+#endif
+extern void KeInitializeSpinLock(kspin_lock *);
+extern uint8_t KeAcquireInterruptSpinLock(kinterrupt *);
+extern void KeReleaseInterruptSpinLock(kinterrupt *, uint8_t);
+extern uint8_t KeSynchronizeExecution(kinterrupt *, void *, void *);
+extern uintptr_t InterlockedExchange(volatile uint32_t *,
+ uintptr_t);
+extern void *ExAllocatePoolWithTag(uint32_t, size_t, uint32_t);
+extern void ExFreePool(void *);
+extern uint32_t IoConnectInterrupt(kinterrupt **, void *, void *,
+ kspin_lock *, uint32_t, uint8_t, uint8_t, uint8_t, uint8_t,
+ uint32_t, uint8_t);
+extern uint8_t MmIsAddressValid(void *);
+extern void *MmGetSystemRoutineAddress(unicode_string *);
+extern void *MmMapIoSpace(uint64_t, uint32_t, uint32_t);
+extern void MmUnmapIoSpace(void *, size_t);
+extern void MmBuildMdlForNonPagedPool(mdl *);
+extern void IoDisconnectInterrupt(kinterrupt *);
+extern uint32_t IoAllocateDriverObjectExtension(driver_object *,
+ void *, uint32_t, void **);
+extern void *IoGetDriverObjectExtension(driver_object *, void *);
+extern uint32_t IoCreateDevice(driver_object *, uint32_t,
+ unicode_string *, uint32_t, uint32_t, uint8_t, device_object **);
+extern void IoDeleteDevice(device_object *);
+extern device_object *IoGetAttachedDevice(device_object *);
+extern uint32_t IofCallDriver(device_object *, irp *);
+extern void IofCompleteRequest(irp *, uint8_t);
+extern void IoAcquireCancelSpinLock(uint8_t *);
+extern void IoReleaseCancelSpinLock(uint8_t);
+extern uint8_t IoCancelIrp(irp *);
+extern void IoDetachDevice(device_object *);
+extern device_object *IoAttachDeviceToDeviceStack(device_object *,
+ device_object *);
+extern mdl *IoAllocateMdl(void *, uint32_t, uint8_t, uint8_t, irp *);
+extern void IoFreeMdl(mdl *);
+extern io_workitem *IoAllocateWorkItem(device_object *);
+extern void ExQueueWorkItem(work_queue_item *, u_int32_t);
+extern void IoFreeWorkItem(io_workitem *);
+extern void IoQueueWorkItem(io_workitem *, io_workitem_func,
+ uint32_t, void *);
+
+#define IoCallDriver(a, b) IofCallDriver(a, b)
+#define IoCompleteRequest(a, b) IofCompleteRequest(a, b)
+
+/*
+ * On the Windows x86 arch, KeAcquireSpinLock() and KeReleaseSpinLock()
+ * routines live in the HAL. We try to imitate this behavior.
+ */
+#ifdef __i386__
+#define KI_USER_SHARED_DATA 0xffdf0000
+#define KeAcquireSpinLock(a, b) *(b) = KfAcquireSpinLock(a)
+#define KeReleaseSpinLock(a, b) KfReleaseSpinLock(a, b)
+#define KeRaiseIrql(a, b) *(b) = KfRaiseIrql(a)
+#define KeLowerIrql(a) KfLowerIrql(a)
+#define KeAcquireSpinLockAtDpcLevel(a) KefAcquireSpinLockAtDpcLevel(a)
+#define KeReleaseSpinLockFromDpcLevel(a) KefReleaseSpinLockFromDpcLevel(a)
+#endif /* __i386__ */
+
+#ifdef __amd64__
+#define KI_USER_SHARED_DATA 0xfffff78000000000UL
+#define KeAcquireSpinLock(a, b) *(b) = KfAcquireSpinLock(a)
+#define KeReleaseSpinLock(a, b) KfReleaseSpinLock(a, b)
+
+/*
+ * These may need to be redefined later;
+ * not sure where they live on amd64 yet.
+ */
+#define KeRaiseIrql(a, b) *(b) = KfRaiseIrql(a)
+#define KeLowerIrql(a) KfLowerIrql(a)
+#endif /* __amd64__ */
+
+__END_DECLS
+
+#endif /* _NTOSKRNL_VAR_H_ */
diff --git a/sys/compat/ndis/pe_var.h b/sys/compat/ndis/pe_var.h
new file mode 100644
index 0000000..84e0162
--- /dev/null
+++ b/sys/compat/ndis/pe_var.h
@@ -0,0 +1,549 @@
+/*-
+ * Copyright (c) 2003
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _PE_VAR_H_
+#define _PE_VAR_H_
+
+/*
+ * Image Format
+ */
+
+#define IMAGE_DOS_SIGNATURE 0x5A4D /* MZ */
+#define IMAGE_OS2_SIGNATURE 0x454E /* NE */
+#define IMAGE_OS2_SIGNATURE_LE 0x454C /* LE */
+#define IMAGE_VXD_SIGNATURE 0x454C /* LE */
+#define IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */
+
+/*
+ * All PE files have one of these, just so if you attempt to
+ * run them, they'll print out a message telling you they can
+ * only be run in Windows.
+ */
+
+struct image_dos_header {
+ uint16_t idh_magic; /* Magic number */
+ uint16_t idh_cblp; /* Bytes on last page of file */
+ uint16_t idh_cp; /* Pages in file */
+ uint16_t idh_crlc; /* Relocations */
+ uint16_t idh_cparhdr; /* Size of header in paragraphs */
+ uint16_t idh_minalloc; /* Minimum extra paragraphs needed */
+ uint16_t idh_maxalloc; /* Maximum extra paragraphs needed */
+ uint16_t idh_ss; /* Initial (relative) SS value */
+ uint16_t idh_sp; /* Initial SP value */
+ uint16_t idh_csum; /* Checksum */
+ uint16_t idh_ip; /* Initial IP value */
+ uint16_t idh_cs; /* Initial (relative) CS value */
+ uint16_t idh_lfarlc; /* File address of relocation table */
+ uint16_t idh_ovno; /* Overlay number */
+ uint16_t idh_rsvd1[4]; /* Reserved words */
+ uint16_t idh_oemid; /* OEM identifier (for idh_oeminfo) */
+ uint16_t idh_oeminfo; /* OEM information; oemid specific */
+ uint16_t idh_rsvd2[10]; /* Reserved words */
+ uint32_t idh_lfanew; /* File address of new exe header */
+};
+
+typedef struct image_dos_header image_dos_header;
+
+/*
+ * File header format.
+ */
+
+struct image_file_header {
+ uint16_t ifh_machine; /* Machine type */
+ uint16_t ifh_numsections; /* # of sections */
+ uint32_t ifh_timestamp; /* Date/time stamp */
+ uint32_t ifh_symtblptr; /* Offset to symbol table */
+ uint32_t ifh_numsyms; /* # of symbols */
+ uint16_t ifh_optionalhdrlen; /* Size of optional header */
+ uint16_t ifh_characteristics; /* Characteristics */
+};
+
+typedef struct image_file_header image_file_header;
+
+/* Machine types */
+
+#define IMAGE_FILE_MACHINE_UNKNOWN 0
+#define IMAGE_FILE_MACHINE_I860 0x014d
+#define IMAGE_FILE_MACHINE_I386 0x014c
+#define IMAGE_FILE_MACHINE_R3000 0x0162
+#define IMAGE_FILE_MACHINE_R4000 0x0166
+#define IMAGE_FILE_MACHINE_R10000 0x0168
+#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169
+#define IMAGE_FILE_MACHINE_ALPHA 0x0184
+#define IMAGE_FILE_MACHINE_SH3 0x01a2
+#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3
+#define IMAGE_FILE_MACHINE_SH3E 0x01a4
+#define IMAGE_FILE_MACHINE_SH4 0x01a6
+#define IMAGE_FILE_MACHINE_SH5 0x01a8
+#define IMAGE_FILE_MACHINE_ARM 0x01c0
+#define IMAGE_FILE_MACHINE_THUMB 0x01c2
+#define IMAGE_FILE_MACHINE_AM33 0x01d3
+#define IMAGE_FILE_MACHINE_POWERPC 0x01f0
+#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1
+#define IMAGE_FILE_MACHINE_IA64 0x0200
+#define IMAGE_FILE_MACHINE_MIPS16 0x0266
+#define IMAGE_FILE_MACHINE_ALPHA64 0x0284
+#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366
+#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466
+#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64
+#define IMAGE_FILE_MACHINE_TRICORE 0x0520
+#define IMAGE_FILE_MACHINE_CEF 0x0cef
+#define IMAGE_FILE_MACHINE_EBC 0x0ebc
+#define IMAGE_FILE_MACHINE_AMD64 0x8664
+#define IMAGE_FILE_MACHINE_M32R 0x9041
+#define IMAGE_FILE_MACHINE_CEE 0xc0ee
+
+/* Characteristics */
+
+#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 /* No relocation info */
+#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002
+#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004
+#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008
+#define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010
+#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020
+#define IMAGE_FILE_16BIT_MACHINE 0x0040
+#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080
+#define IMAGE_FILE_32BIT_MACHINE 0x0100
+#define IMAGE_FILE_DEBUG_STRIPPED 0x0200
+#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400
+#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800
+#define IMAGE_FILE_SYSTEM 0x1000
+#define IMAGE_FILE_DLL 0x2000
+#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000
+#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000
+
+#define IMAGE_SIZEOF_FILE_HEADER 20
+
+/*
+ * Directory format.
+ */
+
+struct image_data_directory {
+ uint32_t idd_vaddr; /* virtual address */
+ uint32_t idd_size; /* size */
+};
+
+typedef struct image_data_directory image_data_directory;
+
+#define IMAGE_DIRECTORY_ENTRIES_MAX 16
+
+/*
+ * Optional header format.
+ */
+
+struct image_optional_header {
+
+ /* Standard fields */
+
+ uint16_t ioh_magic;
+ uint8_t ioh_linkerver_major;
+ uint8_t ioh_linkerver_minor;
+ uint32_t ioh_codesize;
+ uint32_t ioh_datasize;
+ uint32_t ioh_bsssize;
+ uint32_t ioh_entryaddr;
+ uint32_t ioh_codebaseaddr;
+#ifndef __amd64__
+ uint32_t ioh_databaseaddr;
+#endif
+
+ /* NT-specific fields */
+
+ uintptr_t ioh_imagebase;
+ uint32_t ioh_sectalign;
+ uint32_t ioh_filealign;
+ uint16_t ioh_osver_major;
+ uint16_t ioh_osver_minor;
+ uint16_t ioh_imagever_major;
+ uint16_t ioh_imagever_minor;
+ uint16_t ioh_subsys_major;
+ uint16_t ioh_subsys_minor;
+ uint32_t ioh_win32ver;
+ uint32_t ioh_imagesize;
+ uint32_t ioh_headersize;
+ uint32_t ioh_csum;
+ uint16_t ioh_subsys;
+ uint16_t ioh_dll_characteristics;
+ uintptr_t ioh_stackreservesize;
+ uintptr_t ioh_stackcommitsize;
+ uintptr_t ioh_heapreservesize;
+ uintptr_t ioh_heapcommitsize;
+ uint16_t ioh_loaderflags;
+ uint32_t ioh_rva_size_cnt;
+ image_data_directory ioh_datadir[IMAGE_DIRECTORY_ENTRIES_MAX];
+};
+
+typedef struct image_optional_header image_optional_header;
+
+struct image_nt_header {
+ uint32_t inh_signature;
+ image_file_header inh_filehdr;
+ image_optional_header inh_optionalhdr;
+};
+
+typedef struct image_nt_header image_nt_header;
+
+#define IMAGE_SIZEOF_NT_HEADER(nthdr) \
+ (offsetof(image_nt_header, inh_optionalhdr) + \
+ ((image_nt_header *)(nthdr))->inh_filehdr.ifh_optionalhdrlen)
+
+/* Directory Entries */
+
+#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 /* Export Directory */
+#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 /* Import Directory */
+#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 /* Resource Directory */
+#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 /* Exception Directory */
+#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 /* Security Directory */
+#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 /* Base Relocation Table */
+#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 /* Debug Directory */
+#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 /* Description String */
+#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 /* Machine Value (MIPS GP) */
+#define IMAGE_DIRECTORY_ENTRY_TLS 9 /* TLS Directory */
+#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 /* Load Configuration Directory */
+#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 /* Bound Import Directory in headers */
+#define IMAGE_DIRECTORY_ENTRY_IAT 12 /* Import Address Table */
+#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13
+#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14
+
+/* Resource types */
+
+#define RT_CURSOR 1
+#define RT_BITMAP 2
+#define RT_ICON 3
+#define RT_MENU 4
+#define RT_DIALOG 5
+#define RT_STRING 6
+#define RT_FONTDIR 7
+#define RT_FONT 8
+#define RT_ACCELERATOR 9
+#define RT_RCDATA 10
+#define RT_MESSAGETABLE 11
+#define RT_GROUP_CURSOR 12
+#define RT_GROUP_ICON 14
+#define RT_VERSION 16
+#define RT_DLGINCLUDE 17
+#define RT_PLUGPLAY 19
+#define RT_VXD 20
+#define RT_ANICURSOR 21
+#define RT_ANIICON 22
+#define RT_HTML 23
+
+/*
+ * Section header format.
+ */
+
+#define IMAGE_SHORT_NAME_LEN 8
+
+struct image_section_header {
+ uint8_t ish_name[IMAGE_SHORT_NAME_LEN];
+ union {
+ uint32_t ish_paddr;
+ uint32_t ish_vsize;
+ } ish_misc;
+ uint32_t ish_vaddr;
+ uint32_t ish_rawdatasize;
+ uint32_t ish_rawdataaddr;
+ uint32_t ish_relocaddr;
+ uint32_t ish_linenumaddr;
+ uint16_t ish_numrelocs;
+ uint16_t ish_numlinenums;
+ uint32_t ish_characteristics;
+};
+
+typedef struct image_section_header image_section_header;
+
+#define IMAGE_SIZEOF_SECTION_HEADER 40
+
+#define IMAGE_FIRST_SECTION(nthdr) \
+ ((image_section_header *)((vm_offset_t)(nthdr) + \
+ offsetof(image_nt_header, inh_optionalhdr) + \
+ ((image_nt_header *)(nthdr))->inh_filehdr.ifh_optionalhdrlen))
+
+/*
+ * Import format
+ */
+
+struct image_import_by_name {
+ uint16_t iibn_hint;
+ uint8_t iibn_name[1];
+};
+
+#define IMAGE_ORDINAL_FLAG 0x80000000
+#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)
+
+struct image_import_descriptor {
+ uint32_t iid_import_name_table_addr;
+ uint32_t iid_timestamp;
+ uint32_t iid_forwardchain;
+ uint32_t iid_nameaddr;
+ uint32_t iid_import_address_table_addr;
+};
+
+typedef struct image_import_descriptor image_import_descriptor;
+
+struct image_base_reloc {
+ uint32_t ibr_vaddr;
+ uint32_t ibr_blocksize;
+ uint16_t ibr_rel[1];
+};
+
+typedef struct image_base_reloc image_base_reloc;
+
+#define IMR_RELTYPE(x) ((x >> 12) & 0xF)
+#define IMR_RELOFFSET(x) (x & 0xFFF)
+
+/* generic relocation types */
+#define IMAGE_REL_BASED_ABSOLUTE 0
+#define IMAGE_REL_BASED_HIGH 1
+#define IMAGE_REL_BASED_LOW 2
+#define IMAGE_REL_BASED_HIGHLOW 3
+#define IMAGE_REL_BASED_HIGHADJ 4
+#define IMAGE_REL_BASED_MIPS_JMPADDR 5
+#define IMAGE_REL_BASED_SECTION 6
+#define IMAGE_REL_BASED_REL 7
+#define IMAGE_REL_BASED_MIPS_JMPADDR16 9
+#define IMAGE_REL_BASED_IA64_IMM64 9 /* yes, 9 too */
+#define IMAGE_REL_BASED_DIR64 10
+#define IMAGE_REL_BASED_HIGH3ADJ 11
+
+struct image_resource_directory_entry {
+ uint32_t irde_name;
+ uint32_t irde_dataoff;
+};
+
+typedef struct image_resource_directory_entry image_resource_directory_entry;
+
+#define RESOURCE_NAME_STR 0x80000000
+#define RESOURCE_DIR_FLAG 0x80000000
+
+struct image_resource_directory {
+ uint32_t ird_characteristics;
+ uint32_t ird_timestamp;
+ uint16_t ird_majorver;
+ uint16_t ird_minorver;
+ uint16_t ird_named_entries;
+ uint16_t ird_id_entries;
+#ifdef notdef
+ image_resource_directory_entry ird_entries[1];
+#endif
+};
+
+typedef struct image_resource_directory image_resource_directory;
+
+struct image_resource_directory_string {
+ uint16_t irds_len;
+ char irds_name[1];
+};
+
+typedef struct image_resource_directory_string image_resource_directory_string;
+
+struct image_resource_directory_string_u {
+ uint16_t irds_len;
+ char irds_name[1];
+};
+
+typedef struct image_resource_directory_string_u
+ image_resource_directory_string_u;
+
+struct image_resource_data_entry {
+ uint32_t irde_offset;
+ uint32_t irde_size;
+ uint32_t irde_codepage;
+ uint32_t irde_rsvd;
+};
+
+typedef struct image_resource_data_entry image_resource_data_entry;
+
+struct message_resource_data {
+ uint32_t mrd_numblocks;
+#ifdef notdef
+ message_resource_block mrd_blocks[1];
+#endif
+};
+
+typedef struct message_resource_data message_resource_data;
+
+struct message_resource_block {
+ uint32_t mrb_lowid;
+ uint32_t mrb_highid;
+ uint32_t mrb_entryoff;
+};
+
+typedef struct message_resource_block message_resource_block;
+
+struct message_resource_entry {
+ uint16_t mre_len;
+ uint16_t mre_flags;
+ char mre_text[];
+};
+
+typedef struct message_resource_entry message_resource_entry;
+
+#define MESSAGE_RESOURCE_UNICODE 0x0001
+
+struct image_patch_table {
+ char *ipt_name;
+ void (*ipt_func)(void);
+ void (*ipt_wrap)(void);
+ int ipt_argcnt;
+ int ipt_ftype;
+};
+
+typedef struct image_patch_table image_patch_table;
+
+/*
+ * AMD64 support. Microsoft uses a different calling convention
+ * than everyone else on the amd64 platform. Sadly, gcc has no
+ * built-in support for it (yet).
+ *
+ * The three major differences we're concerned with are:
+ *
+ * - The first 4 register-sized arguments are passed in the
+ * %rcx, %rdx, %r8 and %r9 registers, and the rest are pushed
+ * onto the stack. (The ELF ABI uses 6 registers, not 4).
+ *
+ * - The caller must reserve space on the stack for the 4
+ * register arguments in case the callee has to spill them.
+ *
+ * - The stack myst be 16-byte aligned by the time the callee
+ * executes. A call instruction implicitly pushes an 8 byte
+ * return address onto the stack. We have to make sure that
+ * the amount of space we consume, plus the return address,
+ * is a multiple of 16 bytes in size. This means that in
+ * some cases, we may need to chew up an extra 8 bytes on
+ * the stack that will be unused.
+ *
+ * On the bright side, Microsoft seems to be using just the one
+ * calling convention for all functions on amd64, unlike x86 where
+ * they use a mix of _stdcall, _fastcall and _cdecl.
+ */
+
+#ifdef __amd64__
+
+extern uint64_t x86_64_call1(void *, uint64_t);
+extern uint64_t x86_64_call2(void *, uint64_t, uint64_t);
+extern uint64_t x86_64_call3(void *, uint64_t, uint64_t, uint64_t);
+extern uint64_t x86_64_call4(void *, uint64_t, uint64_t, uint64_t, uint64_t);
+extern uint64_t x86_64_call5(void *, uint64_t, uint64_t, uint64_t, uint64_t,
+ uint64_t);
+extern uint64_t x86_64_call6(void *, uint64_t, uint64_t, uint64_t, uint64_t,
+ uint64_t, uint64_t);
+
+
+#define MSCALL1(fn, a) \
+ x86_64_call1((fn), (uint64_t)(a))
+#define MSCALL2(fn, a, b) \
+ x86_64_call2((fn), (uint64_t)(a), (uint64_t)(b))
+#define MSCALL3(fn, a, b, c) \
+ x86_64_call3((fn), (uint64_t)(a), (uint64_t)(b), \
+ (uint64_t)(c))
+#define MSCALL4(fn, a, b, c, d) \
+ x86_64_call4((fn), (uint64_t)(a), (uint64_t)(b), \
+ (uint64_t)(c), (uint64_t)(d))
+#define MSCALL5(fn, a, b, c, d, e) \
+ x86_64_call5((fn), (uint64_t)(a), (uint64_t)(b), \
+ (uint64_t)(c), (uint64_t)(d), (uint64_t)(e))
+#define MSCALL6(fn, a, b, c, d, e, f) \
+ x86_64_call6((fn), (uint64_t)(a), (uint64_t)(b), \
+ (uint64_t)(c), (uint64_t)(d), (uint64_t)(e), (uint64_t)(f))
+
+#endif /* __amd64__ */
+
+#ifdef __i386__
+
+extern uint32_t x86_stdcall_call(void *, int, ...);
+
+#define MSCALL1(fn, a) x86_stdcall_call(fn, 1, (a))
+#define MSCALL2(fn, a, b) x86_stdcall_call(fn, 2, (a), (b))
+#define MSCALL3(fn, a, b, c) x86_stdcall_call(fn, 3, (a), (b), (c))
+#define MSCALL4(fn, a, b, c, d) x86_stdcall_call(fn, 4, (a), (b), (c), (d))
+#define MSCALL5(fn, a, b, c, d, e) \
+ x86_stdcall_call(fn, 5, (a), (b), (c), (d), (e))
+#define MSCALL6(fn, a, b, c, d, e, f) \
+ x86_stdcall_call(fn, 6, (a), (b), (c), (d), (e), (f))
+
+#endif /* __i386__ */
+
+
+#define FUNC void(*)(void)
+
+#ifdef __i386__
+#define IMPORT_SFUNC(x, y) { #x, (FUNC)x, NULL, y, WINDRV_WRAP_STDCALL }
+#define IMPORT_SFUNC_MAP(x, y, z) \
+ { #x, (FUNC)y, NULL, z, WINDRV_WRAP_STDCALL }
+#define IMPORT_FFUNC(x, y) { #x, (FUNC)x, NULL, y, WINDRV_WRAP_FASTCALL }
+#define IMPORT_FFUNC_MAP(x, y, z) \
+ { #x, (FUNC)y, NULL, z, WINDRV_WRAP_FASTCALL }
+#define IMPORT_RFUNC(x, y) { #x, (FUNC)x, NULL, y, WINDRV_WRAP_REGPARM }
+#define IMPORT_RFUNC_MAP(x, y, z) \
+ { #x, (FUNC)y, NULL, z, WINDRV_WRAP_REGPARM }
+#define IMPORT_CFUNC(x, y) { #x, (FUNC)x, NULL, y, WINDRV_WRAP_CDECL }
+#define IMPORT_CFUNC_MAP(x, y, z) \
+ { #x, (FUNC)y, NULL, z, WINDRV_WRAP_CDECL }
+#endif /* __i386__ */
+
+#ifdef __amd64__
+#define IMPORT_SFUNC(x, y) { #x, (FUNC)x, NULL, y, WINDRV_WRAP_AMD64 }
+#define IMPORT_SFUNC_MAP(x, y, z) \
+ { #x, (FUNC)y, NULL, z, WINDRV_WRAP_AMD64 }
+#define IMPORT_FFUNC(x, y) { #x, (FUNC)x, NULL, y, WINDRV_WRAP_AMD64 }
+#define IMPORT_FFUNC_MAP(x, y, z) \
+ { #x, (FUNC)y, NULL, z, WINDRV_WRAP_AMD64 }
+#define IMPORT_RFUNC(x, y) { #x, (FUNC)x, NULL, y, WINDRV_WRAP_AMD64 }
+#define IMPORT_RFUNC_MAP(x, y, z) \
+ { #x, (FUNC)y, NULL, z, WINDRV_WRAP_AMD64 }
+#define IMPORT_CFUNC(x, y) { #x, (FUNC)x, NULL, y, WINDRV_WRAP_AMD64 }
+#define IMPORT_CFUNC_MAP(x, y, z) \
+ { #x, (FUNC)y, NULL, z, WINDRV_WRAP_AMD64 }
+#endif /* __amd64__ */
+
+__BEGIN_DECLS
+extern int pe_get_dos_header(vm_offset_t, image_dos_header *);
+extern int pe_is_nt_image(vm_offset_t);
+extern int pe_get_optional_header(vm_offset_t, image_optional_header *);
+extern int pe_get_file_header(vm_offset_t, image_file_header *);
+extern int pe_get_section_header(vm_offset_t, image_section_header *);
+extern int pe_numsections(vm_offset_t);
+extern vm_offset_t pe_imagebase(vm_offset_t);
+extern vm_offset_t pe_directory_offset(vm_offset_t, uint32_t);
+extern vm_offset_t pe_translate_addr (vm_offset_t, vm_offset_t);
+extern int pe_get_section(vm_offset_t, image_section_header *, const char *);
+extern int pe_relocate(vm_offset_t);
+extern int pe_get_import_descriptor(vm_offset_t, image_import_descriptor *, char *);
+extern int pe_patch_imports(vm_offset_t, char *, image_patch_table *);
+extern int pe_get_messagetable(vm_offset_t, message_resource_data **);
+extern int pe_get_message(vm_offset_t, uint32_t, char **, int *, uint16_t *);
+__END_DECLS
+
+#endif /* _PE_VAR_H_ */
diff --git a/sys/compat/ndis/resource_var.h b/sys/compat/ndis/resource_var.h
new file mode 100644
index 0000000..5ce096c
--- /dev/null
+++ b/sys/compat/ndis/resource_var.h
@@ -0,0 +1,199 @@
+/*-
+ * Copyright (c) 2005
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _RESOURCE_VAR_H_
+#define _RESOURCE_VAR_H_
+
+typedef int cm_resource_type;
+
+struct physaddr {
+ uint64_t np_quad;
+#ifdef notdef
+ uint32_t np_low;
+ uint32_t np_high;
+#endif
+};
+
+typedef struct physaddr physaddr;
+
+enum interface_type {
+ InterfaceTypeUndefined = -1,
+ Internal,
+ Isa,
+ Eisa,
+ MicroChannel,
+ TurboChannel,
+ PCIBus,
+ VMEBus,
+ NuBus,
+ PCMCIABus,
+ CBus,
+ MPIBus,
+ MPSABus,
+ ProcessorInternal,
+ InternalPowerBus,
+ PNPISABus,
+ PNPBus,
+ MaximumInterfaceType
+};
+
+typedef enum interface_type interface_type;
+
+#define CmResourceTypeNull 0 /* ResType_All or ResType_None (0x0000) */
+#define CmResourceTypePort 1 /* ResType_IO (0x0002) */
+#define CmResourceTypeInterrupt 2 /* ResType_IRQ (0x0004) */
+#define CmResourceTypeMemory 3 /* ResType_Mem (0x0001) */
+#define CmResourceTypeDma 4 /* ResType_DMA (0x0003) */
+#define CmResourceTypeDeviceSpecific 5 /* ResType_ClassSpecific (0xFFFF) */
+#define CmResourceTypeBusNumber 6 /* ResType_BusNumber (0x0006) */
+#define CmResourceTypeMaximum 7
+#define CmResourceTypeNonArbitrated 128 /* Not arbitrated if 0x80 bit set */
+#define CmResourceTypeConfigData 128 /* ResType_Reserved (0x8000) */
+#define CmResourceTypeDevicePrivate 129 /* ResType_DevicePrivate (0x8001) */
+#define CmResourceTypePcCardConfig 130 /* ResType_PcCardConfig (0x8002) */
+
+enum cm_share_disposition {
+ CmResourceShareUndetermined = 0, /* Reserved */
+ CmResourceShareDeviceExclusive,
+ CmResourceShareDriverExclusive,
+ CmResourceShareShared
+};
+
+typedef enum cm_share_disposition cm_share_disposition;
+
+/* Define the bit masks for Flags when type is CmResourceTypeInterrupt */
+
+#define CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE 0
+#define CM_RESOURCE_INTERRUPT_LATCHED 1
+
+/* Define the bit masks for Flags when type is CmResourceTypeMemory */
+
+#define CM_RESOURCE_MEMORY_READ_WRITE 0x0000
+#define CM_RESOURCE_MEMORY_READ_ONLY 0x0001
+#define CM_RESOURCE_MEMORY_WRITE_ONLY 0x0002
+#define CM_RESOURCE_MEMORY_PREFETCHABLE 0x0004
+
+#define CM_RESOURCE_MEMORY_COMBINEDWRITE 0x0008
+#define CM_RESOURCE_MEMORY_24 0x0010
+#define CM_RESOURCE_MEMORY_CACHEABLE 0x0020
+
+/* Define the bit masks for Flags when type is CmResourceTypePort */
+
+#define CM_RESOURCE_PORT_MEMORY 0x0000
+#define CM_RESOURCE_PORT_IO 0x0001
+#define CM_RESOURCE_PORT_10_BIT_DECODE 0x0004
+#define CM_RESOURCE_PORT_12_BIT_DECODE 0x0008
+#define CM_RESOURCE_PORT_16_BIT_DECODE 0x0010
+#define CM_RESOURCE_PORT_POSITIVE_DECODE 0x0020
+#define CM_RESOURCE_PORT_PASSIVE_DECODE 0x0040
+#define CM_RESOURCE_PORT_WINDOW_DECODE 0x0080
+
+/* Define the bit masks for Flags when type is CmResourceTypeDma */
+
+#define CM_RESOURCE_DMA_8 0x0000
+#define CM_RESOURCE_DMA_16 0x0001
+#define CM_RESOURCE_DMA_32 0x0002
+#define CM_RESOURCE_DMA_8_AND_16 0x0004
+#define CM_RESOURCE_DMA_BUS_MASTER 0x0008
+#define CM_RESOURCE_DMA_TYPE_A 0x0010
+#define CM_RESOURCE_DMA_TYPE_B 0x0020
+#define CM_RESOURCE_DMA_TYPE_F 0x0040
+
+struct cm_partial_resource_desc {
+ uint8_t cprd_type;
+ uint8_t cprd_sharedisp;
+ uint16_t cprd_flags;
+ union {
+ struct {
+ physaddr cprd_start;
+ uint32_t cprd_len;
+ } cprd_generic;
+ struct {
+ physaddr cprd_start;
+ uint32_t cprd_len;
+ } cprd_port;
+ struct {
+ uint32_t cprd_level;
+ uint32_t cprd_vector;
+ uint32_t cprd_affinity;
+ } cprd_intr;
+ struct {
+ physaddr cprd_start;
+ uint32_t cprd_len;
+ } cprd_mem;
+ struct {
+ uint32_t cprd_chan;
+ uint32_t cprd_port;
+ uint32_t cprd_rsvd;
+ } cprd_dmachan;
+ struct {
+ uint32_t cprd_data[3];
+ } cprd_devpriv;
+ struct {
+ uint32_t cprd_datasize;
+ uint32_t cprd_rsvd1;
+ uint32_t cprd_rsvd2;
+ } cprd_devspec;
+ } u __attribute__((packed));
+};
+
+typedef struct cm_partial_resource_desc cm_partial_resource_desc;
+
+struct cm_partial_resource_list {
+ uint16_t cprl_version;
+ uint16_t cprl_revision;
+ uint32_t cprl_count;
+ cm_partial_resource_desc cprl_partial_descs[1];
+};
+
+typedef struct cm_partial_resource_list cm_partial_resource_list;
+
+struct cm_full_resource_list {
+ interface_type cfrl_type;
+ uint32_t cfrl_busnum;
+ cm_partial_resource_desc cfrl_partiallist;
+};
+
+typedef struct cm_full_resource_list cm_full_resource_list;
+
+struct cm_resource_list {
+ uint32_t crl_count;
+ cm_full_resource_list crl_rlist;
+};
+
+typedef struct cm_resource_list cm_resource_list;
+
+typedef cm_partial_resource_list ndis_resource_list;
+
+#endif /* _RESOURCE_VAR_H_ */
diff --git a/sys/compat/ndis/subr_hal.c b/sys/compat/ndis/subr_hal.c
new file mode 100644
index 0000000..62d97ad
--- /dev/null
+++ b/sys/compat/ndis/subr_hal.c
@@ -0,0 +1,481 @@
+/*-
+ * Copyright (c) 2003
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+
+#include <sys/callout.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/sched.h>
+#include <sys/module.h>
+
+#include <sys/systm.h>
+#include <machine/bus.h>
+
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <compat/ndis/pe_var.h>
+#include <compat/ndis/resource_var.h>
+#include <compat/ndis/cfg_var.h>
+#include <compat/ndis/ntoskrnl_var.h>
+#include <compat/ndis/hal_var.h>
+
+static void KeStallExecutionProcessor(uint32_t);
+static void WRITE_PORT_BUFFER_ULONG(uint32_t *,
+ uint32_t *, uint32_t);
+static void WRITE_PORT_BUFFER_USHORT(uint16_t *,
+ uint16_t *, uint32_t);
+static void WRITE_PORT_BUFFER_UCHAR(uint8_t *,
+ uint8_t *, uint32_t);
+static void WRITE_PORT_ULONG(uint32_t *, uint32_t);
+static void WRITE_PORT_USHORT(uint16_t *, uint16_t);
+static void WRITE_PORT_UCHAR(uint8_t *, uint8_t);
+static uint32_t READ_PORT_ULONG(uint32_t *);
+static uint16_t READ_PORT_USHORT(uint16_t *);
+static uint8_t READ_PORT_UCHAR(uint8_t *);
+static void READ_PORT_BUFFER_ULONG(uint32_t *,
+ uint32_t *, uint32_t);
+static void READ_PORT_BUFFER_USHORT(uint16_t *,
+ uint16_t *, uint32_t);
+static void READ_PORT_BUFFER_UCHAR(uint8_t *,
+ uint8_t *, uint32_t);
+static uint64_t KeQueryPerformanceCounter(uint64_t *);
+static void _KeLowerIrql(uint8_t);
+static uint8_t KeRaiseIrqlToDpcLevel(void);
+static void dummy (void);
+
+#define NDIS_MAXCPUS 64
+static struct mtx disp_lock[NDIS_MAXCPUS];
+
+int
+hal_libinit()
+{
+ image_patch_table *patch;
+ int i;
+
+ for (i = 0; i < NDIS_MAXCPUS; i++)
+ mtx_init(&disp_lock[i], "HAL preemption lock",
+ "HAL lock", MTX_RECURSE|MTX_DEF);
+
+ patch = hal_functbl;
+ while (patch->ipt_func != NULL) {
+ windrv_wrap((funcptr)patch->ipt_func,
+ (funcptr *)&patch->ipt_wrap,
+ patch->ipt_argcnt, patch->ipt_ftype);
+ patch++;
+ }
+
+ return (0);
+}
+
+int
+hal_libfini()
+{
+ image_patch_table *patch;
+ int i;
+
+ for (i = 0; i < NDIS_MAXCPUS; i++)
+ mtx_destroy(&disp_lock[i]);
+
+ patch = hal_functbl;
+ while (patch->ipt_func != NULL) {
+ windrv_unwrap(patch->ipt_wrap);
+ patch++;
+ }
+
+ return (0);
+}
+
+static void
+KeStallExecutionProcessor(usecs)
+ uint32_t usecs;
+{
+ DELAY(usecs);
+}
+
+static void
+WRITE_PORT_ULONG(port, val)
+ uint32_t *port;
+ uint32_t val;
+{
+ bus_space_write_4(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port, val);
+}
+
+static void
+WRITE_PORT_USHORT(uint16_t *port, uint16_t val)
+{
+ bus_space_write_2(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port, val);
+}
+
+static void
+WRITE_PORT_UCHAR(uint8_t *port, uint8_t val)
+{
+ bus_space_write_1(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port, val);
+}
+
+static void
+WRITE_PORT_BUFFER_ULONG(port, val, cnt)
+ uint32_t *port;
+ uint32_t *val;
+ uint32_t cnt;
+{
+ bus_space_write_multi_4(NDIS_BUS_SPACE_IO, 0x0,
+ (bus_size_t)port, val, cnt);
+}
+
+static void
+WRITE_PORT_BUFFER_USHORT(port, val, cnt)
+ uint16_t *port;
+ uint16_t *val;
+ uint32_t cnt;
+{
+ bus_space_write_multi_2(NDIS_BUS_SPACE_IO, 0x0,
+ (bus_size_t)port, val, cnt);
+}
+
+static void
+WRITE_PORT_BUFFER_UCHAR(port, val, cnt)
+ uint8_t *port;
+ uint8_t *val;
+ uint32_t cnt;
+{
+ bus_space_write_multi_1(NDIS_BUS_SPACE_IO, 0x0,
+ (bus_size_t)port, val, cnt);
+}
+
+static uint16_t
+READ_PORT_USHORT(port)
+ uint16_t *port;
+{
+ return (bus_space_read_2(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port));
+}
+
+static uint32_t
+READ_PORT_ULONG(port)
+ uint32_t *port;
+{
+ return (bus_space_read_4(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port));
+}
+
+static uint8_t
+READ_PORT_UCHAR(port)
+ uint8_t *port;
+{
+ return (bus_space_read_1(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port));
+}
+
+static void
+READ_PORT_BUFFER_ULONG(port, val, cnt)
+ uint32_t *port;
+ uint32_t *val;
+ uint32_t cnt;
+{
+ bus_space_read_multi_4(NDIS_BUS_SPACE_IO, 0x0,
+ (bus_size_t)port, val, cnt);
+}
+
+static void
+READ_PORT_BUFFER_USHORT(port, val, cnt)
+ uint16_t *port;
+ uint16_t *val;
+ uint32_t cnt;
+{
+ bus_space_read_multi_2(NDIS_BUS_SPACE_IO, 0x0,
+ (bus_size_t)port, val, cnt);
+}
+
+static void
+READ_PORT_BUFFER_UCHAR(port, val, cnt)
+ uint8_t *port;
+ uint8_t *val;
+ uint32_t cnt;
+{
+ bus_space_read_multi_1(NDIS_BUS_SPACE_IO, 0x0,
+ (bus_size_t)port, val, cnt);
+}
+
+/*
+ * The spinlock implementation in Windows differs from that of FreeBSD.
+ * The basic operation of spinlocks involves two steps: 1) spin in a
+ * tight loop while trying to acquire a lock, 2) after obtaining the
+ * lock, disable preemption. (Note that on uniprocessor systems, you're
+ * allowed to skip the first step and just lock out pre-emption, since
+ * it's not possible for you to be in contention with another running
+ * thread.) Later, you release the lock then re-enable preemption.
+ * The difference between Windows and FreeBSD lies in how preemption
+ * is disabled. In FreeBSD, it's done using critical_enter(), which on
+ * the x86 arch translates to a cli instruction. This masks off all
+ * interrupts, and effectively stops the scheduler from ever running
+ * so _nothing_ can execute except the current thread. In Windows,
+ * preemption is disabled by raising the processor IRQL to DISPATCH_LEVEL.
+ * This stops other threads from running, but does _not_ block device
+ * interrupts. This means ISRs can still run, and they can make other
+ * threads runable, but those other threads won't be able to execute
+ * until the current thread lowers the IRQL to something less than
+ * DISPATCH_LEVEL.
+ *
+ * There's another commonly used IRQL in Windows, which is APC_LEVEL.
+ * An APC is an Asynchronous Procedure Call, which differs from a DPC
+ * (Defered Procedure Call) in that a DPC is queued up to run in
+ * another thread, while an APC runs in the thread that scheduled
+ * it (similar to a signal handler in a UNIX process). We don't
+ * actually support the notion of APCs in FreeBSD, so for now, the
+ * only IRQLs we're interested in are DISPATCH_LEVEL and PASSIVE_LEVEL.
+ *
+ * To simulate DISPATCH_LEVEL, we raise the current thread's priority
+ * to PI_REALTIME, which is the highest we can give it. This should,
+ * if I understand things correctly, prevent anything except for an
+ * interrupt thread from preempting us. PASSIVE_LEVEL is basically
+ * everything else.
+ *
+ * Be aware that, at least on the x86 arch, the Windows spinlock
+ * functions are divided up in peculiar ways. The actual spinlock
+ * functions are KfAcquireSpinLock() and KfReleaseSpinLock(), and
+ * they live in HAL.dll. Meanwhile, KeInitializeSpinLock(),
+ * KefAcquireSpinLockAtDpcLevel() and KefReleaseSpinLockFromDpcLevel()
+ * live in ntoskrnl.exe. Most Windows source code will call
+ * KeAcquireSpinLock() and KeReleaseSpinLock(), but these are just
+ * macros that call KfAcquireSpinLock() and KfReleaseSpinLock().
+ * KefAcquireSpinLockAtDpcLevel() and KefReleaseSpinLockFromDpcLevel()
+ * perform the lock aquisition/release functions without doing the
+ * IRQL manipulation, and are used when one is already running at
+ * DISPATCH_LEVEL. Make sense? Good.
+ *
+ * According to the Microsoft documentation, any thread that calls
+ * KeAcquireSpinLock() must be running at IRQL <= DISPATCH_LEVEL. If
+ * we detect someone trying to acquire a spinlock from DEVICE_LEVEL
+ * or HIGH_LEVEL, we panic.
+ *
+ * Alternate sleep-lock-based spinlock implementation
+ * --------------------------------------------------
+ *
+ * The earlier spinlock implementation was arguably a bit of a hack
+ * and presented several problems. It was basically designed to provide
+ * the functionality of spinlocks without incurring the wrath of
+ * WITNESS. We could get away with using both our spinlock implementation
+ * and FreeBSD sleep locks at the same time, but if WITNESS knew what
+ * we were really up to, it would have spanked us rather severely.
+ *
+ * There's another method we can use based entirely on sleep locks.
+ * First, it's important to realize that everything we're locking
+ * resides inside Project Evil itself: any critical data being locked
+ * by drivers belongs to the drivers, and should not be referenced
+ * by any other OS code outside of the NDISulator. The priority-based
+ * locking scheme has system-wide effects, just like real spinlocks
+ * (blocking preemption affects the whole CPU), but since we keep all
+ * our critical data private, we can use a simpler mechanism that
+ * affects only code/threads directly related to Project Evil.
+ *
+ * The idea is to create a sleep lock mutex for each CPU in the system.
+ * When a CPU running in the NDISulator wants to acquire a spinlock, it
+ * does the following:
+ * - Pin ourselves to the current CPU
+ * - Acquire the mutex for the current CPU
+ * - Spin on the spinlock variable using atomic test and set, just like
+ * a real spinlock.
+ * - Once we have the lock, we execute our critical code
+ *
+ * To give up the lock, we do:
+ * - Clear the spinlock variable with an atomic op
+ * - Release the per-CPU mutex
+ * - Unpin ourselves from the current CPU.
+ *
+ * On a uniprocessor system, this means all threads that access protected
+ * data are serialized through the per-CPU mutex. After one thread
+ * acquires the 'spinlock,' any other thread that uses a spinlock on the
+ * current CPU will block on the per-CPU mutex, which has the same general
+ * effect of blocking pre-emption, but _only_ for those threads that are
+ * running NDISulator code.
+ *
+ * On a multiprocessor system, threads on different CPUs all block on
+ * their respective per-CPU mutex, and the atomic test/set operation
+ * on the spinlock variable provides inter-CPU synchronization, though
+ * only for threads running NDISulator code.
+ *
+ * This method solves an important problem. In Windows, you're allowed
+ * to do an ExAllocatePoolWithTag() with a spinlock held, provided you
+ * allocate from NonPagedPool. This implies an atomic heap allocation
+ * that will not cause the current thread to sleep. (You can't sleep
+ * while holding real spinlock: clowns will eat you.) But in FreeBSD,
+ * malloc(9) _always_ triggers the acquisition of a sleep lock, even
+ * when you use M_NOWAIT. This is not a problem for FreeBSD native
+ * code: you're allowed to sleep in things like interrupt threads. But
+ * it is a problem with the old priority-based spinlock implementation:
+ * even though we get away with it most of the time, we really can't
+ * do a malloc(9) after doing a KeAcquireSpinLock() or KeRaiseIrql().
+ * With the new implementation, it's not a problem: you're allowed to
+ * acquire more than one sleep lock (as long as you avoid lock order
+ * reversals).
+ *
+ * The one drawback to this approach is that now we have a lot of
+ * contention on one per-CPU mutex within the NDISulator code. Whether
+ * or not this is preferable to the expected Windows spinlock behavior
+ * of blocking pre-emption is debatable.
+ */
+
+uint8_t
+KfAcquireSpinLock(lock)
+ kspin_lock *lock;
+{
+ uint8_t oldirql;
+
+ KeRaiseIrql(DISPATCH_LEVEL, &oldirql);
+ KeAcquireSpinLockAtDpcLevel(lock);
+
+ return (oldirql);
+}
+
+void
+KfReleaseSpinLock(kspin_lock *lock, uint8_t newirql)
+{
+ KeReleaseSpinLockFromDpcLevel(lock);
+ KeLowerIrql(newirql);
+}
+
+uint8_t
+KeGetCurrentIrql()
+{
+ if (mtx_owned(&disp_lock[curthread->td_oncpu]))
+ return (DISPATCH_LEVEL);
+ return (PASSIVE_LEVEL);
+}
+
+static uint64_t
+KeQueryPerformanceCounter(freq)
+ uint64_t *freq;
+{
+ if (freq != NULL)
+ *freq = hz;
+
+ return ((uint64_t)ticks);
+}
+
+uint8_t
+KfRaiseIrql(uint8_t irql)
+{
+ uint8_t oldirql;
+
+ sched_pin();
+ oldirql = KeGetCurrentIrql();
+
+ /* I am so going to hell for this. */
+ if (oldirql > irql)
+ panic("IRQL_NOT_LESS_THAN_OR_EQUAL");
+
+ if (oldirql != DISPATCH_LEVEL)
+ mtx_lock(&disp_lock[curthread->td_oncpu]);
+ else
+ sched_unpin();
+
+/*printf("RAISE IRQL: %d %d\n", irql, oldirql);*/
+
+ return (oldirql);
+}
+
+void
+KfLowerIrql(uint8_t oldirql)
+{
+ if (oldirql == DISPATCH_LEVEL)
+ return;
+
+ if (KeGetCurrentIrql() != DISPATCH_LEVEL)
+ panic("IRQL_NOT_GREATER_THAN");
+
+ mtx_unlock(&disp_lock[curthread->td_oncpu]);
+ sched_unpin();
+}
+
+static uint8_t
+KeRaiseIrqlToDpcLevel(void)
+{
+ uint8_t irql;
+
+ KeRaiseIrql(DISPATCH_LEVEL, &irql);
+ return (irql);
+}
+
+static void
+_KeLowerIrql(uint8_t oldirql)
+{
+ KeLowerIrql(oldirql);
+}
+
+static void dummy()
+{
+ printf("hal dummy called...\n");
+}
+
+image_patch_table hal_functbl[] = {
+ IMPORT_SFUNC(KeStallExecutionProcessor, 1),
+ IMPORT_SFUNC(WRITE_PORT_ULONG, 2),
+ IMPORT_SFUNC(WRITE_PORT_USHORT, 2),
+ IMPORT_SFUNC(WRITE_PORT_UCHAR, 2),
+ IMPORT_SFUNC(WRITE_PORT_BUFFER_ULONG, 3),
+ IMPORT_SFUNC(WRITE_PORT_BUFFER_USHORT, 3),
+ IMPORT_SFUNC(WRITE_PORT_BUFFER_UCHAR, 3),
+ IMPORT_SFUNC(READ_PORT_ULONG, 1),
+ IMPORT_SFUNC(READ_PORT_USHORT, 1),
+ IMPORT_SFUNC(READ_PORT_UCHAR, 1),
+ IMPORT_SFUNC(READ_PORT_BUFFER_ULONG, 3),
+ IMPORT_SFUNC(READ_PORT_BUFFER_USHORT, 3),
+ IMPORT_SFUNC(READ_PORT_BUFFER_UCHAR, 3),
+ IMPORT_FFUNC(KfAcquireSpinLock, 1),
+ IMPORT_FFUNC(KfReleaseSpinLock, 1),
+ IMPORT_SFUNC(KeGetCurrentIrql, 0),
+ IMPORT_SFUNC(KeQueryPerformanceCounter, 1),
+ IMPORT_FFUNC(KfLowerIrql, 1),
+ IMPORT_FFUNC(KfRaiseIrql, 1),
+ IMPORT_SFUNC(KeRaiseIrqlToDpcLevel, 0),
+#undef KeLowerIrql
+ IMPORT_SFUNC_MAP(KeLowerIrql, _KeLowerIrql, 1),
+
+ /*
+ * This last entry is a catch-all for any function we haven't
+ * implemented yet. The PE import list patching routine will
+ * use it for any function that doesn't have an explicit match
+ * in this table.
+ */
+
+ { NULL, (FUNC)dummy, NULL, 0, WINDRV_WRAP_STDCALL },
+
+ /* End of list. */
+
+ { NULL, NULL, NULL }
+};
diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c
new file mode 100644
index 0000000..bc13b2f
--- /dev/null
+++ b/sys/compat/ndis/subr_ndis.c
@@ -0,0 +1,3371 @@
+/*-
+ * Copyright (c) 2003
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * This file implements a translation layer between the BSD networking
+ * infrasturcture and Windows(R) NDIS network driver modules. A Windows
+ * NDIS driver calls into several functions in the NDIS.SYS Windows
+ * kernel module and exports a table of functions designed to be called
+ * by the NDIS subsystem. Using the PE loader, we can patch our own
+ * versions of the NDIS routines into a given Windows driver module and
+ * convince the driver that it is in fact running on Windows.
+ *
+ * We provide a table of all our implemented NDIS routines which is patched
+ * into the driver object code. All our exported routines must use the
+ * _stdcall calling convention, since that's what the Windows object code
+ * expects.
+ */
+
+
+#include <sys/ctype.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+
+#include <sys/callout.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/timespec.h>
+#include <sys/smp.h>
+#include <sys/queue.h>
+#include <sys/proc.h>
+#include <sys/filedesc.h>
+#include <sys/namei.h>
+#include <sys/fcntl.h>
+#include <sys/vnode.h>
+#include <sys/kthread.h>
+#include <sys/linker.h>
+#include <sys/mount.h>
+#include <sys/sysproto.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+
+#include <machine/atomic.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <machine/stdarg.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_ioctl.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+
+#include <compat/ndis/pe_var.h>
+#include <compat/ndis/cfg_var.h>
+#include <compat/ndis/resource_var.h>
+#include <compat/ndis/ntoskrnl_var.h>
+#include <compat/ndis/hal_var.h>
+#include <compat/ndis/ndis_var.h>
+#include <dev/if_ndis/if_ndisvar.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/uma.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_map.h>
+
+static char ndis_filepath[MAXPATHLEN];
+
+SYSCTL_STRING(_hw, OID_AUTO, ndis_filepath, CTLFLAG_RW, ndis_filepath,
+ MAXPATHLEN, "Path used by NdisOpenFile() to search for files");
+
+static void NdisInitializeWrapper(ndis_handle *,
+ driver_object *, void *, void *);
+static ndis_status NdisMRegisterMiniport(ndis_handle,
+ ndis_miniport_characteristics *, int);
+static ndis_status NdisAllocateMemoryWithTag(void **,
+ uint32_t, uint32_t);
+static ndis_status NdisAllocateMemory(void **,
+ uint32_t, uint32_t, ndis_physaddr);
+static void NdisFreeMemory(void *, uint32_t, uint32_t);
+static ndis_status NdisMSetAttributesEx(ndis_handle, ndis_handle,
+ uint32_t, uint32_t, ndis_interface_type);
+static void NdisOpenConfiguration(ndis_status *,
+ ndis_handle *, ndis_handle);
+static void NdisOpenConfigurationKeyByIndex(ndis_status *,
+ ndis_handle, uint32_t, unicode_string *, ndis_handle *);
+static void NdisOpenConfigurationKeyByName(ndis_status *,
+ ndis_handle, unicode_string *, ndis_handle *);
+static ndis_status ndis_encode_parm(ndis_miniport_block *,
+ struct sysctl_oid *, ndis_parm_type, ndis_config_parm **);
+static ndis_status ndis_decode_parm(ndis_miniport_block *,
+ ndis_config_parm *, char *);
+static void NdisReadConfiguration(ndis_status *, ndis_config_parm **,
+ ndis_handle, unicode_string *, ndis_parm_type);
+static void NdisWriteConfiguration(ndis_status *, ndis_handle,
+ unicode_string *, ndis_config_parm *);
+static void NdisCloseConfiguration(ndis_handle);
+static void NdisAllocateSpinLock(ndis_spin_lock *);
+static void NdisFreeSpinLock(ndis_spin_lock *);
+static void NdisAcquireSpinLock(ndis_spin_lock *);
+static void NdisReleaseSpinLock(ndis_spin_lock *);
+static void NdisDprAcquireSpinLock(ndis_spin_lock *);
+static void NdisDprReleaseSpinLock(ndis_spin_lock *);
+static void NdisInitializeReadWriteLock(ndis_rw_lock *);
+static void NdisAcquireReadWriteLock(ndis_rw_lock *,
+ uint8_t, ndis_lock_state *);
+static void NdisReleaseReadWriteLock(ndis_rw_lock *, ndis_lock_state *);
+static uint32_t NdisReadPciSlotInformation(ndis_handle, uint32_t,
+ uint32_t, void *, uint32_t);
+static uint32_t NdisWritePciSlotInformation(ndis_handle, uint32_t,
+ uint32_t, void *, uint32_t);
+static void NdisWriteErrorLogEntry(ndis_handle, ndis_error_code, uint32_t, ...);
+static void ndis_map_cb(void *, bus_dma_segment_t *, int, int);
+static void NdisMStartBufferPhysicalMapping(ndis_handle,
+ ndis_buffer *, uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *);
+static void NdisMCompleteBufferPhysicalMapping(ndis_handle,
+ ndis_buffer *, uint32_t);
+static void NdisMInitializeTimer(ndis_miniport_timer *, ndis_handle,
+ ndis_timer_function, void *);
+static void NdisInitializeTimer(ndis_timer *,
+ ndis_timer_function, void *);
+static void NdisSetTimer(ndis_timer *, uint32_t);
+static void NdisMSetPeriodicTimer(ndis_miniport_timer *, uint32_t);
+static void NdisMCancelTimer(ndis_timer *, uint8_t *);
+static void ndis_timercall(kdpc *, ndis_miniport_timer *,
+ void *, void *);
+static void NdisMQueryAdapterResources(ndis_status *, ndis_handle,
+ ndis_resource_list *, uint32_t *);
+static ndis_status NdisMRegisterIoPortRange(void **,
+ ndis_handle, uint32_t, uint32_t);
+static void NdisMDeregisterIoPortRange(ndis_handle,
+ uint32_t, uint32_t, void *);
+static void NdisReadNetworkAddress(ndis_status *, void **,
+ uint32_t *, ndis_handle);
+static ndis_status NdisQueryMapRegisterCount(uint32_t, uint32_t *);
+static ndis_status NdisMAllocateMapRegisters(ndis_handle,
+ uint32_t, uint8_t, uint32_t, uint32_t);
+static void NdisMFreeMapRegisters(ndis_handle);
+static void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int);
+static void NdisMAllocateSharedMemory(ndis_handle, uint32_t,
+ uint8_t, void **, ndis_physaddr *);
+static void ndis_asyncmem_complete(device_object *, void *);
+static ndis_status NdisMAllocateSharedMemoryAsync(ndis_handle,
+ uint32_t, uint8_t, void *);
+static void NdisMFreeSharedMemory(ndis_handle, uint32_t,
+ uint8_t, void *, ndis_physaddr);
+static ndis_status NdisMMapIoSpace(void **, ndis_handle,
+ ndis_physaddr, uint32_t);
+static void NdisMUnmapIoSpace(ndis_handle, void *, uint32_t);
+static uint32_t NdisGetCacheFillSize(void);
+static void *NdisGetRoutineAddress(unicode_string *);
+static uint32_t NdisMGetDmaAlignment(ndis_handle);
+static ndis_status NdisMInitializeScatterGatherDma(ndis_handle,
+ uint8_t, uint32_t);
+static void NdisUnchainBufferAtFront(ndis_packet *, ndis_buffer **);
+static void NdisUnchainBufferAtBack(ndis_packet *, ndis_buffer **);
+static void NdisAllocateBufferPool(ndis_status *,
+ ndis_handle *, uint32_t);
+static void NdisFreeBufferPool(ndis_handle);
+static void NdisAllocateBuffer(ndis_status *, ndis_buffer **,
+ ndis_handle, void *, uint32_t);
+static void NdisFreeBuffer(ndis_buffer *);
+static uint32_t NdisBufferLength(ndis_buffer *);
+static void NdisQueryBuffer(ndis_buffer *, void **, uint32_t *);
+static void NdisQueryBufferSafe(ndis_buffer *, void **,
+ uint32_t *, uint32_t);
+static void *NdisBufferVirtualAddress(ndis_buffer *);
+static void *NdisBufferVirtualAddressSafe(ndis_buffer *, uint32_t);
+static void NdisAdjustBufferLength(ndis_buffer *, int);
+static uint32_t NdisInterlockedIncrement(uint32_t *);
+static uint32_t NdisInterlockedDecrement(uint32_t *);
+static void NdisInitializeEvent(ndis_event *);
+static void NdisSetEvent(ndis_event *);
+static void NdisResetEvent(ndis_event *);
+static uint8_t NdisWaitEvent(ndis_event *, uint32_t);
+static ndis_status NdisUnicodeStringToAnsiString(ansi_string *,
+ unicode_string *);
+static ndis_status
+ NdisAnsiStringToUnicodeString(unicode_string *, ansi_string *);
+static ndis_status NdisMPciAssignResources(ndis_handle,
+ uint32_t, ndis_resource_list **);
+static ndis_status NdisMRegisterInterrupt(ndis_miniport_interrupt *,
+ ndis_handle, uint32_t, uint32_t, uint8_t,
+ uint8_t, ndis_interrupt_mode);
+static void NdisMDeregisterInterrupt(ndis_miniport_interrupt *);
+static void NdisMRegisterAdapterShutdownHandler(ndis_handle, void *,
+ ndis_shutdown_handler);
+static void NdisMDeregisterAdapterShutdownHandler(ndis_handle);
+static uint32_t NDIS_BUFFER_TO_SPAN_PAGES(ndis_buffer *);
+static void NdisGetBufferPhysicalArraySize(ndis_buffer *,
+ uint32_t *);
+static void NdisQueryBufferOffset(ndis_buffer *,
+ uint32_t *, uint32_t *);
+static uint32_t NdisReadPcmciaAttributeMemory(ndis_handle,
+ uint32_t, void *, uint32_t);
+static uint32_t NdisWritePcmciaAttributeMemory(ndis_handle,
+ uint32_t, void *, uint32_t);
+static list_entry *NdisInterlockedInsertHeadList(list_entry *,
+ list_entry *, ndis_spin_lock *);
+static list_entry *NdisInterlockedRemoveHeadList(list_entry *,
+ ndis_spin_lock *);
+static list_entry *NdisInterlockedInsertTailList(list_entry *,
+ list_entry *, ndis_spin_lock *);
+static uint8_t
+ NdisMSynchronizeWithInterrupt(ndis_miniport_interrupt *,
+ void *, void *);
+static void NdisGetCurrentSystemTime(uint64_t *);
+static void NdisGetSystemUpTime(uint32_t *);
+static uint32_t NdisGetVersion(void);
+static void NdisInitializeString(unicode_string *, char *);
+static void NdisInitAnsiString(ansi_string *, char *);
+static void NdisInitUnicodeString(unicode_string *, uint16_t *);
+static void NdisFreeString(unicode_string *);
+static ndis_status NdisMRemoveMiniport(ndis_handle *);
+static void NdisTerminateWrapper(ndis_handle, void *);
+static void NdisMGetDeviceProperty(ndis_handle, device_object **,
+ device_object **, device_object **, cm_resource_list *,
+ cm_resource_list *);
+static void NdisGetFirstBufferFromPacket(ndis_packet *,
+ ndis_buffer **, void **, uint32_t *, uint32_t *);
+static void NdisGetFirstBufferFromPacketSafe(ndis_packet *,
+ ndis_buffer **, void **, uint32_t *, uint32_t *, uint32_t);
+static int ndis_find_sym(linker_file_t, char *, char *, caddr_t *);
+static void NdisOpenFile(ndis_status *, ndis_handle *, uint32_t *,
+ unicode_string *, ndis_physaddr);
+static void NdisMapFile(ndis_status *, void **, ndis_handle);
+static void NdisUnmapFile(ndis_handle);
+static void NdisCloseFile(ndis_handle);
+static uint8_t NdisSystemProcessorCount(void);
+static void NdisGetCurrentProcessorCounts(uint32_t *, uint32_t *, uint32_t *);
+static void NdisMIndicateStatusComplete(ndis_handle);
+static void NdisMIndicateStatus(ndis_handle, ndis_status,
+ void *, uint32_t);
+static uint8_t ndis_intr(kinterrupt *, void *);
+static void ndis_intrhand(kdpc *, ndis_miniport_interrupt *, void *, void *);
+static funcptr ndis_findwrap(funcptr);
+static void NdisCopyFromPacketToPacket(ndis_packet *,
+ uint32_t, uint32_t, ndis_packet *, uint32_t, uint32_t *);
+static void NdisCopyFromPacketToPacketSafe(ndis_packet *,
+ uint32_t, uint32_t, ndis_packet *, uint32_t, uint32_t *, uint32_t);
+static void NdisIMCopySendPerPacketInfo(ndis_packet *, ndis_packet *);
+static ndis_status NdisMRegisterDevice(ndis_handle,
+ unicode_string *, unicode_string *, driver_dispatch **,
+ void **, ndis_handle *);
+static ndis_status NdisMDeregisterDevice(ndis_handle);
+static ndis_status
+ NdisMQueryAdapterInstanceName(unicode_string *, ndis_handle);
+static void NdisMRegisterUnloadHandler(ndis_handle, void *);
+static void dummy(void);
+
+/*
+ * Some really old drivers do not properly check the return value
+ * from NdisAllocatePacket() and NdisAllocateBuffer() and will
+ * sometimes allocate few more buffers/packets that they originally
+ * requested when they created the pool. To prevent this from being
+ * a problem, we allocate a few extra buffers/packets beyond what
+ * the driver asks for. This #define controls how many.
+ */
+#define NDIS_POOL_EXTRA 16
+
+int
+ndis_libinit()
+{
+ image_patch_table *patch;
+
+ strcpy(ndis_filepath, "/compat/ndis");
+
+ patch = ndis_functbl;
+ while (patch->ipt_func != NULL) {
+ windrv_wrap((funcptr)patch->ipt_func,
+ (funcptr *)&patch->ipt_wrap,
+ patch->ipt_argcnt, patch->ipt_ftype);
+ patch++;
+ }
+
+ return (0);
+}
+
+int
+ndis_libfini()
+{
+ image_patch_table *patch;
+
+ patch = ndis_functbl;
+ while (patch->ipt_func != NULL) {
+ windrv_unwrap(patch->ipt_wrap);
+ patch++;
+ }
+
+ return (0);
+}
+
+static funcptr
+ndis_findwrap(func)
+ funcptr func;
+{
+ image_patch_table *patch;
+
+ patch = ndis_functbl;
+ while (patch->ipt_func != NULL) {
+ if ((funcptr)patch->ipt_func == func)
+ return ((funcptr)patch->ipt_wrap);
+ patch++;
+ }
+
+ return (NULL);
+}
+
+/*
+ * This routine does the messy Windows Driver Model device attachment
+ * stuff on behalf of NDIS drivers. We register our own AddDevice
+ * routine here
+ */
+static void
+NdisInitializeWrapper(wrapper, drv, path, unused)
+ ndis_handle *wrapper;
+ driver_object *drv;
+ void *path;
+ void *unused;
+{
+ /*
+ * As of yet, I haven't come up with a compelling
+ * reason to define a private NDIS wrapper structure,
+ * so we use a pointer to the driver object as the
+ * wrapper handle. The driver object has the miniport
+ * characteristics struct for this driver hung off it
+ * via IoAllocateDriverObjectExtension(), and that's
+ * really all the private data we need.
+ */
+
+ *wrapper = drv;
+
+ /*
+ * If this was really Windows, we'd be registering dispatch
+ * routines for the NDIS miniport module here, but we're
+ * not Windows so all we really need to do is set up an
+ * AddDevice function that'll be invoked when a new device
+ * instance appears.
+ */
+
+ drv->dro_driverext->dre_adddevicefunc = NdisAddDevice;
+}
+
+static void
+NdisTerminateWrapper(handle, syspec)
+ ndis_handle handle;
+ void *syspec;
+{
+ /* Nothing to see here, move along. */
+}
+
+static ndis_status
+NdisMRegisterMiniport(handle, characteristics, len)
+ ndis_handle handle;
+ ndis_miniport_characteristics *characteristics;
+ int len;
+{
+ ndis_miniport_characteristics *ch = NULL;
+ driver_object *drv;
+
+ drv = (driver_object *)handle;
+
+ /*
+ * We need to save the NDIS miniport characteristics
+ * somewhere. This data is per-driver, not per-device
+ * (all devices handled by the same driver have the
+ * same characteristics) so we hook it onto the driver
+ * object using IoAllocateDriverObjectExtension().
+ * The extra extension info is automagically deleted when
+ * the driver is unloaded (see windrv_unload()).
+ */
+
+ if (IoAllocateDriverObjectExtension(drv, (void *)1,
+ sizeof(ndis_miniport_characteristics), (void **)&ch) !=
+ STATUS_SUCCESS) {
+ return (NDIS_STATUS_RESOURCES);
+ }
+
+ bzero((char *)ch, sizeof(ndis_miniport_characteristics));
+
+ bcopy((char *)characteristics, (char *)ch, len);
+
+ if (ch->nmc_version_major < 5 || ch->nmc_version_minor < 1) {
+ ch->nmc_shutdown_handler = NULL;
+ ch->nmc_canceltxpkts_handler = NULL;
+ ch->nmc_pnpevent_handler = NULL;
+ }
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+static ndis_status
+NdisAllocateMemoryWithTag(vaddr, len, tag)
+ void **vaddr;
+ uint32_t len;
+ uint32_t tag;
+{
+ void *mem;
+
+ mem = ExAllocatePoolWithTag(NonPagedPool, len, tag);
+ if (mem == NULL) {
+ return (NDIS_STATUS_RESOURCES);
+ }
+ *vaddr = mem;
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+static ndis_status
+NdisAllocateMemory(vaddr, len, flags, highaddr)
+ void **vaddr;
+ uint32_t len;
+ uint32_t flags;
+ ndis_physaddr highaddr;
+{
+ void *mem;
+
+ mem = ExAllocatePoolWithTag(NonPagedPool, len, 0);
+ if (mem == NULL)
+ return (NDIS_STATUS_RESOURCES);
+ *vaddr = mem;
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+static void
+NdisFreeMemory(vaddr, len, flags)
+ void *vaddr;
+ uint32_t len;
+ uint32_t flags;
+{
+ if (len == 0)
+ return;
+
+ ExFreePool(vaddr);
+}
+
+static ndis_status
+NdisMSetAttributesEx(adapter_handle, adapter_ctx, hangsecs,
+ flags, iftype)
+ ndis_handle adapter_handle;
+ ndis_handle adapter_ctx;
+ uint32_t hangsecs;
+ uint32_t flags;
+ ndis_interface_type iftype;
+{
+ ndis_miniport_block *block;
+
+ /*
+ * Save the adapter context, we need it for calling
+ * the driver's internal functions.
+ */
+ block = (ndis_miniport_block *)adapter_handle;
+ block->nmb_miniportadapterctx = adapter_ctx;
+ block->nmb_checkforhangsecs = hangsecs;
+ block->nmb_flags = flags;
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+static void
+NdisOpenConfiguration(status, cfg, wrapctx)
+ ndis_status *status;
+ ndis_handle *cfg;
+ ndis_handle wrapctx;
+{
+ *cfg = wrapctx;
+ *status = NDIS_STATUS_SUCCESS;
+}
+
+static void
+NdisOpenConfigurationKeyByName(status, cfg, subkey, subhandle)
+ ndis_status *status;
+ ndis_handle cfg;
+ unicode_string *subkey;
+ ndis_handle *subhandle;
+{
+ *subhandle = cfg;
+ *status = NDIS_STATUS_SUCCESS;
+}
+
+static void
+NdisOpenConfigurationKeyByIndex(status, cfg, idx, subkey, subhandle)
+ ndis_status *status;
+ ndis_handle cfg;
+ uint32_t idx;
+ unicode_string *subkey;
+ ndis_handle *subhandle;
+{
+ *status = NDIS_STATUS_FAILURE;
+}
+
+static ndis_status
+ndis_encode_parm(block, oid, type, parm)
+ ndis_miniport_block *block;
+ struct sysctl_oid *oid;
+ ndis_parm_type type;
+ ndis_config_parm **parm;
+{
+ ndis_config_parm *p;
+ ndis_parmlist_entry *np;
+ unicode_string *us;
+ ansi_string as;
+ int base = 0;
+ uint32_t val;
+ char tmp[32];
+
+ np = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(ndis_parmlist_entry), 0);
+ if (np == NULL)
+ return (NDIS_STATUS_RESOURCES);
+ InsertHeadList((&block->nmb_parmlist), (&np->np_list));
+ *parm = p = &np->np_parm;
+
+ switch(type) {
+ case ndis_parm_string:
+ /* See if this might be a number. */
+ val = strtoul((char *)oid->oid_arg1, NULL, 10);
+ us = &p->ncp_parmdata.ncp_stringdata;
+ p->ncp_type = ndis_parm_string;
+ if (val) {
+ snprintf(tmp, 32, "%x", val);
+ RtlInitAnsiString(&as, tmp);
+ } else {
+ RtlInitAnsiString(&as, (char *)oid->oid_arg1);
+ }
+
+ if (RtlAnsiStringToUnicodeString(us, &as, TRUE)) {
+ ExFreePool(np);
+ return (NDIS_STATUS_RESOURCES);
+ }
+ break;
+ case ndis_parm_int:
+ if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0)
+ base = 16;
+ else
+ base = 10;
+ p->ncp_type = ndis_parm_int;
+ p->ncp_parmdata.ncp_intdata =
+ strtol((char *)oid->oid_arg1, NULL, base);
+ break;
+ case ndis_parm_hexint:
+#ifdef notdef
+ if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0)
+ base = 16;
+ else
+ base = 10;
+#endif
+ base = 16;
+ p->ncp_type = ndis_parm_hexint;
+ p->ncp_parmdata.ncp_intdata =
+ strtoul((char *)oid->oid_arg1, NULL, base);
+ break;
+ default:
+ return (NDIS_STATUS_FAILURE);
+ break;
+ }
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+static void
+NdisReadConfiguration(status, parm, cfg, key, type)
+ ndis_status *status;
+ ndis_config_parm **parm;
+ ndis_handle cfg;
+ unicode_string *key;
+ ndis_parm_type type;
+{
+ char *keystr = NULL;
+ ndis_miniport_block *block;
+ struct ndis_softc *sc;
+ struct sysctl_oid *oidp;
+ struct sysctl_ctx_entry *e;
+ ansi_string as;
+
+ block = (ndis_miniport_block *)cfg;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+
+ if (key->us_len == 0 || key->us_buf == NULL) {
+ *status = NDIS_STATUS_FAILURE;
+ return;
+ }
+
+ if (RtlUnicodeStringToAnsiString(&as, key, TRUE)) {
+ *status = NDIS_STATUS_RESOURCES;
+ return;
+ }
+
+ keystr = as.as_buf;
+
+ /*
+ * See if registry key is already in a list of known keys
+ * included with the driver.
+ */
+ TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) {
+ oidp = e->entry;
+ if (strcasecmp(oidp->oid_name, keystr) == 0) {
+ if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) {
+ RtlFreeAnsiString(&as);
+ *status = NDIS_STATUS_FAILURE;
+ return;
+ }
+
+ *status = ndis_encode_parm(block, oidp, type, parm);
+ RtlFreeAnsiString(&as);
+ return;
+ }
+ }
+
+ /*
+ * If the key didn't match, add it to the list of dynamically
+ * created ones. Sometimes, drivers refer to registry keys
+ * that aren't documented in their .INF files. These keys
+ * are supposed to be created by some sort of utility or
+ * control panel snap-in that comes with the driver software.
+ * Sometimes it's useful to be able to manipulate these.
+ * If the driver requests the key in the form of a string,
+ * make its default value an empty string, otherwise default
+ * it to "0".
+ */
+
+ if (type == ndis_parm_int || type == ndis_parm_hexint)
+ ndis_add_sysctl(sc, keystr, "(dynamic integer key)",
+ "UNSET", CTLFLAG_RW);
+ else
+ ndis_add_sysctl(sc, keystr, "(dynamic string key)",
+ "UNSET", CTLFLAG_RW);
+
+ RtlFreeAnsiString(&as);
+ *status = NDIS_STATUS_FAILURE;
+}
+
+static ndis_status
+ndis_decode_parm(block, parm, val)
+ ndis_miniport_block *block;
+ ndis_config_parm *parm;
+ char *val;
+{
+ unicode_string *ustr;
+ ansi_string as;
+
+ switch(parm->ncp_type) {
+ case ndis_parm_string:
+ ustr = &parm->ncp_parmdata.ncp_stringdata;
+ if (RtlUnicodeStringToAnsiString(&as, ustr, TRUE))
+ return (NDIS_STATUS_RESOURCES);
+ bcopy(as.as_buf, val, as.as_len);
+ RtlFreeAnsiString(&as);
+ break;
+ case ndis_parm_int:
+ sprintf(val, "%d", parm->ncp_parmdata.ncp_intdata);
+ break;
+ case ndis_parm_hexint:
+ sprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata);
+ break;
+ default:
+ return (NDIS_STATUS_FAILURE);
+ break;
+ }
+ return (NDIS_STATUS_SUCCESS);
+}
+
+static void
+NdisWriteConfiguration(status, cfg, key, parm)
+ ndis_status *status;
+ ndis_handle cfg;
+ unicode_string *key;
+ ndis_config_parm *parm;
+{
+ ansi_string as;
+ char *keystr = NULL;
+ ndis_miniport_block *block;
+ struct ndis_softc *sc;
+ struct sysctl_oid *oidp;
+ struct sysctl_ctx_entry *e;
+ char val[256];
+
+ block = (ndis_miniport_block *)cfg;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+
+ if (RtlUnicodeStringToAnsiString(&as, key, TRUE)) {
+ *status = NDIS_STATUS_RESOURCES;
+ return;
+ }
+
+ keystr = as.as_buf;
+
+ /* Decode the parameter into a string. */
+ bzero(val, sizeof(val));
+ *status = ndis_decode_parm(block, parm, val);
+ if (*status != NDIS_STATUS_SUCCESS) {
+ RtlFreeAnsiString(&as);
+ return;
+ }
+
+ /* See if the key already exists. */
+
+ TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) {
+ oidp = e->entry;
+ if (strcasecmp(oidp->oid_name, keystr) == 0) {
+ /* Found it, set the value. */
+ strcpy((char *)oidp->oid_arg1, val);
+ RtlFreeAnsiString(&as);
+ return;
+ }
+ }
+
+ /* Not found, add a new key with the specified value. */
+ ndis_add_sysctl(sc, keystr, "(dynamically set key)",
+ val, CTLFLAG_RW);
+
+ RtlFreeAnsiString(&as);
+ *status = NDIS_STATUS_SUCCESS;
+}
+
+static void
+NdisCloseConfiguration(cfg)
+ ndis_handle cfg;
+{
+ list_entry *e;
+ ndis_parmlist_entry *pe;
+ ndis_miniport_block *block;
+ ndis_config_parm *p;
+
+ block = (ndis_miniport_block *)cfg;
+
+ while (!IsListEmpty(&block->nmb_parmlist)) {
+ e = RemoveHeadList(&block->nmb_parmlist);
+ pe = CONTAINING_RECORD(e, ndis_parmlist_entry, np_list);
+ p = &pe->np_parm;
+ if (p->ncp_type == ndis_parm_string)
+ RtlFreeUnicodeString(&p->ncp_parmdata.ncp_stringdata);
+ ExFreePool(e);
+ }
+}
+
+/*
+ * Initialize a Windows spinlock.
+ */
+static void
+NdisAllocateSpinLock(lock)
+ ndis_spin_lock *lock;
+{
+ KeInitializeSpinLock(&lock->nsl_spinlock);
+ lock->nsl_kirql = 0;
+}
+
+/*
+ * Destroy a Windows spinlock. This is a no-op for now. There are two reasons
+ * for this. One is that it's sort of superfluous: we don't have to do anything
+ * special to deallocate the spinlock. The other is that there are some buggy
+ * drivers which call NdisFreeSpinLock() _after_ calling NdisFreeMemory() on
+ * the block of memory in which the spinlock resides. (Yes, ADMtek, I'm
+ * talking to you.)
+ */
+static void
+NdisFreeSpinLock(lock)
+ ndis_spin_lock *lock;
+{
+#ifdef notdef
+ KeInitializeSpinLock(&lock->nsl_spinlock);
+ lock->nsl_kirql = 0;
+#endif
+}
+
+/*
+ * Acquire a spinlock from IRQL <= DISPATCH_LEVEL.
+ */
+
+static void
+NdisAcquireSpinLock(lock)
+ ndis_spin_lock *lock;
+{
+ KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql);
+}
+
+/*
+ * Release a spinlock from IRQL == DISPATCH_LEVEL.
+ */
+
+static void
+NdisReleaseSpinLock(lock)
+ ndis_spin_lock *lock;
+{
+ KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql);
+}
+
+/*
+ * Acquire a spinlock when already running at IRQL == DISPATCH_LEVEL.
+ */
+static void
+NdisDprAcquireSpinLock(lock)
+ ndis_spin_lock *lock;
+{
+ KeAcquireSpinLockAtDpcLevel(&lock->nsl_spinlock);
+}
+
+/*
+ * Release a spinlock without leaving IRQL == DISPATCH_LEVEL.
+ */
+static void
+NdisDprReleaseSpinLock(lock)
+ ndis_spin_lock *lock;
+{
+ KeReleaseSpinLockFromDpcLevel(&lock->nsl_spinlock);
+}
+
+static void
+NdisInitializeReadWriteLock(lock)
+ ndis_rw_lock *lock;
+{
+ KeInitializeSpinLock(&lock->nrl_spinlock);
+ bzero((char *)&lock->nrl_rsvd, sizeof(lock->nrl_rsvd));
+}
+
+static void
+NdisAcquireReadWriteLock(ndis_rw_lock *lock, uint8_t writeacc,
+ ndis_lock_state *state)
+{
+ if (writeacc == TRUE) {
+ KeAcquireSpinLock(&lock->nrl_spinlock, &state->nls_oldirql);
+ lock->nrl_rsvd[0]++;
+ } else
+ lock->nrl_rsvd[1]++;
+}
+
+static void
+NdisReleaseReadWriteLock(lock, state)
+ ndis_rw_lock *lock;
+ ndis_lock_state *state;
+{
+ if (lock->nrl_rsvd[0]) {
+ lock->nrl_rsvd[0]--;
+ KeReleaseSpinLock(&lock->nrl_spinlock, state->nls_oldirql);
+ } else
+ lock->nrl_rsvd[1]--;
+}
+
+static uint32_t
+NdisReadPciSlotInformation(adapter, slot, offset, buf, len)
+ ndis_handle adapter;
+ uint32_t slot;
+ uint32_t offset;
+ void *buf;
+ uint32_t len;
+{
+ ndis_miniport_block *block;
+ int i;
+ char *dest;
+ device_t dev;
+
+ block = (ndis_miniport_block *)adapter;
+ dest = buf;
+ if (block == NULL)
+ return (0);
+
+ dev = block->nmb_physdeviceobj->do_devext;
+
+ /*
+ * I have a test system consisting of a Sun w2100z
+ * dual 2.4Ghz Opteron machine and an Atheros 802.11a/b/g
+ * "Aries" miniPCI NIC. (The NIC is installed in the
+ * machine using a miniPCI to PCI bus adapter card.)
+ * When running in SMP mode, I found that
+ * performing a large number of consecutive calls to
+ * NdisReadPciSlotInformation() would result in a
+ * sudden system reset (or in some cases a freeze).
+ * My suspicion is that the multiple reads are somehow
+ * triggering a fatal PCI bus error that leads to a
+ * machine check. The 1us delay in the loop below
+ * seems to prevent this problem.
+ */
+
+ for (i = 0; i < len; i++) {
+ DELAY(1);
+ dest[i] = pci_read_config(dev, i + offset, 1);
+ }
+
+ return (len);
+}
+
+static uint32_t
+NdisWritePciSlotInformation(adapter, slot, offset, buf, len)
+ ndis_handle adapter;
+ uint32_t slot;
+ uint32_t offset;
+ void *buf;
+ uint32_t len;
+{
+ ndis_miniport_block *block;
+ int i;
+ char *dest;
+ device_t dev;
+
+ block = (ndis_miniport_block *)adapter;
+ dest = buf;
+
+ if (block == NULL)
+ return (0);
+
+ dev = block->nmb_physdeviceobj->do_devext;
+ for (i = 0; i < len; i++) {
+ DELAY(1);
+ pci_write_config(dev, i + offset, dest[i], 1);
+ }
+
+ return (len);
+}
+
+/*
+ * The errorlog routine uses a variable argument list, so we
+ * have to declare it this way.
+ */
+
+#define ERRMSGLEN 512
+static void
+NdisWriteErrorLogEntry(ndis_handle adapter, ndis_error_code code,
+ uint32_t numerrors, ...)
+{
+ ndis_miniport_block *block;
+ va_list ap;
+ int i, error;
+ char *str = NULL;
+ uint16_t flags;
+ device_t dev;
+ driver_object *drv;
+ struct ndis_softc *sc;
+ struct ifnet *ifp;
+ unicode_string us;
+ ansi_string as = { 0, 0, NULL };
+
+ block = (ndis_miniport_block *)adapter;
+ dev = block->nmb_physdeviceobj->do_devext;
+ drv = block->nmb_deviceobj->do_drvobj;
+ sc = device_get_softc(dev);
+ ifp = sc->ifp;
+
+ if (ifp != NULL && ifp->if_flags & IFF_DEBUG) {
+ error = pe_get_message((vm_offset_t)drv->dro_driverstart,
+ code, &str, &i, &flags);
+ if (error == 0) {
+ if (flags & MESSAGE_RESOURCE_UNICODE) {
+ RtlInitUnicodeString(&us, (uint16_t *)str);
+ if (RtlUnicodeStringToAnsiString(&as,
+ &us, TRUE) == STATUS_SUCCESS)
+ str = as.as_buf;
+ else
+ str = NULL;
+ }
+ }
+ }
+
+ device_printf(dev, "NDIS ERROR: %x (%s)\n", code,
+ str == NULL ? "unknown error" : str);
+
+ if (ifp != NULL && ifp->if_flags & IFF_DEBUG) {
+ device_printf(dev, "NDIS NUMERRORS: %x\n", numerrors);
+ va_start(ap, numerrors);
+ for (i = 0; i < numerrors; i++)
+ device_printf(dev, "argptr: %p\n",
+ va_arg(ap, void *));
+ va_end(ap);
+ }
+
+ if (as.as_len)
+ RtlFreeAnsiString(&as);
+}
+
+static void
+ndis_map_cb(arg, segs, nseg, error)
+ void *arg;
+ bus_dma_segment_t *segs;
+ int nseg;
+ int error;
+{
+ struct ndis_map_arg *ctx;
+ int i;
+
+ if (error)
+ return;
+
+ ctx = arg;
+
+ for (i = 0; i < nseg; i++) {
+ ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr;
+ ctx->nma_fraglist[i].npu_len = segs[i].ds_len;
+ }
+
+ ctx->nma_cnt = nseg;
+}
+
+static void
+NdisMStartBufferPhysicalMapping(ndis_handle adapter, ndis_buffer *buf,
+ uint32_t mapreg, uint8_t writedev, ndis_paddr_unit *addrarray,
+ uint32_t *arraysize)
+{
+ ndis_miniport_block *block;
+ struct ndis_softc *sc;
+ struct ndis_map_arg nma;
+ bus_dmamap_t map;
+ int error;
+
+ if (adapter == NULL)
+ return;
+
+ block = (ndis_miniport_block *)adapter;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+
+ if (mapreg > sc->ndis_mmapcnt)
+ return;
+
+ map = sc->ndis_mmaps[mapreg];
+ nma.nma_fraglist = addrarray;
+
+ error = bus_dmamap_load(sc->ndis_mtag, map,
+ MmGetMdlVirtualAddress(buf), MmGetMdlByteCount(buf), ndis_map_cb,
+ (void *)&nma, BUS_DMA_NOWAIT);
+
+ if (error)
+ return;
+
+ bus_dmamap_sync(sc->ndis_mtag, map,
+ writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
+
+ *arraysize = nma.nma_cnt;
+}
+
+static void
+NdisMCompleteBufferPhysicalMapping(adapter, buf, mapreg)
+ ndis_handle adapter;
+ ndis_buffer *buf;
+ uint32_t mapreg;
+{
+ ndis_miniport_block *block;
+ struct ndis_softc *sc;
+ bus_dmamap_t map;
+
+ if (adapter == NULL)
+ return;
+
+ block = (ndis_miniport_block *)adapter;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+
+ if (mapreg > sc->ndis_mmapcnt)
+ return;
+
+ map = sc->ndis_mmaps[mapreg];
+
+ bus_dmamap_sync(sc->ndis_mtag, map,
+ BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+
+ bus_dmamap_unload(sc->ndis_mtag, map);
+}
+
+/*
+ * This is an older (?) timer init routine which doesn't
+ * accept a miniport context handle. Serialized miniports should
+ * never call this function.
+ */
+
+static void
+NdisInitializeTimer(timer, func, ctx)
+ ndis_timer *timer;
+ ndis_timer_function func;
+ void *ctx;
+{
+ KeInitializeTimer(&timer->nt_ktimer);
+ KeInitializeDpc(&timer->nt_kdpc, func, ctx);
+ KeSetImportanceDpc(&timer->nt_kdpc, KDPC_IMPORTANCE_LOW);
+}
+
+static void
+ndis_timercall(dpc, timer, sysarg1, sysarg2)
+ kdpc *dpc;
+ ndis_miniport_timer *timer;
+ void *sysarg1;
+ void *sysarg2;
+{
+ /*
+ * Since we're called as a DPC, we should be running
+ * at DISPATCH_LEVEL here. This means to acquire the
+ * spinlock, we can use KeAcquireSpinLockAtDpcLevel()
+ * rather than KeAcquireSpinLock().
+ */
+ if (NDIS_SERIALIZED(timer->nmt_block))
+ KeAcquireSpinLockAtDpcLevel(&timer->nmt_block->nmb_lock);
+
+ MSCALL4(timer->nmt_timerfunc, dpc, timer->nmt_timerctx,
+ sysarg1, sysarg2);
+
+ if (NDIS_SERIALIZED(timer->nmt_block))
+ KeReleaseSpinLockFromDpcLevel(&timer->nmt_block->nmb_lock);
+}
+
+/*
+ * For a long time I wondered why there were two NDIS timer initialization
+ * routines, and why this one needed an NDIS_MINIPORT_TIMER and the
+ * MiniportAdapterHandle. The NDIS_MINIPORT_TIMER has its own callout
+ * function and context pointers separate from those in the DPC, which
+ * allows for another level of indirection: when the timer fires, we
+ * can have our own timer function invoked, and from there we can call
+ * the driver's function. But why go to all that trouble? Then it hit
+ * me: for serialized miniports, the timer callouts are not re-entrant.
+ * By trapping the callouts and having access to the MiniportAdapterHandle,
+ * we can protect the driver callouts by acquiring the NDIS serialization
+ * lock. This is essential for allowing serialized miniports to work
+ * correctly on SMP systems. On UP hosts, setting IRQL to DISPATCH_LEVEL
+ * is enough to prevent other threads from pre-empting you, but with
+ * SMP, you must acquire a lock as well, otherwise the other CPU is
+ * free to clobber you.
+ */
+static void
+NdisMInitializeTimer(timer, handle, func, ctx)
+ ndis_miniport_timer *timer;
+ ndis_handle handle;
+ ndis_timer_function func;
+ void *ctx;
+{
+ ndis_miniport_block *block;
+ struct ndis_softc *sc;
+
+ block = (ndis_miniport_block *)handle;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+
+ /* Save the driver's funcptr and context */
+
+ timer->nmt_timerfunc = func;
+ timer->nmt_timerctx = ctx;
+ timer->nmt_block = handle;
+
+ /*
+ * Set up the timer so it will call our intermediate DPC.
+ * Be sure to use the wrapped entry point, since
+ * ntoskrnl_run_dpc() expects to invoke a function with
+ * Microsoft calling conventions.
+ */
+ KeInitializeTimer(&timer->nmt_ktimer);
+ KeInitializeDpc(&timer->nmt_kdpc,
+ ndis_findwrap((funcptr)ndis_timercall), timer);
+ timer->nmt_ktimer.k_dpc = &timer->nmt_kdpc;
+}
+
+/*
+ * In Windows, there's both an NdisMSetTimer() and an NdisSetTimer(),
+ * but the former is just a macro wrapper around the latter.
+ */
+static void
+NdisSetTimer(timer, msecs)
+ ndis_timer *timer;
+ uint32_t msecs;
+{
+ /*
+ * KeSetTimer() wants the period in
+ * hundred nanosecond intervals.
+ */
+ KeSetTimer(&timer->nt_ktimer,
+ ((int64_t)msecs * -10000), &timer->nt_kdpc);
+}
+
+static void
+NdisMSetPeriodicTimer(timer, msecs)
+ ndis_miniport_timer *timer;
+ uint32_t msecs;
+{
+ KeSetTimerEx(&timer->nmt_ktimer,
+ ((int64_t)msecs * -10000), msecs, &timer->nmt_kdpc);
+}
+
+/*
+ * Technically, this is really NdisCancelTimer(), but we also
+ * (ab)use it for NdisMCancelTimer(), since in our implementation
+ * we don't need the extra info in the ndis_miniport_timer
+ * structure just to cancel a timer.
+ */
+
+static void
+NdisMCancelTimer(timer, cancelled)
+ ndis_timer *timer;
+ uint8_t *cancelled;
+{
+
+ *cancelled = KeCancelTimer(&timer->nt_ktimer);
+}
+
+static void
+NdisMQueryAdapterResources(status, adapter, list, buflen)
+ ndis_status *status;
+ ndis_handle adapter;
+ ndis_resource_list *list;
+ uint32_t *buflen;
+{
+ ndis_miniport_block *block;
+ struct ndis_softc *sc;
+ int rsclen;
+
+ block = (ndis_miniport_block *)adapter;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+
+ rsclen = sizeof(ndis_resource_list) +
+ (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1));
+ if (*buflen < rsclen) {
+ *buflen = rsclen;
+ *status = NDIS_STATUS_INVALID_LENGTH;
+ return;
+ }
+
+ bcopy((char *)block->nmb_rlist, (char *)list, rsclen);
+ *status = NDIS_STATUS_SUCCESS;
+}
+
+static ndis_status
+NdisMRegisterIoPortRange(offset, adapter, port, numports)
+ void **offset;
+ ndis_handle adapter;
+ uint32_t port;
+ uint32_t numports;
+{
+ struct ndis_miniport_block *block;
+ struct ndis_softc *sc;
+
+ if (adapter == NULL)
+ return (NDIS_STATUS_FAILURE);
+
+ block = (ndis_miniport_block *)adapter;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+
+ if (sc->ndis_res_io == NULL)
+ return (NDIS_STATUS_FAILURE);
+
+ /* Don't let the device map more ports than we have. */
+ if (rman_get_size(sc->ndis_res_io) < numports)
+ return (NDIS_STATUS_INVALID_LENGTH);
+
+ *offset = (void *)rman_get_start(sc->ndis_res_io);
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+static void
+NdisMDeregisterIoPortRange(adapter, port, numports, offset)
+ ndis_handle adapter;
+ uint32_t port;
+ uint32_t numports;
+ void *offset;
+{
+}
+
+static void
+NdisReadNetworkAddress(status, addr, addrlen, adapter)
+ ndis_status *status;
+ void **addr;
+ uint32_t *addrlen;
+ ndis_handle adapter;
+{
+ struct ndis_softc *sc;
+ ndis_miniport_block *block;
+ uint8_t empty[] = { 0, 0, 0, 0, 0, 0 };
+
+ block = (ndis_miniport_block *)adapter;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+ if (sc->ifp == NULL) {
+ *status = NDIS_STATUS_FAILURE;
+ return;
+ }
+
+ if (sc->ifp->if_addr == NULL ||
+ bcmp(IF_LLADDR(sc->ifp), empty, ETHER_ADDR_LEN) == 0)
+ *status = NDIS_STATUS_FAILURE;
+ else {
+ *addr = IF_LLADDR(sc->ifp);
+ *addrlen = ETHER_ADDR_LEN;
+ *status = NDIS_STATUS_SUCCESS;
+ }
+}
+
+static ndis_status
+NdisQueryMapRegisterCount(bustype, cnt)
+ uint32_t bustype;
+ uint32_t *cnt;
+{
+ *cnt = 8192;
+ return (NDIS_STATUS_SUCCESS);
+}
+
+static ndis_status
+NdisMAllocateMapRegisters(ndis_handle adapter, uint32_t dmachannel,
+ uint8_t dmasize, uint32_t physmapneeded, uint32_t maxmap)
+{
+ struct ndis_softc *sc;
+ ndis_miniport_block *block;
+ int error, i, nseg = NDIS_MAXSEG;
+
+ block = (ndis_miniport_block *)adapter;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+
+ sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded,
+ M_DEVBUF, M_NOWAIT|M_ZERO);
+
+ if (sc->ndis_mmaps == NULL)
+ return (NDIS_STATUS_RESOURCES);
+
+ error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
+ NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW,
+ NULL, NULL, &sc->ndis_mtag);
+
+ if (error) {
+ free(sc->ndis_mmaps, M_DEVBUF);
+ return (NDIS_STATUS_RESOURCES);
+ }
+
+ for (i = 0; i < physmapneeded; i++)
+ bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]);
+
+ sc->ndis_mmapcnt = physmapneeded;
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+static void
+NdisMFreeMapRegisters(adapter)
+ ndis_handle adapter;
+{
+ struct ndis_softc *sc;
+ ndis_miniport_block *block;
+ int i;
+
+ block = (ndis_miniport_block *)adapter;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+
+ for (i = 0; i < sc->ndis_mmapcnt; i++)
+ bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]);
+
+ free(sc->ndis_mmaps, M_DEVBUF);
+
+ bus_dma_tag_destroy(sc->ndis_mtag);
+}
+
+static void
+ndis_mapshared_cb(arg, segs, nseg, error)
+ void *arg;
+ bus_dma_segment_t *segs;
+ int nseg;
+ int error;
+{
+ ndis_physaddr *p;
+
+ if (error || nseg > 1)
+ return;
+
+ p = arg;
+
+ p->np_quad = segs[0].ds_addr;
+}
+
+/*
+ * This maps to bus_dmamem_alloc().
+ */
+
+static void
+NdisMAllocateSharedMemory(ndis_handle adapter, uint32_t len, uint8_t cached,
+ void **vaddr, ndis_physaddr *paddr)
+{
+ ndis_miniport_block *block;
+ struct ndis_softc *sc;
+ struct ndis_shmem *sh;
+ int error;
+
+ if (adapter == NULL)
+ return;
+
+ block = (ndis_miniport_block *)adapter;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+
+ sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO);
+ if (sh == NULL)
+ return;
+
+ InitializeListHead(&sh->ndis_list);
+
+ /*
+ * When performing shared memory allocations, create a tag
+ * with a lowaddr limit that restricts physical memory mappings
+ * so that they all fall within the first 1GB of memory.
+ * At least one device/driver combination (Linksys Instant
+ * Wireless PCI Card V2.7, Broadcom 802.11b) seems to have
+ * problems with performing DMA operations with physical
+ * addresses that lie above the 1GB mark. I don't know if this
+ * is a hardware limitation or if the addresses are being
+ * truncated within the driver, but this seems to be the only
+ * way to make these cards work reliably in systems with more
+ * than 1GB of physical memory.
+ */
+
+ error = bus_dma_tag_create(sc->ndis_parent_tag, 64,
+ 0, NDIS_BUS_SPACE_SHARED_MAXADDR, BUS_SPACE_MAXADDR, NULL,
+ NULL, len, 1, len, BUS_DMA_ALLOCNOW, NULL, NULL,
+ &sh->ndis_stag);
+
+ if (error) {
+ free(sh, M_DEVBUF);
+ return;
+ }
+
+ error = bus_dmamem_alloc(sh->ndis_stag, vaddr,
+ BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap);
+
+ if (error) {
+ bus_dma_tag_destroy(sh->ndis_stag);
+ free(sh, M_DEVBUF);
+ return;
+ }
+
+ error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr,
+ len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT);
+
+ if (error) {
+ bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap);
+ bus_dma_tag_destroy(sh->ndis_stag);
+ free(sh, M_DEVBUF);
+ return;
+ }
+
+ /*
+ * Save the physical address along with the source address.
+ * The AirGo MIMO driver will call NdisMFreeSharedMemory()
+ * with a bogus virtual address sometimes, but with a valid
+ * physical address. To keep this from causing trouble, we
+ * use the physical address to as a sanity check in case
+ * searching based on the virtual address fails.
+ */
+
+ NDIS_LOCK(sc);
+ sh->ndis_paddr.np_quad = paddr->np_quad;
+ sh->ndis_saddr = *vaddr;
+ InsertHeadList((&sc->ndis_shlist), (&sh->ndis_list));
+ NDIS_UNLOCK(sc);
+}
+
+struct ndis_allocwork {
+ uint32_t na_len;
+ uint8_t na_cached;
+ void *na_ctx;
+ io_workitem *na_iw;
+};
+
+static void
+ndis_asyncmem_complete(dobj, arg)
+ device_object *dobj;
+ void *arg;
+{
+ ndis_miniport_block *block;
+ struct ndis_softc *sc;
+ struct ndis_allocwork *w;
+ void *vaddr;
+ ndis_physaddr paddr;
+ ndis_allocdone_handler donefunc;
+
+ w = arg;
+ block = (ndis_miniport_block *)dobj->do_devext;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+
+ vaddr = NULL;
+ paddr.np_quad = 0;
+
+ donefunc = sc->ndis_chars->nmc_allocate_complete_func;
+ NdisMAllocateSharedMemory(block, w->na_len,
+ w->na_cached, &vaddr, &paddr);
+ MSCALL5(donefunc, block, vaddr, &paddr, w->na_len, w->na_ctx);
+
+ IoFreeWorkItem(w->na_iw);
+ free(w, M_DEVBUF);
+}
+
+static ndis_status
+NdisMAllocateSharedMemoryAsync(ndis_handle adapter, uint32_t len,
+ uint8_t cached, void *ctx)
+{
+ ndis_miniport_block *block;
+ struct ndis_allocwork *w;
+ io_workitem *iw;
+ io_workitem_func ifw;
+
+ if (adapter == NULL)
+ return (NDIS_STATUS_FAILURE);
+
+ block = adapter;
+
+ iw = IoAllocateWorkItem(block->nmb_deviceobj);
+ if (iw == NULL)
+ return (NDIS_STATUS_FAILURE);
+
+ w = malloc(sizeof(struct ndis_allocwork), M_TEMP, M_NOWAIT);
+
+ if (w == NULL)
+ return (NDIS_STATUS_FAILURE);
+
+ w->na_cached = cached;
+ w->na_len = len;
+ w->na_ctx = ctx;
+ w->na_iw = iw;
+
+ ifw = (io_workitem_func)ndis_findwrap((funcptr)ndis_asyncmem_complete);
+ IoQueueWorkItem(iw, ifw, WORKQUEUE_DELAYED, w);
+
+ return (NDIS_STATUS_PENDING);
+}
+
+static void
+NdisMFreeSharedMemory(ndis_handle adapter, uint32_t len, uint8_t cached,
+ void *vaddr, ndis_physaddr paddr)
+{
+ ndis_miniport_block *block;
+ struct ndis_softc *sc;
+ struct ndis_shmem *sh = NULL;
+ list_entry *l;
+
+ if (vaddr == NULL || adapter == NULL)
+ return;
+
+ block = (ndis_miniport_block *)adapter;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+
+ /* Sanity check: is list empty? */
+
+ if (IsListEmpty(&sc->ndis_shlist))
+ return;
+
+ NDIS_LOCK(sc);
+ l = sc->ndis_shlist.nle_flink;
+ while (l != &sc->ndis_shlist) {
+ sh = CONTAINING_RECORD(l, struct ndis_shmem, ndis_list);
+ if (sh->ndis_saddr == vaddr)
+ break;
+ /*
+ * Check the physaddr too, just in case the driver lied
+ * about the virtual address.
+ */
+ if (sh->ndis_paddr.np_quad == paddr.np_quad)
+ break;
+ l = l->nle_flink;
+ }
+
+ if (sh == NULL) {
+ NDIS_UNLOCK(sc);
+ printf("NDIS: buggy driver tried to free "
+ "invalid shared memory: vaddr: %p paddr: 0x%jx\n",
+ vaddr, (uintmax_t)paddr.np_quad);
+ return;
+ }
+
+ RemoveEntryList(&sh->ndis_list);
+
+ NDIS_UNLOCK(sc);
+
+ bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap);
+ bus_dmamem_free(sh->ndis_stag, sh->ndis_saddr, sh->ndis_smap);
+ bus_dma_tag_destroy(sh->ndis_stag);
+
+ free(sh, M_DEVBUF);
+}
+
+static ndis_status
+NdisMMapIoSpace(vaddr, adapter, paddr, len)
+ void **vaddr;
+ ndis_handle adapter;
+ ndis_physaddr paddr;
+ uint32_t len;
+{
+ if (adapter == NULL)
+ return (NDIS_STATUS_FAILURE);
+
+ *vaddr = MmMapIoSpace(paddr.np_quad, len, 0);
+
+ if (*vaddr == NULL)
+ return (NDIS_STATUS_FAILURE);
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+static void
+NdisMUnmapIoSpace(adapter, vaddr, len)
+ ndis_handle adapter;
+ void *vaddr;
+ uint32_t len;
+{
+ MmUnmapIoSpace(vaddr, len);
+}
+
+static uint32_t
+NdisGetCacheFillSize(void)
+{
+ return (128);
+}
+
+static void *
+NdisGetRoutineAddress(ustr)
+ unicode_string *ustr;
+{
+ ansi_string astr;
+
+ if (RtlUnicodeStringToAnsiString(&astr, ustr, TRUE))
+ return (NULL);
+ return (ndis_get_routine_address(ndis_functbl, astr.as_buf));
+}
+
+static uint32_t
+NdisMGetDmaAlignment(handle)
+ ndis_handle handle;
+{
+ return (16);
+}
+
+/*
+ * NDIS has two methods for dealing with NICs that support DMA.
+ * One is to just pass packets to the driver and let it call
+ * NdisMStartBufferPhysicalMapping() to map each buffer in the packet
+ * all by itself, and the other is to let the NDIS library handle the
+ * buffer mapping internally, and hand the driver an already populated
+ * scatter/gather fragment list. If the driver calls
+ * NdisMInitializeScatterGatherDma(), it wants to use the latter
+ * method.
+ */
+
+static ndis_status
+NdisMInitializeScatterGatherDma(ndis_handle adapter, uint8_t is64,
+ uint32_t maxphysmap)
+{
+ struct ndis_softc *sc;
+ ndis_miniport_block *block;
+ int error;
+
+ if (adapter == NULL)
+ return (NDIS_STATUS_FAILURE);
+ block = (ndis_miniport_block *)adapter;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+
+ /* Don't do this twice. */
+ if (sc->ndis_sc == 1)
+ return (NDIS_STATUS_SUCCESS);
+
+ error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW,
+ NULL, NULL, &sc->ndis_ttag);
+
+ sc->ndis_sc = 1;
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+void
+NdisAllocatePacketPool(status, pool, descnum, protrsvdlen)
+ ndis_status *status;
+ ndis_handle *pool;
+ uint32_t descnum;
+ uint32_t protrsvdlen;
+{
+ ndis_packet_pool *p;
+ ndis_packet *packets;
+ int i;
+
+ p = ExAllocatePoolWithTag(NonPagedPool, sizeof(ndis_packet_pool), 0);
+ if (p == NULL) {
+ *status = NDIS_STATUS_RESOURCES;
+ return;
+ }
+
+ p->np_cnt = descnum + NDIS_POOL_EXTRA;
+ p->np_protrsvd = protrsvdlen;
+ p->np_len = sizeof(ndis_packet) + protrsvdlen;
+
+ packets = ExAllocatePoolWithTag(NonPagedPool, p->np_cnt *
+ p->np_len, 0);
+
+
+ if (packets == NULL) {
+ ExFreePool(p);
+ *status = NDIS_STATUS_RESOURCES;
+ return;
+ }
+
+ p->np_pktmem = packets;
+
+ for (i = 0; i < p->np_cnt; i++)
+ InterlockedPushEntrySList(&p->np_head,
+ (struct slist_entry *)&packets[i]);
+
+#ifdef NDIS_DEBUG_PACKETS
+ p->np_dead = 0;
+ KeInitializeSpinLock(&p->np_lock);
+ KeInitializeEvent(&p->np_event, EVENT_TYPE_NOTIFY, TRUE);
+#endif
+
+ *pool = p;
+ *status = NDIS_STATUS_SUCCESS;
+}
+
+void
+NdisAllocatePacketPoolEx(status, pool, descnum, oflowdescnum, protrsvdlen)
+ ndis_status *status;
+ ndis_handle *pool;
+ uint32_t descnum;
+ uint32_t oflowdescnum;
+ uint32_t protrsvdlen;
+{
+ return (NdisAllocatePacketPool(status, pool,
+ descnum + oflowdescnum, protrsvdlen));
+}
+
+uint32_t
+NdisPacketPoolUsage(pool)
+ ndis_handle pool;
+{
+ ndis_packet_pool *p;
+
+ p = (ndis_packet_pool *)pool;
+ return (p->np_cnt - ExQueryDepthSList(&p->np_head));
+}
+
+void
+NdisFreePacketPool(pool)
+ ndis_handle pool;
+{
+ ndis_packet_pool *p;
+ int usage;
+#ifdef NDIS_DEBUG_PACKETS
+ uint8_t irql;
+#endif
+
+ p = (ndis_packet_pool *)pool;
+
+#ifdef NDIS_DEBUG_PACKETS
+ KeAcquireSpinLock(&p->np_lock, &irql);
+#endif
+
+ usage = NdisPacketPoolUsage(pool);
+
+#ifdef NDIS_DEBUG_PACKETS
+ if (usage) {
+ p->np_dead = 1;
+ KeResetEvent(&p->np_event);
+ KeReleaseSpinLock(&p->np_lock, irql);
+ KeWaitForSingleObject(&p->np_event, 0, 0, FALSE, NULL);
+ } else
+ KeReleaseSpinLock(&p->np_lock, irql);
+#endif
+
+ ExFreePool(p->np_pktmem);
+ ExFreePool(p);
+}
+
+void
+NdisAllocatePacket(status, packet, pool)
+ ndis_status *status;
+ ndis_packet **packet;
+ ndis_handle pool;
+{
+ ndis_packet_pool *p;
+ ndis_packet *pkt;
+#ifdef NDIS_DEBUG_PACKETS
+ uint8_t irql;
+#endif
+
+ p = (ndis_packet_pool *)pool;
+
+#ifdef NDIS_DEBUG_PACKETS
+ KeAcquireSpinLock(&p->np_lock, &irql);
+ if (p->np_dead) {
+ KeReleaseSpinLock(&p->np_lock, irql);
+ printf("NDIS: tried to allocate packet from dead pool %p\n",
+ pool);
+ *status = NDIS_STATUS_RESOURCES;
+ return;
+ }
+#endif
+
+ pkt = (ndis_packet *)InterlockedPopEntrySList(&p->np_head);
+
+#ifdef NDIS_DEBUG_PACKETS
+ KeReleaseSpinLock(&p->np_lock, irql);
+#endif
+
+ if (pkt == NULL) {
+ *status = NDIS_STATUS_RESOURCES;
+ return;
+ }
+
+
+ bzero((char *)pkt, sizeof(ndis_packet));
+
+ /* Save pointer to the pool. */
+ pkt->np_private.npp_pool = pool;
+
+ /* Set the oob offset pointer. Lots of things expect this. */
+ pkt->np_private.npp_packetooboffset = offsetof(ndis_packet, np_oob);
+
+ /*
+ * We must initialize the packet flags correctly in order
+ * for the NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO() and
+ * NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO() macros to work
+ * correctly.
+ */
+ pkt->np_private.npp_ndispktflags = NDIS_PACKET_ALLOCATED_BY_NDIS;
+ pkt->np_private.npp_validcounts = FALSE;
+
+ *packet = pkt;
+
+ *status = NDIS_STATUS_SUCCESS;
+}
+
+void
+NdisFreePacket(packet)
+ ndis_packet *packet;
+{
+ ndis_packet_pool *p;
+#ifdef NDIS_DEBUG_PACKETS
+ uint8_t irql;
+#endif
+
+ p = (ndis_packet_pool *)packet->np_private.npp_pool;
+
+#ifdef NDIS_DEBUG_PACKETS
+ KeAcquireSpinLock(&p->np_lock, &irql);
+#endif
+
+ InterlockedPushEntrySList(&p->np_head, (slist_entry *)packet);
+
+#ifdef NDIS_DEBUG_PACKETS
+ if (p->np_dead) {
+ if (ExQueryDepthSList(&p->np_head) == p->np_cnt)
+ KeSetEvent(&p->np_event, IO_NO_INCREMENT, FALSE);
+ }
+ KeReleaseSpinLock(&p->np_lock, irql);
+#endif
+}
+
+static void
+NdisUnchainBufferAtFront(packet, buf)
+ ndis_packet *packet;
+ ndis_buffer **buf;
+{
+ ndis_packet_private *priv;
+
+ if (packet == NULL || buf == NULL)
+ return;
+
+ priv = &packet->np_private;
+
+ priv->npp_validcounts = FALSE;
+
+ if (priv->npp_head == priv->npp_tail) {
+ *buf = priv->npp_head;
+ priv->npp_head = priv->npp_tail = NULL;
+ } else {
+ *buf = priv->npp_head;
+ priv->npp_head = (*buf)->mdl_next;
+ }
+}
+
+static void
+NdisUnchainBufferAtBack(packet, buf)
+ ndis_packet *packet;
+ ndis_buffer **buf;
+{
+ ndis_packet_private *priv;
+ ndis_buffer *tmp;
+
+ if (packet == NULL || buf == NULL)
+ return;
+
+ priv = &packet->np_private;
+
+ priv->npp_validcounts = FALSE;
+
+ if (priv->npp_head == priv->npp_tail) {
+ *buf = priv->npp_head;
+ priv->npp_head = priv->npp_tail = NULL;
+ } else {
+ *buf = priv->npp_tail;
+ tmp = priv->npp_head;
+ while (tmp->mdl_next != priv->npp_tail)
+ tmp = tmp->mdl_next;
+ priv->npp_tail = tmp;
+ tmp->mdl_next = NULL;
+ }
+}
+
+/*
+ * The NDIS "buffer" is really an MDL (memory descriptor list)
+ * which is used to describe a buffer in a way that allows it
+ * to mapped into different contexts. We have to be careful how
+ * we handle them: in some versions of Windows, the NdisFreeBuffer()
+ * routine is an actual function in the NDIS API, but in others
+ * it's just a macro wrapper around IoFreeMdl(). There's really
+ * no way to use the 'descnum' parameter to count how many
+ * "buffers" are allocated since in order to use IoFreeMdl() to
+ * dispose of a buffer, we have to use IoAllocateMdl() to allocate
+ * them, and IoAllocateMdl() just grabs them out of the heap.
+ */
+
+static void
+NdisAllocateBufferPool(status, pool, descnum)
+ ndis_status *status;
+ ndis_handle *pool;
+ uint32_t descnum;
+{
+
+ /*
+ * The only thing we can really do here is verify that descnum
+ * is a reasonable value, but I really don't know what to check
+ * it against.
+ */
+
+ *pool = NonPagedPool;
+ *status = NDIS_STATUS_SUCCESS;
+}
+
+static void
+NdisFreeBufferPool(pool)
+ ndis_handle pool;
+{
+}
+
+static void
+NdisAllocateBuffer(status, buffer, pool, vaddr, len)
+ ndis_status *status;
+ ndis_buffer **buffer;
+ ndis_handle pool;
+ void *vaddr;
+ uint32_t len;
+{
+ ndis_buffer *buf;
+
+ buf = IoAllocateMdl(vaddr, len, FALSE, FALSE, NULL);
+ if (buf == NULL) {
+ *status = NDIS_STATUS_RESOURCES;
+ return;
+ }
+
+ MmBuildMdlForNonPagedPool(buf);
+
+ *buffer = buf;
+ *status = NDIS_STATUS_SUCCESS;
+}
+
+static void
+NdisFreeBuffer(buf)
+ ndis_buffer *buf;
+{
+ IoFreeMdl(buf);
+}
+
+/* Aw c'mon. */
+
+static uint32_t
+NdisBufferLength(buf)
+ ndis_buffer *buf;
+{
+ return (MmGetMdlByteCount(buf));
+}
+
+/*
+ * Get the virtual address and length of a buffer.
+ * Note: the vaddr argument is optional.
+ */
+
+static void
+NdisQueryBuffer(buf, vaddr, len)
+ ndis_buffer *buf;
+ void **vaddr;
+ uint32_t *len;
+{
+ if (vaddr != NULL)
+ *vaddr = MmGetMdlVirtualAddress(buf);
+ *len = MmGetMdlByteCount(buf);
+}
+
+/* Same as above -- we don't care about the priority. */
+
+static void
+NdisQueryBufferSafe(buf, vaddr, len, prio)
+ ndis_buffer *buf;
+ void **vaddr;
+ uint32_t *len;
+ uint32_t prio;
+{
+ if (vaddr != NULL)
+ *vaddr = MmGetMdlVirtualAddress(buf);
+ *len = MmGetMdlByteCount(buf);
+}
+
+/* Damnit Microsoft!! How many ways can you do the same thing?! */
+
+static void *
+NdisBufferVirtualAddress(buf)
+ ndis_buffer *buf;
+{
+ return (MmGetMdlVirtualAddress(buf));
+}
+
+static void *
+NdisBufferVirtualAddressSafe(buf, prio)
+ ndis_buffer *buf;
+ uint32_t prio;
+{
+ return (MmGetMdlVirtualAddress(buf));
+}
+
+static void
+NdisAdjustBufferLength(buf, len)
+ ndis_buffer *buf;
+ int len;
+{
+ MmGetMdlByteCount(buf) = len;
+}
+
+static uint32_t
+NdisInterlockedIncrement(addend)
+ uint32_t *addend;
+{
+ atomic_add_long((u_long *)addend, 1);
+ return (*addend);
+}
+
+static uint32_t
+NdisInterlockedDecrement(addend)
+ uint32_t *addend;
+{
+ atomic_subtract_long((u_long *)addend, 1);
+ return (*addend);
+}
+
+static uint32_t
+NdisGetVersion(void)
+{
+ return (0x00050001);
+}
+
+static void
+NdisInitializeEvent(event)
+ ndis_event *event;
+{
+ /*
+ * NDIS events are always notification
+ * events, and should be initialized to the
+ * not signaled state.
+ */
+ KeInitializeEvent(&event->ne_event, EVENT_TYPE_NOTIFY, FALSE);
+}
+
+static void
+NdisSetEvent(event)
+ ndis_event *event;
+{
+ KeSetEvent(&event->ne_event, IO_NO_INCREMENT, FALSE);
+}
+
+static void
+NdisResetEvent(event)
+ ndis_event *event;
+{
+ KeResetEvent(&event->ne_event);
+}
+
+static uint8_t
+NdisWaitEvent(event, msecs)
+ ndis_event *event;
+ uint32_t msecs;
+{
+ int64_t duetime;
+ uint32_t rval;
+
+ duetime = ((int64_t)msecs * -10000);
+ rval = KeWaitForSingleObject(event,
+ 0, 0, TRUE, msecs ? & duetime : NULL);
+
+ if (rval == STATUS_TIMEOUT)
+ return (FALSE);
+
+ return (TRUE);
+}
+
+static ndis_status
+NdisUnicodeStringToAnsiString(dstr, sstr)
+ ansi_string *dstr;
+ unicode_string *sstr;
+{
+ uint32_t rval;
+
+ rval = RtlUnicodeStringToAnsiString(dstr, sstr, FALSE);
+
+ if (rval == STATUS_INSUFFICIENT_RESOURCES)
+ return (NDIS_STATUS_RESOURCES);
+ if (rval)
+ return (NDIS_STATUS_FAILURE);
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+static ndis_status
+NdisAnsiStringToUnicodeString(dstr, sstr)
+ unicode_string *dstr;
+ ansi_string *sstr;
+{
+ uint32_t rval;
+
+ rval = RtlAnsiStringToUnicodeString(dstr, sstr, FALSE);
+
+ if (rval == STATUS_INSUFFICIENT_RESOURCES)
+ return (NDIS_STATUS_RESOURCES);
+ if (rval)
+ return (NDIS_STATUS_FAILURE);
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+static ndis_status
+NdisMPciAssignResources(adapter, slot, list)
+ ndis_handle adapter;
+ uint32_t slot;
+ ndis_resource_list **list;
+{
+ ndis_miniport_block *block;
+
+ if (adapter == NULL || list == NULL)
+ return (NDIS_STATUS_FAILURE);
+
+ block = (ndis_miniport_block *)adapter;
+ *list = block->nmb_rlist;
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+static uint8_t
+ndis_intr(iobj, arg)
+ kinterrupt *iobj;
+ void *arg;
+{
+ struct ndis_softc *sc;
+ uint8_t is_our_intr = FALSE;
+ int call_isr = 0;
+ ndis_miniport_interrupt *intr;
+
+ sc = arg;
+ intr = sc->ndis_block->nmb_interrupt;
+
+ if (intr == NULL || sc->ndis_block->nmb_miniportadapterctx == NULL)
+ return (FALSE);
+
+ if (sc->ndis_block->nmb_interrupt->ni_isrreq == TRUE)
+ MSCALL3(intr->ni_isrfunc, &is_our_intr, &call_isr,
+ sc->ndis_block->nmb_miniportadapterctx);
+ else {
+ MSCALL1(sc->ndis_chars->nmc_disable_interrupts_func,
+ sc->ndis_block->nmb_miniportadapterctx);
+ call_isr = 1;
+ }
+
+ if (call_isr)
+ IoRequestDpc(sc->ndis_block->nmb_deviceobj, NULL, sc);
+
+ return (is_our_intr);
+}
+
+static void
+ndis_intrhand(dpc, intr, sysarg1, sysarg2)
+ kdpc *dpc;
+ ndis_miniport_interrupt *intr;
+ void *sysarg1;
+ void *sysarg2;
+{
+ struct ndis_softc *sc;
+ ndis_miniport_block *block;
+ ndis_handle adapter;
+
+ block = intr->ni_block;
+ adapter = block->nmb_miniportadapterctx;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+
+ if (NDIS_SERIALIZED(sc->ndis_block))
+ KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
+
+ MSCALL1(intr->ni_dpcfunc, adapter);
+
+ /* If there's a MiniportEnableInterrupt() routine, call it. */
+
+ if (sc->ndis_chars->nmc_enable_interrupts_func != NULL)
+ MSCALL1(sc->ndis_chars->nmc_enable_interrupts_func, adapter);
+
+ if (NDIS_SERIALIZED(sc->ndis_block))
+ KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
+
+ /*
+ * Set the completion event if we've drained all
+ * pending interrupts.
+ */
+
+ KeAcquireSpinLockAtDpcLevel(&intr->ni_dpccountlock);
+ intr->ni_dpccnt--;
+ if (intr->ni_dpccnt == 0)
+ KeSetEvent(&intr->ni_dpcevt, IO_NO_INCREMENT, FALSE);
+ KeReleaseSpinLockFromDpcLevel(&intr->ni_dpccountlock);
+}
+
+static ndis_status
+NdisMRegisterInterrupt(ndis_miniport_interrupt *intr, ndis_handle adapter,
+ uint32_t ivec, uint32_t ilevel, uint8_t reqisr, uint8_t shared,
+ ndis_interrupt_mode imode)
+{
+ ndis_miniport_block *block;
+ ndis_miniport_characteristics *ch;
+ struct ndis_softc *sc;
+ int error;
+
+ block = adapter;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+ ch = IoGetDriverObjectExtension(block->nmb_deviceobj->do_drvobj,
+ (void *)1);
+
+ intr->ni_rsvd = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(struct mtx), 0);
+ if (intr->ni_rsvd == NULL)
+ return (NDIS_STATUS_RESOURCES);
+
+ intr->ni_block = adapter;
+ intr->ni_isrreq = reqisr;
+ intr->ni_shared = shared;
+ intr->ni_dpccnt = 0;
+ intr->ni_isrfunc = ch->nmc_isr_func;
+ intr->ni_dpcfunc = ch->nmc_interrupt_func;
+
+ KeInitializeEvent(&intr->ni_dpcevt, EVENT_TYPE_NOTIFY, TRUE);
+ KeInitializeDpc(&intr->ni_dpc,
+ ndis_findwrap((funcptr)ndis_intrhand), intr);
+ KeSetImportanceDpc(&intr->ni_dpc, KDPC_IMPORTANCE_LOW);
+
+ error = IoConnectInterrupt(&intr->ni_introbj,
+ ndis_findwrap((funcptr)ndis_intr), sc, NULL,
+ ivec, ilevel, 0, imode, shared, 0, FALSE);
+
+ if (error != STATUS_SUCCESS)
+ return (NDIS_STATUS_FAILURE);
+
+ block->nmb_interrupt = intr;
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+static void
+NdisMDeregisterInterrupt(intr)
+ ndis_miniport_interrupt *intr;
+{
+ ndis_miniport_block *block;
+ uint8_t irql;
+
+ block = intr->ni_block;
+
+ /* Should really be KeSynchronizeExecution() */
+
+ KeAcquireSpinLock(intr->ni_introbj->ki_lock, &irql);
+ block->nmb_interrupt = NULL;
+ KeReleaseSpinLock(intr->ni_introbj->ki_lock, irql);
+/*
+ KeFlushQueuedDpcs();
+*/
+ /* Disconnect our ISR */
+
+ IoDisconnectInterrupt(intr->ni_introbj);
+
+ KeWaitForSingleObject(&intr->ni_dpcevt, 0, 0, FALSE, NULL);
+ KeResetEvent(&intr->ni_dpcevt);
+}
+
+static void
+NdisMRegisterAdapterShutdownHandler(adapter, shutdownctx, shutdownfunc)
+ ndis_handle adapter;
+ void *shutdownctx;
+ ndis_shutdown_handler shutdownfunc;
+{
+ ndis_miniport_block *block;
+ ndis_miniport_characteristics *chars;
+ struct ndis_softc *sc;
+
+ if (adapter == NULL)
+ return;
+
+ block = (ndis_miniport_block *)adapter;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+ chars = sc->ndis_chars;
+
+ chars->nmc_shutdown_handler = shutdownfunc;
+ chars->nmc_rsvd0 = shutdownctx;
+}
+
+static void
+NdisMDeregisterAdapterShutdownHandler(adapter)
+ ndis_handle adapter;
+{
+ ndis_miniport_block *block;
+ ndis_miniport_characteristics *chars;
+ struct ndis_softc *sc;
+
+ if (adapter == NULL)
+ return;
+
+ block = (ndis_miniport_block *)adapter;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+ chars = sc->ndis_chars;
+
+ chars->nmc_shutdown_handler = NULL;
+ chars->nmc_rsvd0 = NULL;
+}
+
+static uint32_t
+NDIS_BUFFER_TO_SPAN_PAGES(buf)
+ ndis_buffer *buf;
+{
+ if (buf == NULL)
+ return (0);
+ if (MmGetMdlByteCount(buf) == 0)
+ return (1);
+ return (SPAN_PAGES(MmGetMdlVirtualAddress(buf),
+ MmGetMdlByteCount(buf)));
+}
+
+static void
+NdisGetBufferPhysicalArraySize(buf, pages)
+ ndis_buffer *buf;
+ uint32_t *pages;
+{
+ if (buf == NULL)
+ return;
+
+ *pages = NDIS_BUFFER_TO_SPAN_PAGES(buf);
+}
+
+static void
+NdisQueryBufferOffset(buf, off, len)
+ ndis_buffer *buf;
+ uint32_t *off;
+ uint32_t *len;
+{
+ if (buf == NULL)
+ return;
+
+ *off = MmGetMdlByteOffset(buf);
+ *len = MmGetMdlByteCount(buf);
+}
+
+void
+NdisMSleep(usecs)
+ uint32_t usecs;
+{
+ ktimer timer;
+
+ /*
+ * During system bootstrap, (i.e. cold == 1), we aren't
+ * allowed to sleep, so we have to do a hard DELAY()
+ * instead.
+ */
+
+ if (cold)
+ DELAY(usecs);
+ else {
+ KeInitializeTimer(&timer);
+ KeSetTimer(&timer, ((int64_t)usecs * -10), NULL);
+ KeWaitForSingleObject(&timer, 0, 0, FALSE, NULL);
+ }
+}
+
+static uint32_t
+NdisReadPcmciaAttributeMemory(handle, offset, buf, len)
+ ndis_handle handle;
+ uint32_t offset;
+ void *buf;
+ uint32_t len;
+{
+ struct ndis_softc *sc;
+ ndis_miniport_block *block;
+ bus_space_handle_t bh;
+ bus_space_tag_t bt;
+ char *dest;
+ int i;
+
+ if (handle == NULL)
+ return (0);
+
+ block = (ndis_miniport_block *)handle;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+ dest = buf;
+
+ bh = rman_get_bushandle(sc->ndis_res_am);
+ bt = rman_get_bustag(sc->ndis_res_am);
+
+ for (i = 0; i < len; i++)
+ dest[i] = bus_space_read_1(bt, bh, (offset + i) * 2);
+
+ return (i);
+}
+
+static uint32_t
+NdisWritePcmciaAttributeMemory(handle, offset, buf, len)
+ ndis_handle handle;
+ uint32_t offset;
+ void *buf;
+ uint32_t len;
+{
+ struct ndis_softc *sc;
+ ndis_miniport_block *block;
+ bus_space_handle_t bh;
+ bus_space_tag_t bt;
+ char *src;
+ int i;
+
+ if (handle == NULL)
+ return (0);
+
+ block = (ndis_miniport_block *)handle;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+ src = buf;
+
+ bh = rman_get_bushandle(sc->ndis_res_am);
+ bt = rman_get_bustag(sc->ndis_res_am);
+
+ for (i = 0; i < len; i++)
+ bus_space_write_1(bt, bh, (offset + i) * 2, src[i]);
+
+ return (i);
+}
+
+static list_entry *
+NdisInterlockedInsertHeadList(head, entry, lock)
+ list_entry *head;
+ list_entry *entry;
+ ndis_spin_lock *lock;
+{
+ list_entry *flink;
+
+ KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql);
+ flink = head->nle_flink;
+ entry->nle_flink = flink;
+ entry->nle_blink = head;
+ flink->nle_blink = entry;
+ head->nle_flink = entry;
+ KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql);
+
+ return (flink);
+}
+
+static list_entry *
+NdisInterlockedRemoveHeadList(head, lock)
+ list_entry *head;
+ ndis_spin_lock *lock;
+{
+ list_entry *flink;
+ list_entry *entry;
+
+ KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql);
+ entry = head->nle_flink;
+ flink = entry->nle_flink;
+ head->nle_flink = flink;
+ flink->nle_blink = head;
+ KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql);
+
+ return (entry);
+}
+
+static list_entry *
+NdisInterlockedInsertTailList(head, entry, lock)
+ list_entry *head;
+ list_entry *entry;
+ ndis_spin_lock *lock;
+{
+ list_entry *blink;
+
+ KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql);
+ blink = head->nle_blink;
+ entry->nle_flink = head;
+ entry->nle_blink = blink;
+ blink->nle_flink = entry;
+ head->nle_blink = entry;
+ KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql);
+
+ return (blink);
+}
+
+static uint8_t
+NdisMSynchronizeWithInterrupt(intr, syncfunc, syncctx)
+ ndis_miniport_interrupt *intr;
+ void *syncfunc;
+ void *syncctx;
+{
+ return (KeSynchronizeExecution(intr->ni_introbj, syncfunc, syncctx));
+}
+
+static void
+NdisGetCurrentSystemTime(tval)
+ uint64_t *tval;
+{
+ ntoskrnl_time(tval);
+}
+
+/*
+ * Return the number of milliseconds since the system booted.
+ */
+static void
+NdisGetSystemUpTime(tval)
+ uint32_t *tval;
+{
+ struct timespec ts;
+
+ nanouptime(&ts);
+ *tval = ts.tv_nsec / 1000000 + ts.tv_sec * 1000;
+}
+
+static void
+NdisInitializeString(dst, src)
+ unicode_string *dst;
+ char *src;
+{
+ ansi_string as;
+ RtlInitAnsiString(&as, src);
+ RtlAnsiStringToUnicodeString(dst, &as, TRUE);
+}
+
+static void
+NdisFreeString(str)
+ unicode_string *str;
+{
+ RtlFreeUnicodeString(str);
+}
+
+static ndis_status
+NdisMRemoveMiniport(adapter)
+ ndis_handle *adapter;
+{
+ return (NDIS_STATUS_SUCCESS);
+}
+
+static void
+NdisInitAnsiString(dst, src)
+ ansi_string *dst;
+ char *src;
+{
+ RtlInitAnsiString(dst, src);
+}
+
+static void
+NdisInitUnicodeString(dst, src)
+ unicode_string *dst;
+ uint16_t *src;
+{
+ RtlInitUnicodeString(dst, src);
+}
+
+static void NdisMGetDeviceProperty(adapter, phydevobj,
+ funcdevobj, nextdevobj, resources, transresources)
+ ndis_handle adapter;
+ device_object **phydevobj;
+ device_object **funcdevobj;
+ device_object **nextdevobj;
+ cm_resource_list *resources;
+ cm_resource_list *transresources;
+{
+ ndis_miniport_block *block;
+
+ block = (ndis_miniport_block *)adapter;
+
+ if (phydevobj != NULL)
+ *phydevobj = block->nmb_physdeviceobj;
+ if (funcdevobj != NULL)
+ *funcdevobj = block->nmb_deviceobj;
+ if (nextdevobj != NULL)
+ *nextdevobj = block->nmb_nextdeviceobj;
+}
+
+static void
+NdisGetFirstBufferFromPacket(packet, buf, firstva, firstlen, totlen)
+ ndis_packet *packet;
+ ndis_buffer **buf;
+ void **firstva;
+ uint32_t *firstlen;
+ uint32_t *totlen;
+{
+ ndis_buffer *tmp;
+
+ tmp = packet->np_private.npp_head;
+ *buf = tmp;
+ if (tmp == NULL) {
+ *firstva = NULL;
+ *firstlen = *totlen = 0;
+ } else {
+ *firstva = MmGetMdlVirtualAddress(tmp);
+ *firstlen = *totlen = MmGetMdlByteCount(tmp);
+ for (tmp = tmp->mdl_next; tmp != NULL; tmp = tmp->mdl_next)
+ *totlen += MmGetMdlByteCount(tmp);
+ }
+}
+
+static void
+NdisGetFirstBufferFromPacketSafe(packet, buf, firstva, firstlen, totlen, prio)
+ ndis_packet *packet;
+ ndis_buffer **buf;
+ void **firstva;
+ uint32_t *firstlen;
+ uint32_t *totlen;
+ uint32_t prio;
+{
+ NdisGetFirstBufferFromPacket(packet, buf, firstva, firstlen, totlen);
+}
+
+static int
+ndis_find_sym(lf, filename, suffix, sym)
+ linker_file_t lf;
+ char *filename;
+ char *suffix;
+ caddr_t *sym;
+{
+ char *fullsym;
+ char *suf;
+ int i;
+
+ fullsym = ExAllocatePoolWithTag(NonPagedPool, MAXPATHLEN, 0);
+ if (fullsym == NULL)
+ return (ENOMEM);
+
+ bzero(fullsym, MAXPATHLEN);
+ strncpy(fullsym, filename, MAXPATHLEN);
+ if (strlen(filename) < 4) {
+ ExFreePool(fullsym);
+ return (EINVAL);
+ }
+
+ /* If the filename has a .ko suffix, strip if off. */
+ suf = fullsym + (strlen(filename) - 3);
+ if (strcmp(suf, ".ko") == 0)
+ *suf = '\0';
+
+ for (i = 0; i < strlen(fullsym); i++) {
+ if (fullsym[i] == '.')
+ fullsym[i] = '_';
+ else
+ fullsym[i] = tolower(fullsym[i]);
+ }
+ strcat(fullsym, suffix);
+ *sym = linker_file_lookup_symbol(lf, fullsym, 0);
+ ExFreePool(fullsym);
+ if (*sym == 0)
+ return (ENOENT);
+
+ return (0);
+}
+
+struct ndis_checkmodule {
+ char *afilename;
+ ndis_fh *fh;
+};
+
+/*
+ * See if a single module contains the symbols for a specified file.
+ */
+static int
+NdisCheckModule(linker_file_t lf, void *context)
+{
+ struct ndis_checkmodule *nc;
+ caddr_t kldstart, kldend;
+
+ nc = (struct ndis_checkmodule *)context;
+ if (ndis_find_sym(lf, nc->afilename, "_start", &kldstart))
+ return (0);
+ if (ndis_find_sym(lf, nc->afilename, "_end", &kldend))
+ return (0);
+ nc->fh->nf_vp = lf;
+ nc->fh->nf_map = NULL;
+ nc->fh->nf_type = NDIS_FH_TYPE_MODULE;
+ nc->fh->nf_maplen = (kldend - kldstart) & 0xFFFFFFFF;
+ return (1);
+}
+
+/* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */
+static void
+NdisOpenFile(status, filehandle, filelength, filename, highestaddr)
+ ndis_status *status;
+ ndis_handle *filehandle;
+ uint32_t *filelength;
+ unicode_string *filename;
+ ndis_physaddr highestaddr;
+{
+ ansi_string as;
+ char *afilename = NULL;
+ struct thread *td = curthread;
+ struct nameidata nd;
+ int flags, error;
+ struct vattr vat;
+ struct vattr *vap = &vat;
+ ndis_fh *fh;
+ char *path;
+ struct ndis_checkmodule nc;
+
+ if (RtlUnicodeStringToAnsiString(&as, filename, TRUE)) {
+ *status = NDIS_STATUS_RESOURCES;
+ return;
+ }
+
+ afilename = strdup(as.as_buf, M_DEVBUF);
+ RtlFreeAnsiString(&as);
+
+ fh = ExAllocatePoolWithTag(NonPagedPool, sizeof(ndis_fh), 0);
+ if (fh == NULL) {
+ free(afilename, M_DEVBUF);
+ *status = NDIS_STATUS_RESOURCES;
+ return;
+ }
+
+ fh->nf_name = afilename;
+
+ /*
+ * During system bootstrap, it's impossible to load files
+ * from the rootfs since it's not mounted yet. We therefore
+ * offer the possibility of opening files that have been
+ * preloaded as modules instead. Both choices will work
+ * when kldloading a module from multiuser, but only the
+ * module option will work during bootstrap. The module
+ * loading option works by using the ndiscvt(8) utility
+ * to convert the arbitrary file into a .ko using objcopy(1).
+ * This file will contain two special symbols: filename_start
+ * and filename_end. All we have to do is traverse the KLD
+ * list in search of those symbols and we've found the file
+ * data. As an added bonus, ndiscvt(8) will also generate
+ * a normal .o file which can be linked statically with
+ * the kernel. This means that the symbols will actual reside
+ * in the kernel's symbol table, but that doesn't matter to
+ * us since the kernel appears to us as just another module.
+ */
+
+ nc.afilename = afilename;
+ nc.fh = fh;
+ if (linker_file_foreach(NdisCheckModule, &nc)) {
+ *filelength = fh->nf_maplen;
+ *filehandle = fh;
+ *status = NDIS_STATUS_SUCCESS;
+ return;
+ }
+
+ if (TAILQ_EMPTY(&mountlist)) {
+ ExFreePool(fh);
+ *status = NDIS_STATUS_FILE_NOT_FOUND;
+ printf("NDIS: could not find file %s in linker list\n",
+ afilename);
+ printf("NDIS: and no filesystems mounted yet, "
+ "aborting NdisOpenFile()\n");
+ free(afilename, M_DEVBUF);
+ return;
+ }
+
+ path = ExAllocatePoolWithTag(NonPagedPool, MAXPATHLEN, 0);
+ if (path == NULL) {
+ ExFreePool(fh);
+ free(afilename, M_DEVBUF);
+ *status = NDIS_STATUS_RESOURCES;
+ return;
+ }
+
+ snprintf(path, MAXPATHLEN, "%s/%s", ndis_filepath, afilename);
+
+ /* Some threads don't have a current working directory. */
+
+ if (td->td_proc->p_fd->fd_rdir == NULL)
+ td->td_proc->p_fd->fd_rdir = rootvnode;
+ if (td->td_proc->p_fd->fd_cdir == NULL)
+ td->td_proc->p_fd->fd_cdir = rootvnode;
+
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td);
+
+ flags = FREAD;
+ error = vn_open(&nd, &flags, 0, NULL);
+ if (error) {
+ *status = NDIS_STATUS_FILE_NOT_FOUND;
+ ExFreePool(fh);
+ printf("NDIS: open file %s failed: %d\n", path, error);
+ ExFreePool(path);
+ free(afilename, M_DEVBUF);
+ return;
+ }
+
+ ExFreePool(path);
+
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+
+ /* Get the file size. */
+ VOP_GETATTR(nd.ni_vp, vap, td->td_ucred);
+ VOP_UNLOCK(nd.ni_vp, 0);
+
+ fh->nf_vp = nd.ni_vp;
+ fh->nf_map = NULL;
+ fh->nf_type = NDIS_FH_TYPE_VFS;
+ *filehandle = fh;
+ *filelength = fh->nf_maplen = vap->va_size & 0xFFFFFFFF;
+ *status = NDIS_STATUS_SUCCESS;
+}
+
+static void
+NdisMapFile(status, mappedbuffer, filehandle)
+ ndis_status *status;
+ void **mappedbuffer;
+ ndis_handle filehandle;
+{
+ ndis_fh *fh;
+ struct thread *td = curthread;
+ linker_file_t lf;
+ caddr_t kldstart;
+ int error;
+ ssize_t resid;
+ struct vnode *vp;
+
+ if (filehandle == NULL) {
+ *status = NDIS_STATUS_FAILURE;
+ return;
+ }
+
+ fh = (ndis_fh *)filehandle;
+
+ if (fh->nf_vp == NULL) {
+ *status = NDIS_STATUS_FAILURE;
+ return;
+ }
+
+ if (fh->nf_map != NULL) {
+ *status = NDIS_STATUS_ALREADY_MAPPED;
+ return;
+ }
+
+ if (fh->nf_type == NDIS_FH_TYPE_MODULE) {
+ lf = fh->nf_vp;
+ if (ndis_find_sym(lf, fh->nf_name, "_start", &kldstart)) {
+ *status = NDIS_STATUS_FAILURE;
+ return;
+ }
+ fh->nf_map = kldstart;
+ *status = NDIS_STATUS_SUCCESS;
+ *mappedbuffer = fh->nf_map;
+ return;
+ }
+
+ fh->nf_map = ExAllocatePoolWithTag(NonPagedPool, fh->nf_maplen, 0);
+
+ if (fh->nf_map == NULL) {
+ *status = NDIS_STATUS_RESOURCES;
+ return;
+ }
+
+ vp = fh->nf_vp;
+ error = vn_rdwr(UIO_READ, vp, fh->nf_map, fh->nf_maplen, 0,
+ UIO_SYSSPACE, 0, td->td_ucred, NOCRED, &resid, td);
+
+ if (error)
+ *status = NDIS_STATUS_FAILURE;
+ else {
+ *status = NDIS_STATUS_SUCCESS;
+ *mappedbuffer = fh->nf_map;
+ }
+}
+
+static void
+NdisUnmapFile(filehandle)
+ ndis_handle filehandle;
+{
+ ndis_fh *fh;
+ fh = (ndis_fh *)filehandle;
+
+ if (fh->nf_map == NULL)
+ return;
+
+ if (fh->nf_type == NDIS_FH_TYPE_VFS)
+ ExFreePool(fh->nf_map);
+ fh->nf_map = NULL;
+}
+
+static void
+NdisCloseFile(filehandle)
+ ndis_handle filehandle;
+{
+ struct thread *td = curthread;
+ ndis_fh *fh;
+ struct vnode *vp;
+
+ if (filehandle == NULL)
+ return;
+
+ fh = (ndis_fh *)filehandle;
+ if (fh->nf_map != NULL) {
+ if (fh->nf_type == NDIS_FH_TYPE_VFS)
+ ExFreePool(fh->nf_map);
+ fh->nf_map = NULL;
+ }
+
+ if (fh->nf_vp == NULL)
+ return;
+
+ if (fh->nf_type == NDIS_FH_TYPE_VFS) {
+ vp = fh->nf_vp;
+ vn_close(vp, FREAD, td->td_ucred, td);
+ }
+
+ fh->nf_vp = NULL;
+ free(fh->nf_name, M_DEVBUF);
+ ExFreePool(fh);
+}
+
+static uint8_t
+NdisSystemProcessorCount()
+{
+ return (mp_ncpus);
+}
+
+static void
+NdisGetCurrentProcessorCounts(idle_count, kernel_and_user, index)
+ uint32_t *idle_count;
+ uint32_t *kernel_and_user;
+ uint32_t *index;
+{
+ struct pcpu *pcpu;
+
+ pcpu = pcpu_find(curthread->td_oncpu);
+ *index = pcpu->pc_cpuid;
+ *idle_count = pcpu->pc_cp_time[CP_IDLE];
+ *kernel_and_user = pcpu->pc_cp_time[CP_INTR];
+}
+
+typedef void (*ndis_statusdone_handler)(ndis_handle);
+typedef void (*ndis_status_handler)(ndis_handle, ndis_status,
+ void *, uint32_t);
+
+static void
+NdisMIndicateStatusComplete(adapter)
+ ndis_handle adapter;
+{
+ ndis_miniport_block *block;
+ ndis_statusdone_handler statusdonefunc;
+
+ block = (ndis_miniport_block *)adapter;
+ statusdonefunc = block->nmb_statusdone_func;
+
+ MSCALL1(statusdonefunc, adapter);
+}
+
+static void
+NdisMIndicateStatus(adapter, status, sbuf, slen)
+ ndis_handle adapter;
+ ndis_status status;
+ void *sbuf;
+ uint32_t slen;
+{
+ ndis_miniport_block *block;
+ ndis_status_handler statusfunc;
+
+ block = (ndis_miniport_block *)adapter;
+ statusfunc = block->nmb_status_func;
+
+ MSCALL4(statusfunc, adapter, status, sbuf, slen);
+}
+
+/*
+ * The DDK documentation says that you should use IoQueueWorkItem()
+ * instead of ExQueueWorkItem(). The problem is, IoQueueWorkItem()
+ * is fundamentally incompatible with NdisScheduleWorkItem(), which
+ * depends on the API semantics of ExQueueWorkItem(). In our world,
+ * ExQueueWorkItem() is implemented on top of IoAllocateQueueItem()
+ * anyway.
+ *
+ * There are actually three distinct APIs here. NdisScheduleWorkItem()
+ * takes a pointer to an NDIS_WORK_ITEM. ExQueueWorkItem() takes a pointer
+ * to a WORK_QUEUE_ITEM. And finally, IoQueueWorkItem() takes a pointer
+ * to an opaque work item thingie which you get from IoAllocateWorkItem().
+ * An NDIS_WORK_ITEM is not the same as a WORK_QUEUE_ITEM. However,
+ * the NDIS_WORK_ITEM has some opaque storage at the end of it, and we
+ * (ab)use this storage as a WORK_QUEUE_ITEM, which is what we submit
+ * to ExQueueWorkItem().
+ *
+ * Got all that? (Sheesh.)
+ */
+
+ndis_status
+NdisScheduleWorkItem(work)
+ ndis_work_item *work;
+{
+ work_queue_item *wqi;
+
+ wqi = (work_queue_item *)work->nwi_wraprsvd;
+ ExInitializeWorkItem(wqi,
+ (work_item_func)work->nwi_func, work->nwi_ctx);
+ ExQueueWorkItem(wqi, WORKQUEUE_DELAYED);
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+static void
+NdisCopyFromPacketToPacket(dpkt, doff, reqlen, spkt, soff, cpylen)
+ ndis_packet *dpkt;
+ uint32_t doff;
+ uint32_t reqlen;
+ ndis_packet *spkt;
+ uint32_t soff;
+ uint32_t *cpylen;
+{
+ ndis_buffer *src, *dst;
+ char *sptr, *dptr;
+ int resid, copied, len, scnt, dcnt;
+
+ *cpylen = 0;
+
+ src = spkt->np_private.npp_head;
+ dst = dpkt->np_private.npp_head;
+
+ sptr = MmGetMdlVirtualAddress(src);
+ dptr = MmGetMdlVirtualAddress(dst);
+ scnt = MmGetMdlByteCount(src);
+ dcnt = MmGetMdlByteCount(dst);
+
+ while (soff) {
+ if (MmGetMdlByteCount(src) > soff) {
+ sptr += soff;
+ scnt = MmGetMdlByteCount(src)- soff;
+ break;
+ }
+ soff -= MmGetMdlByteCount(src);
+ src = src->mdl_next;
+ if (src == NULL)
+ return;
+ sptr = MmGetMdlVirtualAddress(src);
+ }
+
+ while (doff) {
+ if (MmGetMdlByteCount(dst) > doff) {
+ dptr += doff;
+ dcnt = MmGetMdlByteCount(dst) - doff;
+ break;
+ }
+ doff -= MmGetMdlByteCount(dst);
+ dst = dst->mdl_next;
+ if (dst == NULL)
+ return;
+ dptr = MmGetMdlVirtualAddress(dst);
+ }
+
+ resid = reqlen;
+ copied = 0;
+
+ while(1) {
+ if (resid < scnt)
+ len = resid;
+ else
+ len = scnt;
+ if (dcnt < len)
+ len = dcnt;
+
+ bcopy(sptr, dptr, len);
+
+ copied += len;
+ resid -= len;
+ if (resid == 0)
+ break;
+
+ dcnt -= len;
+ if (dcnt == 0) {
+ dst = dst->mdl_next;
+ if (dst == NULL)
+ break;
+ dptr = MmGetMdlVirtualAddress(dst);
+ dcnt = MmGetMdlByteCount(dst);
+ }
+
+ scnt -= len;
+ if (scnt == 0) {
+ src = src->mdl_next;
+ if (src == NULL)
+ break;
+ sptr = MmGetMdlVirtualAddress(src);
+ scnt = MmGetMdlByteCount(src);
+ }
+ }
+
+ *cpylen = copied;
+}
+
+static void
+NdisCopyFromPacketToPacketSafe(dpkt, doff, reqlen, spkt, soff, cpylen, prio)
+ ndis_packet *dpkt;
+ uint32_t doff;
+ uint32_t reqlen;
+ ndis_packet *spkt;
+ uint32_t soff;
+ uint32_t *cpylen;
+ uint32_t prio;
+{
+ NdisCopyFromPacketToPacket(dpkt, doff, reqlen, spkt, soff, cpylen);
+}
+
+static void
+NdisIMCopySendPerPacketInfo(dpkt, spkt)
+ ndis_packet *dpkt;
+ ndis_packet *spkt;
+{
+ memcpy(&dpkt->np_ext, &spkt->np_ext, sizeof(ndis_packet_extension));
+}
+
+static ndis_status
+NdisMRegisterDevice(handle, devname, symname, majorfuncs, devobj, devhandle)
+ ndis_handle handle;
+ unicode_string *devname;
+ unicode_string *symname;
+ driver_dispatch *majorfuncs[];
+ void **devobj;
+ ndis_handle *devhandle;
+{
+ uint32_t status;
+ device_object *dobj;
+
+ status = IoCreateDevice(handle, 0, devname,
+ FILE_DEVICE_UNKNOWN, 0, FALSE, &dobj);
+
+ if (status == STATUS_SUCCESS) {
+ *devobj = dobj;
+ *devhandle = dobj;
+ }
+
+ return (status);
+}
+
+static ndis_status
+NdisMDeregisterDevice(handle)
+ ndis_handle handle;
+{
+ IoDeleteDevice(handle);
+ return (NDIS_STATUS_SUCCESS);
+}
+
+static ndis_status
+NdisMQueryAdapterInstanceName(name, handle)
+ unicode_string *name;
+ ndis_handle handle;
+{
+ ndis_miniport_block *block;
+ device_t dev;
+ ansi_string as;
+
+ block = (ndis_miniport_block *)handle;
+ dev = block->nmb_physdeviceobj->do_devext;
+
+ RtlInitAnsiString(&as, __DECONST(char *, device_get_nameunit(dev)));
+ if (RtlAnsiStringToUnicodeString(name, &as, TRUE))
+ return (NDIS_STATUS_RESOURCES);
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+static void
+NdisMRegisterUnloadHandler(handle, func)
+ ndis_handle handle;
+ void *func;
+{
+}
+
+static void
+dummy()
+{
+ printf("NDIS dummy called...\n");
+}
+
+/*
+ * Note: a couple of entries in this table specify the
+ * number of arguments as "foo + 1". These are routines
+ * that accept a 64-bit argument, passed by value. On
+ * x86, these arguments consume two longwords on the stack,
+ * so we lie and say there's one additional argument so
+ * that the wrapping routines will do the right thing.
+ */
+
+image_patch_table ndis_functbl[] = {
+ IMPORT_SFUNC(NdisCopyFromPacketToPacket, 6),
+ IMPORT_SFUNC(NdisCopyFromPacketToPacketSafe, 7),
+ IMPORT_SFUNC(NdisIMCopySendPerPacketInfo, 2),
+ IMPORT_SFUNC(NdisScheduleWorkItem, 1),
+ IMPORT_SFUNC(NdisMIndicateStatusComplete, 1),
+ IMPORT_SFUNC(NdisMIndicateStatus, 4),
+ IMPORT_SFUNC(NdisSystemProcessorCount, 0),
+ IMPORT_SFUNC(NdisGetCurrentProcessorCounts, 3),
+ IMPORT_SFUNC(NdisUnchainBufferAtBack, 2),
+ IMPORT_SFUNC(NdisGetFirstBufferFromPacket, 5),
+ IMPORT_SFUNC(NdisGetFirstBufferFromPacketSafe, 6),
+ IMPORT_SFUNC(NdisGetBufferPhysicalArraySize, 2),
+ IMPORT_SFUNC(NdisMGetDeviceProperty, 6),
+ IMPORT_SFUNC(NdisInitAnsiString, 2),
+ IMPORT_SFUNC(NdisInitUnicodeString, 2),
+ IMPORT_SFUNC(NdisWriteConfiguration, 4),
+ IMPORT_SFUNC(NdisAnsiStringToUnicodeString, 2),
+ IMPORT_SFUNC(NdisTerminateWrapper, 2),
+ IMPORT_SFUNC(NdisOpenConfigurationKeyByName, 4),
+ IMPORT_SFUNC(NdisOpenConfigurationKeyByIndex, 5),
+ IMPORT_SFUNC(NdisMRemoveMiniport, 1),
+ IMPORT_SFUNC(NdisInitializeString, 2),
+ IMPORT_SFUNC(NdisFreeString, 1),
+ IMPORT_SFUNC(NdisGetCurrentSystemTime, 1),
+ IMPORT_SFUNC(NdisGetRoutineAddress, 1),
+ IMPORT_SFUNC(NdisGetSystemUpTime, 1),
+ IMPORT_SFUNC(NdisGetVersion, 0),
+ IMPORT_SFUNC(NdisMSynchronizeWithInterrupt, 3),
+ IMPORT_SFUNC(NdisMAllocateSharedMemoryAsync, 4),
+ IMPORT_SFUNC(NdisInterlockedInsertHeadList, 3),
+ IMPORT_SFUNC(NdisInterlockedInsertTailList, 3),
+ IMPORT_SFUNC(NdisInterlockedRemoveHeadList, 2),
+ IMPORT_SFUNC(NdisInitializeWrapper, 4),
+ IMPORT_SFUNC(NdisMRegisterMiniport, 3),
+ IMPORT_SFUNC(NdisAllocateMemoryWithTag, 3),
+ IMPORT_SFUNC(NdisAllocateMemory, 4 + 1),
+ IMPORT_SFUNC(NdisMSetAttributesEx, 5),
+ IMPORT_SFUNC(NdisCloseConfiguration, 1),
+ IMPORT_SFUNC(NdisReadConfiguration, 5),
+ IMPORT_SFUNC(NdisOpenConfiguration, 3),
+ IMPORT_SFUNC(NdisAcquireSpinLock, 1),
+ IMPORT_SFUNC(NdisReleaseSpinLock, 1),
+ IMPORT_SFUNC(NdisDprAcquireSpinLock, 1),
+ IMPORT_SFUNC(NdisDprReleaseSpinLock, 1),
+ IMPORT_SFUNC(NdisAllocateSpinLock, 1),
+ IMPORT_SFUNC(NdisInitializeReadWriteLock, 1),
+ IMPORT_SFUNC(NdisAcquireReadWriteLock, 3),
+ IMPORT_SFUNC(NdisReleaseReadWriteLock, 2),
+ IMPORT_SFUNC(NdisFreeSpinLock, 1),
+ IMPORT_SFUNC(NdisFreeMemory, 3),
+ IMPORT_SFUNC(NdisReadPciSlotInformation, 5),
+ IMPORT_SFUNC(NdisWritePciSlotInformation, 5),
+ IMPORT_SFUNC_MAP(NdisImmediateReadPciSlotInformation,
+ NdisReadPciSlotInformation, 5),
+ IMPORT_SFUNC_MAP(NdisImmediateWritePciSlotInformation,
+ NdisWritePciSlotInformation, 5),
+ IMPORT_CFUNC(NdisWriteErrorLogEntry, 0),
+ IMPORT_SFUNC(NdisMStartBufferPhysicalMapping, 6),
+ IMPORT_SFUNC(NdisMCompleteBufferPhysicalMapping, 3),
+ IMPORT_SFUNC(NdisMInitializeTimer, 4),
+ IMPORT_SFUNC(NdisInitializeTimer, 3),
+ IMPORT_SFUNC(NdisSetTimer, 2),
+ IMPORT_SFUNC(NdisMCancelTimer, 2),
+ IMPORT_SFUNC_MAP(NdisCancelTimer, NdisMCancelTimer, 2),
+ IMPORT_SFUNC(NdisMSetPeriodicTimer, 2),
+ IMPORT_SFUNC(NdisMQueryAdapterResources, 4),
+ IMPORT_SFUNC(NdisMRegisterIoPortRange, 4),
+ IMPORT_SFUNC(NdisMDeregisterIoPortRange, 4),
+ IMPORT_SFUNC(NdisReadNetworkAddress, 4),
+ IMPORT_SFUNC(NdisQueryMapRegisterCount, 2),
+ IMPORT_SFUNC(NdisMAllocateMapRegisters, 5),
+ IMPORT_SFUNC(NdisMFreeMapRegisters, 1),
+ IMPORT_SFUNC(NdisMAllocateSharedMemory, 5),
+ IMPORT_SFUNC(NdisMMapIoSpace, 4 + 1),
+ IMPORT_SFUNC(NdisMUnmapIoSpace, 3),
+ IMPORT_SFUNC(NdisGetCacheFillSize, 0),
+ IMPORT_SFUNC(NdisMGetDmaAlignment, 1),
+ IMPORT_SFUNC(NdisMInitializeScatterGatherDma, 3),
+ IMPORT_SFUNC(NdisAllocatePacketPool, 4),
+ IMPORT_SFUNC(NdisAllocatePacketPoolEx, 5),
+ IMPORT_SFUNC(NdisAllocatePacket, 3),
+ IMPORT_SFUNC(NdisFreePacket, 1),
+ IMPORT_SFUNC(NdisFreePacketPool, 1),
+ IMPORT_SFUNC_MAP(NdisDprAllocatePacket, NdisAllocatePacket, 3),
+ IMPORT_SFUNC_MAP(NdisDprFreePacket, NdisFreePacket, 1),
+ IMPORT_SFUNC(NdisAllocateBufferPool, 3),
+ IMPORT_SFUNC(NdisAllocateBuffer, 5),
+ IMPORT_SFUNC(NdisQueryBuffer, 3),
+ IMPORT_SFUNC(NdisQueryBufferSafe, 4),
+ IMPORT_SFUNC(NdisBufferVirtualAddress, 1),
+ IMPORT_SFUNC(NdisBufferVirtualAddressSafe, 2),
+ IMPORT_SFUNC(NdisBufferLength, 1),
+ IMPORT_SFUNC(NdisFreeBuffer, 1),
+ IMPORT_SFUNC(NdisFreeBufferPool, 1),
+ IMPORT_SFUNC(NdisInterlockedIncrement, 1),
+ IMPORT_SFUNC(NdisInterlockedDecrement, 1),
+ IMPORT_SFUNC(NdisInitializeEvent, 1),
+ IMPORT_SFUNC(NdisSetEvent, 1),
+ IMPORT_SFUNC(NdisResetEvent, 1),
+ IMPORT_SFUNC(NdisWaitEvent, 2),
+ IMPORT_SFUNC(NdisUnicodeStringToAnsiString, 2),
+ IMPORT_SFUNC(NdisMPciAssignResources, 3),
+ IMPORT_SFUNC(NdisMFreeSharedMemory, 5 + 1),
+ IMPORT_SFUNC(NdisMRegisterInterrupt, 7),
+ IMPORT_SFUNC(NdisMDeregisterInterrupt, 1),
+ IMPORT_SFUNC(NdisMRegisterAdapterShutdownHandler, 3),
+ IMPORT_SFUNC(NdisMDeregisterAdapterShutdownHandler, 1),
+ IMPORT_SFUNC(NDIS_BUFFER_TO_SPAN_PAGES, 1),
+ IMPORT_SFUNC(NdisQueryBufferOffset, 3),
+ IMPORT_SFUNC(NdisAdjustBufferLength, 2),
+ IMPORT_SFUNC(NdisPacketPoolUsage, 1),
+ IMPORT_SFUNC(NdisMSleep, 1),
+ IMPORT_SFUNC(NdisUnchainBufferAtFront, 2),
+ IMPORT_SFUNC(NdisReadPcmciaAttributeMemory, 4),
+ IMPORT_SFUNC(NdisWritePcmciaAttributeMemory, 4),
+ IMPORT_SFUNC(NdisOpenFile, 5 + 1),
+ IMPORT_SFUNC(NdisMapFile, 3),
+ IMPORT_SFUNC(NdisUnmapFile, 1),
+ IMPORT_SFUNC(NdisCloseFile, 1),
+ IMPORT_SFUNC(NdisMRegisterDevice, 6),
+ IMPORT_SFUNC(NdisMDeregisterDevice, 1),
+ IMPORT_SFUNC(NdisMQueryAdapterInstanceName, 2),
+ IMPORT_SFUNC(NdisMRegisterUnloadHandler, 2),
+ IMPORT_SFUNC(ndis_timercall, 4),
+ IMPORT_SFUNC(ndis_asyncmem_complete, 2),
+ IMPORT_SFUNC(ndis_intr, 2),
+ IMPORT_SFUNC(ndis_intrhand, 4),
+
+ /*
+ * This last entry is a catch-all for any function we haven't
+ * implemented yet. The PE import list patching routine will
+ * use it for any function that doesn't have an explicit match
+ * in this table.
+ */
+
+ { NULL, (FUNC)dummy, NULL, 0, WINDRV_WRAP_STDCALL },
+
+ /* End of list. */
+
+ { NULL, NULL, NULL }
+};
diff --git a/sys/compat/ndis/subr_ntoskrnl.c b/sys/compat/ndis/subr_ntoskrnl.c
new file mode 100644
index 0000000..02e8e45
--- /dev/null
+++ b/sys/compat/ndis/subr_ntoskrnl.c
@@ -0,0 +1,4457 @@
+/*-
+ * Copyright (c) 2003
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/ctype.h>
+#include <sys/unistd.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <sys/callout.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/condvar.h>
+#include <sys/kthread.h>
+#include <sys/module.h>
+#include <sys/smp.h>
+#include <sys/sched.h>
+#include <sys/sysctl.h>
+
+#include <machine/atomic.h>
+#include <machine/bus.h>
+#include <machine/stdarg.h>
+#include <machine/resource.h>
+
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/uma.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_map.h>
+#include <vm/vm_extern.h>
+
+#include <compat/ndis/pe_var.h>
+#include <compat/ndis/cfg_var.h>
+#include <compat/ndis/resource_var.h>
+#include <compat/ndis/ntoskrnl_var.h>
+#include <compat/ndis/hal_var.h>
+#include <compat/ndis/ndis_var.h>
+
+#ifdef NTOSKRNL_DEBUG_TIMERS
+static int sysctl_show_timers(SYSCTL_HANDLER_ARGS);
+
+SYSCTL_PROC(_debug, OID_AUTO, ntoskrnl_timers, CTLTYPE_INT | CTLFLAG_RW,
+ NULL, 0, sysctl_show_timers, "I",
+ "Show ntoskrnl timer stats");
+#endif
+
+struct kdpc_queue {
+ list_entry kq_disp;
+ struct thread *kq_td;
+ int kq_cpu;
+ int kq_exit;
+ int kq_running;
+ kspin_lock kq_lock;
+ nt_kevent kq_proc;
+ nt_kevent kq_done;
+};
+
+typedef struct kdpc_queue kdpc_queue;
+
+struct wb_ext {
+ struct cv we_cv;
+ struct thread *we_td;
+};
+
+typedef struct wb_ext wb_ext;
+
+#define NTOSKRNL_TIMEOUTS 256
+#ifdef NTOSKRNL_DEBUG_TIMERS
+static uint64_t ntoskrnl_timer_fires;
+static uint64_t ntoskrnl_timer_sets;
+static uint64_t ntoskrnl_timer_reloads;
+static uint64_t ntoskrnl_timer_cancels;
+#endif
+
+struct callout_entry {
+ struct callout ce_callout;
+ list_entry ce_list;
+};
+
+typedef struct callout_entry callout_entry;
+
+static struct list_entry ntoskrnl_calllist;
+static struct mtx ntoskrnl_calllock;
+struct kuser_shared_data kuser_shared_data;
+
+static struct list_entry ntoskrnl_intlist;
+static kspin_lock ntoskrnl_intlock;
+
+static uint8_t RtlEqualUnicodeString(unicode_string *,
+ unicode_string *, uint8_t);
+static void RtlCopyString(ansi_string *, const ansi_string *);
+static void RtlCopyUnicodeString(unicode_string *,
+ unicode_string *);
+static irp *IoBuildSynchronousFsdRequest(uint32_t, device_object *,
+ void *, uint32_t, uint64_t *, nt_kevent *, io_status_block *);
+static irp *IoBuildAsynchronousFsdRequest(uint32_t,
+ device_object *, void *, uint32_t, uint64_t *, io_status_block *);
+static irp *IoBuildDeviceIoControlRequest(uint32_t,
+ device_object *, void *, uint32_t, void *, uint32_t,
+ uint8_t, nt_kevent *, io_status_block *);
+static irp *IoAllocateIrp(uint8_t, uint8_t);
+static void IoReuseIrp(irp *, uint32_t);
+static void IoFreeIrp(irp *);
+static void IoInitializeIrp(irp *, uint16_t, uint8_t);
+static irp *IoMakeAssociatedIrp(irp *, uint8_t);
+static uint32_t KeWaitForMultipleObjects(uint32_t,
+ nt_dispatch_header **, uint32_t, uint32_t, uint32_t, uint8_t,
+ int64_t *, wait_block *);
+static void ntoskrnl_waittest(nt_dispatch_header *, uint32_t);
+static void ntoskrnl_satisfy_wait(nt_dispatch_header *, struct thread *);
+static void ntoskrnl_satisfy_multiple_waits(wait_block *);
+static int ntoskrnl_is_signalled(nt_dispatch_header *, struct thread *);
+static void ntoskrnl_insert_timer(ktimer *, int);
+static void ntoskrnl_remove_timer(ktimer *);
+#ifdef NTOSKRNL_DEBUG_TIMERS
+static void ntoskrnl_show_timers(void);
+#endif
+static void ntoskrnl_timercall(void *);
+static void ntoskrnl_dpc_thread(void *);
+static void ntoskrnl_destroy_dpc_threads(void);
+static void ntoskrnl_destroy_workitem_threads(void);
+static void ntoskrnl_workitem_thread(void *);
+static void ntoskrnl_workitem(device_object *, void *);
+static void ntoskrnl_unicode_to_ascii(uint16_t *, char *, int);
+static void ntoskrnl_ascii_to_unicode(char *, uint16_t *, int);
+static uint8_t ntoskrnl_insert_dpc(list_entry *, kdpc *);
+static void WRITE_REGISTER_USHORT(uint16_t *, uint16_t);
+static uint16_t READ_REGISTER_USHORT(uint16_t *);
+static void WRITE_REGISTER_ULONG(uint32_t *, uint32_t);
+static uint32_t READ_REGISTER_ULONG(uint32_t *);
+static void WRITE_REGISTER_UCHAR(uint8_t *, uint8_t);
+static uint8_t READ_REGISTER_UCHAR(uint8_t *);
+static int64_t _allmul(int64_t, int64_t);
+static int64_t _alldiv(int64_t, int64_t);
+static int64_t _allrem(int64_t, int64_t);
+static int64_t _allshr(int64_t, uint8_t);
+static int64_t _allshl(int64_t, uint8_t);
+static uint64_t _aullmul(uint64_t, uint64_t);
+static uint64_t _aulldiv(uint64_t, uint64_t);
+static uint64_t _aullrem(uint64_t, uint64_t);
+static uint64_t _aullshr(uint64_t, uint8_t);
+static uint64_t _aullshl(uint64_t, uint8_t);
+static slist_entry *ntoskrnl_pushsl(slist_header *, slist_entry *);
+static void InitializeSListHead(slist_header *);
+static slist_entry *ntoskrnl_popsl(slist_header *);
+static void ExFreePoolWithTag(void *, uint32_t);
+static void ExInitializePagedLookasideList(paged_lookaside_list *,
+ lookaside_alloc_func *, lookaside_free_func *,
+ uint32_t, size_t, uint32_t, uint16_t);
+static void ExDeletePagedLookasideList(paged_lookaside_list *);
+static void ExInitializeNPagedLookasideList(npaged_lookaside_list *,
+ lookaside_alloc_func *, lookaside_free_func *,
+ uint32_t, size_t, uint32_t, uint16_t);
+static void ExDeleteNPagedLookasideList(npaged_lookaside_list *);
+static slist_entry
+ *ExInterlockedPushEntrySList(slist_header *,
+ slist_entry *, kspin_lock *);
+static slist_entry
+ *ExInterlockedPopEntrySList(slist_header *, kspin_lock *);
+static uint32_t InterlockedIncrement(volatile uint32_t *);
+static uint32_t InterlockedDecrement(volatile uint32_t *);
+static void ExInterlockedAddLargeStatistic(uint64_t *, uint32_t);
+static void *MmAllocateContiguousMemory(uint32_t, uint64_t);
+static void *MmAllocateContiguousMemorySpecifyCache(uint32_t,
+ uint64_t, uint64_t, uint64_t, enum nt_caching_type);
+static void MmFreeContiguousMemory(void *);
+static void MmFreeContiguousMemorySpecifyCache(void *, uint32_t,
+ enum nt_caching_type);
+static uint32_t MmSizeOfMdl(void *, size_t);
+static void *MmMapLockedPages(mdl *, uint8_t);
+static void *MmMapLockedPagesSpecifyCache(mdl *,
+ uint8_t, uint32_t, void *, uint32_t, uint32_t);
+static void MmUnmapLockedPages(void *, mdl *);
+static device_t ntoskrnl_finddev(device_t, uint64_t, struct resource **);
+static void RtlZeroMemory(void *, size_t);
+static void RtlSecureZeroMemory(void *, size_t);
+static void RtlFillMemory(void *, size_t, uint8_t);
+static void RtlMoveMemory(void *, const void *, size_t);
+static ndis_status RtlCharToInteger(const char *, uint32_t, uint32_t *);
+static void RtlCopyMemory(void *, const void *, size_t);
+static size_t RtlCompareMemory(const void *, const void *, size_t);
+static ndis_status RtlUnicodeStringToInteger(unicode_string *,
+ uint32_t, uint32_t *);
+static int atoi (const char *);
+static long atol (const char *);
+static int rand(void);
+static void srand(unsigned int);
+static void KeQuerySystemTime(uint64_t *);
+static uint32_t KeTickCount(void);
+static uint8_t IoIsWdmVersionAvailable(uint8_t, uint8_t);
+static int32_t IoOpenDeviceRegistryKey(struct device_object *, uint32_t,
+ uint32_t, void **);
+static void ntoskrnl_thrfunc(void *);
+static ndis_status PsCreateSystemThread(ndis_handle *,
+ uint32_t, void *, ndis_handle, void *, void *, void *);
+static ndis_status PsTerminateSystemThread(ndis_status);
+static ndis_status IoGetDeviceObjectPointer(unicode_string *,
+ uint32_t, void *, device_object *);
+static ndis_status IoGetDeviceProperty(device_object *, uint32_t,
+ uint32_t, void *, uint32_t *);
+static void KeInitializeMutex(kmutant *, uint32_t);
+static uint32_t KeReleaseMutex(kmutant *, uint8_t);
+static uint32_t KeReadStateMutex(kmutant *);
+static ndis_status ObReferenceObjectByHandle(ndis_handle,
+ uint32_t, void *, uint8_t, void **, void **);
+static void ObfDereferenceObject(void *);
+static uint32_t ZwClose(ndis_handle);
+static uint32_t WmiQueryTraceInformation(uint32_t, void *, uint32_t,
+ uint32_t, void *);
+static uint32_t WmiTraceMessage(uint64_t, uint32_t, void *, uint16_t, ...);
+static uint32_t IoWMIRegistrationControl(device_object *, uint32_t);
+static void *ntoskrnl_memset(void *, int, size_t);
+static void *ntoskrnl_memmove(void *, void *, size_t);
+static void *ntoskrnl_memchr(void *, unsigned char, size_t);
+static char *ntoskrnl_strstr(char *, char *);
+static char *ntoskrnl_strncat(char *, char *, size_t);
+static int ntoskrnl_toupper(int);
+static int ntoskrnl_tolower(int);
+static funcptr ntoskrnl_findwrap(funcptr);
+static uint32_t DbgPrint(char *, ...);
+static void DbgBreakPoint(void);
+static void KeBugCheckEx(uint32_t, u_long, u_long, u_long, u_long);
+static int32_t KeDelayExecutionThread(uint8_t, uint8_t, int64_t *);
+static int32_t KeSetPriorityThread(struct thread *, int32_t);
+static void dummy(void);
+
+static struct mtx ntoskrnl_dispatchlock;
+static struct mtx ntoskrnl_interlock;
+static kspin_lock ntoskrnl_cancellock;
+static int ntoskrnl_kth = 0;
+static struct nt_objref_head ntoskrnl_reflist;
+static uma_zone_t mdl_zone;
+static uma_zone_t iw_zone;
+static struct kdpc_queue *kq_queues;
+static struct kdpc_queue *wq_queues;
+static int wq_idx = 0;
+
+int
+ntoskrnl_libinit()
+{
+ image_patch_table *patch;
+ int error;
+ struct proc *p;
+ kdpc_queue *kq;
+ callout_entry *e;
+ int i;
+
+ mtx_init(&ntoskrnl_dispatchlock,
+ "ntoskrnl dispatch lock", MTX_NDIS_LOCK, MTX_DEF|MTX_RECURSE);
+ mtx_init(&ntoskrnl_interlock, MTX_NTOSKRNL_SPIN_LOCK, NULL, MTX_SPIN);
+ KeInitializeSpinLock(&ntoskrnl_cancellock);
+ KeInitializeSpinLock(&ntoskrnl_intlock);
+ TAILQ_INIT(&ntoskrnl_reflist);
+
+ InitializeListHead(&ntoskrnl_calllist);
+ InitializeListHead(&ntoskrnl_intlist);
+ mtx_init(&ntoskrnl_calllock, MTX_NTOSKRNL_SPIN_LOCK, NULL, MTX_SPIN);
+
+ kq_queues = ExAllocatePoolWithTag(NonPagedPool,
+#ifdef NTOSKRNL_MULTIPLE_DPCS
+ sizeof(kdpc_queue) * mp_ncpus, 0);
+#else
+ sizeof(kdpc_queue), 0);
+#endif
+
+ if (kq_queues == NULL)
+ return (ENOMEM);
+
+ wq_queues = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(kdpc_queue) * WORKITEM_THREADS, 0);
+
+ if (wq_queues == NULL)
+ return (ENOMEM);
+
+#ifdef NTOSKRNL_MULTIPLE_DPCS
+ bzero((char *)kq_queues, sizeof(kdpc_queue) * mp_ncpus);
+#else
+ bzero((char *)kq_queues, sizeof(kdpc_queue));
+#endif
+ bzero((char *)wq_queues, sizeof(kdpc_queue) * WORKITEM_THREADS);
+
+ /*
+ * Launch the DPC threads.
+ */
+
+#ifdef NTOSKRNL_MULTIPLE_DPCS
+ for (i = 0; i < mp_ncpus; i++) {
+#else
+ for (i = 0; i < 1; i++) {
+#endif
+ kq = kq_queues + i;
+ kq->kq_cpu = i;
+ error = kproc_create(ntoskrnl_dpc_thread, kq, &p,
+ RFHIGHPID, NDIS_KSTACK_PAGES, "Windows DPC %d", i);
+ if (error)
+ panic("failed to launch DPC thread");
+ }
+
+ /*
+ * Launch the workitem threads.
+ */
+
+ for (i = 0; i < WORKITEM_THREADS; i++) {
+ kq = wq_queues + i;
+ error = kproc_create(ntoskrnl_workitem_thread, kq, &p,
+ RFHIGHPID, NDIS_KSTACK_PAGES, "Windows Workitem %d", i);
+ if (error)
+ panic("failed to launch workitem thread");
+ }
+
+ patch = ntoskrnl_functbl;
+ while (patch->ipt_func != NULL) {
+ windrv_wrap((funcptr)patch->ipt_func,
+ (funcptr *)&patch->ipt_wrap,
+ patch->ipt_argcnt, patch->ipt_ftype);
+ patch++;
+ }
+
+ for (i = 0; i < NTOSKRNL_TIMEOUTS; i++) {
+ e = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(callout_entry), 0);
+ if (e == NULL)
+ panic("failed to allocate timeouts");
+ mtx_lock_spin(&ntoskrnl_calllock);
+ InsertHeadList((&ntoskrnl_calllist), (&e->ce_list));
+ mtx_unlock_spin(&ntoskrnl_calllock);
+ }
+
+ /*
+ * MDLs are supposed to be variable size (they describe
+ * buffers containing some number of pages, but we don't
+ * know ahead of time how many pages that will be). But
+ * always allocating them off the heap is very slow. As
+ * a compromise, we create an MDL UMA zone big enough to
+ * handle any buffer requiring up to 16 pages, and we
+ * use those for any MDLs for buffers of 16 pages or less
+ * in size. For buffers larger than that (which we assume
+ * will be few and far between, we allocate the MDLs off
+ * the heap.
+ */
+
+ mdl_zone = uma_zcreate("Windows MDL", MDL_ZONE_SIZE,
+ NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
+
+ iw_zone = uma_zcreate("Windows WorkItem", sizeof(io_workitem),
+ NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
+
+ return (0);
+}
+
+int
+ntoskrnl_libfini()
+{
+ image_patch_table *patch;
+ callout_entry *e;
+ list_entry *l;
+
+ patch = ntoskrnl_functbl;
+ while (patch->ipt_func != NULL) {
+ windrv_unwrap(patch->ipt_wrap);
+ patch++;
+ }
+
+ /* Stop the workitem queues. */
+ ntoskrnl_destroy_workitem_threads();
+ /* Stop the DPC queues. */
+ ntoskrnl_destroy_dpc_threads();
+
+ ExFreePool(kq_queues);
+ ExFreePool(wq_queues);
+
+ uma_zdestroy(mdl_zone);
+ uma_zdestroy(iw_zone);
+
+ mtx_lock_spin(&ntoskrnl_calllock);
+ while(!IsListEmpty(&ntoskrnl_calllist)) {
+ l = RemoveHeadList(&ntoskrnl_calllist);
+ e = CONTAINING_RECORD(l, callout_entry, ce_list);
+ mtx_unlock_spin(&ntoskrnl_calllock);
+ ExFreePool(e);
+ mtx_lock_spin(&ntoskrnl_calllock);
+ }
+ mtx_unlock_spin(&ntoskrnl_calllock);
+
+ mtx_destroy(&ntoskrnl_dispatchlock);
+ mtx_destroy(&ntoskrnl_interlock);
+ mtx_destroy(&ntoskrnl_calllock);
+
+ return (0);
+}
+
+/*
+ * We need to be able to reference this externally from the wrapper;
+ * GCC only generates a local implementation of memset.
+ */
+static void *
+ntoskrnl_memset(buf, ch, size)
+ void *buf;
+ int ch;
+ size_t size;
+{
+ return (memset(buf, ch, size));
+}
+
+static void *
+ntoskrnl_memmove(dst, src, size)
+ void *src;
+ void *dst;
+ size_t size;
+{
+ bcopy(src, dst, size);
+ return (dst);
+}
+
+static void *
+ntoskrnl_memchr(void *buf, unsigned char ch, size_t len)
+{
+ if (len != 0) {
+ unsigned char *p = buf;
+
+ do {
+ if (*p++ == ch)
+ return (p - 1);
+ } while (--len != 0);
+ }
+ return (NULL);
+}
+
+static char *
+ntoskrnl_strstr(s, find)
+ char *s, *find;
+{
+ char c, sc;
+ size_t len;
+
+ if ((c = *find++) != 0) {
+ len = strlen(find);
+ do {
+ do {
+ if ((sc = *s++) == 0)
+ return (NULL);
+ } while (sc != c);
+ } while (strncmp(s, find, len) != 0);
+ s--;
+ }
+ return ((char *)s);
+}
+
+/* Taken from libc */
+static char *
+ntoskrnl_strncat(dst, src, n)
+ char *dst;
+ char *src;
+ size_t n;
+{
+ if (n != 0) {
+ char *d = dst;
+ const char *s = src;
+
+ while (*d != 0)
+ d++;
+ do {
+ if ((*d = *s++) == 0)
+ break;
+ d++;
+ } while (--n != 0);
+ *d = 0;
+ }
+ return (dst);
+}
+
+static int
+ntoskrnl_toupper(c)
+ int c;
+{
+ return (toupper(c));
+}
+
+static int
+ntoskrnl_tolower(c)
+ int c;
+{
+ return (tolower(c));
+}
+
+static uint8_t
+RtlEqualUnicodeString(unicode_string *str1, unicode_string *str2,
+ uint8_t caseinsensitive)
+{
+ int i;
+
+ if (str1->us_len != str2->us_len)
+ return (FALSE);
+
+ for (i = 0; i < str1->us_len; i++) {
+ if (caseinsensitive == TRUE) {
+ if (toupper((char)(str1->us_buf[i] & 0xFF)) !=
+ toupper((char)(str2->us_buf[i] & 0xFF)))
+ return (FALSE);
+ } else {
+ if (str1->us_buf[i] != str2->us_buf[i])
+ return (FALSE);
+ }
+ }
+
+ return (TRUE);
+}
+
+static void
+RtlCopyString(dst, src)
+ ansi_string *dst;
+ const ansi_string *src;
+{
+ if (src != NULL && src->as_buf != NULL && dst->as_buf != NULL) {
+ dst->as_len = min(src->as_len, dst->as_maxlen);
+ memcpy(dst->as_buf, src->as_buf, dst->as_len);
+ if (dst->as_len < dst->as_maxlen)
+ dst->as_buf[dst->as_len] = 0;
+ } else
+ dst->as_len = 0;
+}
+
+static void
+RtlCopyUnicodeString(dest, src)
+ unicode_string *dest;
+ unicode_string *src;
+{
+
+ if (dest->us_maxlen >= src->us_len)
+ dest->us_len = src->us_len;
+ else
+ dest->us_len = dest->us_maxlen;
+ memcpy(dest->us_buf, src->us_buf, dest->us_len);
+}
+
+static void
+ntoskrnl_ascii_to_unicode(ascii, unicode, len)
+ char *ascii;
+ uint16_t *unicode;
+ int len;
+{
+ int i;
+ uint16_t *ustr;
+
+ ustr = unicode;
+ for (i = 0; i < len; i++) {
+ *ustr = (uint16_t)ascii[i];
+ ustr++;
+ }
+}
+
+static void
+ntoskrnl_unicode_to_ascii(unicode, ascii, len)
+ uint16_t *unicode;
+ char *ascii;
+ int len;
+{
+ int i;
+ uint8_t *astr;
+
+ astr = ascii;
+ for (i = 0; i < len / 2; i++) {
+ *astr = (uint8_t)unicode[i];
+ astr++;
+ }
+}
+
+uint32_t
+RtlUnicodeStringToAnsiString(ansi_string *dest, unicode_string *src, uint8_t allocate)
+{
+ if (dest == NULL || src == NULL)
+ return (STATUS_INVALID_PARAMETER);
+
+ dest->as_len = src->us_len / 2;
+ if (dest->as_maxlen < dest->as_len)
+ dest->as_len = dest->as_maxlen;
+
+ if (allocate == TRUE) {
+ dest->as_buf = ExAllocatePoolWithTag(NonPagedPool,
+ (src->us_len / 2) + 1, 0);
+ if (dest->as_buf == NULL)
+ return (STATUS_INSUFFICIENT_RESOURCES);
+ dest->as_len = dest->as_maxlen = src->us_len / 2;
+ } else {
+ dest->as_len = src->us_len / 2; /* XXX */
+ if (dest->as_maxlen < dest->as_len)
+ dest->as_len = dest->as_maxlen;
+ }
+
+ ntoskrnl_unicode_to_ascii(src->us_buf, dest->as_buf,
+ dest->as_len * 2);
+
+ return (STATUS_SUCCESS);
+}
+
+uint32_t
+RtlAnsiStringToUnicodeString(unicode_string *dest, ansi_string *src,
+ uint8_t allocate)
+{
+ if (dest == NULL || src == NULL)
+ return (STATUS_INVALID_PARAMETER);
+
+ if (allocate == TRUE) {
+ dest->us_buf = ExAllocatePoolWithTag(NonPagedPool,
+ src->as_len * 2, 0);
+ if (dest->us_buf == NULL)
+ return (STATUS_INSUFFICIENT_RESOURCES);
+ dest->us_len = dest->us_maxlen = strlen(src->as_buf) * 2;
+ } else {
+ dest->us_len = src->as_len * 2; /* XXX */
+ if (dest->us_maxlen < dest->us_len)
+ dest->us_len = dest->us_maxlen;
+ }
+
+ ntoskrnl_ascii_to_unicode(src->as_buf, dest->us_buf,
+ dest->us_len / 2);
+
+ return (STATUS_SUCCESS);
+}
+
+void *
+ExAllocatePoolWithTag(pooltype, len, tag)
+ uint32_t pooltype;
+ size_t len;
+ uint32_t tag;
+{
+ void *buf;
+
+ buf = malloc(len, M_DEVBUF, M_NOWAIT|M_ZERO);
+ if (buf == NULL)
+ return (NULL);
+
+ return (buf);
+}
+
+static void
+ExFreePoolWithTag(buf, tag)
+ void *buf;
+ uint32_t tag;
+{
+ ExFreePool(buf);
+}
+
+void
+ExFreePool(buf)
+ void *buf;
+{
+ free(buf, M_DEVBUF);
+}
+
+uint32_t
+IoAllocateDriverObjectExtension(drv, clid, extlen, ext)
+ driver_object *drv;
+ void *clid;
+ uint32_t extlen;
+ void **ext;
+{
+ custom_extension *ce;
+
+ ce = ExAllocatePoolWithTag(NonPagedPool, sizeof(custom_extension)
+ + extlen, 0);
+
+ if (ce == NULL)
+ return (STATUS_INSUFFICIENT_RESOURCES);
+
+ ce->ce_clid = clid;
+ InsertTailList((&drv->dro_driverext->dre_usrext), (&ce->ce_list));
+
+ *ext = (void *)(ce + 1);
+
+ return (STATUS_SUCCESS);
+}
+
+void *
+IoGetDriverObjectExtension(drv, clid)
+ driver_object *drv;
+ void *clid;
+{
+ list_entry *e;
+ custom_extension *ce;
+
+ /*
+ * Sanity check. Our dummy bus drivers don't have
+ * any driver extentions.
+ */
+
+ if (drv->dro_driverext == NULL)
+ return (NULL);
+
+ e = drv->dro_driverext->dre_usrext.nle_flink;
+ while (e != &drv->dro_driverext->dre_usrext) {
+ ce = (custom_extension *)e;
+ if (ce->ce_clid == clid)
+ return ((void *)(ce + 1));
+ e = e->nle_flink;
+ }
+
+ return (NULL);
+}
+
+
+uint32_t
+IoCreateDevice(driver_object *drv, uint32_t devextlen, unicode_string *devname,
+ uint32_t devtype, uint32_t devchars, uint8_t exclusive,
+ device_object **newdev)
+{
+ device_object *dev;
+
+ dev = ExAllocatePoolWithTag(NonPagedPool, sizeof(device_object), 0);
+ if (dev == NULL)
+ return (STATUS_INSUFFICIENT_RESOURCES);
+
+ dev->do_type = devtype;
+ dev->do_drvobj = drv;
+ dev->do_currirp = NULL;
+ dev->do_flags = 0;
+
+ if (devextlen) {
+ dev->do_devext = ExAllocatePoolWithTag(NonPagedPool,
+ devextlen, 0);
+
+ if (dev->do_devext == NULL) {
+ ExFreePool(dev);
+ return (STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ bzero(dev->do_devext, devextlen);
+ } else
+ dev->do_devext = NULL;
+
+ dev->do_size = sizeof(device_object) + devextlen;
+ dev->do_refcnt = 1;
+ dev->do_attacheddev = NULL;
+ dev->do_nextdev = NULL;
+ dev->do_devtype = devtype;
+ dev->do_stacksize = 1;
+ dev->do_alignreq = 1;
+ dev->do_characteristics = devchars;
+ dev->do_iotimer = NULL;
+ KeInitializeEvent(&dev->do_devlock, EVENT_TYPE_SYNC, TRUE);
+
+ /*
+ * Vpd is used for disk/tape devices,
+ * but we don't support those. (Yet.)
+ */
+ dev->do_vpb = NULL;
+
+ dev->do_devobj_ext = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(devobj_extension), 0);
+
+ if (dev->do_devobj_ext == NULL) {
+ if (dev->do_devext != NULL)
+ ExFreePool(dev->do_devext);
+ ExFreePool(dev);
+ return (STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ dev->do_devobj_ext->dve_type = 0;
+ dev->do_devobj_ext->dve_size = sizeof(devobj_extension);
+ dev->do_devobj_ext->dve_devobj = dev;
+
+ /*
+ * Attach this device to the driver object's list
+ * of devices. Note: this is not the same as attaching
+ * the device to the device stack. The driver's AddDevice
+ * routine must explicitly call IoAddDeviceToDeviceStack()
+ * to do that.
+ */
+
+ if (drv->dro_devobj == NULL) {
+ drv->dro_devobj = dev;
+ dev->do_nextdev = NULL;
+ } else {
+ dev->do_nextdev = drv->dro_devobj;
+ drv->dro_devobj = dev;
+ }
+
+ *newdev = dev;
+
+ return (STATUS_SUCCESS);
+}
+
+void
+IoDeleteDevice(dev)
+ device_object *dev;
+{
+ device_object *prev;
+
+ if (dev == NULL)
+ return;
+
+ if (dev->do_devobj_ext != NULL)
+ ExFreePool(dev->do_devobj_ext);
+
+ if (dev->do_devext != NULL)
+ ExFreePool(dev->do_devext);
+
+ /* Unlink the device from the driver's device list. */
+
+ prev = dev->do_drvobj->dro_devobj;
+ if (prev == dev)
+ dev->do_drvobj->dro_devobj = dev->do_nextdev;
+ else {
+ while (prev->do_nextdev != dev)
+ prev = prev->do_nextdev;
+ prev->do_nextdev = dev->do_nextdev;
+ }
+
+ ExFreePool(dev);
+}
+
+device_object *
+IoGetAttachedDevice(dev)
+ device_object *dev;
+{
+ device_object *d;
+
+ if (dev == NULL)
+ return (NULL);
+
+ d = dev;
+
+ while (d->do_attacheddev != NULL)
+ d = d->do_attacheddev;
+
+ return (d);
+}
+
+static irp *
+IoBuildSynchronousFsdRequest(func, dobj, buf, len, off, event, status)
+ uint32_t func;
+ device_object *dobj;
+ void *buf;
+ uint32_t len;
+ uint64_t *off;
+ nt_kevent *event;
+ io_status_block *status;
+{
+ irp *ip;
+
+ ip = IoBuildAsynchronousFsdRequest(func, dobj, buf, len, off, status);
+ if (ip == NULL)
+ return (NULL);
+ ip->irp_usrevent = event;
+
+ return (ip);
+}
+
+static irp *
+IoBuildAsynchronousFsdRequest(func, dobj, buf, len, off, status)
+ uint32_t func;
+ device_object *dobj;
+ void *buf;
+ uint32_t len;
+ uint64_t *off;
+ io_status_block *status;
+{
+ irp *ip;
+ io_stack_location *sl;
+
+ ip = IoAllocateIrp(dobj->do_stacksize, TRUE);
+ if (ip == NULL)
+ return (NULL);
+
+ ip->irp_usriostat = status;
+ ip->irp_tail.irp_overlay.irp_thread = NULL;
+
+ sl = IoGetNextIrpStackLocation(ip);
+ sl->isl_major = func;
+ sl->isl_minor = 0;
+ sl->isl_flags = 0;
+ sl->isl_ctl = 0;
+ sl->isl_devobj = dobj;
+ sl->isl_fileobj = NULL;
+ sl->isl_completionfunc = NULL;
+
+ ip->irp_userbuf = buf;
+
+ if (dobj->do_flags & DO_BUFFERED_IO) {
+ ip->irp_assoc.irp_sysbuf =
+ ExAllocatePoolWithTag(NonPagedPool, len, 0);
+ if (ip->irp_assoc.irp_sysbuf == NULL) {
+ IoFreeIrp(ip);
+ return (NULL);
+ }
+ bcopy(buf, ip->irp_assoc.irp_sysbuf, len);
+ }
+
+ if (dobj->do_flags & DO_DIRECT_IO) {
+ ip->irp_mdl = IoAllocateMdl(buf, len, FALSE, FALSE, ip);
+ if (ip->irp_mdl == NULL) {
+ if (ip->irp_assoc.irp_sysbuf != NULL)
+ ExFreePool(ip->irp_assoc.irp_sysbuf);
+ IoFreeIrp(ip);
+ return (NULL);
+ }
+ ip->irp_userbuf = NULL;
+ ip->irp_assoc.irp_sysbuf = NULL;
+ }
+
+ if (func == IRP_MJ_READ) {
+ sl->isl_parameters.isl_read.isl_len = len;
+ if (off != NULL)
+ sl->isl_parameters.isl_read.isl_byteoff = *off;
+ else
+ sl->isl_parameters.isl_read.isl_byteoff = 0;
+ }
+
+ if (func == IRP_MJ_WRITE) {
+ sl->isl_parameters.isl_write.isl_len = len;
+ if (off != NULL)
+ sl->isl_parameters.isl_write.isl_byteoff = *off;
+ else
+ sl->isl_parameters.isl_write.isl_byteoff = 0;
+ }
+
+ return (ip);
+}
+
+static irp *
+IoBuildDeviceIoControlRequest(uint32_t iocode, device_object *dobj, void *ibuf,
+ uint32_t ilen, void *obuf, uint32_t olen, uint8_t isinternal,
+ nt_kevent *event, io_status_block *status)
+{
+ irp *ip;
+ io_stack_location *sl;
+ uint32_t buflen;
+
+ ip = IoAllocateIrp(dobj->do_stacksize, TRUE);
+ if (ip == NULL)
+ return (NULL);
+ ip->irp_usrevent = event;
+ ip->irp_usriostat = status;
+ ip->irp_tail.irp_overlay.irp_thread = NULL;
+
+ sl = IoGetNextIrpStackLocation(ip);
+ sl->isl_major = isinternal == TRUE ?
+ IRP_MJ_INTERNAL_DEVICE_CONTROL : IRP_MJ_DEVICE_CONTROL;
+ sl->isl_minor = 0;
+ sl->isl_flags = 0;
+ sl->isl_ctl = 0;
+ sl->isl_devobj = dobj;
+ sl->isl_fileobj = NULL;
+ sl->isl_completionfunc = NULL;
+ sl->isl_parameters.isl_ioctl.isl_iocode = iocode;
+ sl->isl_parameters.isl_ioctl.isl_ibuflen = ilen;
+ sl->isl_parameters.isl_ioctl.isl_obuflen = olen;
+
+ switch(IO_METHOD(iocode)) {
+ case METHOD_BUFFERED:
+ if (ilen > olen)
+ buflen = ilen;
+ else
+ buflen = olen;
+ if (buflen) {
+ ip->irp_assoc.irp_sysbuf =
+ ExAllocatePoolWithTag(NonPagedPool, buflen, 0);
+ if (ip->irp_assoc.irp_sysbuf == NULL) {
+ IoFreeIrp(ip);
+ return (NULL);
+ }
+ }
+ if (ilen && ibuf != NULL) {
+ bcopy(ibuf, ip->irp_assoc.irp_sysbuf, ilen);
+ bzero((char *)ip->irp_assoc.irp_sysbuf + ilen,
+ buflen - ilen);
+ } else
+ bzero(ip->irp_assoc.irp_sysbuf, ilen);
+ ip->irp_userbuf = obuf;
+ break;
+ case METHOD_IN_DIRECT:
+ case METHOD_OUT_DIRECT:
+ if (ilen && ibuf != NULL) {
+ ip->irp_assoc.irp_sysbuf =
+ ExAllocatePoolWithTag(NonPagedPool, ilen, 0);
+ if (ip->irp_assoc.irp_sysbuf == NULL) {
+ IoFreeIrp(ip);
+ return (NULL);
+ }
+ bcopy(ibuf, ip->irp_assoc.irp_sysbuf, ilen);
+ }
+ if (olen && obuf != NULL) {
+ ip->irp_mdl = IoAllocateMdl(obuf, olen,
+ FALSE, FALSE, ip);
+ /*
+ * Normally we would MmProbeAndLockPages()
+ * here, but we don't have to in our
+ * imlementation.
+ */
+ }
+ break;
+ case METHOD_NEITHER:
+ ip->irp_userbuf = obuf;
+ sl->isl_parameters.isl_ioctl.isl_type3ibuf = ibuf;
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Ideally, we should associate this IRP with the calling
+ * thread here.
+ */
+
+ return (ip);
+}
+
+static irp *
+IoAllocateIrp(uint8_t stsize, uint8_t chargequota)
+{
+ irp *i;
+
+ i = ExAllocatePoolWithTag(NonPagedPool, IoSizeOfIrp(stsize), 0);
+ if (i == NULL)
+ return (NULL);
+
+ IoInitializeIrp(i, IoSizeOfIrp(stsize), stsize);
+
+ return (i);
+}
+
+static irp *
+IoMakeAssociatedIrp(irp *ip, uint8_t stsize)
+{
+ irp *associrp;
+
+ associrp = IoAllocateIrp(stsize, FALSE);
+ if (associrp == NULL)
+ return (NULL);
+
+ mtx_lock(&ntoskrnl_dispatchlock);
+ associrp->irp_flags |= IRP_ASSOCIATED_IRP;
+ associrp->irp_tail.irp_overlay.irp_thread =
+ ip->irp_tail.irp_overlay.irp_thread;
+ associrp->irp_assoc.irp_master = ip;
+ mtx_unlock(&ntoskrnl_dispatchlock);
+
+ return (associrp);
+}
+
+static void
+IoFreeIrp(ip)
+ irp *ip;
+{
+ ExFreePool(ip);
+}
+
+static void
+IoInitializeIrp(irp *io, uint16_t psize, uint8_t ssize)
+{
+ bzero((char *)io, IoSizeOfIrp(ssize));
+ io->irp_size = psize;
+ io->irp_stackcnt = ssize;
+ io->irp_currentstackloc = ssize;
+ InitializeListHead(&io->irp_thlist);
+ io->irp_tail.irp_overlay.irp_csl =
+ (io_stack_location *)(io + 1) + ssize;
+}
+
+static void
+IoReuseIrp(ip, status)
+ irp *ip;
+ uint32_t status;
+{
+ uint8_t allocflags;
+
+ allocflags = ip->irp_allocflags;
+ IoInitializeIrp(ip, ip->irp_size, ip->irp_stackcnt);
+ ip->irp_iostat.isb_status = status;
+ ip->irp_allocflags = allocflags;
+}
+
+void
+IoAcquireCancelSpinLock(uint8_t *irql)
+{
+ KeAcquireSpinLock(&ntoskrnl_cancellock, irql);
+}
+
+void
+IoReleaseCancelSpinLock(uint8_t irql)
+{
+ KeReleaseSpinLock(&ntoskrnl_cancellock, irql);
+}
+
+uint8_t
+IoCancelIrp(irp *ip)
+{
+ cancel_func cfunc;
+ uint8_t cancelirql;
+
+ IoAcquireCancelSpinLock(&cancelirql);
+ cfunc = IoSetCancelRoutine(ip, NULL);
+ ip->irp_cancel = TRUE;
+ if (cfunc == NULL) {
+ IoReleaseCancelSpinLock(cancelirql);
+ return (FALSE);
+ }
+ ip->irp_cancelirql = cancelirql;
+ MSCALL2(cfunc, IoGetCurrentIrpStackLocation(ip)->isl_devobj, ip);
+ return (uint8_t)IoSetCancelValue(ip, TRUE);
+}
+
+uint32_t
+IofCallDriver(dobj, ip)
+ device_object *dobj;
+ irp *ip;
+{
+ driver_object *drvobj;
+ io_stack_location *sl;
+ uint32_t status;
+ driver_dispatch disp;
+
+ drvobj = dobj->do_drvobj;
+
+ if (ip->irp_currentstackloc <= 0)
+ panic("IoCallDriver(): out of stack locations");
+
+ IoSetNextIrpStackLocation(ip);
+ sl = IoGetCurrentIrpStackLocation(ip);
+
+ sl->isl_devobj = dobj;
+
+ disp = drvobj->dro_dispatch[sl->isl_major];
+ status = MSCALL2(disp, dobj, ip);
+
+ return (status);
+}
+
+void
+IofCompleteRequest(irp *ip, uint8_t prioboost)
+{
+ uint32_t status;
+ device_object *dobj;
+ io_stack_location *sl;
+ completion_func cf;
+
+ KASSERT(ip->irp_iostat.isb_status != STATUS_PENDING,
+ ("incorrect IRP(%p) status (STATUS_PENDING)", ip));
+
+ sl = IoGetCurrentIrpStackLocation(ip);
+ IoSkipCurrentIrpStackLocation(ip);
+
+ do {
+ if (sl->isl_ctl & SL_PENDING_RETURNED)
+ ip->irp_pendingreturned = TRUE;
+
+ if (ip->irp_currentstackloc != (ip->irp_stackcnt + 1))
+ dobj = IoGetCurrentIrpStackLocation(ip)->isl_devobj;
+ else
+ dobj = NULL;
+
+ if (sl->isl_completionfunc != NULL &&
+ ((ip->irp_iostat.isb_status == STATUS_SUCCESS &&
+ sl->isl_ctl & SL_INVOKE_ON_SUCCESS) ||
+ (ip->irp_iostat.isb_status != STATUS_SUCCESS &&
+ sl->isl_ctl & SL_INVOKE_ON_ERROR) ||
+ (ip->irp_cancel == TRUE &&
+ sl->isl_ctl & SL_INVOKE_ON_CANCEL))) {
+ cf = sl->isl_completionfunc;
+ status = MSCALL3(cf, dobj, ip, sl->isl_completionctx);
+ if (status == STATUS_MORE_PROCESSING_REQUIRED)
+ return;
+ } else {
+ if ((ip->irp_currentstackloc <= ip->irp_stackcnt) &&
+ (ip->irp_pendingreturned == TRUE))
+ IoMarkIrpPending(ip);
+ }
+
+ /* move to the next. */
+ IoSkipCurrentIrpStackLocation(ip);
+ sl++;
+ } while (ip->irp_currentstackloc <= (ip->irp_stackcnt + 1));
+
+ if (ip->irp_usriostat != NULL)
+ *ip->irp_usriostat = ip->irp_iostat;
+ if (ip->irp_usrevent != NULL)
+ KeSetEvent(ip->irp_usrevent, prioboost, FALSE);
+
+ /* Handle any associated IRPs. */
+
+ if (ip->irp_flags & IRP_ASSOCIATED_IRP) {
+ uint32_t masterirpcnt;
+ irp *masterirp;
+ mdl *m;
+
+ masterirp = ip->irp_assoc.irp_master;
+ masterirpcnt =
+ InterlockedDecrement(&masterirp->irp_assoc.irp_irpcnt);
+
+ while ((m = ip->irp_mdl) != NULL) {
+ ip->irp_mdl = m->mdl_next;
+ IoFreeMdl(m);
+ }
+ IoFreeIrp(ip);
+ if (masterirpcnt == 0)
+ IoCompleteRequest(masterirp, IO_NO_INCREMENT);
+ return;
+ }
+
+ /* With any luck, these conditions will never arise. */
+
+ if (ip->irp_flags & IRP_PAGING_IO) {
+ if (ip->irp_mdl != NULL)
+ IoFreeMdl(ip->irp_mdl);
+ IoFreeIrp(ip);
+ }
+}
+
+void
+ntoskrnl_intr(arg)
+ void *arg;
+{
+ kinterrupt *iobj;
+ uint8_t irql;
+ uint8_t claimed;
+ list_entry *l;
+
+ KeAcquireSpinLock(&ntoskrnl_intlock, &irql);
+ l = ntoskrnl_intlist.nle_flink;
+ while (l != &ntoskrnl_intlist) {
+ iobj = CONTAINING_RECORD(l, kinterrupt, ki_list);
+ claimed = MSCALL2(iobj->ki_svcfunc, iobj, iobj->ki_svcctx);
+ if (claimed == TRUE)
+ break;
+ l = l->nle_flink;
+ }
+ KeReleaseSpinLock(&ntoskrnl_intlock, irql);
+}
+
+uint8_t
+KeAcquireInterruptSpinLock(iobj)
+ kinterrupt *iobj;
+{
+ uint8_t irql;
+ KeAcquireSpinLock(&ntoskrnl_intlock, &irql);
+ return (irql);
+}
+
+void
+KeReleaseInterruptSpinLock(kinterrupt *iobj, uint8_t irql)
+{
+ KeReleaseSpinLock(&ntoskrnl_intlock, irql);
+}
+
+uint8_t
+KeSynchronizeExecution(iobj, syncfunc, syncctx)
+ kinterrupt *iobj;
+ void *syncfunc;
+ void *syncctx;
+{
+ uint8_t irql;
+
+ KeAcquireSpinLock(&ntoskrnl_intlock, &irql);
+ MSCALL1(syncfunc, syncctx);
+ KeReleaseSpinLock(&ntoskrnl_intlock, irql);
+
+ return (TRUE);
+}
+
+/*
+ * IoConnectInterrupt() is passed only the interrupt vector and
+ * irql that a device wants to use, but no device-specific tag
+ * of any kind. This conflicts rather badly with FreeBSD's
+ * bus_setup_intr(), which needs the device_t for the device
+ * requesting interrupt delivery. In order to bypass this
+ * inconsistency, we implement a second level of interrupt
+ * dispatching on top of bus_setup_intr(). All devices use
+ * ntoskrnl_intr() as their ISR, and any device requesting
+ * interrupts will be registered with ntoskrnl_intr()'s interrupt
+ * dispatch list. When an interrupt arrives, we walk the list
+ * and invoke all the registered ISRs. This effectively makes all
+ * interrupts shared, but it's the only way to duplicate the
+ * semantics of IoConnectInterrupt() and IoDisconnectInterrupt() properly.
+ */
+
+uint32_t
+IoConnectInterrupt(kinterrupt **iobj, void *svcfunc, void *svcctx,
+ kspin_lock *lock, uint32_t vector, uint8_t irql, uint8_t syncirql,
+ uint8_t imode, uint8_t shared, uint32_t affinity, uint8_t savefloat)
+{
+ uint8_t curirql;
+
+ *iobj = ExAllocatePoolWithTag(NonPagedPool, sizeof(kinterrupt), 0);
+ if (*iobj == NULL)
+ return (STATUS_INSUFFICIENT_RESOURCES);
+
+ (*iobj)->ki_svcfunc = svcfunc;
+ (*iobj)->ki_svcctx = svcctx;
+
+ if (lock == NULL) {
+ KeInitializeSpinLock(&(*iobj)->ki_lock_priv);
+ (*iobj)->ki_lock = &(*iobj)->ki_lock_priv;
+ } else
+ (*iobj)->ki_lock = lock;
+
+ KeAcquireSpinLock(&ntoskrnl_intlock, &curirql);
+ InsertHeadList((&ntoskrnl_intlist), (&(*iobj)->ki_list));
+ KeReleaseSpinLock(&ntoskrnl_intlock, curirql);
+
+ return (STATUS_SUCCESS);
+}
+
+void
+IoDisconnectInterrupt(iobj)
+ kinterrupt *iobj;
+{
+ uint8_t irql;
+
+ if (iobj == NULL)
+ return;
+
+ KeAcquireSpinLock(&ntoskrnl_intlock, &irql);
+ RemoveEntryList((&iobj->ki_list));
+ KeReleaseSpinLock(&ntoskrnl_intlock, irql);
+
+ ExFreePool(iobj);
+}
+
+device_object *
+IoAttachDeviceToDeviceStack(src, dst)
+ device_object *src;
+ device_object *dst;
+{
+ device_object *attached;
+
+ mtx_lock(&ntoskrnl_dispatchlock);
+ attached = IoGetAttachedDevice(dst);
+ attached->do_attacheddev = src;
+ src->do_attacheddev = NULL;
+ src->do_stacksize = attached->do_stacksize + 1;
+ mtx_unlock(&ntoskrnl_dispatchlock);
+
+ return (attached);
+}
+
+void
+IoDetachDevice(topdev)
+ device_object *topdev;
+{
+ device_object *tail;
+
+ mtx_lock(&ntoskrnl_dispatchlock);
+
+ /* First, break the chain. */
+ tail = topdev->do_attacheddev;
+ if (tail == NULL) {
+ mtx_unlock(&ntoskrnl_dispatchlock);
+ return;
+ }
+ topdev->do_attacheddev = tail->do_attacheddev;
+ topdev->do_refcnt--;
+
+ /* Now reduce the stacksize count for the takm_il objects. */
+
+ tail = topdev->do_attacheddev;
+ while (tail != NULL) {
+ tail->do_stacksize--;
+ tail = tail->do_attacheddev;
+ }
+
+ mtx_unlock(&ntoskrnl_dispatchlock);
+}
+
+/*
+ * For the most part, an object is considered signalled if
+ * dh_sigstate == TRUE. The exception is for mutant objects
+ * (mutexes), where the logic works like this:
+ *
+ * - If the thread already owns the object and sigstate is
+ * less than or equal to 0, then the object is considered
+ * signalled (recursive acquisition).
+ * - If dh_sigstate == 1, the object is also considered
+ * signalled.
+ */
+
+static int
+ntoskrnl_is_signalled(obj, td)
+ nt_dispatch_header *obj;
+ struct thread *td;
+{
+ kmutant *km;
+
+ if (obj->dh_type == DISP_TYPE_MUTANT) {
+ km = (kmutant *)obj;
+ if ((obj->dh_sigstate <= 0 && km->km_ownerthread == td) ||
+ obj->dh_sigstate == 1)
+ return (TRUE);
+ return (FALSE);
+ }
+
+ if (obj->dh_sigstate > 0)
+ return (TRUE);
+ return (FALSE);
+}
+
+static void
+ntoskrnl_satisfy_wait(obj, td)
+ nt_dispatch_header *obj;
+ struct thread *td;
+{
+ kmutant *km;
+
+ switch (obj->dh_type) {
+ case DISP_TYPE_MUTANT:
+ km = (struct kmutant *)obj;
+ obj->dh_sigstate--;
+ /*
+ * If sigstate reaches 0, the mutex is now
+ * non-signalled (the new thread owns it).
+ */
+ if (obj->dh_sigstate == 0) {
+ km->km_ownerthread = td;
+ if (km->km_abandoned == TRUE)
+ km->km_abandoned = FALSE;
+ }
+ break;
+ /* Synchronization objects get reset to unsignalled. */
+ case DISP_TYPE_SYNCHRONIZATION_EVENT:
+ case DISP_TYPE_SYNCHRONIZATION_TIMER:
+ obj->dh_sigstate = 0;
+ break;
+ case DISP_TYPE_SEMAPHORE:
+ obj->dh_sigstate--;
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+ntoskrnl_satisfy_multiple_waits(wb)
+ wait_block *wb;
+{
+ wait_block *cur;
+ struct thread *td;
+
+ cur = wb;
+ td = wb->wb_kthread;
+
+ do {
+ ntoskrnl_satisfy_wait(wb->wb_object, td);
+ cur->wb_awakened = TRUE;
+ cur = cur->wb_next;
+ } while (cur != wb);
+}
+
+/* Always called with dispatcher lock held. */
+static void
+ntoskrnl_waittest(obj, increment)
+ nt_dispatch_header *obj;
+ uint32_t increment;
+{
+ wait_block *w, *next;
+ list_entry *e;
+ struct thread *td;
+ wb_ext *we;
+ int satisfied;
+
+ /*
+ * Once an object has been signalled, we walk its list of
+ * wait blocks. If a wait block can be awakened, then satisfy
+ * waits as necessary and wake the thread.
+ *
+ * The rules work like this:
+ *
+ * If a wait block is marked as WAITTYPE_ANY, then
+ * we can satisfy the wait conditions on the current
+ * object and wake the thread right away. Satisfying
+ * the wait also has the effect of breaking us out
+ * of the search loop.
+ *
+ * If the object is marked as WAITTYLE_ALL, then the
+ * wait block will be part of a circularly linked
+ * list of wait blocks belonging to a waiting thread
+ * that's sleeping in KeWaitForMultipleObjects(). In
+ * order to wake the thread, all the objects in the
+ * wait list must be in the signalled state. If they
+ * are, we then satisfy all of them and wake the
+ * thread.
+ *
+ */
+
+ e = obj->dh_waitlisthead.nle_flink;
+
+ while (e != &obj->dh_waitlisthead && obj->dh_sigstate > 0) {
+ w = CONTAINING_RECORD(e, wait_block, wb_waitlist);
+ we = w->wb_ext;
+ td = we->we_td;
+ satisfied = FALSE;
+ if (w->wb_waittype == WAITTYPE_ANY) {
+ /*
+ * Thread can be awakened if
+ * any wait is satisfied.
+ */
+ ntoskrnl_satisfy_wait(obj, td);
+ satisfied = TRUE;
+ w->wb_awakened = TRUE;
+ } else {
+ /*
+ * Thread can only be woken up
+ * if all waits are satisfied.
+ * If the thread is waiting on multiple
+ * objects, they should all be linked
+ * through the wb_next pointers in the
+ * wait blocks.
+ */
+ satisfied = TRUE;
+ next = w->wb_next;
+ while (next != w) {
+ if (ntoskrnl_is_signalled(obj, td) == FALSE) {
+ satisfied = FALSE;
+ break;
+ }
+ next = next->wb_next;
+ }
+ ntoskrnl_satisfy_multiple_waits(w);
+ }
+
+ if (satisfied == TRUE)
+ cv_broadcastpri(&we->we_cv,
+ (w->wb_oldpri - (increment * 4)) > PRI_MIN_KERN ?
+ w->wb_oldpri - (increment * 4) : PRI_MIN_KERN);
+
+ e = e->nle_flink;
+ }
+}
+
+/*
+ * Return the number of 100 nanosecond intervals since
+ * January 1, 1601. (?!?!)
+ */
+void
+ntoskrnl_time(tval)
+ uint64_t *tval;
+{
+ struct timespec ts;
+
+ nanotime(&ts);
+ *tval = (uint64_t)ts.tv_nsec / 100 + (uint64_t)ts.tv_sec * 10000000 +
+ 11644473600 * 10000000; /* 100ns ticks from 1601 to 1970 */
+}
+
+static void
+KeQuerySystemTime(current_time)
+ uint64_t *current_time;
+{
+ ntoskrnl_time(current_time);
+}
+
+static uint32_t
+KeTickCount(void)
+{
+ struct timeval tv;
+ getmicrouptime(&tv);
+ return tvtohz(&tv);
+}
+
+
+/*
+ * KeWaitForSingleObject() is a tricky beast, because it can be used
+ * with several different object types: semaphores, timers, events,
+ * mutexes and threads. Semaphores don't appear very often, but the
+ * other object types are quite common. KeWaitForSingleObject() is
+ * what's normally used to acquire a mutex, and it can be used to
+ * wait for a thread termination.
+ *
+ * The Windows NDIS API is implemented in terms of Windows kernel
+ * primitives, and some of the object manipulation is duplicated in
+ * NDIS. For example, NDIS has timers and events, which are actually
+ * Windows kevents and ktimers. Now, you're supposed to only use the
+ * NDIS variants of these objects within the confines of the NDIS API,
+ * but there are some naughty developers out there who will use
+ * KeWaitForSingleObject() on NDIS timer and event objects, so we
+ * have to support that as well. Conseqently, our NDIS timer and event
+ * code has to be closely tied into our ntoskrnl timer and event code,
+ * just as it is in Windows.
+ *
+ * KeWaitForSingleObject() may do different things for different kinds
+ * of objects:
+ *
+ * - For events, we check if the event has been signalled. If the
+ * event is already in the signalled state, we just return immediately,
+ * otherwise we wait for it to be set to the signalled state by someone
+ * else calling KeSetEvent(). Events can be either synchronization or
+ * notification events.
+ *
+ * - For timers, if the timer has already fired and the timer is in
+ * the signalled state, we just return, otherwise we wait on the
+ * timer. Unlike an event, timers get signalled automatically when
+ * they expire rather than someone having to trip them manually.
+ * Timers initialized with KeInitializeTimer() are always notification
+ * events: KeInitializeTimerEx() lets you initialize a timer as
+ * either a notification or synchronization event.
+ *
+ * - For mutexes, we try to acquire the mutex and if we can't, we wait
+ * on the mutex until it's available and then grab it. When a mutex is
+ * released, it enters the signalled state, which wakes up one of the
+ * threads waiting to acquire it. Mutexes are always synchronization
+ * events.
+ *
+ * - For threads, the only thing we do is wait until the thread object
+ * enters a signalled state, which occurs when the thread terminates.
+ * Threads are always notification events.
+ *
+ * A notification event wakes up all threads waiting on an object. A
+ * synchronization event wakes up just one. Also, a synchronization event
+ * is auto-clearing, which means we automatically set the event back to
+ * the non-signalled state once the wakeup is done.
+ */
+
+uint32_t
+KeWaitForSingleObject(void *arg, uint32_t reason, uint32_t mode,
+ uint8_t alertable, int64_t *duetime)
+{
+ wait_block w;
+ struct thread *td = curthread;
+ struct timeval tv;
+ int error = 0;
+ uint64_t curtime;
+ wb_ext we;
+ nt_dispatch_header *obj;
+
+ obj = arg;
+
+ if (obj == NULL)
+ return (STATUS_INVALID_PARAMETER);
+
+ mtx_lock(&ntoskrnl_dispatchlock);
+
+ cv_init(&we.we_cv, "KeWFS");
+ we.we_td = td;
+
+ /*
+ * Check to see if this object is already signalled,
+ * and just return without waiting if it is.
+ */
+ if (ntoskrnl_is_signalled(obj, td) == TRUE) {
+ /* Sanity check the signal state value. */
+ if (obj->dh_sigstate != INT32_MIN) {
+ ntoskrnl_satisfy_wait(obj, curthread);
+ mtx_unlock(&ntoskrnl_dispatchlock);
+ return (STATUS_SUCCESS);
+ } else {
+ /*
+ * There's a limit to how many times we can
+ * recursively acquire a mutant. If we hit
+ * the limit, something is very wrong.
+ */
+ if (obj->dh_type == DISP_TYPE_MUTANT) {
+ mtx_unlock(&ntoskrnl_dispatchlock);
+ panic("mutant limit exceeded");
+ }
+ }
+ }
+
+ bzero((char *)&w, sizeof(wait_block));
+ w.wb_object = obj;
+ w.wb_ext = &we;
+ w.wb_waittype = WAITTYPE_ANY;
+ w.wb_next = &w;
+ w.wb_waitkey = 0;
+ w.wb_awakened = FALSE;
+ w.wb_oldpri = td->td_priority;
+
+ InsertTailList((&obj->dh_waitlisthead), (&w.wb_waitlist));
+
+ /*
+ * The timeout value is specified in 100 nanosecond units
+ * and can be a positive or negative number. If it's positive,
+ * then the duetime is absolute, and we need to convert it
+ * to an absolute offset relative to now in order to use it.
+ * If it's negative, then the duetime is relative and we
+ * just have to convert the units.
+ */
+
+ if (duetime != NULL) {
+ if (*duetime < 0) {
+ tv.tv_sec = - (*duetime) / 10000000;
+ tv.tv_usec = (- (*duetime) / 10) -
+ (tv.tv_sec * 1000000);
+ } else {
+ ntoskrnl_time(&curtime);
+ if (*duetime < curtime)
+ tv.tv_sec = tv.tv_usec = 0;
+ else {
+ tv.tv_sec = ((*duetime) - curtime) / 10000000;
+ tv.tv_usec = ((*duetime) - curtime) / 10 -
+ (tv.tv_sec * 1000000);
+ }
+ }
+ }
+
+ if (duetime == NULL)
+ cv_wait(&we.we_cv, &ntoskrnl_dispatchlock);
+ else
+ error = cv_timedwait(&we.we_cv,
+ &ntoskrnl_dispatchlock, tvtohz(&tv));
+
+ RemoveEntryList(&w.wb_waitlist);
+
+ cv_destroy(&we.we_cv);
+
+ /* We timed out. Leave the object alone and return status. */
+
+ if (error == EWOULDBLOCK) {
+ mtx_unlock(&ntoskrnl_dispatchlock);
+ return (STATUS_TIMEOUT);
+ }
+
+ mtx_unlock(&ntoskrnl_dispatchlock);
+
+ return (STATUS_SUCCESS);
+/*
+ return (KeWaitForMultipleObjects(1, &obj, WAITTYPE_ALL, reason,
+ mode, alertable, duetime, &w));
+*/
+}
+
+static uint32_t
+KeWaitForMultipleObjects(uint32_t cnt, nt_dispatch_header *obj[], uint32_t wtype,
+ uint32_t reason, uint32_t mode, uint8_t alertable, int64_t *duetime,
+ wait_block *wb_array)
+{
+ struct thread *td = curthread;
+ wait_block *whead, *w;
+ wait_block _wb_array[MAX_WAIT_OBJECTS];
+ nt_dispatch_header *cur;
+ struct timeval tv;
+ int i, wcnt = 0, error = 0;
+ uint64_t curtime;
+ struct timespec t1, t2;
+ uint32_t status = STATUS_SUCCESS;
+ wb_ext we;
+
+ if (cnt > MAX_WAIT_OBJECTS)
+ return (STATUS_INVALID_PARAMETER);
+ if (cnt > THREAD_WAIT_OBJECTS && wb_array == NULL)
+ return (STATUS_INVALID_PARAMETER);
+
+ mtx_lock(&ntoskrnl_dispatchlock);
+
+ cv_init(&we.we_cv, "KeWFM");
+ we.we_td = td;
+
+ if (wb_array == NULL)
+ whead = _wb_array;
+ else
+ whead = wb_array;
+
+ bzero((char *)whead, sizeof(wait_block) * cnt);
+
+ /* First pass: see if we can satisfy any waits immediately. */
+
+ wcnt = 0;
+ w = whead;
+
+ for (i = 0; i < cnt; i++) {
+ InsertTailList((&obj[i]->dh_waitlisthead),
+ (&w->wb_waitlist));
+ w->wb_ext = &we;
+ w->wb_object = obj[i];
+ w->wb_waittype = wtype;
+ w->wb_waitkey = i;
+ w->wb_awakened = FALSE;
+ w->wb_oldpri = td->td_priority;
+ w->wb_next = w + 1;
+ w++;
+ wcnt++;
+ if (ntoskrnl_is_signalled(obj[i], td)) {
+ /*
+ * There's a limit to how many times
+ * we can recursively acquire a mutant.
+ * If we hit the limit, something
+ * is very wrong.
+ */
+ if (obj[i]->dh_sigstate == INT32_MIN &&
+ obj[i]->dh_type == DISP_TYPE_MUTANT) {
+ mtx_unlock(&ntoskrnl_dispatchlock);
+ panic("mutant limit exceeded");
+ }
+
+ /*
+ * If this is a WAITTYPE_ANY wait, then
+ * satisfy the waited object and exit
+ * right now.
+ */
+
+ if (wtype == WAITTYPE_ANY) {
+ ntoskrnl_satisfy_wait(obj[i], td);
+ status = STATUS_WAIT_0 + i;
+ goto wait_done;
+ } else {
+ w--;
+ wcnt--;
+ w->wb_object = NULL;
+ RemoveEntryList(&w->wb_waitlist);
+ }
+ }
+ }
+
+ /*
+ * If this is a WAITTYPE_ALL wait and all objects are
+ * already signalled, satisfy the waits and exit now.
+ */
+
+ if (wtype == WAITTYPE_ALL && wcnt == 0) {
+ for (i = 0; i < cnt; i++)
+ ntoskrnl_satisfy_wait(obj[i], td);
+ status = STATUS_SUCCESS;
+ goto wait_done;
+ }
+
+ /*
+ * Create a circular waitblock list. The waitcount
+ * must always be non-zero when we get here.
+ */
+
+ (w - 1)->wb_next = whead;
+
+ /* Wait on any objects that aren't yet signalled. */
+
+ /* Calculate timeout, if any. */
+
+ if (duetime != NULL) {
+ if (*duetime < 0) {
+ tv.tv_sec = - (*duetime) / 10000000;
+ tv.tv_usec = (- (*duetime) / 10) -
+ (tv.tv_sec * 1000000);
+ } else {
+ ntoskrnl_time(&curtime);
+ if (*duetime < curtime)
+ tv.tv_sec = tv.tv_usec = 0;
+ else {
+ tv.tv_sec = ((*duetime) - curtime) / 10000000;
+ tv.tv_usec = ((*duetime) - curtime) / 10 -
+ (tv.tv_sec * 1000000);
+ }
+ }
+ }
+
+ while (wcnt) {
+ nanotime(&t1);
+
+ if (duetime == NULL)
+ cv_wait(&we.we_cv, &ntoskrnl_dispatchlock);
+ else
+ error = cv_timedwait(&we.we_cv,
+ &ntoskrnl_dispatchlock, tvtohz(&tv));
+
+ /* Wait with timeout expired. */
+
+ if (error) {
+ status = STATUS_TIMEOUT;
+ goto wait_done;
+ }
+
+ nanotime(&t2);
+
+ /* See what's been signalled. */
+
+ w = whead;
+ do {
+ cur = w->wb_object;
+ if (ntoskrnl_is_signalled(cur, td) == TRUE ||
+ w->wb_awakened == TRUE) {
+ /* Sanity check the signal state value. */
+ if (cur->dh_sigstate == INT32_MIN &&
+ cur->dh_type == DISP_TYPE_MUTANT) {
+ mtx_unlock(&ntoskrnl_dispatchlock);
+ panic("mutant limit exceeded");
+ }
+ wcnt--;
+ if (wtype == WAITTYPE_ANY) {
+ status = w->wb_waitkey &
+ STATUS_WAIT_0;
+ goto wait_done;
+ }
+ }
+ w = w->wb_next;
+ } while (w != whead);
+
+ /*
+ * If all objects have been signalled, or if this
+ * is a WAITTYPE_ANY wait and we were woke up by
+ * someone, we can bail.
+ */
+
+ if (wcnt == 0) {
+ status = STATUS_SUCCESS;
+ goto wait_done;
+ }
+
+ /*
+ * If this is WAITTYPE_ALL wait, and there's still
+ * objects that haven't been signalled, deduct the
+ * time that's elapsed so far from the timeout and
+ * wait again (or continue waiting indefinitely if
+ * there's no timeout).
+ */
+
+ if (duetime != NULL) {
+ tv.tv_sec -= (t2.tv_sec - t1.tv_sec);
+ tv.tv_usec -= (t2.tv_nsec - t1.tv_nsec) / 1000;
+ }
+ }
+
+
+wait_done:
+
+ cv_destroy(&we.we_cv);
+
+ for (i = 0; i < cnt; i++) {
+ if (whead[i].wb_object != NULL)
+ RemoveEntryList(&whead[i].wb_waitlist);
+
+ }
+ mtx_unlock(&ntoskrnl_dispatchlock);
+
+ return (status);
+}
+
+static void
+WRITE_REGISTER_USHORT(uint16_t *reg, uint16_t val)
+{
+ bus_space_write_2(NDIS_BUS_SPACE_MEM, 0x0, (bus_size_t)reg, val);
+}
+
+static uint16_t
+READ_REGISTER_USHORT(reg)
+ uint16_t *reg;
+{
+ return (bus_space_read_2(NDIS_BUS_SPACE_MEM, 0x0, (bus_size_t)reg));
+}
+
+static void
+WRITE_REGISTER_ULONG(reg, val)
+ uint32_t *reg;
+ uint32_t val;
+{
+ bus_space_write_4(NDIS_BUS_SPACE_MEM, 0x0, (bus_size_t)reg, val);
+}
+
+static uint32_t
+READ_REGISTER_ULONG(reg)
+ uint32_t *reg;
+{
+ return (bus_space_read_4(NDIS_BUS_SPACE_MEM, 0x0, (bus_size_t)reg));
+}
+
+static uint8_t
+READ_REGISTER_UCHAR(uint8_t *reg)
+{
+ return (bus_space_read_1(NDIS_BUS_SPACE_MEM, 0x0, (bus_size_t)reg));
+}
+
+static void
+WRITE_REGISTER_UCHAR(uint8_t *reg, uint8_t val)
+{
+ bus_space_write_1(NDIS_BUS_SPACE_MEM, 0x0, (bus_size_t)reg, val);
+}
+
+static int64_t
+_allmul(a, b)
+ int64_t a;
+ int64_t b;
+{
+ return (a * b);
+}
+
+static int64_t
+_alldiv(a, b)
+ int64_t a;
+ int64_t b;
+{
+ return (a / b);
+}
+
+static int64_t
+_allrem(a, b)
+ int64_t a;
+ int64_t b;
+{
+ return (a % b);
+}
+
+static uint64_t
+_aullmul(a, b)
+ uint64_t a;
+ uint64_t b;
+{
+ return (a * b);
+}
+
+static uint64_t
+_aulldiv(a, b)
+ uint64_t a;
+ uint64_t b;
+{
+ return (a / b);
+}
+
+static uint64_t
+_aullrem(a, b)
+ uint64_t a;
+ uint64_t b;
+{
+ return (a % b);
+}
+
+static int64_t
+_allshl(int64_t a, uint8_t b)
+{
+ return (a << b);
+}
+
+static uint64_t
+_aullshl(uint64_t a, uint8_t b)
+{
+ return (a << b);
+}
+
+static int64_t
+_allshr(int64_t a, uint8_t b)
+{
+ return (a >> b);
+}
+
+static uint64_t
+_aullshr(uint64_t a, uint8_t b)
+{
+ return (a >> b);
+}
+
+static slist_entry *
+ntoskrnl_pushsl(head, entry)
+ slist_header *head;
+ slist_entry *entry;
+{
+ slist_entry *oldhead;
+
+ oldhead = head->slh_list.slh_next;
+ entry->sl_next = head->slh_list.slh_next;
+ head->slh_list.slh_next = entry;
+ head->slh_list.slh_depth++;
+ head->slh_list.slh_seq++;
+
+ return (oldhead);
+}
+
+static void
+InitializeSListHead(head)
+ slist_header *head;
+{
+ memset(head, 0, sizeof(*head));
+}
+
+static slist_entry *
+ntoskrnl_popsl(head)
+ slist_header *head;
+{
+ slist_entry *first;
+
+ first = head->slh_list.slh_next;
+ if (first != NULL) {
+ head->slh_list.slh_next = first->sl_next;
+ head->slh_list.slh_depth--;
+ head->slh_list.slh_seq++;
+ }
+
+ return (first);
+}
+
+/*
+ * We need this to make lookaside lists work for amd64.
+ * We pass a pointer to ExAllocatePoolWithTag() the lookaside
+ * list structure. For amd64 to work right, this has to be a
+ * pointer to the wrapped version of the routine, not the
+ * original. Letting the Windows driver invoke the original
+ * function directly will result in a convention calling
+ * mismatch and a pretty crash. On x86, this effectively
+ * becomes a no-op since ipt_func and ipt_wrap are the same.
+ */
+
+static funcptr
+ntoskrnl_findwrap(func)
+ funcptr func;
+{
+ image_patch_table *patch;
+
+ patch = ntoskrnl_functbl;
+ while (patch->ipt_func != NULL) {
+ if ((funcptr)patch->ipt_func == func)
+ return ((funcptr)patch->ipt_wrap);
+ patch++;
+ }
+
+ return (NULL);
+}
+
+static void
+ExInitializePagedLookasideList(paged_lookaside_list *lookaside,
+ lookaside_alloc_func *allocfunc, lookaside_free_func *freefunc,
+ uint32_t flags, size_t size, uint32_t tag, uint16_t depth)
+{
+ bzero((char *)lookaside, sizeof(paged_lookaside_list));
+
+ if (size < sizeof(slist_entry))
+ lookaside->nll_l.gl_size = sizeof(slist_entry);
+ else
+ lookaside->nll_l.gl_size = size;
+ lookaside->nll_l.gl_tag = tag;
+ if (allocfunc == NULL)
+ lookaside->nll_l.gl_allocfunc =
+ ntoskrnl_findwrap((funcptr)ExAllocatePoolWithTag);
+ else
+ lookaside->nll_l.gl_allocfunc = allocfunc;
+
+ if (freefunc == NULL)
+ lookaside->nll_l.gl_freefunc =
+ ntoskrnl_findwrap((funcptr)ExFreePool);
+ else
+ lookaside->nll_l.gl_freefunc = freefunc;
+
+#ifdef __i386__
+ KeInitializeSpinLock(&lookaside->nll_obsoletelock);
+#endif
+
+ lookaside->nll_l.gl_type = NonPagedPool;
+ lookaside->nll_l.gl_depth = depth;
+ lookaside->nll_l.gl_maxdepth = LOOKASIDE_DEPTH;
+}
+
+static void
+ExDeletePagedLookasideList(lookaside)
+ paged_lookaside_list *lookaside;
+{
+ void *buf;
+ void (*freefunc)(void *);
+
+ freefunc = lookaside->nll_l.gl_freefunc;
+ while((buf = ntoskrnl_popsl(&lookaside->nll_l.gl_listhead)) != NULL)
+ MSCALL1(freefunc, buf);
+}
+
+static void
+ExInitializeNPagedLookasideList(npaged_lookaside_list *lookaside,
+ lookaside_alloc_func *allocfunc, lookaside_free_func *freefunc,
+ uint32_t flags, size_t size, uint32_t tag, uint16_t depth)
+{
+ bzero((char *)lookaside, sizeof(npaged_lookaside_list));
+
+ if (size < sizeof(slist_entry))
+ lookaside->nll_l.gl_size = sizeof(slist_entry);
+ else
+ lookaside->nll_l.gl_size = size;
+ lookaside->nll_l.gl_tag = tag;
+ if (allocfunc == NULL)
+ lookaside->nll_l.gl_allocfunc =
+ ntoskrnl_findwrap((funcptr)ExAllocatePoolWithTag);
+ else
+ lookaside->nll_l.gl_allocfunc = allocfunc;
+
+ if (freefunc == NULL)
+ lookaside->nll_l.gl_freefunc =
+ ntoskrnl_findwrap((funcptr)ExFreePool);
+ else
+ lookaside->nll_l.gl_freefunc = freefunc;
+
+#ifdef __i386__
+ KeInitializeSpinLock(&lookaside->nll_obsoletelock);
+#endif
+
+ lookaside->nll_l.gl_type = NonPagedPool;
+ lookaside->nll_l.gl_depth = depth;
+ lookaside->nll_l.gl_maxdepth = LOOKASIDE_DEPTH;
+}
+
+static void
+ExDeleteNPagedLookasideList(lookaside)
+ npaged_lookaside_list *lookaside;
+{
+ void *buf;
+ void (*freefunc)(void *);
+
+ freefunc = lookaside->nll_l.gl_freefunc;
+ while((buf = ntoskrnl_popsl(&lookaside->nll_l.gl_listhead)) != NULL)
+ MSCALL1(freefunc, buf);
+}
+
+slist_entry *
+InterlockedPushEntrySList(head, entry)
+ slist_header *head;
+ slist_entry *entry;
+{
+ slist_entry *oldhead;
+
+ mtx_lock_spin(&ntoskrnl_interlock);
+ oldhead = ntoskrnl_pushsl(head, entry);
+ mtx_unlock_spin(&ntoskrnl_interlock);
+
+ return (oldhead);
+}
+
+slist_entry *
+InterlockedPopEntrySList(head)
+ slist_header *head;
+{
+ slist_entry *first;
+
+ mtx_lock_spin(&ntoskrnl_interlock);
+ first = ntoskrnl_popsl(head);
+ mtx_unlock_spin(&ntoskrnl_interlock);
+
+ return (first);
+}
+
+static slist_entry *
+ExInterlockedPushEntrySList(head, entry, lock)
+ slist_header *head;
+ slist_entry *entry;
+ kspin_lock *lock;
+{
+ return (InterlockedPushEntrySList(head, entry));
+}
+
+static slist_entry *
+ExInterlockedPopEntrySList(head, lock)
+ slist_header *head;
+ kspin_lock *lock;
+{
+ return (InterlockedPopEntrySList(head));
+}
+
+uint16_t
+ExQueryDepthSList(head)
+ slist_header *head;
+{
+ uint16_t depth;
+
+ mtx_lock_spin(&ntoskrnl_interlock);
+ depth = head->slh_list.slh_depth;
+ mtx_unlock_spin(&ntoskrnl_interlock);
+
+ return (depth);
+}
+
+void
+KeInitializeSpinLock(lock)
+ kspin_lock *lock;
+{
+ *lock = 0;
+}
+
+#ifdef __i386__
+void
+KefAcquireSpinLockAtDpcLevel(lock)
+ kspin_lock *lock;
+{
+#ifdef NTOSKRNL_DEBUG_SPINLOCKS
+ int i = 0;
+#endif
+
+ while (atomic_cmpset_acq_int((volatile u_int *)lock, 0, 1) == 0) {
+ /* sit and spin */;
+#ifdef NTOSKRNL_DEBUG_SPINLOCKS
+ i++;
+ if (i > 200000000)
+ panic("DEADLOCK!");
+#endif
+ }
+}
+
+void
+KefReleaseSpinLockFromDpcLevel(lock)
+ kspin_lock *lock;
+{
+ atomic_store_rel_int((volatile u_int *)lock, 0);
+}
+
+uint8_t
+KeAcquireSpinLockRaiseToDpc(kspin_lock *lock)
+{
+ uint8_t oldirql;
+
+ if (KeGetCurrentIrql() > DISPATCH_LEVEL)
+ panic("IRQL_NOT_LESS_THAN_OR_EQUAL");
+
+ KeRaiseIrql(DISPATCH_LEVEL, &oldirql);
+ KeAcquireSpinLockAtDpcLevel(lock);
+
+ return (oldirql);
+}
+#else
+void
+KeAcquireSpinLockAtDpcLevel(kspin_lock *lock)
+{
+ while (atomic_cmpset_acq_int((volatile u_int *)lock, 0, 1) == 0)
+ /* sit and spin */;
+}
+
+void
+KeReleaseSpinLockFromDpcLevel(kspin_lock *lock)
+{
+ atomic_store_rel_int((volatile u_int *)lock, 0);
+}
+#endif /* __i386__ */
+
+uintptr_t
+InterlockedExchange(dst, val)
+ volatile uint32_t *dst;
+ uintptr_t val;
+{
+ uintptr_t r;
+
+ mtx_lock_spin(&ntoskrnl_interlock);
+ r = *dst;
+ *dst = val;
+ mtx_unlock_spin(&ntoskrnl_interlock);
+
+ return (r);
+}
+
+static uint32_t
+InterlockedIncrement(addend)
+ volatile uint32_t *addend;
+{
+ atomic_add_long((volatile u_long *)addend, 1);
+ return (*addend);
+}
+
+static uint32_t
+InterlockedDecrement(addend)
+ volatile uint32_t *addend;
+{
+ atomic_subtract_long((volatile u_long *)addend, 1);
+ return (*addend);
+}
+
+static void
+ExInterlockedAddLargeStatistic(addend, inc)
+ uint64_t *addend;
+ uint32_t inc;
+{
+ mtx_lock_spin(&ntoskrnl_interlock);
+ *addend += inc;
+ mtx_unlock_spin(&ntoskrnl_interlock);
+};
+
+mdl *
+IoAllocateMdl(void *vaddr, uint32_t len, uint8_t secondarybuf,
+ uint8_t chargequota, irp *iopkt)
+{
+ mdl *m;
+ int zone = 0;
+
+ if (MmSizeOfMdl(vaddr, len) > MDL_ZONE_SIZE)
+ m = ExAllocatePoolWithTag(NonPagedPool,
+ MmSizeOfMdl(vaddr, len), 0);
+ else {
+ m = uma_zalloc(mdl_zone, M_NOWAIT | M_ZERO);
+ zone++;
+ }
+
+ if (m == NULL)
+ return (NULL);
+
+ MmInitializeMdl(m, vaddr, len);
+
+ /*
+ * MmInitializMdl() clears the flags field, so we
+ * have to set this here. If the MDL came from the
+ * MDL UMA zone, tag it so we can release it to
+ * the right place later.
+ */
+ if (zone)
+ m->mdl_flags = MDL_ZONE_ALLOCED;
+
+ if (iopkt != NULL) {
+ if (secondarybuf == TRUE) {
+ mdl *last;
+ last = iopkt->irp_mdl;
+ while (last->mdl_next != NULL)
+ last = last->mdl_next;
+ last->mdl_next = m;
+ } else {
+ if (iopkt->irp_mdl != NULL)
+ panic("leaking an MDL in IoAllocateMdl()");
+ iopkt->irp_mdl = m;
+ }
+ }
+
+ return (m);
+}
+
+void
+IoFreeMdl(m)
+ mdl *m;
+{
+ if (m == NULL)
+ return;
+
+ if (m->mdl_flags & MDL_ZONE_ALLOCED)
+ uma_zfree(mdl_zone, m);
+ else
+ ExFreePool(m);
+}
+
+static void *
+MmAllocateContiguousMemory(size, highest)
+ uint32_t size;
+ uint64_t highest;
+{
+ void *addr;
+ size_t pagelength = roundup(size, PAGE_SIZE);
+
+ addr = ExAllocatePoolWithTag(NonPagedPool, pagelength, 0);
+
+ return (addr);
+}
+
+static void *
+MmAllocateContiguousMemorySpecifyCache(size, lowest, highest,
+ boundary, cachetype)
+ uint32_t size;
+ uint64_t lowest;
+ uint64_t highest;
+ uint64_t boundary;
+ enum nt_caching_type cachetype;
+{
+ vm_memattr_t memattr;
+ void *ret;
+
+ switch (cachetype) {
+ case MmNonCached:
+ memattr = VM_MEMATTR_UNCACHEABLE;
+ break;
+ case MmWriteCombined:
+ memattr = VM_MEMATTR_WRITE_COMBINING;
+ break;
+ case MmNonCachedUnordered:
+ memattr = VM_MEMATTR_UNCACHEABLE;
+ break;
+ case MmCached:
+ case MmHardwareCoherentCached:
+ case MmUSWCCached:
+ default:
+ memattr = VM_MEMATTR_DEFAULT;
+ break;
+ }
+
+ ret = (void *)kmem_alloc_contig(kernel_map, size, M_ZERO | M_NOWAIT,
+ lowest, highest, PAGE_SIZE, boundary, memattr);
+ if (ret != NULL)
+ malloc_type_allocated(M_DEVBUF, round_page(size));
+ return (ret);
+}
+
+static void
+MmFreeContiguousMemory(base)
+ void *base;
+{
+ ExFreePool(base);
+}
+
+static void
+MmFreeContiguousMemorySpecifyCache(base, size, cachetype)
+ void *base;
+ uint32_t size;
+ enum nt_caching_type cachetype;
+{
+ contigfree(base, size, M_DEVBUF);
+}
+
+static uint32_t
+MmSizeOfMdl(vaddr, len)
+ void *vaddr;
+ size_t len;
+{
+ uint32_t l;
+
+ l = sizeof(struct mdl) +
+ (sizeof(vm_offset_t *) * SPAN_PAGES(vaddr, len));
+
+ return (l);
+}
+
+/*
+ * The Microsoft documentation says this routine fills in the
+ * page array of an MDL with the _physical_ page addresses that
+ * comprise the buffer, but we don't really want to do that here.
+ * Instead, we just fill in the page array with the kernel virtual
+ * addresses of the buffers.
+ */
+void
+MmBuildMdlForNonPagedPool(m)
+ mdl *m;
+{
+ vm_offset_t *mdl_pages;
+ int pagecnt, i;
+
+ pagecnt = SPAN_PAGES(m->mdl_byteoffset, m->mdl_bytecount);
+
+ if (pagecnt > (m->mdl_size - sizeof(mdl)) / sizeof(vm_offset_t *))
+ panic("not enough pages in MDL to describe buffer");
+
+ mdl_pages = MmGetMdlPfnArray(m);
+
+ for (i = 0; i < pagecnt; i++)
+ *mdl_pages = (vm_offset_t)m->mdl_startva + (i * PAGE_SIZE);
+
+ m->mdl_flags |= MDL_SOURCE_IS_NONPAGED_POOL;
+ m->mdl_mappedsystemva = MmGetMdlVirtualAddress(m);
+}
+
+static void *
+MmMapLockedPages(mdl *buf, uint8_t accessmode)
+{
+ buf->mdl_flags |= MDL_MAPPED_TO_SYSTEM_VA;
+ return (MmGetMdlVirtualAddress(buf));
+}
+
+static void *
+MmMapLockedPagesSpecifyCache(mdl *buf, uint8_t accessmode, uint32_t cachetype,
+ void *vaddr, uint32_t bugcheck, uint32_t prio)
+{
+ return (MmMapLockedPages(buf, accessmode));
+}
+
+static void
+MmUnmapLockedPages(vaddr, buf)
+ void *vaddr;
+ mdl *buf;
+{
+ buf->mdl_flags &= ~MDL_MAPPED_TO_SYSTEM_VA;
+}
+
+/*
+ * This function has a problem in that it will break if you
+ * compile this module without PAE and try to use it on a PAE
+ * kernel. Unfortunately, there's no way around this at the
+ * moment. It's slightly less broken that using pmap_kextract().
+ * You'd think the virtual memory subsystem would help us out
+ * here, but it doesn't.
+ */
+
+static uint64_t
+MmGetPhysicalAddress(void *base)
+{
+ return (pmap_extract(kernel_map->pmap, (vm_offset_t)base));
+}
+
+void *
+MmGetSystemRoutineAddress(ustr)
+ unicode_string *ustr;
+{
+ ansi_string astr;
+
+ if (RtlUnicodeStringToAnsiString(&astr, ustr, TRUE))
+ return (NULL);
+ return (ndis_get_routine_address(ntoskrnl_functbl, astr.as_buf));
+}
+
+uint8_t
+MmIsAddressValid(vaddr)
+ void *vaddr;
+{
+ if (pmap_extract(kernel_map->pmap, (vm_offset_t)vaddr))
+ return (TRUE);
+
+ return (FALSE);
+}
+
+void *
+MmMapIoSpace(paddr, len, cachetype)
+ uint64_t paddr;
+ uint32_t len;
+ uint32_t cachetype;
+{
+ devclass_t nexus_class;
+ device_t *nexus_devs, devp;
+ int nexus_count = 0;
+ device_t matching_dev = NULL;
+ struct resource *res;
+ int i;
+ vm_offset_t v;
+
+ /* There will always be at least one nexus. */
+
+ nexus_class = devclass_find("nexus");
+ devclass_get_devices(nexus_class, &nexus_devs, &nexus_count);
+
+ for (i = 0; i < nexus_count; i++) {
+ devp = nexus_devs[i];
+ matching_dev = ntoskrnl_finddev(devp, paddr, &res);
+ if (matching_dev)
+ break;
+ }
+
+ free(nexus_devs, M_TEMP);
+
+ if (matching_dev == NULL)
+ return (NULL);
+
+ v = (vm_offset_t)rman_get_virtual(res);
+ if (paddr > rman_get_start(res))
+ v += paddr - rman_get_start(res);
+
+ return ((void *)v);
+}
+
+void
+MmUnmapIoSpace(vaddr, len)
+ void *vaddr;
+ size_t len;
+{
+}
+
+
+static device_t
+ntoskrnl_finddev(dev, paddr, res)
+ device_t dev;
+ uint64_t paddr;
+ struct resource **res;
+{
+ device_t *children = NULL;
+ device_t matching_dev;
+ int childcnt;
+ struct resource *r;
+ struct resource_list *rl;
+ struct resource_list_entry *rle;
+ uint32_t flags;
+ int i;
+
+ /* We only want devices that have been successfully probed. */
+
+ if (device_is_alive(dev) == FALSE)
+ return (NULL);
+
+ rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
+ if (rl != NULL) {
+ STAILQ_FOREACH(rle, rl, link) {
+ r = rle->res;
+
+ if (r == NULL)
+ continue;
+
+ flags = rman_get_flags(r);
+
+ if (rle->type == SYS_RES_MEMORY &&
+ paddr >= rman_get_start(r) &&
+ paddr <= rman_get_end(r)) {
+ if (!(flags & RF_ACTIVE))
+ bus_activate_resource(dev,
+ SYS_RES_MEMORY, 0, r);
+ *res = r;
+ return (dev);
+ }
+ }
+ }
+
+ /*
+ * If this device has children, do another
+ * level of recursion to inspect them.
+ */
+
+ device_get_children(dev, &children, &childcnt);
+
+ for (i = 0; i < childcnt; i++) {
+ matching_dev = ntoskrnl_finddev(children[i], paddr, res);
+ if (matching_dev != NULL) {
+ free(children, M_TEMP);
+ return (matching_dev);
+ }
+ }
+
+
+ /* Won't somebody please think of the children! */
+
+ if (children != NULL)
+ free(children, M_TEMP);
+
+ return (NULL);
+}
+
+/*
+ * Workitems are unlike DPCs, in that they run in a user-mode thread
+ * context rather than at DISPATCH_LEVEL in kernel context. In our
+ * case we run them in kernel context anyway.
+ */
+static void
+ntoskrnl_workitem_thread(arg)
+ void *arg;
+{
+ kdpc_queue *kq;
+ list_entry *l;
+ io_workitem *iw;
+ uint8_t irql;
+
+ kq = arg;
+
+ InitializeListHead(&kq->kq_disp);
+ kq->kq_td = curthread;
+ kq->kq_exit = 0;
+ KeInitializeSpinLock(&kq->kq_lock);
+ KeInitializeEvent(&kq->kq_proc, EVENT_TYPE_SYNC, FALSE);
+
+ while (1) {
+ KeWaitForSingleObject(&kq->kq_proc, 0, 0, TRUE, NULL);
+
+ KeAcquireSpinLock(&kq->kq_lock, &irql);
+
+ if (kq->kq_exit) {
+ kq->kq_exit = 0;
+ KeReleaseSpinLock(&kq->kq_lock, irql);
+ break;
+ }
+
+ while (!IsListEmpty(&kq->kq_disp)) {
+ l = RemoveHeadList(&kq->kq_disp);
+ iw = CONTAINING_RECORD(l,
+ io_workitem, iw_listentry);
+ InitializeListHead((&iw->iw_listentry));
+ if (iw->iw_func == NULL)
+ continue;
+ KeReleaseSpinLock(&kq->kq_lock, irql);
+ MSCALL2(iw->iw_func, iw->iw_dobj, iw->iw_ctx);
+ KeAcquireSpinLock(&kq->kq_lock, &irql);
+ }
+
+ KeReleaseSpinLock(&kq->kq_lock, irql);
+ }
+
+ kproc_exit(0);
+ return; /* notreached */
+}
+
+static ndis_status
+RtlCharToInteger(src, base, val)
+ const char *src;
+ uint32_t base;
+ uint32_t *val;
+{
+ int negative = 0;
+ uint32_t res;
+
+ if (!src || !val)
+ return (STATUS_ACCESS_VIOLATION);
+ while (*src != '\0' && *src <= ' ')
+ src++;
+ if (*src == '+')
+ src++;
+ else if (*src == '-') {
+ src++;
+ negative = 1;
+ }
+ if (base == 0) {
+ base = 10;
+ if (*src == '0') {
+ src++;
+ if (*src == 'b') {
+ base = 2;
+ src++;
+ } else if (*src == 'o') {
+ base = 8;
+ src++;
+ } else if (*src == 'x') {
+ base = 16;
+ src++;
+ }
+ }
+ } else if (!(base == 2 || base == 8 || base == 10 || base == 16))
+ return (STATUS_INVALID_PARAMETER);
+
+ for (res = 0; *src; src++) {
+ int v;
+ if (isdigit(*src))
+ v = *src - '0';
+ else if (isxdigit(*src))
+ v = tolower(*src) - 'a' + 10;
+ else
+ v = base;
+ if (v >= base)
+ return (STATUS_INVALID_PARAMETER);
+ res = res * base + v;
+ }
+ *val = negative ? -res : res;
+ return (STATUS_SUCCESS);
+}
+
+static void
+ntoskrnl_destroy_workitem_threads(void)
+{
+ kdpc_queue *kq;
+ int i;
+
+ for (i = 0; i < WORKITEM_THREADS; i++) {
+ kq = wq_queues + i;
+ kq->kq_exit = 1;
+ KeSetEvent(&kq->kq_proc, IO_NO_INCREMENT, FALSE);
+ while (kq->kq_exit)
+ tsleep(kq->kq_td->td_proc, PWAIT, "waitiw", hz/10);
+ }
+}
+
+io_workitem *
+IoAllocateWorkItem(dobj)
+ device_object *dobj;
+{
+ io_workitem *iw;
+
+ iw = uma_zalloc(iw_zone, M_NOWAIT);
+ if (iw == NULL)
+ return (NULL);
+
+ InitializeListHead(&iw->iw_listentry);
+ iw->iw_dobj = dobj;
+
+ mtx_lock(&ntoskrnl_dispatchlock);
+ iw->iw_idx = wq_idx;
+ WORKIDX_INC(wq_idx);
+ mtx_unlock(&ntoskrnl_dispatchlock);
+
+ return (iw);
+}
+
+void
+IoFreeWorkItem(iw)
+ io_workitem *iw;
+{
+ uma_zfree(iw_zone, iw);
+}
+
+void
+IoQueueWorkItem(iw, iw_func, qtype, ctx)
+ io_workitem *iw;
+ io_workitem_func iw_func;
+ uint32_t qtype;
+ void *ctx;
+{
+ kdpc_queue *kq;
+ list_entry *l;
+ io_workitem *cur;
+ uint8_t irql;
+
+ kq = wq_queues + iw->iw_idx;
+
+ KeAcquireSpinLock(&kq->kq_lock, &irql);
+
+ /*
+ * Traverse the list and make sure this workitem hasn't
+ * already been inserted. Queuing the same workitem
+ * twice will hose the list but good.
+ */
+
+ l = kq->kq_disp.nle_flink;
+ while (l != &kq->kq_disp) {
+ cur = CONTAINING_RECORD(l, io_workitem, iw_listentry);
+ if (cur == iw) {
+ /* Already queued -- do nothing. */
+ KeReleaseSpinLock(&kq->kq_lock, irql);
+ return;
+ }
+ l = l->nle_flink;
+ }
+
+ iw->iw_func = iw_func;
+ iw->iw_ctx = ctx;
+
+ InsertTailList((&kq->kq_disp), (&iw->iw_listentry));
+ KeReleaseSpinLock(&kq->kq_lock, irql);
+
+ KeSetEvent(&kq->kq_proc, IO_NO_INCREMENT, FALSE);
+}
+
+static void
+ntoskrnl_workitem(dobj, arg)
+ device_object *dobj;
+ void *arg;
+{
+ io_workitem *iw;
+ work_queue_item *w;
+ work_item_func f;
+
+ iw = arg;
+ w = (work_queue_item *)dobj;
+ f = (work_item_func)w->wqi_func;
+ uma_zfree(iw_zone, iw);
+ MSCALL2(f, w, w->wqi_ctx);
+}
+
+/*
+ * The ExQueueWorkItem() API is deprecated in Windows XP. Microsoft
+ * warns that it's unsafe and to use IoQueueWorkItem() instead. The
+ * problem with ExQueueWorkItem() is that it can't guard against
+ * the condition where a driver submits a job to the work queue and
+ * is then unloaded before the job is able to run. IoQueueWorkItem()
+ * acquires a reference to the device's device_object via the
+ * object manager and retains it until after the job has completed,
+ * which prevents the driver from being unloaded before the job
+ * runs. (We don't currently support this behavior, though hopefully
+ * that will change once the object manager API is fleshed out a bit.)
+ *
+ * Having said all that, the ExQueueWorkItem() API remains, because
+ * there are still other parts of Windows that use it, including
+ * NDIS itself: NdisScheduleWorkItem() calls ExQueueWorkItem().
+ * We fake up the ExQueueWorkItem() API on top of our implementation
+ * of IoQueueWorkItem(). Workitem thread #3 is reserved exclusively
+ * for ExQueueWorkItem() jobs, and we pass a pointer to the work
+ * queue item (provided by the caller) in to IoAllocateWorkItem()
+ * instead of the device_object. We need to save this pointer so
+ * we can apply a sanity check: as with the DPC queue and other
+ * workitem queues, we can't allow the same work queue item to
+ * be queued twice. If it's already pending, we silently return
+ */
+
+void
+ExQueueWorkItem(w, qtype)
+ work_queue_item *w;
+ uint32_t qtype;
+{
+ io_workitem *iw;
+ io_workitem_func iwf;
+ kdpc_queue *kq;
+ list_entry *l;
+ io_workitem *cur;
+ uint8_t irql;
+
+
+ /*
+ * We need to do a special sanity test to make sure
+ * the ExQueueWorkItem() API isn't used to queue
+ * the same workitem twice. Rather than checking the
+ * io_workitem pointer itself, we test the attached
+ * device object, which is really a pointer to the
+ * legacy work queue item structure.
+ */
+
+ kq = wq_queues + WORKITEM_LEGACY_THREAD;
+ KeAcquireSpinLock(&kq->kq_lock, &irql);
+ l = kq->kq_disp.nle_flink;
+ while (l != &kq->kq_disp) {
+ cur = CONTAINING_RECORD(l, io_workitem, iw_listentry);
+ if (cur->iw_dobj == (device_object *)w) {
+ /* Already queued -- do nothing. */
+ KeReleaseSpinLock(&kq->kq_lock, irql);
+ return;
+ }
+ l = l->nle_flink;
+ }
+ KeReleaseSpinLock(&kq->kq_lock, irql);
+
+ iw = IoAllocateWorkItem((device_object *)w);
+ if (iw == NULL)
+ return;
+
+ iw->iw_idx = WORKITEM_LEGACY_THREAD;
+ iwf = (io_workitem_func)ntoskrnl_findwrap((funcptr)ntoskrnl_workitem);
+ IoQueueWorkItem(iw, iwf, qtype, iw);
+}
+
+static void
+RtlZeroMemory(dst, len)
+ void *dst;
+ size_t len;
+{
+ bzero(dst, len);
+}
+
+static void
+RtlSecureZeroMemory(dst, len)
+ void *dst;
+ size_t len;
+{
+ memset(dst, 0, len);
+}
+
+static void
+RtlFillMemory(void *dst, size_t len, uint8_t c)
+{
+ memset(dst, c, len);
+}
+
+static void
+RtlMoveMemory(dst, src, len)
+ void *dst;
+ const void *src;
+ size_t len;
+{
+ memmove(dst, src, len);
+}
+
+static void
+RtlCopyMemory(dst, src, len)
+ void *dst;
+ const void *src;
+ size_t len;
+{
+ bcopy(src, dst, len);
+}
+
+static size_t
+RtlCompareMemory(s1, s2, len)
+ const void *s1;
+ const void *s2;
+ size_t len;
+{
+ size_t i;
+ uint8_t *m1, *m2;
+
+ m1 = __DECONST(char *, s1);
+ m2 = __DECONST(char *, s2);
+
+ for (i = 0; i < len && m1[i] == m2[i]; i++);
+ return (i);
+}
+
+void
+RtlInitAnsiString(dst, src)
+ ansi_string *dst;
+ char *src;
+{
+ ansi_string *a;
+
+ a = dst;
+ if (a == NULL)
+ return;
+ if (src == NULL) {
+ a->as_len = a->as_maxlen = 0;
+ a->as_buf = NULL;
+ } else {
+ a->as_buf = src;
+ a->as_len = a->as_maxlen = strlen(src);
+ }
+}
+
+void
+RtlInitUnicodeString(dst, src)
+ unicode_string *dst;
+ uint16_t *src;
+{
+ unicode_string *u;
+ int i;
+
+ u = dst;
+ if (u == NULL)
+ return;
+ if (src == NULL) {
+ u->us_len = u->us_maxlen = 0;
+ u->us_buf = NULL;
+ } else {
+ i = 0;
+ while(src[i] != 0)
+ i++;
+ u->us_buf = src;
+ u->us_len = u->us_maxlen = i * 2;
+ }
+}
+
+ndis_status
+RtlUnicodeStringToInteger(ustr, base, val)
+ unicode_string *ustr;
+ uint32_t base;
+ uint32_t *val;
+{
+ uint16_t *uchr;
+ int len, neg = 0;
+ char abuf[64];
+ char *astr;
+
+ uchr = ustr->us_buf;
+ len = ustr->us_len;
+ bzero(abuf, sizeof(abuf));
+
+ if ((char)((*uchr) & 0xFF) == '-') {
+ neg = 1;
+ uchr++;
+ len -= 2;
+ } else if ((char)((*uchr) & 0xFF) == '+') {
+ neg = 0;
+ uchr++;
+ len -= 2;
+ }
+
+ if (base == 0) {
+ if ((char)((*uchr) & 0xFF) == 'b') {
+ base = 2;
+ uchr++;
+ len -= 2;
+ } else if ((char)((*uchr) & 0xFF) == 'o') {
+ base = 8;
+ uchr++;
+ len -= 2;
+ } else if ((char)((*uchr) & 0xFF) == 'x') {
+ base = 16;
+ uchr++;
+ len -= 2;
+ } else
+ base = 10;
+ }
+
+ astr = abuf;
+ if (neg) {
+ strcpy(astr, "-");
+ astr++;
+ }
+
+ ntoskrnl_unicode_to_ascii(uchr, astr, len);
+ *val = strtoul(abuf, NULL, base);
+
+ return (STATUS_SUCCESS);
+}
+
+void
+RtlFreeUnicodeString(ustr)
+ unicode_string *ustr;
+{
+ if (ustr->us_buf == NULL)
+ return;
+ ExFreePool(ustr->us_buf);
+ ustr->us_buf = NULL;
+}
+
+void
+RtlFreeAnsiString(astr)
+ ansi_string *astr;
+{
+ if (astr->as_buf == NULL)
+ return;
+ ExFreePool(astr->as_buf);
+ astr->as_buf = NULL;
+}
+
+static int
+atoi(str)
+ const char *str;
+{
+ return (int)strtol(str, (char **)NULL, 10);
+}
+
+static long
+atol(str)
+ const char *str;
+{
+ return strtol(str, (char **)NULL, 10);
+}
+
+static int
+rand(void)
+{
+ struct timeval tv;
+
+ microtime(&tv);
+ srandom(tv.tv_usec);
+ return ((int)random());
+}
+
+static void
+srand(seed)
+ unsigned int seed;
+{
+ srandom(seed);
+}
+
+static uint8_t
+IoIsWdmVersionAvailable(uint8_t major, uint8_t minor)
+{
+ if (major == WDM_MAJOR && minor == WDM_MINOR_WINXP)
+ return (TRUE);
+ return (FALSE);
+}
+
+static int32_t
+IoOpenDeviceRegistryKey(struct device_object *devobj, uint32_t type,
+ uint32_t mask, void **key)
+{
+ return (NDIS_STATUS_INVALID_DEVICE_REQUEST);
+}
+
+static ndis_status
+IoGetDeviceObjectPointer(name, reqaccess, fileobj, devobj)
+ unicode_string *name;
+ uint32_t reqaccess;
+ void *fileobj;
+ device_object *devobj;
+{
+ return (STATUS_SUCCESS);
+}
+
+static ndis_status
+IoGetDeviceProperty(devobj, regprop, buflen, prop, reslen)
+ device_object *devobj;
+ uint32_t regprop;
+ uint32_t buflen;
+ void *prop;
+ uint32_t *reslen;
+{
+ driver_object *drv;
+ uint16_t **name;
+
+ drv = devobj->do_drvobj;
+
+ switch (regprop) {
+ case DEVPROP_DRIVER_KEYNAME:
+ name = prop;
+ *name = drv->dro_drivername.us_buf;
+ *reslen = drv->dro_drivername.us_len;
+ break;
+ default:
+ return (STATUS_INVALID_PARAMETER_2);
+ break;
+ }
+
+ return (STATUS_SUCCESS);
+}
+
+static void
+KeInitializeMutex(kmutex, level)
+ kmutant *kmutex;
+ uint32_t level;
+{
+ InitializeListHead((&kmutex->km_header.dh_waitlisthead));
+ kmutex->km_abandoned = FALSE;
+ kmutex->km_apcdisable = 1;
+ kmutex->km_header.dh_sigstate = 1;
+ kmutex->km_header.dh_type = DISP_TYPE_MUTANT;
+ kmutex->km_header.dh_size = sizeof(kmutant) / sizeof(uint32_t);
+ kmutex->km_ownerthread = NULL;
+}
+
+static uint32_t
+KeReleaseMutex(kmutant *kmutex, uint8_t kwait)
+{
+ uint32_t prevstate;
+
+ mtx_lock(&ntoskrnl_dispatchlock);
+ prevstate = kmutex->km_header.dh_sigstate;
+ if (kmutex->km_ownerthread != curthread) {
+ mtx_unlock(&ntoskrnl_dispatchlock);
+ return (STATUS_MUTANT_NOT_OWNED);
+ }
+
+ kmutex->km_header.dh_sigstate++;
+ kmutex->km_abandoned = FALSE;
+
+ if (kmutex->km_header.dh_sigstate == 1) {
+ kmutex->km_ownerthread = NULL;
+ ntoskrnl_waittest(&kmutex->km_header, IO_NO_INCREMENT);
+ }
+
+ mtx_unlock(&ntoskrnl_dispatchlock);
+
+ return (prevstate);
+}
+
+static uint32_t
+KeReadStateMutex(kmutex)
+ kmutant *kmutex;
+{
+ return (kmutex->km_header.dh_sigstate);
+}
+
+void
+KeInitializeEvent(nt_kevent *kevent, uint32_t type, uint8_t state)
+{
+ InitializeListHead((&kevent->k_header.dh_waitlisthead));
+ kevent->k_header.dh_sigstate = state;
+ if (type == EVENT_TYPE_NOTIFY)
+ kevent->k_header.dh_type = DISP_TYPE_NOTIFICATION_EVENT;
+ else
+ kevent->k_header.dh_type = DISP_TYPE_SYNCHRONIZATION_EVENT;
+ kevent->k_header.dh_size = sizeof(nt_kevent) / sizeof(uint32_t);
+}
+
+uint32_t
+KeResetEvent(kevent)
+ nt_kevent *kevent;
+{
+ uint32_t prevstate;
+
+ mtx_lock(&ntoskrnl_dispatchlock);
+ prevstate = kevent->k_header.dh_sigstate;
+ kevent->k_header.dh_sigstate = FALSE;
+ mtx_unlock(&ntoskrnl_dispatchlock);
+
+ return (prevstate);
+}
+
+uint32_t
+KeSetEvent(nt_kevent *kevent, uint32_t increment, uint8_t kwait)
+{
+ uint32_t prevstate;
+ wait_block *w;
+ nt_dispatch_header *dh;
+ struct thread *td;
+ wb_ext *we;
+
+ mtx_lock(&ntoskrnl_dispatchlock);
+ prevstate = kevent->k_header.dh_sigstate;
+ dh = &kevent->k_header;
+
+ if (IsListEmpty(&dh->dh_waitlisthead))
+ /*
+ * If there's nobody in the waitlist, just set
+ * the state to signalled.
+ */
+ dh->dh_sigstate = 1;
+ else {
+ /*
+ * Get the first waiter. If this is a synchronization
+ * event, just wake up that one thread (don't bother
+ * setting the state to signalled since we're supposed
+ * to automatically clear synchronization events anyway).
+ *
+ * If it's a notification event, or the first
+ * waiter is doing a WAITTYPE_ALL wait, go through
+ * the full wait satisfaction process.
+ */
+ w = CONTAINING_RECORD(dh->dh_waitlisthead.nle_flink,
+ wait_block, wb_waitlist);
+ we = w->wb_ext;
+ td = we->we_td;
+ if (kevent->k_header.dh_type == DISP_TYPE_NOTIFICATION_EVENT ||
+ w->wb_waittype == WAITTYPE_ALL) {
+ if (prevstate == 0) {
+ dh->dh_sigstate = 1;
+ ntoskrnl_waittest(dh, increment);
+ }
+ } else {
+ w->wb_awakened |= TRUE;
+ cv_broadcastpri(&we->we_cv,
+ (w->wb_oldpri - (increment * 4)) > PRI_MIN_KERN ?
+ w->wb_oldpri - (increment * 4) : PRI_MIN_KERN);
+ }
+ }
+
+ mtx_unlock(&ntoskrnl_dispatchlock);
+
+ return (prevstate);
+}
+
+void
+KeClearEvent(kevent)
+ nt_kevent *kevent;
+{
+ kevent->k_header.dh_sigstate = FALSE;
+}
+
+uint32_t
+KeReadStateEvent(kevent)
+ nt_kevent *kevent;
+{
+ return (kevent->k_header.dh_sigstate);
+}
+
+/*
+ * The object manager in Windows is responsible for managing
+ * references and access to various types of objects, including
+ * device_objects, events, threads, timers and so on. However,
+ * there's a difference in the way objects are handled in user
+ * mode versus kernel mode.
+ *
+ * In user mode (i.e. Win32 applications), all objects are
+ * managed by the object manager. For example, when you create
+ * a timer or event object, you actually end up with an
+ * object_header (for the object manager's bookkeeping
+ * purposes) and an object body (which contains the actual object
+ * structure, e.g. ktimer, kevent, etc...). This allows Windows
+ * to manage resource quotas and to enforce access restrictions
+ * on basically every kind of system object handled by the kernel.
+ *
+ * However, in kernel mode, you only end up using the object
+ * manager some of the time. For example, in a driver, you create
+ * a timer object by simply allocating the memory for a ktimer
+ * structure and initializing it with KeInitializeTimer(). Hence,
+ * the timer has no object_header and no reference counting or
+ * security/resource checks are done on it. The assumption in
+ * this case is that if you're running in kernel mode, you know
+ * what you're doing, and you're already at an elevated privilege
+ * anyway.
+ *
+ * There are some exceptions to this. The two most important ones
+ * for our purposes are device_objects and threads. We need to use
+ * the object manager to do reference counting on device_objects,
+ * and for threads, you can only get a pointer to a thread's
+ * dispatch header by using ObReferenceObjectByHandle() on the
+ * handle returned by PsCreateSystemThread().
+ */
+
+static ndis_status
+ObReferenceObjectByHandle(ndis_handle handle, uint32_t reqaccess, void *otype,
+ uint8_t accessmode, void **object, void **handleinfo)
+{
+ nt_objref *nr;
+
+ nr = malloc(sizeof(nt_objref), M_DEVBUF, M_NOWAIT|M_ZERO);
+ if (nr == NULL)
+ return (STATUS_INSUFFICIENT_RESOURCES);
+
+ InitializeListHead((&nr->no_dh.dh_waitlisthead));
+ nr->no_obj = handle;
+ nr->no_dh.dh_type = DISP_TYPE_THREAD;
+ nr->no_dh.dh_sigstate = 0;
+ nr->no_dh.dh_size = (uint8_t)(sizeof(struct thread) /
+ sizeof(uint32_t));
+ TAILQ_INSERT_TAIL(&ntoskrnl_reflist, nr, link);
+ *object = nr;
+
+ return (STATUS_SUCCESS);
+}
+
+static void
+ObfDereferenceObject(object)
+ void *object;
+{
+ nt_objref *nr;
+
+ nr = object;
+ TAILQ_REMOVE(&ntoskrnl_reflist, nr, link);
+ free(nr, M_DEVBUF);
+}
+
+static uint32_t
+ZwClose(handle)
+ ndis_handle handle;
+{
+ return (STATUS_SUCCESS);
+}
+
+static uint32_t
+WmiQueryTraceInformation(traceclass, traceinfo, infolen, reqlen, buf)
+ uint32_t traceclass;
+ void *traceinfo;
+ uint32_t infolen;
+ uint32_t reqlen;
+ void *buf;
+{
+ return (STATUS_NOT_FOUND);
+}
+
+static uint32_t
+WmiTraceMessage(uint64_t loghandle, uint32_t messageflags,
+ void *guid, uint16_t messagenum, ...)
+{
+ return (STATUS_SUCCESS);
+}
+
+static uint32_t
+IoWMIRegistrationControl(dobj, action)
+ device_object *dobj;
+ uint32_t action;
+{
+ return (STATUS_SUCCESS);
+}
+
+/*
+ * This is here just in case the thread returns without calling
+ * PsTerminateSystemThread().
+ */
+static void
+ntoskrnl_thrfunc(arg)
+ void *arg;
+{
+ thread_context *thrctx;
+ uint32_t (*tfunc)(void *);
+ void *tctx;
+ uint32_t rval;
+
+ thrctx = arg;
+ tfunc = thrctx->tc_thrfunc;
+ tctx = thrctx->tc_thrctx;
+ free(thrctx, M_TEMP);
+
+ rval = MSCALL1(tfunc, tctx);
+
+ PsTerminateSystemThread(rval);
+ return; /* notreached */
+}
+
+static ndis_status
+PsCreateSystemThread(handle, reqaccess, objattrs, phandle,
+ clientid, thrfunc, thrctx)
+ ndis_handle *handle;
+ uint32_t reqaccess;
+ void *objattrs;
+ ndis_handle phandle;
+ void *clientid;
+ void *thrfunc;
+ void *thrctx;
+{
+ int error;
+ thread_context *tc;
+ struct proc *p;
+
+ tc = malloc(sizeof(thread_context), M_TEMP, M_NOWAIT);
+ if (tc == NULL)
+ return (STATUS_INSUFFICIENT_RESOURCES);
+
+ tc->tc_thrctx = thrctx;
+ tc->tc_thrfunc = thrfunc;
+
+ error = kproc_create(ntoskrnl_thrfunc, tc, &p,
+ RFHIGHPID, NDIS_KSTACK_PAGES, "Windows Kthread %d", ntoskrnl_kth);
+
+ if (error) {
+ free(tc, M_TEMP);
+ return (STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ *handle = p;
+ ntoskrnl_kth++;
+
+ return (STATUS_SUCCESS);
+}
+
+/*
+ * In Windows, the exit of a thread is an event that you're allowed
+ * to wait on, assuming you've obtained a reference to the thread using
+ * ObReferenceObjectByHandle(). Unfortunately, the only way we can
+ * simulate this behavior is to register each thread we create in a
+ * reference list, and if someone holds a reference to us, we poke
+ * them.
+ */
+static ndis_status
+PsTerminateSystemThread(status)
+ ndis_status status;
+{
+ struct nt_objref *nr;
+
+ mtx_lock(&ntoskrnl_dispatchlock);
+ TAILQ_FOREACH(nr, &ntoskrnl_reflist, link) {
+ if (nr->no_obj != curthread->td_proc)
+ continue;
+ nr->no_dh.dh_sigstate = 1;
+ ntoskrnl_waittest(&nr->no_dh, IO_NO_INCREMENT);
+ break;
+ }
+ mtx_unlock(&ntoskrnl_dispatchlock);
+
+ ntoskrnl_kth--;
+
+ kproc_exit(0);
+ return (0); /* notreached */
+}
+
+static uint32_t
+DbgPrint(char *fmt, ...)
+{
+ va_list ap;
+
+ if (bootverbose) {
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+ }
+
+ return (STATUS_SUCCESS);
+}
+
+static void
+DbgBreakPoint(void)
+{
+
+ kdb_enter(KDB_WHY_NDIS, "DbgBreakPoint(): breakpoint");
+}
+
+static void
+KeBugCheckEx(code, param1, param2, param3, param4)
+ uint32_t code;
+ u_long param1;
+ u_long param2;
+ u_long param3;
+ u_long param4;
+{
+ panic("KeBugCheckEx: STOP 0x%X", code);
+}
+
+static void
+ntoskrnl_timercall(arg)
+ void *arg;
+{
+ ktimer *timer;
+ struct timeval tv;
+ kdpc *dpc;
+
+ mtx_lock(&ntoskrnl_dispatchlock);
+
+ timer = arg;
+
+#ifdef NTOSKRNL_DEBUG_TIMERS
+ ntoskrnl_timer_fires++;
+#endif
+ ntoskrnl_remove_timer(timer);
+
+ /*
+ * This should never happen, but complain
+ * if it does.
+ */
+
+ if (timer->k_header.dh_inserted == FALSE) {
+ mtx_unlock(&ntoskrnl_dispatchlock);
+ printf("NTOS: timer %p fired even though "
+ "it was canceled\n", timer);
+ return;
+ }
+
+ /* Mark the timer as no longer being on the timer queue. */
+
+ timer->k_header.dh_inserted = FALSE;
+
+ /* Now signal the object and satisfy any waits on it. */
+
+ timer->k_header.dh_sigstate = 1;
+ ntoskrnl_waittest(&timer->k_header, IO_NO_INCREMENT);
+
+ /*
+ * If this is a periodic timer, re-arm it
+ * so it will fire again. We do this before
+ * calling any deferred procedure calls because
+ * it's possible the DPC might cancel the timer,
+ * in which case it would be wrong for us to
+ * re-arm it again afterwards.
+ */
+
+ if (timer->k_period) {
+ tv.tv_sec = 0;
+ tv.tv_usec = timer->k_period * 1000;
+ timer->k_header.dh_inserted = TRUE;
+ ntoskrnl_insert_timer(timer, tvtohz(&tv));
+#ifdef NTOSKRNL_DEBUG_TIMERS
+ ntoskrnl_timer_reloads++;
+#endif
+ }
+
+ dpc = timer->k_dpc;
+
+ mtx_unlock(&ntoskrnl_dispatchlock);
+
+ /* If there's a DPC associated with the timer, queue it up. */
+
+ if (dpc != NULL)
+ KeInsertQueueDpc(dpc, NULL, NULL);
+}
+
+#ifdef NTOSKRNL_DEBUG_TIMERS
+static int
+sysctl_show_timers(SYSCTL_HANDLER_ARGS)
+{
+ int ret;
+
+ ret = 0;
+ ntoskrnl_show_timers();
+ return (sysctl_handle_int(oidp, &ret, 0, req));
+}
+
+static void
+ntoskrnl_show_timers()
+{
+ int i = 0;
+ list_entry *l;
+
+ mtx_lock_spin(&ntoskrnl_calllock);
+ l = ntoskrnl_calllist.nle_flink;
+ while(l != &ntoskrnl_calllist) {
+ i++;
+ l = l->nle_flink;
+ }
+ mtx_unlock_spin(&ntoskrnl_calllock);
+
+ printf("\n");
+ printf("%d timers available (out of %d)\n", i, NTOSKRNL_TIMEOUTS);
+ printf("timer sets: %qu\n", ntoskrnl_timer_sets);
+ printf("timer reloads: %qu\n", ntoskrnl_timer_reloads);
+ printf("timer cancels: %qu\n", ntoskrnl_timer_cancels);
+ printf("timer fires: %qu\n", ntoskrnl_timer_fires);
+ printf("\n");
+}
+#endif
+
+/*
+ * Must be called with dispatcher lock held.
+ */
+
+static void
+ntoskrnl_insert_timer(timer, ticks)
+ ktimer *timer;
+ int ticks;
+{
+ callout_entry *e;
+ list_entry *l;
+ struct callout *c;
+
+ /*
+ * Try and allocate a timer.
+ */
+ mtx_lock_spin(&ntoskrnl_calllock);
+ if (IsListEmpty(&ntoskrnl_calllist)) {
+ mtx_unlock_spin(&ntoskrnl_calllock);
+#ifdef NTOSKRNL_DEBUG_TIMERS
+ ntoskrnl_show_timers();
+#endif
+ panic("out of timers!");
+ }
+ l = RemoveHeadList(&ntoskrnl_calllist);
+ mtx_unlock_spin(&ntoskrnl_calllock);
+
+ e = CONTAINING_RECORD(l, callout_entry, ce_list);
+ c = &e->ce_callout;
+
+ timer->k_callout = c;
+
+ callout_init(c, CALLOUT_MPSAFE);
+ callout_reset(c, ticks, ntoskrnl_timercall, timer);
+}
+
+static void
+ntoskrnl_remove_timer(timer)
+ ktimer *timer;
+{
+ callout_entry *e;
+
+ e = (callout_entry *)timer->k_callout;
+ callout_stop(timer->k_callout);
+
+ mtx_lock_spin(&ntoskrnl_calllock);
+ InsertHeadList((&ntoskrnl_calllist), (&e->ce_list));
+ mtx_unlock_spin(&ntoskrnl_calllock);
+}
+
+void
+KeInitializeTimer(timer)
+ ktimer *timer;
+{
+ if (timer == NULL)
+ return;
+
+ KeInitializeTimerEx(timer, EVENT_TYPE_NOTIFY);
+}
+
+void
+KeInitializeTimerEx(timer, type)
+ ktimer *timer;
+ uint32_t type;
+{
+ if (timer == NULL)
+ return;
+
+ bzero((char *)timer, sizeof(ktimer));
+ InitializeListHead((&timer->k_header.dh_waitlisthead));
+ timer->k_header.dh_sigstate = FALSE;
+ timer->k_header.dh_inserted = FALSE;
+ if (type == EVENT_TYPE_NOTIFY)
+ timer->k_header.dh_type = DISP_TYPE_NOTIFICATION_TIMER;
+ else
+ timer->k_header.dh_type = DISP_TYPE_SYNCHRONIZATION_TIMER;
+ timer->k_header.dh_size = sizeof(ktimer) / sizeof(uint32_t);
+}
+
+/*
+ * DPC subsystem. A Windows Defered Procedure Call has the following
+ * properties:
+ * - It runs at DISPATCH_LEVEL.
+ * - It can have one of 3 importance values that control when it
+ * runs relative to other DPCs in the queue.
+ * - On SMP systems, it can be set to run on a specific processor.
+ * In order to satisfy the last property, we create a DPC thread for
+ * each CPU in the system and bind it to that CPU. Each thread
+ * maintains three queues with different importance levels, which
+ * will be processed in order from lowest to highest.
+ *
+ * In Windows, interrupt handlers run as DPCs. (Not to be confused
+ * with ISRs, which run in interrupt context and can preempt DPCs.)
+ * ISRs are given the highest importance so that they'll take
+ * precedence over timers and other things.
+ */
+
+static void
+ntoskrnl_dpc_thread(arg)
+ void *arg;
+{
+ kdpc_queue *kq;
+ kdpc *d;
+ list_entry *l;
+ uint8_t irql;
+
+ kq = arg;
+
+ InitializeListHead(&kq->kq_disp);
+ kq->kq_td = curthread;
+ kq->kq_exit = 0;
+ kq->kq_running = FALSE;
+ KeInitializeSpinLock(&kq->kq_lock);
+ KeInitializeEvent(&kq->kq_proc, EVENT_TYPE_SYNC, FALSE);
+ KeInitializeEvent(&kq->kq_done, EVENT_TYPE_SYNC, FALSE);
+
+ /*
+ * Elevate our priority. DPCs are used to run interrupt
+ * handlers, and they should trigger as soon as possible
+ * once scheduled by an ISR.
+ */
+
+ thread_lock(curthread);
+#ifdef NTOSKRNL_MULTIPLE_DPCS
+ sched_bind(curthread, kq->kq_cpu);
+#endif
+ sched_prio(curthread, PRI_MIN_KERN);
+ thread_unlock(curthread);
+
+ while (1) {
+ KeWaitForSingleObject(&kq->kq_proc, 0, 0, TRUE, NULL);
+
+ KeAcquireSpinLock(&kq->kq_lock, &irql);
+
+ if (kq->kq_exit) {
+ kq->kq_exit = 0;
+ KeReleaseSpinLock(&kq->kq_lock, irql);
+ break;
+ }
+
+ kq->kq_running = TRUE;
+
+ while (!IsListEmpty(&kq->kq_disp)) {
+ l = RemoveHeadList((&kq->kq_disp));
+ d = CONTAINING_RECORD(l, kdpc, k_dpclistentry);
+ InitializeListHead((&d->k_dpclistentry));
+ KeReleaseSpinLockFromDpcLevel(&kq->kq_lock);
+ MSCALL4(d->k_deferedfunc, d, d->k_deferredctx,
+ d->k_sysarg1, d->k_sysarg2);
+ KeAcquireSpinLockAtDpcLevel(&kq->kq_lock);
+ }
+
+ kq->kq_running = FALSE;
+
+ KeReleaseSpinLock(&kq->kq_lock, irql);
+
+ KeSetEvent(&kq->kq_done, IO_NO_INCREMENT, FALSE);
+ }
+
+ kproc_exit(0);
+ return; /* notreached */
+}
+
+static void
+ntoskrnl_destroy_dpc_threads(void)
+{
+ kdpc_queue *kq;
+ kdpc dpc;
+ int i;
+
+ kq = kq_queues;
+#ifdef NTOSKRNL_MULTIPLE_DPCS
+ for (i = 0; i < mp_ncpus; i++) {
+#else
+ for (i = 0; i < 1; i++) {
+#endif
+ kq += i;
+
+ kq->kq_exit = 1;
+ KeInitializeDpc(&dpc, NULL, NULL);
+ KeSetTargetProcessorDpc(&dpc, i);
+ KeInsertQueueDpc(&dpc, NULL, NULL);
+ while (kq->kq_exit)
+ tsleep(kq->kq_td->td_proc, PWAIT, "dpcw", hz/10);
+ }
+}
+
+static uint8_t
+ntoskrnl_insert_dpc(head, dpc)
+ list_entry *head;
+ kdpc *dpc;
+{
+ list_entry *l;
+ kdpc *d;
+
+ l = head->nle_flink;
+ while (l != head) {
+ d = CONTAINING_RECORD(l, kdpc, k_dpclistentry);
+ if (d == dpc)
+ return (FALSE);
+ l = l->nle_flink;
+ }
+
+ if (dpc->k_importance == KDPC_IMPORTANCE_LOW)
+ InsertTailList((head), (&dpc->k_dpclistentry));
+ else
+ InsertHeadList((head), (&dpc->k_dpclistentry));
+
+ return (TRUE);
+}
+
+void
+KeInitializeDpc(dpc, dpcfunc, dpcctx)
+ kdpc *dpc;
+ void *dpcfunc;
+ void *dpcctx;
+{
+
+ if (dpc == NULL)
+ return;
+
+ dpc->k_deferedfunc = dpcfunc;
+ dpc->k_deferredctx = dpcctx;
+ dpc->k_num = KDPC_CPU_DEFAULT;
+ dpc->k_importance = KDPC_IMPORTANCE_MEDIUM;
+ InitializeListHead((&dpc->k_dpclistentry));
+}
+
+uint8_t
+KeInsertQueueDpc(dpc, sysarg1, sysarg2)
+ kdpc *dpc;
+ void *sysarg1;
+ void *sysarg2;
+{
+ kdpc_queue *kq;
+ uint8_t r;
+ uint8_t irql;
+
+ if (dpc == NULL)
+ return (FALSE);
+
+ kq = kq_queues;
+
+#ifdef NTOSKRNL_MULTIPLE_DPCS
+ KeRaiseIrql(DISPATCH_LEVEL, &irql);
+
+ /*
+ * By default, the DPC is queued to run on the same CPU
+ * that scheduled it.
+ */
+
+ if (dpc->k_num == KDPC_CPU_DEFAULT)
+ kq += curthread->td_oncpu;
+ else
+ kq += dpc->k_num;
+ KeAcquireSpinLockAtDpcLevel(&kq->kq_lock);
+#else
+ KeAcquireSpinLock(&kq->kq_lock, &irql);
+#endif
+
+ r = ntoskrnl_insert_dpc(&kq->kq_disp, dpc);
+ if (r == TRUE) {
+ dpc->k_sysarg1 = sysarg1;
+ dpc->k_sysarg2 = sysarg2;
+ }
+ KeReleaseSpinLock(&kq->kq_lock, irql);
+
+ if (r == FALSE)
+ return (r);
+
+ KeSetEvent(&kq->kq_proc, IO_NO_INCREMENT, FALSE);
+
+ return (r);
+}
+
+uint8_t
+KeRemoveQueueDpc(dpc)
+ kdpc *dpc;
+{
+ kdpc_queue *kq;
+ uint8_t irql;
+
+ if (dpc == NULL)
+ return (FALSE);
+
+#ifdef NTOSKRNL_MULTIPLE_DPCS
+ KeRaiseIrql(DISPATCH_LEVEL, &irql);
+
+ kq = kq_queues + dpc->k_num;
+
+ KeAcquireSpinLockAtDpcLevel(&kq->kq_lock);
+#else
+ kq = kq_queues;
+ KeAcquireSpinLock(&kq->kq_lock, &irql);
+#endif
+
+ if (dpc->k_dpclistentry.nle_flink == &dpc->k_dpclistentry) {
+ KeReleaseSpinLockFromDpcLevel(&kq->kq_lock);
+ KeLowerIrql(irql);
+ return (FALSE);
+ }
+
+ RemoveEntryList((&dpc->k_dpclistentry));
+ InitializeListHead((&dpc->k_dpclistentry));
+
+ KeReleaseSpinLock(&kq->kq_lock, irql);
+
+ return (TRUE);
+}
+
+void
+KeSetImportanceDpc(dpc, imp)
+ kdpc *dpc;
+ uint32_t imp;
+{
+ if (imp != KDPC_IMPORTANCE_LOW &&
+ imp != KDPC_IMPORTANCE_MEDIUM &&
+ imp != KDPC_IMPORTANCE_HIGH)
+ return;
+
+ dpc->k_importance = (uint8_t)imp;
+}
+
+void
+KeSetTargetProcessorDpc(kdpc *dpc, uint8_t cpu)
+{
+ if (cpu > mp_ncpus)
+ return;
+
+ dpc->k_num = cpu;
+}
+
+void
+KeFlushQueuedDpcs(void)
+{
+ kdpc_queue *kq;
+ int i;
+
+ /*
+ * Poke each DPC queue and wait
+ * for them to drain.
+ */
+
+#ifdef NTOSKRNL_MULTIPLE_DPCS
+ for (i = 0; i < mp_ncpus; i++) {
+#else
+ for (i = 0; i < 1; i++) {
+#endif
+ kq = kq_queues + i;
+ KeSetEvent(&kq->kq_proc, IO_NO_INCREMENT, FALSE);
+ KeWaitForSingleObject(&kq->kq_done, 0, 0, TRUE, NULL);
+ }
+}
+
+uint32_t
+KeGetCurrentProcessorNumber(void)
+{
+ return ((uint32_t)curthread->td_oncpu);
+}
+
+uint8_t
+KeSetTimerEx(timer, duetime, period, dpc)
+ ktimer *timer;
+ int64_t duetime;
+ uint32_t period;
+ kdpc *dpc;
+{
+ struct timeval tv;
+ uint64_t curtime;
+ uint8_t pending;
+
+ if (timer == NULL)
+ return (FALSE);
+
+ mtx_lock(&ntoskrnl_dispatchlock);
+
+ if (timer->k_header.dh_inserted == TRUE) {
+ ntoskrnl_remove_timer(timer);
+#ifdef NTOSKRNL_DEBUG_TIMERS
+ ntoskrnl_timer_cancels++;
+#endif
+ timer->k_header.dh_inserted = FALSE;
+ pending = TRUE;
+ } else
+ pending = FALSE;
+
+ timer->k_duetime = duetime;
+ timer->k_period = period;
+ timer->k_header.dh_sigstate = FALSE;
+ timer->k_dpc = dpc;
+
+ if (duetime < 0) {
+ tv.tv_sec = - (duetime) / 10000000;
+ tv.tv_usec = (- (duetime) / 10) -
+ (tv.tv_sec * 1000000);
+ } else {
+ ntoskrnl_time(&curtime);
+ if (duetime < curtime)
+ tv.tv_sec = tv.tv_usec = 0;
+ else {
+ tv.tv_sec = ((duetime) - curtime) / 10000000;
+ tv.tv_usec = ((duetime) - curtime) / 10 -
+ (tv.tv_sec * 1000000);
+ }
+ }
+
+ timer->k_header.dh_inserted = TRUE;
+ ntoskrnl_insert_timer(timer, tvtohz(&tv));
+#ifdef NTOSKRNL_DEBUG_TIMERS
+ ntoskrnl_timer_sets++;
+#endif
+
+ mtx_unlock(&ntoskrnl_dispatchlock);
+
+ return (pending);
+}
+
+uint8_t
+KeSetTimer(timer, duetime, dpc)
+ ktimer *timer;
+ int64_t duetime;
+ kdpc *dpc;
+{
+ return (KeSetTimerEx(timer, duetime, 0, dpc));
+}
+
+/*
+ * The Windows DDK documentation seems to say that cancelling
+ * a timer that has a DPC will result in the DPC also being
+ * cancelled, but this isn't really the case.
+ */
+
+uint8_t
+KeCancelTimer(timer)
+ ktimer *timer;
+{
+ uint8_t pending;
+
+ if (timer == NULL)
+ return (FALSE);
+
+ mtx_lock(&ntoskrnl_dispatchlock);
+
+ pending = timer->k_header.dh_inserted;
+
+ if (timer->k_header.dh_inserted == TRUE) {
+ timer->k_header.dh_inserted = FALSE;
+ ntoskrnl_remove_timer(timer);
+#ifdef NTOSKRNL_DEBUG_TIMERS
+ ntoskrnl_timer_cancels++;
+#endif
+ }
+
+ mtx_unlock(&ntoskrnl_dispatchlock);
+
+ return (pending);
+}
+
+uint8_t
+KeReadStateTimer(timer)
+ ktimer *timer;
+{
+ return (timer->k_header.dh_sigstate);
+}
+
+static int32_t
+KeDelayExecutionThread(uint8_t wait_mode, uint8_t alertable, int64_t *interval)
+{
+ ktimer timer;
+
+ if (wait_mode != 0)
+ panic("invalid wait_mode %d", wait_mode);
+
+ KeInitializeTimer(&timer);
+ KeSetTimer(&timer, *interval, NULL);
+ KeWaitForSingleObject(&timer, 0, 0, alertable, NULL);
+
+ return STATUS_SUCCESS;
+}
+
+static uint64_t
+KeQueryInterruptTime(void)
+{
+ int ticks;
+ struct timeval tv;
+
+ getmicrouptime(&tv);
+
+ ticks = tvtohz(&tv);
+
+ return ticks * ((10000000 + hz - 1) / hz);
+}
+
+static struct thread *
+KeGetCurrentThread(void)
+{
+
+ return curthread;
+}
+
+static int32_t
+KeSetPriorityThread(td, pri)
+ struct thread *td;
+ int32_t pri;
+{
+ int32_t old;
+
+ if (td == NULL)
+ return LOW_REALTIME_PRIORITY;
+
+ if (td->td_priority <= PRI_MIN_KERN)
+ old = HIGH_PRIORITY;
+ else if (td->td_priority >= PRI_MAX_KERN)
+ old = LOW_PRIORITY;
+ else
+ old = LOW_REALTIME_PRIORITY;
+
+ thread_lock(td);
+ if (pri == HIGH_PRIORITY)
+ sched_prio(td, PRI_MIN_KERN);
+ if (pri == LOW_REALTIME_PRIORITY)
+ sched_prio(td, PRI_MIN_KERN + (PRI_MAX_KERN - PRI_MIN_KERN) / 2);
+ if (pri == LOW_PRIORITY)
+ sched_prio(td, PRI_MAX_KERN);
+ thread_unlock(td);
+
+ return old;
+}
+
+static void
+dummy()
+{
+ printf("ntoskrnl dummy called...\n");
+}
+
+
+image_patch_table ntoskrnl_functbl[] = {
+ IMPORT_SFUNC(RtlZeroMemory, 2),
+ IMPORT_SFUNC(RtlSecureZeroMemory, 2),
+ IMPORT_SFUNC(RtlFillMemory, 3),
+ IMPORT_SFUNC(RtlMoveMemory, 3),
+ IMPORT_SFUNC(RtlCharToInteger, 3),
+ IMPORT_SFUNC(RtlCopyMemory, 3),
+ IMPORT_SFUNC(RtlCopyString, 2),
+ IMPORT_SFUNC(RtlCompareMemory, 3),
+ IMPORT_SFUNC(RtlEqualUnicodeString, 3),
+ IMPORT_SFUNC(RtlCopyUnicodeString, 2),
+ IMPORT_SFUNC(RtlUnicodeStringToAnsiString, 3),
+ IMPORT_SFUNC(RtlAnsiStringToUnicodeString, 3),
+ IMPORT_SFUNC(RtlInitAnsiString, 2),
+ IMPORT_SFUNC_MAP(RtlInitString, RtlInitAnsiString, 2),
+ IMPORT_SFUNC(RtlInitUnicodeString, 2),
+ IMPORT_SFUNC(RtlFreeAnsiString, 1),
+ IMPORT_SFUNC(RtlFreeUnicodeString, 1),
+ IMPORT_SFUNC(RtlUnicodeStringToInteger, 3),
+ IMPORT_CFUNC(sprintf, 0),
+ IMPORT_CFUNC(vsprintf, 0),
+ IMPORT_CFUNC_MAP(_snprintf, snprintf, 0),
+ IMPORT_CFUNC_MAP(_vsnprintf, vsnprintf, 0),
+ IMPORT_CFUNC(DbgPrint, 0),
+ IMPORT_SFUNC(DbgBreakPoint, 0),
+ IMPORT_SFUNC(KeBugCheckEx, 5),
+ IMPORT_CFUNC(strncmp, 0),
+ IMPORT_CFUNC(strcmp, 0),
+ IMPORT_CFUNC_MAP(stricmp, strcasecmp, 0),
+ IMPORT_CFUNC(strncpy, 0),
+ IMPORT_CFUNC(strcpy, 0),
+ IMPORT_CFUNC(strlen, 0),
+ IMPORT_CFUNC_MAP(toupper, ntoskrnl_toupper, 0),
+ IMPORT_CFUNC_MAP(tolower, ntoskrnl_tolower, 0),
+ IMPORT_CFUNC_MAP(strstr, ntoskrnl_strstr, 0),
+ IMPORT_CFUNC_MAP(strncat, ntoskrnl_strncat, 0),
+ IMPORT_CFUNC_MAP(strchr, index, 0),
+ IMPORT_CFUNC_MAP(strrchr, rindex, 0),
+ IMPORT_CFUNC(memcpy, 0),
+ IMPORT_CFUNC_MAP(memmove, ntoskrnl_memmove, 0),
+ IMPORT_CFUNC_MAP(memset, ntoskrnl_memset, 0),
+ IMPORT_CFUNC_MAP(memchr, ntoskrnl_memchr, 0),
+ IMPORT_SFUNC(IoAllocateDriverObjectExtension, 4),
+ IMPORT_SFUNC(IoGetDriverObjectExtension, 2),
+ IMPORT_FFUNC(IofCallDriver, 2),
+ IMPORT_FFUNC(IofCompleteRequest, 2),
+ IMPORT_SFUNC(IoAcquireCancelSpinLock, 1),
+ IMPORT_SFUNC(IoReleaseCancelSpinLock, 1),
+ IMPORT_SFUNC(IoCancelIrp, 1),
+ IMPORT_SFUNC(IoConnectInterrupt, 11),
+ IMPORT_SFUNC(IoDisconnectInterrupt, 1),
+ IMPORT_SFUNC(IoCreateDevice, 7),
+ IMPORT_SFUNC(IoDeleteDevice, 1),
+ IMPORT_SFUNC(IoGetAttachedDevice, 1),
+ IMPORT_SFUNC(IoAttachDeviceToDeviceStack, 2),
+ IMPORT_SFUNC(IoDetachDevice, 1),
+ IMPORT_SFUNC(IoBuildSynchronousFsdRequest, 7),
+ IMPORT_SFUNC(IoBuildAsynchronousFsdRequest, 6),
+ IMPORT_SFUNC(IoBuildDeviceIoControlRequest, 9),
+ IMPORT_SFUNC(IoAllocateIrp, 2),
+ IMPORT_SFUNC(IoReuseIrp, 2),
+ IMPORT_SFUNC(IoMakeAssociatedIrp, 2),
+ IMPORT_SFUNC(IoFreeIrp, 1),
+ IMPORT_SFUNC(IoInitializeIrp, 3),
+ IMPORT_SFUNC(KeAcquireInterruptSpinLock, 1),
+ IMPORT_SFUNC(KeReleaseInterruptSpinLock, 2),
+ IMPORT_SFUNC(KeSynchronizeExecution, 3),
+ IMPORT_SFUNC(KeWaitForSingleObject, 5),
+ IMPORT_SFUNC(KeWaitForMultipleObjects, 8),
+ IMPORT_SFUNC(_allmul, 4),
+ IMPORT_SFUNC(_alldiv, 4),
+ IMPORT_SFUNC(_allrem, 4),
+ IMPORT_RFUNC(_allshr, 0),
+ IMPORT_RFUNC(_allshl, 0),
+ IMPORT_SFUNC(_aullmul, 4),
+ IMPORT_SFUNC(_aulldiv, 4),
+ IMPORT_SFUNC(_aullrem, 4),
+ IMPORT_RFUNC(_aullshr, 0),
+ IMPORT_RFUNC(_aullshl, 0),
+ IMPORT_CFUNC(atoi, 0),
+ IMPORT_CFUNC(atol, 0),
+ IMPORT_CFUNC(rand, 0),
+ IMPORT_CFUNC(srand, 0),
+ IMPORT_SFUNC(WRITE_REGISTER_USHORT, 2),
+ IMPORT_SFUNC(READ_REGISTER_USHORT, 1),
+ IMPORT_SFUNC(WRITE_REGISTER_ULONG, 2),
+ IMPORT_SFUNC(READ_REGISTER_ULONG, 1),
+ IMPORT_SFUNC(READ_REGISTER_UCHAR, 1),
+ IMPORT_SFUNC(WRITE_REGISTER_UCHAR, 2),
+ IMPORT_SFUNC(ExInitializePagedLookasideList, 7),
+ IMPORT_SFUNC(ExDeletePagedLookasideList, 1),
+ IMPORT_SFUNC(ExInitializeNPagedLookasideList, 7),
+ IMPORT_SFUNC(ExDeleteNPagedLookasideList, 1),
+ IMPORT_FFUNC(InterlockedPopEntrySList, 1),
+ IMPORT_FFUNC(InitializeSListHead, 1),
+ IMPORT_FFUNC(InterlockedPushEntrySList, 2),
+ IMPORT_SFUNC(ExQueryDepthSList, 1),
+ IMPORT_FFUNC_MAP(ExpInterlockedPopEntrySList,
+ InterlockedPopEntrySList, 1),
+ IMPORT_FFUNC_MAP(ExpInterlockedPushEntrySList,
+ InterlockedPushEntrySList, 2),
+ IMPORT_FFUNC(ExInterlockedPopEntrySList, 2),
+ IMPORT_FFUNC(ExInterlockedPushEntrySList, 3),
+ IMPORT_SFUNC(ExAllocatePoolWithTag, 3),
+ IMPORT_SFUNC(ExFreePoolWithTag, 2),
+ IMPORT_SFUNC(ExFreePool, 1),
+#ifdef __i386__
+ IMPORT_FFUNC(KefAcquireSpinLockAtDpcLevel, 1),
+ IMPORT_FFUNC(KefReleaseSpinLockFromDpcLevel,1),
+ IMPORT_FFUNC(KeAcquireSpinLockRaiseToDpc, 1),
+#else
+ /*
+ * For AMD64, we can get away with just mapping
+ * KeAcquireSpinLockRaiseToDpc() directly to KfAcquireSpinLock()
+ * because the calling conventions end up being the same.
+ * On i386, we have to be careful because KfAcquireSpinLock()
+ * is _fastcall but KeAcquireSpinLockRaiseToDpc() isn't.
+ */
+ IMPORT_SFUNC(KeAcquireSpinLockAtDpcLevel, 1),
+ IMPORT_SFUNC(KeReleaseSpinLockFromDpcLevel, 1),
+ IMPORT_SFUNC_MAP(KeAcquireSpinLockRaiseToDpc, KfAcquireSpinLock, 1),
+#endif
+ IMPORT_SFUNC_MAP(KeReleaseSpinLock, KfReleaseSpinLock, 1),
+ IMPORT_FFUNC(InterlockedIncrement, 1),
+ IMPORT_FFUNC(InterlockedDecrement, 1),
+ IMPORT_FFUNC(InterlockedExchange, 2),
+ IMPORT_FFUNC(ExInterlockedAddLargeStatistic, 2),
+ IMPORT_SFUNC(IoAllocateMdl, 5),
+ IMPORT_SFUNC(IoFreeMdl, 1),
+ IMPORT_SFUNC(MmAllocateContiguousMemory, 2 + 1),
+ IMPORT_SFUNC(MmAllocateContiguousMemorySpecifyCache, 5 + 3),
+ IMPORT_SFUNC(MmFreeContiguousMemory, 1),
+ IMPORT_SFUNC(MmFreeContiguousMemorySpecifyCache, 3),
+ IMPORT_SFUNC(MmSizeOfMdl, 1),
+ IMPORT_SFUNC(MmMapLockedPages, 2),
+ IMPORT_SFUNC(MmMapLockedPagesSpecifyCache, 6),
+ IMPORT_SFUNC(MmUnmapLockedPages, 2),
+ IMPORT_SFUNC(MmBuildMdlForNonPagedPool, 1),
+ IMPORT_SFUNC(MmGetPhysicalAddress, 1),
+ IMPORT_SFUNC(MmGetSystemRoutineAddress, 1),
+ IMPORT_SFUNC(MmIsAddressValid, 1),
+ IMPORT_SFUNC(MmMapIoSpace, 3 + 1),
+ IMPORT_SFUNC(MmUnmapIoSpace, 2),
+ IMPORT_SFUNC(KeInitializeSpinLock, 1),
+ IMPORT_SFUNC(IoIsWdmVersionAvailable, 2),
+ IMPORT_SFUNC(IoOpenDeviceRegistryKey, 4),
+ IMPORT_SFUNC(IoGetDeviceObjectPointer, 4),
+ IMPORT_SFUNC(IoGetDeviceProperty, 5),
+ IMPORT_SFUNC(IoAllocateWorkItem, 1),
+ IMPORT_SFUNC(IoFreeWorkItem, 1),
+ IMPORT_SFUNC(IoQueueWorkItem, 4),
+ IMPORT_SFUNC(ExQueueWorkItem, 2),
+ IMPORT_SFUNC(ntoskrnl_workitem, 2),
+ IMPORT_SFUNC(KeInitializeMutex, 2),
+ IMPORT_SFUNC(KeReleaseMutex, 2),
+ IMPORT_SFUNC(KeReadStateMutex, 1),
+ IMPORT_SFUNC(KeInitializeEvent, 3),
+ IMPORT_SFUNC(KeSetEvent, 3),
+ IMPORT_SFUNC(KeResetEvent, 1),
+ IMPORT_SFUNC(KeClearEvent, 1),
+ IMPORT_SFUNC(KeReadStateEvent, 1),
+ IMPORT_SFUNC(KeInitializeTimer, 1),
+ IMPORT_SFUNC(KeInitializeTimerEx, 2),
+ IMPORT_SFUNC(KeSetTimer, 3),
+ IMPORT_SFUNC(KeSetTimerEx, 4),
+ IMPORT_SFUNC(KeCancelTimer, 1),
+ IMPORT_SFUNC(KeReadStateTimer, 1),
+ IMPORT_SFUNC(KeInitializeDpc, 3),
+ IMPORT_SFUNC(KeInsertQueueDpc, 3),
+ IMPORT_SFUNC(KeRemoveQueueDpc, 1),
+ IMPORT_SFUNC(KeSetImportanceDpc, 2),
+ IMPORT_SFUNC(KeSetTargetProcessorDpc, 2),
+ IMPORT_SFUNC(KeFlushQueuedDpcs, 0),
+ IMPORT_SFUNC(KeGetCurrentProcessorNumber, 1),
+ IMPORT_SFUNC(ObReferenceObjectByHandle, 6),
+ IMPORT_FFUNC(ObfDereferenceObject, 1),
+ IMPORT_SFUNC(ZwClose, 1),
+ IMPORT_SFUNC(PsCreateSystemThread, 7),
+ IMPORT_SFUNC(PsTerminateSystemThread, 1),
+ IMPORT_SFUNC(IoWMIRegistrationControl, 2),
+ IMPORT_SFUNC(WmiQueryTraceInformation, 5),
+ IMPORT_CFUNC(WmiTraceMessage, 0),
+ IMPORT_SFUNC(KeQuerySystemTime, 1),
+ IMPORT_CFUNC(KeTickCount, 0),
+ IMPORT_SFUNC(KeDelayExecutionThread, 3),
+ IMPORT_SFUNC(KeQueryInterruptTime, 0),
+ IMPORT_SFUNC(KeGetCurrentThread, 0),
+ IMPORT_SFUNC(KeSetPriorityThread, 2),
+
+ /*
+ * This last entry is a catch-all for any function we haven't
+ * implemented yet. The PE import list patching routine will
+ * use it for any function that doesn't have an explicit match
+ * in this table.
+ */
+
+ { NULL, (FUNC)dummy, NULL, 0, WINDRV_WRAP_STDCALL },
+
+ /* End of list. */
+
+ { NULL, NULL, NULL }
+};
diff --git a/sys/compat/ndis/subr_pe.c b/sys/compat/ndis/subr_pe.c
new file mode 100644
index 0000000..fcbaef2
--- /dev/null
+++ b/sys/compat/ndis/subr_pe.c
@@ -0,0 +1,642 @@
+/*-
+ * Copyright (c) 2003
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * This file contains routines for relocating and dynamically linking
+ * executable object code files in the Windows(r) PE (Portable Executable)
+ * format. In Windows, anything with a .EXE, .DLL or .SYS extention is
+ * considered an executable, and all such files have some structures in
+ * common. The PE format was apparently based largely on COFF but has
+ * mutated significantly over time. We are mainly concerned with .SYS files,
+ * so this module implements only enough routines to be able to parse the
+ * headers and sections of a .SYS object file and perform the necessary
+ * relocations and jump table patching to allow us to call into it
+ * (and to have it call back to us). Note that while this module
+ * can handle fixups for imported symbols, it knows nothing about
+ * exporting them.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+#ifdef _KERNEL
+#include <sys/systm.h>
+#else
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#endif
+
+#include <compat/ndis/pe_var.h>
+
+static vm_offset_t pe_functbl_match(image_patch_table *, char *);
+
+/*
+ * Check for an MS-DOS executable header. All Windows binaries
+ * have a small MS-DOS executable prepended to them to print out
+ * the "This program requires Windows" message. Even .SYS files
+ * have this header, in spite of the fact that you're can't actually
+ * run them directly.
+ */
+
+int
+pe_get_dos_header(imgbase, hdr)
+ vm_offset_t imgbase;
+ image_dos_header *hdr;
+{
+ uint16_t signature;
+
+ if (imgbase == 0 || hdr == NULL)
+ return (EINVAL);
+
+ signature = *(uint16_t *)imgbase;
+ if (signature != IMAGE_DOS_SIGNATURE)
+ return (ENOEXEC);
+
+ bcopy ((char *)imgbase, (char *)hdr, sizeof(image_dos_header));
+
+ return (0);
+}
+
+/*
+ * Verify that this image has a Windows NT PE signature.
+ */
+
+int
+pe_is_nt_image(imgbase)
+ vm_offset_t imgbase;
+{
+ uint32_t signature;
+ image_dos_header *dos_hdr;
+
+ if (imgbase == 0)
+ return (EINVAL);
+
+ signature = *(uint16_t *)imgbase;
+ if (signature == IMAGE_DOS_SIGNATURE) {
+ dos_hdr = (image_dos_header *)imgbase;
+ signature = *(uint32_t *)(imgbase + dos_hdr->idh_lfanew);
+ if (signature == IMAGE_NT_SIGNATURE)
+ return (0);
+ }
+
+ return (ENOEXEC);
+}
+
+/*
+ * Return a copy of the optional header. This contains the
+ * executable entry point and the directory listing which we
+ * need to find the relocations and imports later.
+ */
+
+int
+pe_get_optional_header(imgbase, hdr)
+ vm_offset_t imgbase;
+ image_optional_header *hdr;
+{
+ image_dos_header *dos_hdr;
+ image_nt_header *nt_hdr;
+
+ if (imgbase == 0 || hdr == NULL)
+ return (EINVAL);
+
+ if (pe_is_nt_image(imgbase))
+ return (EINVAL);
+
+ dos_hdr = (image_dos_header *)(imgbase);
+ nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
+
+ bcopy ((char *)&nt_hdr->inh_optionalhdr, (char *)hdr,
+ nt_hdr->inh_filehdr.ifh_optionalhdrlen);
+
+ return (0);
+}
+
+/*
+ * Return a copy of the file header. Contains the number of
+ * sections in this image.
+ */
+
+int
+pe_get_file_header(imgbase, hdr)
+ vm_offset_t imgbase;
+ image_file_header *hdr;
+{
+ image_dos_header *dos_hdr;
+ image_nt_header *nt_hdr;
+
+ if (imgbase == 0 || hdr == NULL)
+ return (EINVAL);
+
+ if (pe_is_nt_image(imgbase))
+ return (EINVAL);
+
+ dos_hdr = (image_dos_header *)imgbase;
+ nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
+
+ /*
+ * Note: the size of the nt_header is variable since it
+ * can contain optional fields, as indicated by ifh_optionalhdrlen.
+ * However it happens we're only interested in fields in the
+ * non-variant portion of the nt_header structure, so we don't
+ * bother copying the optional parts here.
+ */
+
+ bcopy ((char *)&nt_hdr->inh_filehdr, (char *)hdr,
+ sizeof(image_file_header));
+
+ return (0);
+}
+
+/*
+ * Return the header of the first section in this image (usually
+ * .text).
+ */
+
+int
+pe_get_section_header(imgbase, hdr)
+ vm_offset_t imgbase;
+ image_section_header *hdr;
+{
+ image_dos_header *dos_hdr;
+ image_nt_header *nt_hdr;
+ image_section_header *sect_hdr;
+
+ if (imgbase == 0 || hdr == NULL)
+ return (EINVAL);
+
+ if (pe_is_nt_image(imgbase))
+ return (EINVAL);
+
+ dos_hdr = (image_dos_header *)imgbase;
+ nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
+ sect_hdr = IMAGE_FIRST_SECTION(nt_hdr);
+
+ bcopy ((char *)sect_hdr, (char *)hdr, sizeof(image_section_header));
+
+ return (0);
+}
+
+/*
+ * Return the number of sections in this executable, or 0 on error.
+ */
+
+int
+pe_numsections(imgbase)
+ vm_offset_t imgbase;
+{
+ image_file_header file_hdr;
+
+ if (pe_get_file_header(imgbase, &file_hdr))
+ return (0);
+
+ return (file_hdr.ifh_numsections);
+}
+
+/*
+ * Return the base address that this image was linked for.
+ * This helps us calculate relocation addresses later.
+ */
+
+vm_offset_t
+pe_imagebase(imgbase)
+ vm_offset_t imgbase;
+{
+ image_optional_header optional_hdr;
+
+ if (pe_get_optional_header(imgbase, &optional_hdr))
+ return (0);
+
+ return (optional_hdr.ioh_imagebase);
+}
+
+/*
+ * Return the offset of a given directory structure within the
+ * image. Directories reside within sections.
+ */
+
+vm_offset_t
+pe_directory_offset(imgbase, diridx)
+ vm_offset_t imgbase;
+ uint32_t diridx;
+{
+ image_optional_header opt_hdr;
+ vm_offset_t dir;
+
+ if (pe_get_optional_header(imgbase, &opt_hdr))
+ return (0);
+
+ if (diridx >= opt_hdr.ioh_rva_size_cnt)
+ return (0);
+
+ dir = opt_hdr.ioh_datadir[diridx].idd_vaddr;
+
+ return (pe_translate_addr(imgbase, dir));
+}
+
+vm_offset_t
+pe_translate_addr(imgbase, rva)
+ vm_offset_t imgbase;
+ vm_offset_t rva;
+{
+ image_optional_header opt_hdr;
+ image_section_header *sect_hdr;
+ image_dos_header *dos_hdr;
+ image_nt_header *nt_hdr;
+ int i = 0, sections, fixedlen;
+
+ if (pe_get_optional_header(imgbase, &opt_hdr))
+ return (0);
+
+ sections = pe_numsections(imgbase);
+
+ dos_hdr = (image_dos_header *)imgbase;
+ nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
+ sect_hdr = IMAGE_FIRST_SECTION(nt_hdr);
+
+ /*
+ * The test here is to see if the RVA falls somewhere
+ * inside the section, based on the section's start RVA
+ * and its length. However it seems sometimes the
+ * virtual length isn't enough to cover the entire
+ * area of the section. We fudge by taking into account
+ * the section alignment and rounding the section length
+ * up to a page boundary.
+ */
+ while (i++ < sections) {
+ fixedlen = sect_hdr->ish_misc.ish_vsize;
+ fixedlen += ((opt_hdr.ioh_sectalign - 1) -
+ sect_hdr->ish_misc.ish_vsize) &
+ (opt_hdr.ioh_sectalign - 1);
+ if (sect_hdr->ish_vaddr <= (uint32_t)rva &&
+ (sect_hdr->ish_vaddr + fixedlen) >
+ (uint32_t)rva)
+ break;
+ sect_hdr++;
+ }
+
+ if (i > sections)
+ return (0);
+
+ return ((vm_offset_t)(imgbase + rva - sect_hdr->ish_vaddr +
+ sect_hdr->ish_rawdataaddr));
+}
+
+/*
+ * Get the section header for a particular section. Note that
+ * section names can be anything, but there are some standard
+ * ones (.text, .data, .rdata, .reloc).
+ */
+
+int
+pe_get_section(imgbase, hdr, name)
+ vm_offset_t imgbase;
+ image_section_header *hdr;
+ const char *name;
+{
+ image_dos_header *dos_hdr;
+ image_nt_header *nt_hdr;
+ image_section_header *sect_hdr;
+
+ int i, sections;
+
+ if (imgbase == 0 || hdr == NULL)
+ return (EINVAL);
+
+ if (pe_is_nt_image(imgbase))
+ return (EINVAL);
+
+ sections = pe_numsections(imgbase);
+
+ dos_hdr = (image_dos_header *)imgbase;
+ nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
+ sect_hdr = IMAGE_FIRST_SECTION(nt_hdr);
+
+ for (i = 0; i < sections; i++) {
+ if (!strcmp ((char *)&sect_hdr->ish_name, name)) {
+ bcopy((char *)sect_hdr, (char *)hdr,
+ sizeof(image_section_header));
+ return (0);
+ } else
+ sect_hdr++;
+ }
+
+ return (ENOEXEC);
+}
+
+/*
+ * Apply the base relocations to this image. The relocation table
+ * resides within the .reloc section. Relocations are specified in
+ * blocks which refer to a particular page. We apply the relocations
+ * one page block at a time.
+ */
+
+int
+pe_relocate(imgbase)
+ vm_offset_t imgbase;
+{
+ image_section_header sect;
+ image_base_reloc *relhdr;
+ uint16_t rel, *sloc;
+ vm_offset_t base;
+ vm_size_t delta;
+ uint32_t *lloc;
+ uint64_t *qloc;
+ int i, count;
+ vm_offset_t txt;
+
+ base = pe_imagebase(imgbase);
+ pe_get_section(imgbase, &sect, ".text");
+ txt = pe_translate_addr(imgbase, sect.ish_vaddr);
+ delta = (uint32_t)(txt) - base - sect.ish_vaddr;
+
+ pe_get_section(imgbase, &sect, ".reloc");
+
+ relhdr = (image_base_reloc *)(imgbase + sect.ish_rawdataaddr);
+
+ do {
+ count = (relhdr->ibr_blocksize -
+ (sizeof(uint32_t) * 2)) / sizeof(uint16_t);
+ for (i = 0; i < count; i++) {
+ rel = relhdr->ibr_rel[i];
+ switch (IMR_RELTYPE(rel)) {
+ case IMAGE_REL_BASED_ABSOLUTE:
+ break;
+ case IMAGE_REL_BASED_HIGHLOW:
+ lloc = (uint32_t *)pe_translate_addr(imgbase,
+ relhdr->ibr_vaddr + IMR_RELOFFSET(rel));
+ *lloc = pe_translate_addr(imgbase,
+ (*lloc - base));
+ break;
+ case IMAGE_REL_BASED_HIGH:
+ sloc = (uint16_t *)pe_translate_addr(imgbase,
+ relhdr->ibr_vaddr + IMR_RELOFFSET(rel));
+ *sloc += (delta & 0xFFFF0000) >> 16;
+ break;
+ case IMAGE_REL_BASED_LOW:
+ sloc = (uint16_t *)pe_translate_addr(imgbase,
+ relhdr->ibr_vaddr + IMR_RELOFFSET(rel));
+ *sloc += (delta & 0xFFFF);
+ break;
+ case IMAGE_REL_BASED_DIR64:
+ qloc = (uint64_t *)pe_translate_addr(imgbase,
+ relhdr->ibr_vaddr + IMR_RELOFFSET(rel));
+ *qloc = pe_translate_addr(imgbase,
+ (*qloc - base));
+ break;
+
+ default:
+ printf("[%d]reloc type: %d\n",i,
+ IMR_RELTYPE(rel));
+ break;
+ }
+ }
+ relhdr = (image_base_reloc *)((vm_offset_t)relhdr +
+ relhdr->ibr_blocksize);
+ } while (relhdr->ibr_blocksize);
+
+ return (0);
+}
+
+/*
+ * Return the import descriptor for a particular module. An image
+ * may be linked against several modules, typically HAL.dll, ntoskrnl.exe
+ * and NDIS.SYS. For each module, there is a list of imported function
+ * names and their addresses.
+ *
+ * Note: module names are case insensitive!
+ */
+
+int
+pe_get_import_descriptor(imgbase, desc, module)
+ vm_offset_t imgbase;
+ image_import_descriptor *desc;
+ char *module;
+{
+ vm_offset_t offset;
+ image_import_descriptor *imp_desc;
+ char *modname;
+
+ if (imgbase == 0 || module == NULL || desc == NULL)
+ return (EINVAL);
+
+ offset = pe_directory_offset(imgbase, IMAGE_DIRECTORY_ENTRY_IMPORT);
+ if (offset == 0)
+ return (ENOENT);
+
+ imp_desc = (void *)offset;
+
+ while (imp_desc->iid_nameaddr) {
+ modname = (char *)pe_translate_addr(imgbase,
+ imp_desc->iid_nameaddr);
+ if (!strncasecmp(module, modname, strlen(module))) {
+ bcopy((char *)imp_desc, (char *)desc,
+ sizeof(image_import_descriptor));
+ return (0);
+ }
+ imp_desc++;
+ }
+
+ return (ENOENT);
+}
+
+int
+pe_get_messagetable(imgbase, md)
+ vm_offset_t imgbase;
+ message_resource_data **md;
+{
+ image_resource_directory *rdir, *rtype;
+ image_resource_directory_entry *dent, *dent2;
+ image_resource_data_entry *rent;
+ vm_offset_t offset;
+ int i;
+
+ if (imgbase == 0)
+ return (EINVAL);
+
+ offset = pe_directory_offset(imgbase, IMAGE_DIRECTORY_ENTRY_RESOURCE);
+ if (offset == 0)
+ return (ENOENT);
+
+ rdir = (image_resource_directory *)offset;
+
+ dent = (image_resource_directory_entry *)(offset +
+ sizeof(image_resource_directory));
+
+ for (i = 0; i < rdir->ird_id_entries; i++){
+ if (dent->irde_name != RT_MESSAGETABLE) {
+ dent++;
+ continue;
+ }
+ dent2 = dent;
+ while (dent2->irde_dataoff & RESOURCE_DIR_FLAG) {
+ rtype = (image_resource_directory *)(offset +
+ (dent2->irde_dataoff & ~RESOURCE_DIR_FLAG));
+ dent2 = (image_resource_directory_entry *)
+ ((uintptr_t)rtype +
+ sizeof(image_resource_directory));
+ }
+ rent = (image_resource_data_entry *)(offset +
+ dent2->irde_dataoff);
+ *md = (message_resource_data *)pe_translate_addr(imgbase,
+ rent->irde_offset);
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
+int
+pe_get_message(imgbase, id, str, len, flags)
+ vm_offset_t imgbase;
+ uint32_t id;
+ char **str;
+ int *len;
+ uint16_t *flags;
+{
+ message_resource_data *md = NULL;
+ message_resource_block *mb;
+ message_resource_entry *me;
+ uint32_t i;
+
+ pe_get_messagetable(imgbase, &md);
+
+ if (md == NULL)
+ return (ENOENT);
+
+ mb = (message_resource_block *)((uintptr_t)md +
+ sizeof(message_resource_data));
+
+ for (i = 0; i < md->mrd_numblocks; i++) {
+ if (id >= mb->mrb_lowid && id <= mb->mrb_highid) {
+ me = (message_resource_entry *)((uintptr_t)md +
+ mb->mrb_entryoff);
+ for (i = id - mb->mrb_lowid; i > 0; i--)
+ me = (message_resource_entry *)((uintptr_t)me +
+ me->mre_len);
+ *str = me->mre_text;
+ *len = me->mre_len;
+ *flags = me->mre_flags;
+ return (0);
+ }
+ mb++;
+ }
+
+ return (ENOENT);
+}
+
+/*
+ * Find the function that matches a particular name. This doesn't
+ * need to be particularly speedy since it's only run when loading
+ * a module for the first time.
+ */
+
+static vm_offset_t
+pe_functbl_match(functbl, name)
+ image_patch_table *functbl;
+ char *name;
+{
+ image_patch_table *p;
+
+ if (functbl == NULL || name == NULL)
+ return (0);
+
+ p = functbl;
+
+ while (p->ipt_name != NULL) {
+ if (!strcmp(p->ipt_name, name))
+ return ((vm_offset_t)p->ipt_wrap);
+ p++;
+ }
+ printf("no match for %s\n", name);
+
+ /*
+ * Return the wrapper pointer for this routine.
+ * For x86, this is the same as the funcptr.
+ * For amd64, this points to a wrapper routine
+ * that does calling convention translation and
+ * then invokes the underlying routine.
+ */
+ return ((vm_offset_t)p->ipt_wrap);
+}
+
+/*
+ * Patch the imported function addresses for a given module.
+ * The caller must specify the module name and provide a table
+ * of function pointers that will be patched into the jump table.
+ * Note that there are actually two copies of the jump table: one
+ * copy is left alone. In a .SYS file, the jump tables are usually
+ * merged into the INIT segment.
+ */
+
+int
+pe_patch_imports(imgbase, module, functbl)
+ vm_offset_t imgbase;
+ char *module;
+ image_patch_table *functbl;
+{
+ image_import_descriptor imp_desc;
+ char *fname;
+ vm_offset_t *nptr, *fptr;
+ vm_offset_t func;
+
+ if (imgbase == 0 || module == NULL || functbl == NULL)
+ return (EINVAL);
+
+ if (pe_get_import_descriptor(imgbase, &imp_desc, module))
+ return (ENOEXEC);
+
+ nptr = (vm_offset_t *)pe_translate_addr(imgbase,
+ imp_desc.iid_import_name_table_addr);
+ fptr = (vm_offset_t *)pe_translate_addr(imgbase,
+ imp_desc.iid_import_address_table_addr);
+
+ while (nptr != NULL && pe_translate_addr(imgbase, *nptr)) {
+ fname = (char *)pe_translate_addr(imgbase, (*nptr) + 2);
+ func = pe_functbl_match(functbl, fname);
+ if (func)
+ *fptr = func;
+#ifdef notdef
+ if (*fptr == 0)
+ return (ENOENT);
+#endif
+ nptr++;
+ fptr++;
+ }
+
+ return (0);
+}
diff --git a/sys/compat/ndis/subr_usbd.c b/sys/compat/ndis/subr_usbd.c
new file mode 100644
index 0000000..b989630
--- /dev/null
+++ b/sys/compat/ndis/subr_usbd.c
@@ -0,0 +1,1458 @@
+/*-
+ * Copyright (c) 2005
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/unistd.h>
+#include <sys/types.h>
+
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sx.h>
+#include <sys/condvar.h>
+#include <sys/module.h>
+#include <sys/conf.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <machine/bus.h>
+#include <sys/bus.h>
+
+#include <sys/queue.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_ioctl.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_device.h>
+#include <dev/usb/usb_request.h>
+
+#include <compat/ndis/pe_var.h>
+#include <compat/ndis/cfg_var.h>
+#include <compat/ndis/resource_var.h>
+#include <compat/ndis/ntoskrnl_var.h>
+#include <compat/ndis/ndis_var.h>
+#include <compat/ndis/hal_var.h>
+#include <compat/ndis/usbd_var.h>
+#include <dev/if_ndis/if_ndisvar.h>
+
+static driver_object usbd_driver;
+static usb_callback_t usbd_non_isoc_callback;
+static usb_callback_t usbd_ctrl_callback;
+
+#define USBD_CTRL_READ_PIPE 0
+#define USBD_CTRL_WRITE_PIPE 1
+#define USBD_CTRL_MAX_PIPE 2
+#define USBD_CTRL_READ_BUFFER_SP 256
+#define USBD_CTRL_WRITE_BUFFER_SP 256
+#define USBD_CTRL_READ_BUFFER_SIZE \
+ (sizeof(struct usb_device_request) + USBD_CTRL_READ_BUFFER_SP)
+#define USBD_CTRL_WRITE_BUFFER_SIZE \
+ (sizeof(struct usb_device_request) + USBD_CTRL_WRITE_BUFFER_SP)
+static struct usb_config usbd_default_epconfig[USBD_CTRL_MAX_PIPE] = {
+ [USBD_CTRL_READ_PIPE] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* control pipe */
+ .direction = UE_DIR_ANY,
+ .if_index = 0,
+ .bufsize = USBD_CTRL_READ_BUFFER_SIZE,
+ .flags = { .short_xfer_ok = 1, },
+ .callback = &usbd_ctrl_callback,
+ .timeout = 5000, /* 5 seconds */
+ },
+ [USBD_CTRL_WRITE_PIPE] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* control pipe */
+ .direction = UE_DIR_ANY,
+ .if_index = 0,
+ .bufsize = USBD_CTRL_WRITE_BUFFER_SIZE,
+ .flags = { .proxy_buffer = 1, },
+ .callback = &usbd_ctrl_callback,
+ .timeout = 5000, /* 5 seconds */
+ }
+};
+
+static int32_t usbd_func_bulkintr(irp *);
+static int32_t usbd_func_vendorclass(irp *);
+static int32_t usbd_func_selconf(irp *);
+static int32_t usbd_func_abort_pipe(irp *);
+static usb_error_t usbd_setup_endpoint(irp *, uint8_t,
+ struct usb_endpoint_descriptor *);
+static usb_error_t usbd_setup_endpoint_default(irp *, uint8_t);
+static usb_error_t usbd_setup_endpoint_one(irp *, uint8_t,
+ struct ndisusb_ep *, struct usb_config *);
+static int32_t usbd_func_getdesc(irp *);
+static union usbd_urb *usbd_geturb(irp *);
+static struct ndisusb_ep*usbd_get_ndisep(irp *, usb_endpoint_descriptor_t *);
+static int32_t usbd_iodispatch(device_object *, irp *);
+static int32_t usbd_ioinvalid(device_object *, irp *);
+static int32_t usbd_pnp(device_object *, irp *);
+static int32_t usbd_power(device_object *, irp *);
+static void usbd_irpcancel(device_object *, irp *);
+static int32_t usbd_submit_urb(irp *);
+static int32_t usbd_urb2nt(int32_t);
+static void usbd_task(device_object *, void *);
+static int32_t usbd_taskadd(irp *, unsigned);
+static void usbd_xfertask(device_object *, void *);
+static void dummy(void);
+
+static union usbd_urb *USBD_CreateConfigurationRequestEx(
+ usb_config_descriptor_t *,
+ struct usbd_interface_list_entry *);
+static union usbd_urb *USBD_CreateConfigurationRequest(
+ usb_config_descriptor_t *,
+ uint16_t *);
+static void USBD_GetUSBDIVersion(usbd_version_info *);
+static usb_interface_descriptor_t *USBD_ParseConfigurationDescriptorEx(
+ usb_config_descriptor_t *, void *, int32_t, int32_t,
+ int32_t, int32_t, int32_t);
+static usb_interface_descriptor_t *USBD_ParseConfigurationDescriptor(
+ usb_config_descriptor_t *, uint8_t, uint8_t);
+
+/*
+ * We need to wrap these functions because these need `context switch' from
+ * Windows to UNIX before it's called.
+ */
+static funcptr usbd_iodispatch_wrap;
+static funcptr usbd_ioinvalid_wrap;
+static funcptr usbd_pnp_wrap;
+static funcptr usbd_power_wrap;
+static funcptr usbd_irpcancel_wrap;
+static funcptr usbd_task_wrap;
+static funcptr usbd_xfertask_wrap;
+
+int
+usbd_libinit(void)
+{
+ image_patch_table *patch;
+ int i;
+
+ patch = usbd_functbl;
+ while (patch->ipt_func != NULL) {
+ windrv_wrap((funcptr)patch->ipt_func,
+ (funcptr *)&patch->ipt_wrap,
+ patch->ipt_argcnt, patch->ipt_ftype);
+ patch++;
+ }
+
+ windrv_wrap((funcptr)usbd_ioinvalid,
+ (funcptr *)&usbd_ioinvalid_wrap, 2, WINDRV_WRAP_STDCALL);
+ windrv_wrap((funcptr)usbd_iodispatch,
+ (funcptr *)&usbd_iodispatch_wrap, 2, WINDRV_WRAP_STDCALL);
+ windrv_wrap((funcptr)usbd_pnp,
+ (funcptr *)&usbd_pnp_wrap, 2, WINDRV_WRAP_STDCALL);
+ windrv_wrap((funcptr)usbd_power,
+ (funcptr *)&usbd_power_wrap, 2, WINDRV_WRAP_STDCALL);
+ windrv_wrap((funcptr)usbd_irpcancel,
+ (funcptr *)&usbd_irpcancel_wrap, 2, WINDRV_WRAP_STDCALL);
+ windrv_wrap((funcptr)usbd_task,
+ (funcptr *)&usbd_task_wrap, 2, WINDRV_WRAP_STDCALL);
+ windrv_wrap((funcptr)usbd_xfertask,
+ (funcptr *)&usbd_xfertask_wrap, 2, WINDRV_WRAP_STDCALL);
+
+ /* Create a fake USB driver instance. */
+
+ windrv_bus_attach(&usbd_driver, "USB Bus");
+
+ /* Set up our dipatch routine. */
+ for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
+ usbd_driver.dro_dispatch[i] =
+ (driver_dispatch)usbd_ioinvalid_wrap;
+
+ usbd_driver.dro_dispatch[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
+ (driver_dispatch)usbd_iodispatch_wrap;
+ usbd_driver.dro_dispatch[IRP_MJ_DEVICE_CONTROL] =
+ (driver_dispatch)usbd_iodispatch_wrap;
+ usbd_driver.dro_dispatch[IRP_MJ_POWER] =
+ (driver_dispatch)usbd_power_wrap;
+ usbd_driver.dro_dispatch[IRP_MJ_PNP] =
+ (driver_dispatch)usbd_pnp_wrap;
+
+ return (0);
+}
+
+int
+usbd_libfini(void)
+{
+ image_patch_table *patch;
+
+ patch = usbd_functbl;
+ while (patch->ipt_func != NULL) {
+ windrv_unwrap(patch->ipt_wrap);
+ patch++;
+ }
+
+ windrv_unwrap(usbd_ioinvalid_wrap);
+ windrv_unwrap(usbd_iodispatch_wrap);
+ windrv_unwrap(usbd_pnp_wrap);
+ windrv_unwrap(usbd_power_wrap);
+ windrv_unwrap(usbd_irpcancel_wrap);
+ windrv_unwrap(usbd_task_wrap);
+ windrv_unwrap(usbd_xfertask_wrap);
+
+ free(usbd_driver.dro_drivername.us_buf, M_DEVBUF);
+
+ return (0);
+}
+
+static int32_t
+usbd_iodispatch(device_object *dobj, irp *ip)
+{
+ device_t dev = dobj->do_devext;
+ int32_t status;
+ struct io_stack_location *irp_sl;
+
+ irp_sl = IoGetCurrentIrpStackLocation(ip);
+ switch (irp_sl->isl_parameters.isl_ioctl.isl_iocode) {
+ case IOCTL_INTERNAL_USB_SUBMIT_URB:
+ IRP_NDIS_DEV(ip) = dev;
+
+ status = usbd_submit_urb(ip);
+ break;
+ default:
+ device_printf(dev, "ioctl 0x%x isn't supported\n",
+ irp_sl->isl_parameters.isl_ioctl.isl_iocode);
+ status = USBD_STATUS_NOT_SUPPORTED;
+ break;
+ }
+
+ if (status == USBD_STATUS_PENDING)
+ return (STATUS_PENDING);
+
+ ip->irp_iostat.isb_status = usbd_urb2nt(status);
+ if (status != USBD_STATUS_SUCCESS)
+ ip->irp_iostat.isb_info = 0;
+ return (ip->irp_iostat.isb_status);
+}
+
+static int32_t
+usbd_ioinvalid(device_object *dobj, irp *ip)
+{
+ device_t dev = dobj->do_devext;
+ struct io_stack_location *irp_sl;
+
+ irp_sl = IoGetCurrentIrpStackLocation(ip);
+ device_printf(dev, "invalid I/O dispatch %d:%d\n", irp_sl->isl_major,
+ irp_sl->isl_minor);
+
+ ip->irp_iostat.isb_status = STATUS_FAILURE;
+ ip->irp_iostat.isb_info = 0;
+
+ IoCompleteRequest(ip, IO_NO_INCREMENT);
+
+ return (STATUS_FAILURE);
+}
+
+static int32_t
+usbd_pnp(device_object *dobj, irp *ip)
+{
+ device_t dev = dobj->do_devext;
+ struct io_stack_location *irp_sl;
+
+ irp_sl = IoGetCurrentIrpStackLocation(ip);
+ device_printf(dev, "%s: unsupported I/O dispatch %d:%d\n",
+ __func__, irp_sl->isl_major, irp_sl->isl_minor);
+
+ ip->irp_iostat.isb_status = STATUS_FAILURE;
+ ip->irp_iostat.isb_info = 0;
+
+ IoCompleteRequest(ip, IO_NO_INCREMENT);
+
+ return (STATUS_FAILURE);
+}
+
+static int32_t
+usbd_power(device_object *dobj, irp *ip)
+{
+ device_t dev = dobj->do_devext;
+ struct io_stack_location *irp_sl;
+
+ irp_sl = IoGetCurrentIrpStackLocation(ip);
+ device_printf(dev, "%s: unsupported I/O dispatch %d:%d\n",
+ __func__, irp_sl->isl_major, irp_sl->isl_minor);
+
+ ip->irp_iostat.isb_status = STATUS_FAILURE;
+ ip->irp_iostat.isb_info = 0;
+
+ IoCompleteRequest(ip, IO_NO_INCREMENT);
+
+ return (STATUS_FAILURE);
+}
+
+/* Convert USBD_STATUS to NTSTATUS */
+static int32_t
+usbd_urb2nt(int32_t status)
+{
+
+ switch (status) {
+ case USBD_STATUS_SUCCESS:
+ return (STATUS_SUCCESS);
+ case USBD_STATUS_DEVICE_GONE:
+ return (STATUS_DEVICE_NOT_CONNECTED);
+ case USBD_STATUS_PENDING:
+ return (STATUS_PENDING);
+ case USBD_STATUS_NOT_SUPPORTED:
+ return (STATUS_NOT_IMPLEMENTED);
+ case USBD_STATUS_NO_MEMORY:
+ return (STATUS_NO_MEMORY);
+ case USBD_STATUS_REQUEST_FAILED:
+ return (STATUS_NOT_SUPPORTED);
+ case USBD_STATUS_CANCELED:
+ return (STATUS_CANCELLED);
+ default:
+ break;
+ }
+
+ return (STATUS_FAILURE);
+}
+
+/* Convert FreeBSD's usb_error_t to USBD_STATUS */
+static int32_t
+usbd_usb2urb(int status)
+{
+
+ switch (status) {
+ case USB_ERR_NORMAL_COMPLETION:
+ return (USBD_STATUS_SUCCESS);
+ case USB_ERR_PENDING_REQUESTS:
+ return (USBD_STATUS_PENDING);
+ case USB_ERR_TIMEOUT:
+ return (USBD_STATUS_TIMEOUT);
+ case USB_ERR_SHORT_XFER:
+ return (USBD_STATUS_ERROR_SHORT_TRANSFER);
+ case USB_ERR_IOERROR:
+ return (USBD_STATUS_XACT_ERROR);
+ case USB_ERR_NOMEM:
+ return (USBD_STATUS_NO_MEMORY);
+ case USB_ERR_INVAL:
+ return (USBD_STATUS_REQUEST_FAILED);
+ case USB_ERR_NOT_STARTED:
+ case USB_ERR_TOO_DEEP:
+ case USB_ERR_NO_POWER:
+ return (USBD_STATUS_DEVICE_GONE);
+ case USB_ERR_CANCELLED:
+ return (USBD_STATUS_CANCELED);
+ default:
+ break;
+ }
+
+ return (USBD_STATUS_NOT_SUPPORTED);
+}
+
+static union usbd_urb *
+usbd_geturb(irp *ip)
+{
+ struct io_stack_location *irp_sl;
+
+ irp_sl = IoGetCurrentIrpStackLocation(ip);
+
+ return (irp_sl->isl_parameters.isl_others.isl_arg1);
+}
+
+static int32_t
+usbd_submit_urb(irp *ip)
+{
+ device_t dev = IRP_NDIS_DEV(ip);
+ int32_t status;
+ union usbd_urb *urb;
+
+ urb = usbd_geturb(ip);
+ /*
+ * In a case of URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER,
+ * USBD_URB_STATUS(urb) would be set at callback functions like
+ * usbd_intr() or usbd_xfereof().
+ */
+ switch (urb->uu_hdr.uuh_func) {
+ case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
+ status = usbd_func_bulkintr(ip);
+ if (status != USBD_STATUS_SUCCESS &&
+ status != USBD_STATUS_PENDING)
+ USBD_URB_STATUS(urb) = status;
+ break;
+ case URB_FUNCTION_VENDOR_DEVICE:
+ case URB_FUNCTION_VENDOR_INTERFACE:
+ case URB_FUNCTION_VENDOR_ENDPOINT:
+ case URB_FUNCTION_VENDOR_OTHER:
+ case URB_FUNCTION_CLASS_DEVICE:
+ case URB_FUNCTION_CLASS_INTERFACE:
+ case URB_FUNCTION_CLASS_ENDPOINT:
+ case URB_FUNCTION_CLASS_OTHER:
+ status = usbd_func_vendorclass(ip);
+ USBD_URB_STATUS(urb) = status;
+ break;
+ case URB_FUNCTION_SELECT_CONFIGURATION:
+ status = usbd_func_selconf(ip);
+ USBD_URB_STATUS(urb) = status;
+ break;
+ case URB_FUNCTION_ABORT_PIPE:
+ status = usbd_func_abort_pipe(ip);
+ USBD_URB_STATUS(urb) = status;
+ break;
+ case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
+ status = usbd_func_getdesc(ip);
+ USBD_URB_STATUS(urb) = status;
+ break;
+ default:
+ device_printf(dev, "func 0x%x isn't supported\n",
+ urb->uu_hdr.uuh_func);
+ USBD_URB_STATUS(urb) = status = USBD_STATUS_NOT_SUPPORTED;
+ break;
+ }
+
+ return (status);
+}
+
+static int32_t
+usbd_func_getdesc(irp *ip)
+{
+#define NDISUSB_GETDESC_MAXRETRIES 3
+ device_t dev = IRP_NDIS_DEV(ip);
+ struct ndis_softc *sc = device_get_softc(dev);
+ struct usbd_urb_control_descriptor_request *ctldesc;
+ uint16_t actlen;
+ uint32_t len;
+ union usbd_urb *urb;
+ usb_config_descriptor_t *cdp;
+ usb_error_t status;
+
+ urb = usbd_geturb(ip);
+ ctldesc = &urb->uu_ctldesc;
+ if (ctldesc->ucd_desctype == UDESC_CONFIG) {
+ /*
+ * The NDIS driver is not allowed to change the
+ * config! There is only one choice!
+ */
+ cdp = usbd_get_config_descriptor(sc->ndisusb_dev);
+ if (cdp == NULL) {
+ status = USB_ERR_INVAL;
+ goto exit;
+ }
+ if (cdp->bDescriptorType != UDESC_CONFIG) {
+ device_printf(dev, "bad desc %d\n",
+ cdp->bDescriptorType);
+ status = USB_ERR_INVAL;
+ goto exit;
+ }
+ /* get minimum length */
+ len = MIN(UGETW(cdp->wTotalLength), ctldesc->ucd_trans_buflen);
+ /* copy out config descriptor */
+ memcpy(ctldesc->ucd_trans_buf, cdp, len);
+ /* set actual length */
+ actlen = len;
+ status = USB_ERR_NORMAL_COMPLETION;
+ } else {
+ NDISUSB_LOCK(sc);
+ status = usbd_req_get_desc(sc->ndisusb_dev, &sc->ndisusb_mtx,
+ &actlen, ctldesc->ucd_trans_buf, 2,
+ ctldesc->ucd_trans_buflen, ctldesc->ucd_langid,
+ ctldesc->ucd_desctype, ctldesc->ucd_idx,
+ NDISUSB_GETDESC_MAXRETRIES);
+ NDISUSB_UNLOCK(sc);
+ }
+exit:
+ if (status != USB_ERR_NORMAL_COMPLETION) {
+ ctldesc->ucd_trans_buflen = 0;
+ return usbd_usb2urb(status);
+ }
+
+ ctldesc->ucd_trans_buflen = actlen;
+ ip->irp_iostat.isb_info = actlen;
+
+ return (USBD_STATUS_SUCCESS);
+#undef NDISUSB_GETDESC_MAXRETRIES
+}
+
+static int32_t
+usbd_func_selconf(irp *ip)
+{
+ device_t dev = IRP_NDIS_DEV(ip);
+ int i, j;
+ struct ndis_softc *sc = device_get_softc(dev);
+ struct usb_device *udev = sc->ndisusb_dev;
+ struct usb_endpoint *ep = NULL;
+ struct usbd_interface_information *intf;
+ struct usbd_pipe_information *pipe;
+ struct usbd_urb_select_configuration *selconf;
+ union usbd_urb *urb;
+ usb_config_descriptor_t *conf;
+ usb_endpoint_descriptor_t *edesc;
+ usb_error_t ret;
+
+ urb = usbd_geturb(ip);
+
+ selconf = &urb->uu_selconf;
+ conf = selconf->usc_conf;
+ if (conf == NULL) {
+ device_printf(dev, "select configuration is NULL\n");
+ return usbd_usb2urb(USB_ERR_NORMAL_COMPLETION);
+ }
+
+ intf = &selconf->usc_intf;
+ for (i = 0; i < conf->bNumInterface && intf->uii_len > 0; i++) {
+ ret = usbd_set_alt_interface_index(udev,
+ intf->uii_intfnum, intf->uii_altset);
+ if (ret != USB_ERR_NORMAL_COMPLETION && ret != USB_ERR_IN_USE) {
+ device_printf(dev,
+ "setting alternate interface failed: %s\n",
+ usbd_errstr(ret));
+ return usbd_usb2urb(ret);
+ }
+
+ for (j = 0; (ep = usb_endpoint_foreach(udev, ep)); j++) {
+ if (j >= intf->uii_numeps) {
+ device_printf(dev,
+ "endpoint %d and above are ignored",
+ intf->uii_numeps);
+ break;
+ }
+ edesc = ep->edesc;
+ pipe = &intf->uii_pipes[j];
+ pipe->upi_handle = edesc;
+ pipe->upi_epaddr = edesc->bEndpointAddress;
+ pipe->upi_maxpktsize = UGETW(edesc->wMaxPacketSize);
+ pipe->upi_type = UE_GET_XFERTYPE(edesc->bmAttributes);
+
+ ret = usbd_setup_endpoint(ip, intf->uii_intfnum, edesc);
+ if (ret != USB_ERR_NORMAL_COMPLETION)
+ return usbd_usb2urb(ret);
+
+ if (pipe->upi_type != UE_INTERRUPT)
+ continue;
+
+ /* XXX we're following linux USB's interval policy. */
+ if (udev->speed == USB_SPEED_LOW)
+ pipe->upi_interval = edesc->bInterval + 5;
+ else if (udev->speed == USB_SPEED_FULL)
+ pipe->upi_interval = edesc->bInterval;
+ else {
+ int k0 = 0, k1 = 1;
+ do {
+ k1 = k1 * 2;
+ k0 = k0 + 1;
+ } while (k1 < edesc->bInterval);
+ pipe->upi_interval = k0;
+ }
+ }
+
+ intf = (struct usbd_interface_information *)(((char *)intf) +
+ intf->uii_len);
+ }
+
+ return (USBD_STATUS_SUCCESS);
+}
+
+static usb_error_t
+usbd_setup_endpoint_one(irp *ip, uint8_t ifidx, struct ndisusb_ep *ne,
+ struct usb_config *epconf)
+{
+ device_t dev = IRP_NDIS_DEV(ip);
+ struct ndis_softc *sc = device_get_softc(dev);
+ struct usb_xfer *xfer;
+ usb_error_t status;
+
+ InitializeListHead(&ne->ne_active);
+ InitializeListHead(&ne->ne_pending);
+ KeInitializeSpinLock(&ne->ne_lock);
+
+ status = usbd_transfer_setup(sc->ndisusb_dev, &ifidx, ne->ne_xfer,
+ epconf, 1, sc, &sc->ndisusb_mtx);
+ if (status != USB_ERR_NORMAL_COMPLETION) {
+ device_printf(dev, "couldn't setup xfer: %s\n",
+ usbd_errstr(status));
+ return (status);
+ }
+ xfer = ne->ne_xfer[0];
+ usbd_xfer_set_priv(xfer, ne);
+
+ return (status);
+}
+
+static usb_error_t
+usbd_setup_endpoint_default(irp *ip, uint8_t ifidx)
+{
+ device_t dev = IRP_NDIS_DEV(ip);
+ struct ndis_softc *sc = device_get_softc(dev);
+ usb_error_t status;
+
+ if (ifidx > 0)
+ device_printf(dev, "warning: ifidx > 0 isn't supported.\n");
+
+ status = usbd_setup_endpoint_one(ip, ifidx, &sc->ndisusb_dread_ep,
+ &usbd_default_epconfig[USBD_CTRL_READ_PIPE]);
+ if (status != USB_ERR_NORMAL_COMPLETION)
+ return (status);
+
+ status = usbd_setup_endpoint_one(ip, ifidx, &sc->ndisusb_dwrite_ep,
+ &usbd_default_epconfig[USBD_CTRL_WRITE_PIPE]);
+ return (status);
+}
+
+static usb_error_t
+usbd_setup_endpoint(irp *ip, uint8_t ifidx,
+ struct usb_endpoint_descriptor *ep)
+{
+ device_t dev = IRP_NDIS_DEV(ip);
+ struct ndis_softc *sc = device_get_softc(dev);
+ struct ndisusb_ep *ne;
+ struct usb_config cfg;
+ struct usb_xfer *xfer;
+ usb_error_t status;
+
+ /* check for non-supported transfer types */
+ if (UE_GET_XFERTYPE(ep->bmAttributes) == UE_CONTROL ||
+ UE_GET_XFERTYPE(ep->bmAttributes) == UE_ISOCHRONOUS) {
+ device_printf(dev, "%s: unsuppotted transfer types %#x\n",
+ __func__, UE_GET_XFERTYPE(ep->bmAttributes));
+ return (USB_ERR_INVAL);
+ }
+
+ ne = &sc->ndisusb_ep[NDISUSB_GET_ENDPT(ep->bEndpointAddress)];
+ InitializeListHead(&ne->ne_active);
+ InitializeListHead(&ne->ne_pending);
+ KeInitializeSpinLock(&ne->ne_lock);
+ ne->ne_dirin = UE_GET_DIR(ep->bEndpointAddress) >> 7;
+
+ memset(&cfg, 0, sizeof(struct usb_config));
+ cfg.type = UE_GET_XFERTYPE(ep->bmAttributes);
+ cfg.endpoint = UE_GET_ADDR(ep->bEndpointAddress);
+ cfg.direction = UE_GET_DIR(ep->bEndpointAddress);
+ cfg.callback = &usbd_non_isoc_callback;
+ cfg.bufsize = UGETW(ep->wMaxPacketSize);
+ cfg.flags.proxy_buffer = 1;
+ if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN)
+ cfg.flags.short_xfer_ok = 1;
+
+ status = usbd_transfer_setup(sc->ndisusb_dev, &ifidx, ne->ne_xfer,
+ &cfg, 1, sc, &sc->ndisusb_mtx);
+ if (status != USB_ERR_NORMAL_COMPLETION) {
+ device_printf(dev, "couldn't setup xfer: %s\n",
+ usbd_errstr(status));
+ return (status);
+ }
+ xfer = ne->ne_xfer[0];
+ usbd_xfer_set_priv(xfer, ne);
+ if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN)
+ usbd_xfer_set_timeout(xfer, NDISUSB_NO_TIMEOUT);
+ else {
+ if (UE_GET_XFERTYPE(ep->bmAttributes) == UE_BULK)
+ usbd_xfer_set_timeout(xfer, NDISUSB_TX_TIMEOUT);
+ else
+ usbd_xfer_set_timeout(xfer, NDISUSB_INTR_TIMEOUT);
+ }
+
+ return (status);
+}
+
+static int32_t
+usbd_func_abort_pipe(irp *ip)
+{
+ device_t dev = IRP_NDIS_DEV(ip);
+ struct ndis_softc *sc = device_get_softc(dev);
+ struct ndisusb_ep *ne;
+ union usbd_urb *urb;
+
+ urb = usbd_geturb(ip);
+ ne = usbd_get_ndisep(ip, urb->uu_pipe.upr_handle);
+ if (ne == NULL) {
+ device_printf(IRP_NDIS_DEV(ip), "get NULL endpoint info.\n");
+ return (USBD_STATUS_INVALID_PIPE_HANDLE);
+ }
+
+ NDISUSB_LOCK(sc);
+ usbd_transfer_stop(ne->ne_xfer[0]);
+ usbd_transfer_start(ne->ne_xfer[0]);
+ NDISUSB_UNLOCK(sc);
+
+ return (USBD_STATUS_SUCCESS);
+}
+
+static int32_t
+usbd_func_vendorclass(irp *ip)
+{
+ device_t dev = IRP_NDIS_DEV(ip);
+ int32_t error;
+ struct ndis_softc *sc = device_get_softc(dev);
+ struct ndisusb_ep *ne;
+ struct ndisusb_xfer *nx;
+ struct usbd_urb_vendor_or_class_request *vcreq;
+ union usbd_urb *urb;
+
+ if (!(sc->ndisusb_status & NDISUSB_STATUS_SETUP_EP)) {
+ /*
+ * XXX In some cases the interface number isn't 0. However
+ * some driver (eg. RTL8187L NDIS driver) calls this function
+ * before calling URB_FUNCTION_SELECT_CONFIGURATION.
+ */
+ error = usbd_setup_endpoint_default(ip, 0);
+ if (error != USB_ERR_NORMAL_COMPLETION)
+ return usbd_usb2urb(error);
+ sc->ndisusb_status |= NDISUSB_STATUS_SETUP_EP;
+ }
+
+ urb = usbd_geturb(ip);
+ vcreq = &urb->uu_vcreq;
+ ne = (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) ?
+ &sc->ndisusb_dread_ep : &sc->ndisusb_dwrite_ep;
+ IRP_NDISUSB_EP(ip) = ne;
+ ip->irp_cancelfunc = (cancel_func)usbd_irpcancel_wrap;
+
+ nx = malloc(sizeof(struct ndisusb_xfer), M_USBDEV, M_NOWAIT | M_ZERO);
+ if (nx == NULL) {
+ device_printf(IRP_NDIS_DEV(ip), "out of memory\n");
+ return (USBD_STATUS_NO_MEMORY);
+ }
+ nx->nx_ep = ne;
+ nx->nx_priv = ip;
+ KeAcquireSpinLockAtDpcLevel(&ne->ne_lock);
+ InsertTailList((&ne->ne_pending), (&nx->nx_next));
+ KeReleaseSpinLockFromDpcLevel(&ne->ne_lock);
+
+ /* we've done to setup xfer. Let's transfer it. */
+ ip->irp_iostat.isb_status = STATUS_PENDING;
+ ip->irp_iostat.isb_info = 0;
+ USBD_URB_STATUS(urb) = USBD_STATUS_PENDING;
+ IoMarkIrpPending(ip);
+
+ error = usbd_taskadd(ip, NDISUSB_TASK_VENDOR);
+ if (error != USBD_STATUS_SUCCESS)
+ return (error);
+
+ return (USBD_STATUS_PENDING);
+}
+
+static void
+usbd_irpcancel(device_object *dobj, irp *ip)
+{
+ device_t dev = IRP_NDIS_DEV(ip);
+ struct ndis_softc *sc = device_get_softc(dev);
+ struct ndisusb_ep *ne = IRP_NDISUSB_EP(ip);
+
+ if (ne == NULL) {
+ ip->irp_cancel = TRUE;
+ IoReleaseCancelSpinLock(ip->irp_cancelirql);
+ return;
+ }
+
+ /*
+ * Make sure that the current USB transfer proxy is
+ * cancelled and then restarted.
+ */
+ NDISUSB_LOCK(sc);
+ usbd_transfer_stop(ne->ne_xfer[0]);
+ usbd_transfer_start(ne->ne_xfer[0]);
+ NDISUSB_UNLOCK(sc);
+
+ ip->irp_cancel = TRUE;
+ IoReleaseCancelSpinLock(ip->irp_cancelirql);
+}
+
+static void
+usbd_xfer_complete(struct ndis_softc *sc, struct ndisusb_ep *ne,
+ struct ndisusb_xfer *nx, usb_error_t status)
+{
+ struct ndisusb_xferdone *nd;
+ uint8_t irql;
+
+ nd = malloc(sizeof(struct ndisusb_xferdone), M_USBDEV,
+ M_NOWAIT | M_ZERO);
+ if (nd == NULL) {
+ device_printf(sc->ndis_dev, "out of memory");
+ return;
+ }
+ nd->nd_xfer = nx;
+ nd->nd_status = status;
+
+ KeAcquireSpinLock(&sc->ndisusb_xferdonelock, &irql);
+ InsertTailList((&sc->ndisusb_xferdonelist), (&nd->nd_donelist));
+ KeReleaseSpinLock(&sc->ndisusb_xferdonelock, irql);
+
+ IoQueueWorkItem(sc->ndisusb_xferdoneitem,
+ (io_workitem_func)usbd_xfertask_wrap, WORKQUEUE_CRITICAL, sc);
+}
+
+static struct ndisusb_xfer *
+usbd_aq_getfirst(struct ndis_softc *sc, struct ndisusb_ep *ne)
+{
+ struct ndisusb_xfer *nx;
+
+ KeAcquireSpinLockAtDpcLevel(&ne->ne_lock);
+ if (IsListEmpty(&ne->ne_active)) {
+ device_printf(sc->ndis_dev,
+ "%s: the active queue can't be empty.\n", __func__);
+ KeReleaseSpinLockFromDpcLevel(&ne->ne_lock);
+ return (NULL);
+ }
+ nx = CONTAINING_RECORD(ne->ne_active.nle_flink, struct ndisusb_xfer,
+ nx_next);
+ RemoveEntryList(&nx->nx_next);
+ KeReleaseSpinLockFromDpcLevel(&ne->ne_lock);
+
+ return (nx);
+}
+
+static void
+usbd_non_isoc_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+ irp *ip;
+ struct ndis_softc *sc = usbd_xfer_softc(xfer);
+ struct ndisusb_ep *ne = usbd_xfer_get_priv(xfer);
+ struct ndisusb_xfer *nx;
+ struct usbd_urb_bulk_or_intr_transfer *ubi;
+ struct usb_page_cache *pc;
+ uint8_t irql;
+ uint32_t len;
+ union usbd_urb *urb;
+ usb_endpoint_descriptor_t *ep;
+ int actlen, sumlen;
+
+ usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
+ nx = usbd_aq_getfirst(sc, ne);
+ pc = usbd_xfer_get_frame(xfer, 0);
+ if (nx == NULL)
+ return;
+
+ /* copy in data with regard to the URB */
+ if (ne->ne_dirin != 0)
+ usbd_copy_out(pc, 0, nx->nx_urbbuf, actlen);
+ nx->nx_urbbuf += actlen;
+ nx->nx_urbactlen += actlen;
+ nx->nx_urblen -= actlen;
+
+ /* check for short transfer */
+ if (actlen < sumlen)
+ nx->nx_urblen = 0;
+ else {
+ /* check remainder */
+ if (nx->nx_urblen > 0) {
+ KeAcquireSpinLock(&ne->ne_lock, &irql);
+ InsertHeadList((&ne->ne_active), (&nx->nx_next));
+ KeReleaseSpinLock(&ne->ne_lock, irql);
+
+ ip = nx->nx_priv;
+ urb = usbd_geturb(ip);
+ ubi = &urb->uu_bulkintr;
+ ep = ubi->ubi_epdesc;
+ goto extra;
+ }
+ }
+ usbd_xfer_complete(sc, ne, nx,
+ ((actlen < sumlen) && (nx->nx_shortxfer == 0)) ?
+ USB_ERR_SHORT_XFER : USB_ERR_NORMAL_COMPLETION);
+
+ /* fall through */
+ case USB_ST_SETUP:
+next:
+ /* get next transfer */
+ KeAcquireSpinLock(&ne->ne_lock, &irql);
+ if (IsListEmpty(&ne->ne_pending)) {
+ KeReleaseSpinLock(&ne->ne_lock, irql);
+ return;
+ }
+ nx = CONTAINING_RECORD(ne->ne_pending.nle_flink,
+ struct ndisusb_xfer, nx_next);
+ RemoveEntryList(&nx->nx_next);
+ /* add a entry to the active queue's tail. */
+ InsertTailList((&ne->ne_active), (&nx->nx_next));
+ KeReleaseSpinLock(&ne->ne_lock, irql);
+
+ ip = nx->nx_priv;
+ urb = usbd_geturb(ip);
+ ubi = &urb->uu_bulkintr;
+ ep = ubi->ubi_epdesc;
+
+ nx->nx_urbbuf = ubi->ubi_trans_buf;
+ nx->nx_urbactlen = 0;
+ nx->nx_urblen = ubi->ubi_trans_buflen;
+ nx->nx_shortxfer = (ubi->ubi_trans_flags &
+ USBD_SHORT_TRANSFER_OK) ? 1 : 0;
+extra:
+ len = MIN(usbd_xfer_max_len(xfer), nx->nx_urblen);
+ pc = usbd_xfer_get_frame(xfer, 0);
+ if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_OUT)
+ usbd_copy_in(pc, 0, nx->nx_urbbuf, len);
+ usbd_xfer_set_frame_len(xfer, 0, len);
+ usbd_xfer_set_frames(xfer, 1);
+ usbd_transfer_submit(xfer);
+ break;
+ default:
+ nx = usbd_aq_getfirst(sc, ne);
+ if (nx == NULL)
+ return;
+ if (error != USB_ERR_CANCELLED) {
+ usbd_xfer_set_stall(xfer);
+ device_printf(sc->ndis_dev, "usb xfer warning (%s)\n",
+ usbd_errstr(error));
+ }
+ usbd_xfer_complete(sc, ne, nx, error);
+ if (error != USB_ERR_CANCELLED)
+ goto next;
+ break;
+ }
+}
+
+static void
+usbd_ctrl_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+ irp *ip;
+ struct ndis_softc *sc = usbd_xfer_softc(xfer);
+ struct ndisusb_ep *ne = usbd_xfer_get_priv(xfer);
+ struct ndisusb_xfer *nx;
+ uint8_t irql;
+ union usbd_urb *urb;
+ struct usbd_urb_vendor_or_class_request *vcreq;
+ struct usb_page_cache *pc;
+ uint8_t type = 0;
+ struct usb_device_request req;
+ int len;
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
+ nx = usbd_aq_getfirst(sc, ne);
+ if (nx == NULL)
+ return;
+
+ ip = nx->nx_priv;
+ urb = usbd_geturb(ip);
+ vcreq = &urb->uu_vcreq;
+
+ if (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) {
+ pc = usbd_xfer_get_frame(xfer, 1);
+ len = usbd_xfer_frame_len(xfer, 1);
+ usbd_copy_out(pc, 0, vcreq->uvc_trans_buf, len);
+ nx->nx_urbactlen += len;
+ }
+
+ usbd_xfer_complete(sc, ne, nx, USB_ERR_NORMAL_COMPLETION);
+ /* fall through */
+ case USB_ST_SETUP:
+next:
+ /* get next transfer */
+ KeAcquireSpinLock(&ne->ne_lock, &irql);
+ if (IsListEmpty(&ne->ne_pending)) {
+ KeReleaseSpinLock(&ne->ne_lock, irql);
+ return;
+ }
+ nx = CONTAINING_RECORD(ne->ne_pending.nle_flink,
+ struct ndisusb_xfer, nx_next);
+ RemoveEntryList(&nx->nx_next);
+ /* add a entry to the active queue's tail. */
+ InsertTailList((&ne->ne_active), (&nx->nx_next));
+ KeReleaseSpinLock(&ne->ne_lock, irql);
+
+ ip = nx->nx_priv;
+ urb = usbd_geturb(ip);
+ vcreq = &urb->uu_vcreq;
+
+ switch (urb->uu_hdr.uuh_func) {
+ case URB_FUNCTION_CLASS_DEVICE:
+ type = UT_CLASS | UT_DEVICE;
+ break;
+ case URB_FUNCTION_CLASS_INTERFACE:
+ type = UT_CLASS | UT_INTERFACE;
+ break;
+ case URB_FUNCTION_CLASS_OTHER:
+ type = UT_CLASS | UT_OTHER;
+ break;
+ case URB_FUNCTION_CLASS_ENDPOINT:
+ type = UT_CLASS | UT_ENDPOINT;
+ break;
+ case URB_FUNCTION_VENDOR_DEVICE:
+ type = UT_VENDOR | UT_DEVICE;
+ break;
+ case URB_FUNCTION_VENDOR_INTERFACE:
+ type = UT_VENDOR | UT_INTERFACE;
+ break;
+ case URB_FUNCTION_VENDOR_OTHER:
+ type = UT_VENDOR | UT_OTHER;
+ break;
+ case URB_FUNCTION_VENDOR_ENDPOINT:
+ type = UT_VENDOR | UT_ENDPOINT;
+ break;
+ default:
+ /* never reached. */
+ break;
+ }
+
+ type |= (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) ?
+ UT_READ : UT_WRITE;
+ type |= vcreq->uvc_reserved1;
+
+ req.bmRequestType = type;
+ req.bRequest = vcreq->uvc_req;
+ USETW(req.wIndex, vcreq->uvc_idx);
+ USETW(req.wValue, vcreq->uvc_value);
+ USETW(req.wLength, vcreq->uvc_trans_buflen);
+
+ nx->nx_urbbuf = vcreq->uvc_trans_buf;
+ nx->nx_urblen = vcreq->uvc_trans_buflen;
+ nx->nx_urbactlen = 0;
+
+ pc = usbd_xfer_get_frame(xfer, 0);
+ usbd_copy_in(pc, 0, &req, sizeof(req));
+ usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
+ usbd_xfer_set_frames(xfer, 1);
+ if (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) {
+ if (vcreq->uvc_trans_buflen >= USBD_CTRL_READ_BUFFER_SP)
+ device_printf(sc->ndis_dev,
+ "warning: not enough buffer space (%d).\n",
+ vcreq->uvc_trans_buflen);
+ usbd_xfer_set_frame_len(xfer, 1,
+ MIN(usbd_xfer_max_len(xfer),
+ vcreq->uvc_trans_buflen));
+ usbd_xfer_set_frames(xfer, 2);
+ } else {
+ if (nx->nx_urblen > USBD_CTRL_WRITE_BUFFER_SP)
+ device_printf(sc->ndis_dev,
+ "warning: not enough write buffer space"
+ " (%d).\n", nx->nx_urblen);
+ /*
+ * XXX with my local tests there was no cases to require
+ * a extra buffer until now but it'd need to update in
+ * the future if it needs to be.
+ */
+ if (nx->nx_urblen > 0) {
+ pc = usbd_xfer_get_frame(xfer, 1);
+ usbd_copy_in(pc, 0, nx->nx_urbbuf,
+ nx->nx_urblen);
+ usbd_xfer_set_frame_len(xfer, 1, nx->nx_urblen);
+ usbd_xfer_set_frames(xfer, 2);
+ }
+ }
+ usbd_transfer_submit(xfer);
+ break;
+ default:
+ nx = usbd_aq_getfirst(sc, ne);
+ if (nx == NULL)
+ return;
+ if (error != USB_ERR_CANCELLED) {
+ usbd_xfer_set_stall(xfer);
+ device_printf(sc->ndis_dev, "usb xfer warning (%s)\n",
+ usbd_errstr(error));
+ }
+ usbd_xfer_complete(sc, ne, nx, error);
+ if (error != USB_ERR_CANCELLED)
+ goto next;
+ break;
+ }
+}
+
+static struct ndisusb_ep *
+usbd_get_ndisep(irp *ip, usb_endpoint_descriptor_t *ep)
+{
+ device_t dev = IRP_NDIS_DEV(ip);
+ struct ndis_softc *sc = device_get_softc(dev);
+ struct ndisusb_ep *ne;
+
+ ne = &sc->ndisusb_ep[NDISUSB_GET_ENDPT(ep->bEndpointAddress)];
+
+ IRP_NDISUSB_EP(ip) = ne;
+ ip->irp_cancelfunc = (cancel_func)usbd_irpcancel_wrap;
+
+ return (ne);
+}
+
+static void
+usbd_xfertask(device_object *dobj, void *arg)
+{
+ int error;
+ irp *ip;
+ device_t dev;
+ list_entry *l;
+ struct ndis_softc *sc = arg;
+ struct ndisusb_xferdone *nd;
+ struct ndisusb_xfer *nq;
+ struct usbd_urb_bulk_or_intr_transfer *ubi;
+ struct usbd_urb_vendor_or_class_request *vcreq;
+ union usbd_urb *urb;
+ usb_error_t status;
+ void *priv;
+
+ dev = sc->ndis_dev;
+
+ if (IsListEmpty(&sc->ndisusb_xferdonelist))
+ return;
+
+ KeAcquireSpinLockAtDpcLevel(&sc->ndisusb_xferdonelock);
+ l = sc->ndisusb_xferdonelist.nle_flink;
+ while (l != &sc->ndisusb_xferdonelist) {
+ nd = CONTAINING_RECORD(l, struct ndisusb_xferdone, nd_donelist);
+ nq = nd->nd_xfer;
+ priv = nq->nx_priv;
+ status = nd->nd_status;
+ error = 0;
+ ip = priv;
+ urb = usbd_geturb(ip);
+
+ ip->irp_cancelfunc = NULL;
+ IRP_NDISUSB_EP(ip) = NULL;
+
+ switch (status) {
+ case USB_ERR_NORMAL_COMPLETION:
+ if (urb->uu_hdr.uuh_func ==
+ URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER) {
+ ubi = &urb->uu_bulkintr;
+ ubi->ubi_trans_buflen = nq->nx_urbactlen;
+ } else {
+ vcreq = &urb->uu_vcreq;
+ vcreq->uvc_trans_buflen = nq->nx_urbactlen;
+ }
+ ip->irp_iostat.isb_info = nq->nx_urbactlen;
+ ip->irp_iostat.isb_status = STATUS_SUCCESS;
+ USBD_URB_STATUS(urb) = USBD_STATUS_SUCCESS;
+ break;
+ case USB_ERR_CANCELLED:
+ ip->irp_iostat.isb_info = 0;
+ ip->irp_iostat.isb_status = STATUS_CANCELLED;
+ USBD_URB_STATUS(urb) = USBD_STATUS_CANCELED;
+ break;
+ default:
+ ip->irp_iostat.isb_info = 0;
+ USBD_URB_STATUS(urb) = usbd_usb2urb(status);
+ ip->irp_iostat.isb_status =
+ usbd_urb2nt(USBD_URB_STATUS(urb));
+ break;
+ }
+
+ l = l->nle_flink;
+ RemoveEntryList(&nd->nd_donelist);
+ free(nq, M_USBDEV);
+ free(nd, M_USBDEV);
+ if (error)
+ continue;
+ KeReleaseSpinLockFromDpcLevel(&sc->ndisusb_xferdonelock);
+ /* NB: call after cleaning */
+ IoCompleteRequest(ip, IO_NO_INCREMENT);
+ KeAcquireSpinLockAtDpcLevel(&sc->ndisusb_xferdonelock);
+ }
+ KeReleaseSpinLockFromDpcLevel(&sc->ndisusb_xferdonelock);
+}
+
+/*
+ * this function is for mainly deferring a task to the another thread because
+ * we don't want to be in the scope of HAL lock.
+ */
+static int32_t
+usbd_taskadd(irp *ip, unsigned type)
+{
+ device_t dev = IRP_NDIS_DEV(ip);
+ struct ndis_softc *sc = device_get_softc(dev);
+ struct ndisusb_task *nt;
+
+ nt = malloc(sizeof(struct ndisusb_task), M_USBDEV, M_NOWAIT | M_ZERO);
+ if (nt == NULL)
+ return (USBD_STATUS_NO_MEMORY);
+ nt->nt_type = type;
+ nt->nt_ctx = ip;
+
+ KeAcquireSpinLockAtDpcLevel(&sc->ndisusb_tasklock);
+ InsertTailList((&sc->ndisusb_tasklist), (&nt->nt_tasklist));
+ KeReleaseSpinLockFromDpcLevel(&sc->ndisusb_tasklock);
+
+ IoQueueWorkItem(sc->ndisusb_taskitem,
+ (io_workitem_func)usbd_task_wrap, WORKQUEUE_CRITICAL, sc);
+
+ return (USBD_STATUS_SUCCESS);
+}
+
+static void
+usbd_task(device_object *dobj, void *arg)
+{
+ irp *ip;
+ list_entry *l;
+ struct ndis_softc *sc = arg;
+ struct ndisusb_ep *ne;
+ struct ndisusb_task *nt;
+ union usbd_urb *urb;
+
+ if (IsListEmpty(&sc->ndisusb_tasklist))
+ return;
+
+ KeAcquireSpinLockAtDpcLevel(&sc->ndisusb_tasklock);
+ l = sc->ndisusb_tasklist.nle_flink;
+ while (l != &sc->ndisusb_tasklist) {
+ nt = CONTAINING_RECORD(l, struct ndisusb_task, nt_tasklist);
+
+ ip = nt->nt_ctx;
+ urb = usbd_geturb(ip);
+
+ KeReleaseSpinLockFromDpcLevel(&sc->ndisusb_tasklock);
+ NDISUSB_LOCK(sc);
+ switch (nt->nt_type) {
+ case NDISUSB_TASK_TSTART:
+ ne = usbd_get_ndisep(ip, urb->uu_bulkintr.ubi_epdesc);
+ if (ne == NULL)
+ goto exit;
+ usbd_transfer_start(ne->ne_xfer[0]);
+ break;
+ case NDISUSB_TASK_IRPCANCEL:
+ ne = usbd_get_ndisep(ip,
+ (nt->nt_type == NDISUSB_TASK_IRPCANCEL) ?
+ urb->uu_bulkintr.ubi_epdesc :
+ urb->uu_pipe.upr_handle);
+ if (ne == NULL)
+ goto exit;
+
+ usbd_transfer_stop(ne->ne_xfer[0]);
+ usbd_transfer_start(ne->ne_xfer[0]);
+ break;
+ case NDISUSB_TASK_VENDOR:
+ ne = (urb->uu_vcreq.uvc_trans_flags &
+ USBD_TRANSFER_DIRECTION_IN) ?
+ &sc->ndisusb_dread_ep : &sc->ndisusb_dwrite_ep;
+ usbd_transfer_start(ne->ne_xfer[0]);
+ break;
+ default:
+ break;
+ }
+exit:
+ NDISUSB_UNLOCK(sc);
+ KeAcquireSpinLockAtDpcLevel(&sc->ndisusb_tasklock);
+
+ l = l->nle_flink;
+ RemoveEntryList(&nt->nt_tasklist);
+ free(nt, M_USBDEV);
+ }
+ KeReleaseSpinLockFromDpcLevel(&sc->ndisusb_tasklock);
+}
+
+static int32_t
+usbd_func_bulkintr(irp *ip)
+{
+ int32_t error;
+ struct ndisusb_ep *ne;
+ struct ndisusb_xfer *nx;
+ struct usbd_urb_bulk_or_intr_transfer *ubi;
+ union usbd_urb *urb;
+ usb_endpoint_descriptor_t *ep;
+
+ urb = usbd_geturb(ip);
+ ubi = &urb->uu_bulkintr;
+ ep = ubi->ubi_epdesc;
+ if (ep == NULL)
+ return (USBD_STATUS_INVALID_PIPE_HANDLE);
+
+ ne = usbd_get_ndisep(ip, ep);
+ if (ne == NULL) {
+ device_printf(IRP_NDIS_DEV(ip), "get NULL endpoint info.\n");
+ return (USBD_STATUS_INVALID_PIPE_HANDLE);
+ }
+
+ nx = malloc(sizeof(struct ndisusb_xfer), M_USBDEV, M_NOWAIT | M_ZERO);
+ if (nx == NULL) {
+ device_printf(IRP_NDIS_DEV(ip), "out of memory\n");
+ return (USBD_STATUS_NO_MEMORY);
+ }
+ nx->nx_ep = ne;
+ nx->nx_priv = ip;
+ KeAcquireSpinLockAtDpcLevel(&ne->ne_lock);
+ InsertTailList((&ne->ne_pending), (&nx->nx_next));
+ KeReleaseSpinLockFromDpcLevel(&ne->ne_lock);
+
+ /* we've done to setup xfer. Let's transfer it. */
+ ip->irp_iostat.isb_status = STATUS_PENDING;
+ ip->irp_iostat.isb_info = 0;
+ USBD_URB_STATUS(urb) = USBD_STATUS_PENDING;
+ IoMarkIrpPending(ip);
+
+ error = usbd_taskadd(ip, NDISUSB_TASK_TSTART);
+ if (error != USBD_STATUS_SUCCESS)
+ return (error);
+
+ return (USBD_STATUS_PENDING);
+}
+
+static union usbd_urb *
+USBD_CreateConfigurationRequest(usb_config_descriptor_t *conf, uint16_t *len)
+{
+ struct usbd_interface_list_entry list[2];
+ union usbd_urb *urb;
+
+ bzero(list, sizeof(struct usbd_interface_list_entry) * 2);
+ list[0].uil_intfdesc = USBD_ParseConfigurationDescriptorEx(conf, conf,
+ -1, -1, -1, -1, -1);
+ urb = USBD_CreateConfigurationRequestEx(conf, list);
+ if (urb == NULL)
+ return (NULL);
+
+ *len = urb->uu_selconf.usc_hdr.uuh_len;
+ return (urb);
+}
+
+static union usbd_urb *
+USBD_CreateConfigurationRequestEx(usb_config_descriptor_t *conf,
+ struct usbd_interface_list_entry *list)
+{
+ int i, j, size;
+ struct usbd_interface_information *intf;
+ struct usbd_pipe_information *pipe;
+ struct usbd_urb_select_configuration *selconf;
+ usb_interface_descriptor_t *desc;
+
+ for (i = 0, size = 0; i < conf->bNumInterface; i++) {
+ j = list[i].uil_intfdesc->bNumEndpoints;
+ size = size + sizeof(struct usbd_interface_information) +
+ sizeof(struct usbd_pipe_information) * (j - 1);
+ }
+ size += sizeof(struct usbd_urb_select_configuration) -
+ sizeof(struct usbd_interface_information);
+
+ selconf = ExAllocatePoolWithTag(NonPagedPool, size, 0);
+ if (selconf == NULL)
+ return (NULL);
+ selconf->usc_hdr.uuh_func = URB_FUNCTION_SELECT_CONFIGURATION;
+ selconf->usc_hdr.uuh_len = size;
+ selconf->usc_handle = conf;
+ selconf->usc_conf = conf;
+
+ intf = &selconf->usc_intf;
+ for (i = 0; i < conf->bNumInterface; i++) {
+ if (list[i].uil_intfdesc == NULL)
+ break;
+
+ list[i].uil_intf = intf;
+ desc = list[i].uil_intfdesc;
+
+ intf->uii_len = sizeof(struct usbd_interface_information) +
+ (desc->bNumEndpoints - 1) *
+ sizeof(struct usbd_pipe_information);
+ intf->uii_intfnum = desc->bInterfaceNumber;
+ intf->uii_altset = desc->bAlternateSetting;
+ intf->uii_intfclass = desc->bInterfaceClass;
+ intf->uii_intfsubclass = desc->bInterfaceSubClass;
+ intf->uii_intfproto = desc->bInterfaceProtocol;
+ intf->uii_handle = desc;
+ intf->uii_numeps = desc->bNumEndpoints;
+
+ pipe = &intf->uii_pipes[0];
+ for (j = 0; j < intf->uii_numeps; j++)
+ pipe[j].upi_maxtxsize =
+ USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;
+
+ intf = (struct usbd_interface_information *)((char *)intf +
+ intf->uii_len);
+ }
+
+ return ((union usbd_urb *)selconf);
+}
+
+static void
+USBD_GetUSBDIVersion(usbd_version_info *ui)
+{
+
+ /* Pretend to be Windows XP. */
+
+ ui->uvi_usbdi_vers = USBDI_VERSION;
+ ui->uvi_supported_vers = USB_VER_2_0;
+}
+
+static usb_interface_descriptor_t *
+USBD_ParseConfigurationDescriptor(usb_config_descriptor_t *conf,
+ uint8_t intfnum, uint8_t altset)
+{
+
+ return USBD_ParseConfigurationDescriptorEx(conf, conf, intfnum, altset,
+ -1, -1, -1);
+}
+
+static usb_interface_descriptor_t *
+USBD_ParseConfigurationDescriptorEx(usb_config_descriptor_t *conf,
+ void *start, int32_t intfnum, int32_t altset, int32_t intfclass,
+ int32_t intfsubclass, int32_t intfproto)
+{
+ struct usb_descriptor *next = NULL;
+ usb_interface_descriptor_t *desc;
+
+ while ((next = usb_desc_foreach(conf, next)) != NULL) {
+ desc = (usb_interface_descriptor_t *)next;
+ if (desc->bDescriptorType != UDESC_INTERFACE)
+ continue;
+ if (!(intfnum == -1 || desc->bInterfaceNumber == intfnum))
+ continue;
+ if (!(altset == -1 || desc->bAlternateSetting == altset))
+ continue;
+ if (!(intfclass == -1 || desc->bInterfaceClass == intfclass))
+ continue;
+ if (!(intfsubclass == -1 ||
+ desc->bInterfaceSubClass == intfsubclass))
+ continue;
+ if (!(intfproto == -1 || desc->bInterfaceProtocol == intfproto))
+ continue;
+ return (desc);
+ }
+
+ return (NULL);
+}
+
+static void
+dummy(void)
+{
+ printf("USBD dummy called\n");
+}
+
+image_patch_table usbd_functbl[] = {
+ IMPORT_SFUNC(USBD_CreateConfigurationRequest, 2),
+ IMPORT_SFUNC(USBD_CreateConfigurationRequestEx, 2),
+ IMPORT_SFUNC_MAP(_USBD_CreateConfigurationRequestEx@8,
+ USBD_CreateConfigurationRequestEx, 2),
+ IMPORT_SFUNC(USBD_GetUSBDIVersion, 1),
+ IMPORT_SFUNC(USBD_ParseConfigurationDescriptor, 3),
+ IMPORT_SFUNC(USBD_ParseConfigurationDescriptorEx, 7),
+ IMPORT_SFUNC_MAP(_USBD_ParseConfigurationDescriptorEx@28,
+ USBD_ParseConfigurationDescriptorEx, 7),
+
+ /*
+ * This last entry is a catch-all for any function we haven't
+ * implemented yet. The PE import list patching routine will
+ * use it for any function that doesn't have an explicit match
+ * in this table.
+ */
+
+ { NULL, (FUNC)dummy, NULL, 0, WINDRV_WRAP_STDCALL },
+
+ /* End of list. */
+
+ { NULL, NULL, NULL }
+};
+
+MODULE_DEPEND(ndis, usb, 1, 1, 1);
diff --git a/sys/compat/ndis/usbd_var.h b/sys/compat/ndis/usbd_var.h
new file mode 100644
index 0000000..019bd32
--- /dev/null
+++ b/sys/compat/ndis/usbd_var.h
@@ -0,0 +1,222 @@
+/*-
+ * Copyright (c) 2003
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _USBD_VAR_H_
+#define _USBD_VAR_H_
+
+#define IOCTL_INTERNAL_USB_SUBMIT_URB 0x00220003
+
+#define URB_FUNCTION_SELECT_CONFIGURATION 0x0000
+#define URB_FUNCTION_ABORT_PIPE 0x0002
+#define URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER 0x0009
+#define URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE 0x000B
+#define URB_FUNCTION_VENDOR_DEVICE 0x0017
+#define URB_FUNCTION_VENDOR_INTERFACE 0x0018
+#define URB_FUNCTION_VENDOR_ENDPOINT 0x0019
+#define URB_FUNCTION_CLASS_DEVICE 0x001A
+#define URB_FUNCTION_CLASS_INTERFACE 0x001B
+#define URB_FUNCTION_CLASS_ENDPOINT 0x001C
+#define URB_FUNCTION_CLASS_OTHER 0x001F
+#define URB_FUNCTION_VENDOR_OTHER 0x0020
+
+#define USBD_STATUS_SUCCESS 0x00000000
+#define USBD_STATUS_CANCELED 0x00010000
+#define USBD_STATUS_PENDING 0x40000000
+#define USBD_STATUS_NO_MEMORY 0x80000100
+#define USBD_STATUS_REQUEST_FAILED 0x80000500
+#define USBD_STATUS_INVALID_PIPE_HANDLE 0x80000600
+#define USBD_STATUS_ERROR_SHORT_TRANSFER 0x80000900
+#define USBD_STATUS_CRC 0xC0000001
+#define USBD_STATUS_BTSTUFF 0xC0000002
+#define USBD_STATUS_DATA_TOGGLE_MISMATCH 0xC0000003
+#define USBD_STATUS_STALL_PID 0xC0000004
+#define USBD_STATUS_DEV_NOT_RESPONDING 0xC0000005
+#define USBD_STATUS_PID_CHECK_FAILURE 0xC0000006
+#define USBD_STATUS_UNEXPECTED_PID 0xC0000007
+#define USBD_STATUS_DATA_OVERRUN 0xC0000008
+#define USBD_STATUS_DATA_UNDERRUN 0xC0000009
+#define USBD_STATUS_RESERVED1 0xC000000A
+#define USBD_STATUS_RESERVED2 0xC000000B
+#define USBD_STATUS_BUFFER_OVERRUN 0xC000000C
+#define USBD_STATUS_BUFFER_UNDERRUN 0xC000000D
+#define USBD_STATUS_NOT_ACCESSED 0xC000000F
+#define USBD_STATUS_FIFO 0xC0000010
+#define USBD_STATUS_XACT_ERROR 0xC0000011
+#define USBD_STATUS_BABBLE_DETECTED 0xC0000012
+#define USBD_STATUS_DATA_BUFFER_ERROR 0xC0000013
+#define USBD_STATUS_NOT_SUPPORTED 0xC0000E00
+#define USBD_STATUS_TIMEOUT 0xC0006000
+#define USBD_STATUS_DEVICE_GONE 0xC0007000
+
+struct usbd_urb_header {
+ uint16_t uuh_len;
+ uint16_t uuh_func;
+ int32_t uuh_status;
+ void *uuh_handle;
+ uint32_t uuh_flags;
+};
+
+enum usbd_pipe_type {
+ UsbdPipeTypeControl = UE_CONTROL,
+ UsbdPipeTypeIsochronous = UE_ISOCHRONOUS,
+ UsbdPipeTypeBulk = UE_BULK,
+ UsbdPipeTypeInterrupt = UE_INTERRUPT
+};
+
+struct usbd_pipe_information {
+ uint16_t upi_maxpktsize;
+ uint8_t upi_epaddr;
+ uint8_t upi_interval;
+ enum usbd_pipe_type upi_type;
+ usb_endpoint_descriptor_t *upi_handle;
+ uint32_t upi_maxtxsize;
+#define USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE PAGE_SIZE
+ uint32_t upi_flags;
+};
+
+struct usbd_interface_information {
+ uint16_t uii_len;
+ uint8_t uii_intfnum;
+ uint8_t uii_altset;
+ uint8_t uii_intfclass;
+ uint8_t uii_intfsubclass;
+ uint8_t uii_intfproto;
+ uint8_t uii_reserved;
+ void *uii_handle;
+ uint32_t uii_numeps;
+ struct usbd_pipe_information uii_pipes[1];
+};
+
+struct usbd_urb_select_interface {
+ struct usbd_urb_header usi_hdr;
+ void *usi_handle;
+ struct usbd_interface_information uusi_intf;
+};
+
+struct usbd_urb_select_configuration {
+ struct usbd_urb_header usc_hdr;
+ usb_config_descriptor_t *usc_conf;
+ void *usc_handle;
+ struct usbd_interface_information usc_intf;
+};
+
+struct usbd_urb_pipe_request {
+ struct usbd_urb_header upr_hdr;
+ usb_endpoint_descriptor_t *upr_handle;
+};
+
+struct usbd_hcd_area {
+ void *reserved8[8];
+};
+
+struct usbd_urb_bulk_or_intr_transfer {
+ struct usbd_urb_header ubi_hdr;
+ usb_endpoint_descriptor_t *ubi_epdesc;
+ uint32_t ubi_trans_flags;
+#define USBD_SHORT_TRANSFER_OK 0x00000002
+ uint32_t ubi_trans_buflen;
+ void *ubi_trans_buf;
+ struct mdl *ubi_mdl;
+ union usbd_urb *ubi_urblink;
+ struct usbd_hcd_area ubi_hca;
+};
+
+struct usbd_urb_control_descriptor_request {
+ struct usbd_urb_header ucd_hdr;
+ void *ucd_reserved0;
+ uint32_t ucd_reserved1;
+ uint32_t ucd_trans_buflen;
+ void *ucd_trans_buf;
+ struct mdl *ucd_mdl;
+ union nt_urb *ucd_urblink;
+ struct usbd_hcd_area ucd_hca;
+ uint16_t ucd_reserved2;
+ uint8_t ucd_idx;
+ uint8_t ucd_desctype;
+ uint16_t ucd_langid;
+ uint16_t ucd_reserved3;
+};
+
+struct usbd_urb_vendor_or_class_request {
+ struct usbd_urb_header uvc_hdr;
+ void *uvc_reserved0;
+ uint32_t uvc_trans_flags;
+#define USBD_TRANSFER_DIRECTION_IN 1
+ uint32_t uvc_trans_buflen;
+ void *uvc_trans_buf;
+ struct mdl *uvc_mdl;
+ union nt_urb *uvc_urblink;
+ struct usbd_hcd_area uvc_hca;
+ uint8_t uvc_reserved1;
+ uint8_t uvc_req;
+ uint16_t uvc_value;
+ uint16_t uvc_idx;
+ uint16_t uvc_reserved2;
+};
+
+struct usbd_interface_list_entry {
+ usb_interface_descriptor_t *uil_intfdesc;
+ struct usbd_interface_information *uil_intf;
+};
+
+union usbd_urb {
+ struct usbd_urb_header uu_hdr;
+ struct usbd_urb_select_configuration uu_selconf;
+ struct usbd_urb_bulk_or_intr_transfer uu_bulkintr;
+ struct usbd_urb_control_descriptor_request uu_ctldesc;
+ struct usbd_urb_vendor_or_class_request uu_vcreq;
+ struct usbd_urb_pipe_request uu_pipe;
+};
+
+#define USBD_URB_STATUS(urb) ((urb)->uu_hdr.uuh_status)
+
+#define USBDI_VERSION 0x00000500
+#define USB_VER_1_1 0x00000110
+#define USB_VER_2_0 0x00000200
+
+struct usbd_version_info {
+ uint32_t uvi_usbdi_vers;
+ uint32_t uvi_supported_vers;
+};
+
+typedef struct usbd_version_info usbd_version_info;
+
+extern image_patch_table usbd_functbl[];
+
+__BEGIN_DECLS
+extern int usbd_libinit(void);
+extern int usbd_libfini(void);
+__END_DECLS
+
+#endif /* _USBD_VAR_H_ */
diff --git a/sys/compat/ndis/winx32_wrap.S b/sys/compat/ndis/winx32_wrap.S
new file mode 100644
index 0000000..c051504
--- /dev/null
+++ b/sys/compat/ndis/winx32_wrap.S
@@ -0,0 +1,385 @@
+/*-
+ * Copyright (c) 2005
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/* The 'ret' macro doesn't work in this file if GPROF is enabled. */
+#ifdef GPROF
+#undef GPROF
+#endif
+
+#include <machine/asmacros.h>
+
+/*
+ * This file contains assembly language wrappers for the different
+ * calling conventions supported by Windows on the i386 architecture.
+ * In FreeBSD, the whole OS typically use same C calling convention
+ * everywhere, namely _cdecl. Windows, on the other hand, uses several
+ * different C calling conventions depending on the circumstances:
+ *
+ * _stdcall: Used for most ordinary Windows APIs. With _stdcall,
+ * arguments are passed on the stack, and the callee unwinds the stack
+ * before returning control to the caller. Not suitable for variadic
+ * functions.
+ *
+ * _fastcall: Used for some APIs that may be invoked frequently and
+ * where speed is a critical factor (e.g. KeAcquireSpinLock() and
+ * KeReleaseSpinLock()) Similar to _stdcall, except the first 2 32-bit
+ * or smaller arguments are passed in the %ecx and %edx registers
+ * instead of on the stack. Not suitable for variadic functions.
+ *
+ * _cdecl: Used for standard C library routines and for variadic
+ * functions.
+ *
+ * _regparm(3): Used for certain assembly routines. All arguments
+ * passed in %eax, %ecx and %edx.
+ *
+ * Furthermore, there is an additional wrinkle that's not obvious
+ * with all code: Microsoft supports the use of exceptions in C
+ * (__try/__except) both in user _and_ kernel mode. Sadly, Windows
+ * structured exception handling uses machine-specific features
+ * that conflict rather badly with FreeBSD. (See utility routines
+ * at the end of this module for more details.)
+ *
+ * We want to support these calling conventions in as portable a manner
+ * as possible. The trick is doing it not only with different versions
+ * of GNU C, but with compilers other than GNU C (e.g. the Solaris
+ * SunOne C compiler). The only sure fire method is with assembly
+ * language trampoline code which both fixes up the argument passing,
+ * stack unwinding and exception/thread context all at once.
+ *
+ * You'll notice that we call the thunk/unthunk routines in the
+ * *_wrap() functions in an awkward way. Rather than branching
+ * directly to the address, we load the address into a register
+ * first as a literal value, then we branch to it. This is done
+ * to insure that the assembler doesn't translate the branch into
+ * a relative branch. We use the *_wrap() routines here as templates
+ * and create the actual trampolines at run time, at which point
+ * we only know the absolute addresses of the thunk and unthunk
+ * routines. So we need to make sure the templates have enough
+ * room in them for the full address.
+ *
+ * Also note that when we call the a thunk/unthunk routine after
+ * invoking a wrapped function, we have to make sure to preserve
+ * the value returned from that function. Most functions return
+ * a 32-bit value in %eax, however some routines return 64-bit
+ * values, which span both %eax and %edx. Consequently, we have
+ * to preserve both registers.
+ */
+
+/*
+ * Handle _stdcall going from Windows to UNIX.
+ * This is frustrating, because to do it right you have to
+ * know how many arguments the called function takes, and there's
+ * no way to figure this out on the fly: you just have to be told
+ * ahead of time. We assume there will be 16 arguments. I don't
+ * think there are any Windows APIs that require this many.
+ */
+
+ .globl x86_stdcall_wrap_call
+ .globl x86_stdcall_wrap_arg
+ .globl x86_stdcall_wrap_end
+
+ENTRY(x86_stdcall_wrap)
+ push %esi
+ push %edi
+ sub $64,%esp
+ mov %esp,%esi
+ add $64+8+4,%esi
+ mov %esp,%edi
+ mov $16,%ecx # handle up to 16 args
+ rep
+ movsl
+
+ movl $ctxsw_wtou, %eax
+ call *%eax # unthunk
+
+x86_stdcall_wrap_call:
+ movl $0,%eax
+ call *%eax # jump to routine
+ push %eax # preserve return val
+ push %edx
+
+ movl $ctxsw_utow, %eax
+ call *%eax # thunk
+
+ pop %edx
+ pop %eax # restore return val
+
+ add $64,%esp # clean the stack
+ pop %edi
+ pop %esi
+x86_stdcall_wrap_arg:
+ ret $0xFF
+x86_stdcall_wrap_end:
+
+
+/*
+ * Handle _stdcall going from UNIX to Windows. This routine
+ * expects to be passed the function to be called, number of
+ * args and the arguments for the Windows function on the stack.
+ */
+
+ENTRY(x86_stdcall_call)
+ push %esi # must preserve %esi
+ push %edi # and %edi
+
+ mov 16(%esp),%eax # get arg cnt
+ mov %eax,%ecx # save as copy count
+ mov %esp,%esi # Set source address register to point to
+ add $20,%esi # first agument to be forwarded.
+ shl $2,%eax # turn arg cnt into offset
+ sub %eax,%esp # shift stack to new location
+ mov %esp,%edi # store dest copy addr
+ rep # do the copy
+ movsl
+
+ call ctxsw_utow # thunk
+
+ call *12(%edi) # branch to stdcall routine
+ push %eax # preserve return val
+ push %edx
+
+ call ctxsw_wtou # unthunk
+
+ pop %edx
+ pop %eax # restore return val
+ mov %edi,%esp # restore stack
+ pop %edi # restore %edi
+ pop %esi # and %esi
+ ret
+
+/*
+ * Fastcall support. Similar to _stdcall, except the first
+ * two arguments are passed in %ecx and %edx. It happens we
+ * only support a small number of _fastcall APIs, none of them
+ * take more than three arguments. So to keep the code size
+ * and complexity down, we only handle 3 arguments here.
+ */
+
+/* Call _fastcall function going from Windows to UNIX. */
+
+ .globl x86_fastcall_wrap_call
+ .globl x86_fastcall_wrap_arg
+ .globl x86_fastcall_wrap_end
+
+ENTRY(x86_fastcall_wrap)
+ mov 4(%esp),%eax
+ push %eax
+ push %edx
+ push %ecx
+
+ movl $ctxsw_wtou, %eax
+ call *%eax # unthunk
+
+x86_fastcall_wrap_call:
+ mov $0,%eax
+ call *%eax # branch to fastcall routine
+ push %eax # preserve return val
+ push %edx
+
+ movl $ctxsw_utow, %eax
+ call *%eax # thunk
+
+ pop %edx
+ pop %eax # restore return val
+ add $12,%esp # clean the stack
+x86_fastcall_wrap_arg:
+ ret $0xFF
+x86_fastcall_wrap_end:
+
+/*
+ * Call _fastcall function going from UNIX to Windows.
+ * This routine isn't normally used since NDIS miniport drivers
+ * only have _stdcall entry points, but it's provided anyway
+ * to round out the API, and for testing purposes.
+ */
+
+ENTRY(x86_fastcall_call)
+ mov 4(%esp),%eax
+ push 16(%esp)
+
+ call ctxsw_utow # thunk
+
+ mov 12(%esp),%ecx
+ mov 16(%esp),%edx
+ call *8(%esp) # branch to fastcall routine
+ push %eax # preserve return val
+ push %edx
+
+ call ctxsw_wtou # unthunk
+
+ pop %edx
+ pop %eax # restore return val
+ add $4,%esp # clean the stack
+ ret
+
+/*
+ * Call regparm(3) function going from Windows to UNIX. Arguments
+ * are passed in %eax, %edx and %ecx. Note that while additional
+ * arguments are passed on the stack, we never bother when them,
+ * since the only regparm(3) routines we need to wrap never take
+ * more than 3 arguments.
+ */
+
+ .globl x86_regparm_wrap_call
+ .globl x86_regparm_wrap_end
+
+ENTRY(x86_regparm_wrap)
+ push %ecx
+ push %edx
+ push %eax
+
+ movl $ctxsw_wtou, %eax
+ call *%eax # unthunk
+
+x86_regparm_wrap_call:
+ movl $0,%eax
+ call *%eax # jump to routine
+ push %eax # preserve return val
+ push %edx # preserve return val
+
+ movl $ctxsw_utow, %eax
+ call *%eax # thunk
+
+ pop %edx # restore return val
+ pop %eax # restore return val
+ add $12,%esp # restore stack
+ ret
+x86_regparm_wrap_end:
+
+/*
+ * Call regparm(3) function going from UNIX to Windows.
+ * This routine isn't normally used since NDIS miniport drivers
+ * only have _stdcall entry points, but it's provided anyway
+ * to round out the API, and for testing purposes.
+ */
+
+ENTRY(x86_regparm_call)
+ call ctxsw_utow # thunk
+
+ mov 8(%esp),%eax
+ mov 12(%esp),%edx
+ mov 16(%esp),%ecx
+ call *4(%esp) # branch to fastcall routine
+ push %eax # preserve return val
+ push %edx # preserve return val
+
+ call ctxsw_wtou # unthunk
+
+ pop %edx # restore return val
+ pop %eax # restore return val
+ ret
+
+/*
+ * Ugly hack alert:
+ *
+ * On Win32/i386, using __try/__except results in code that tries to
+ * manipulate what's supposed to be the Windows Threada Environment
+ * Block (TEB), which one accesses via the %fs register. In particular,
+ * %fs:0 (the first DWORD in the TEB) points to the exception
+ * registration list. Unfortunately, FreeBSD uses %fs for the
+ * per-cpu data structure (pcpu), and we can't allow Windows code
+ * to muck with that. I don't even know what Solaris uses %fs for
+ * (or if it even uses it at all).
+ *
+ * Even worse, in 32-bit protected mode, %fs is a selector that
+ * refers to an entry in either the GDT or the LDT. Ideally, we would
+ * like to be able to temporarily point it at another descriptor
+ * while Windows code executes, but to do that we need a separate
+ * descriptor entry of our own to play with.
+ *
+ * Therefore, we go to some trouble to learn the existing layout of
+ * the GDT and update it to include an extra entry that we can use.
+ * We need the following utility routines to help us do that. On
+ * FreeBSD, index #7 in the GDT happens to be unused, so we turn
+ * this into our own data segment descriptor. It would be better
+ * if we could use a private LDT entry, but there's no easy way to
+ * do that in SMP mode because of the way FreeBSD handles user LDTs.
+ *
+ * Once we have a custom descriptor, we have to thunk/unthunk whenever
+ * we cross between FreeBSD code and Windows code. The thunking is
+ * based on the premise that when executing instructions in the
+ * Windows binary itself, we won't go to sleep. This is because in
+ * order to yield the CPU, the code has to call back out to a FreeBSD
+ * routine first, and when that happens we can unthunk in order to
+ * restore FreeBSD context. What we're desperately trying to avoid is
+ * being involuntarily pre-empted with the %fs register still pointing
+ * to our fake TIB: if FreeBSD code runs with %fs pointing at our
+ * Windows TIB instead of pcpu, we'll panic the kernel. Fortunately,
+ * the only way involuntary preemption can occur is if an interrupt
+ * fires, and the trap handler saves/restores %fs for us.
+ *
+ * The thunking routines themselves, ctxsw_utow() (Context SWitch UNIX
+ * to Windows) and ctxsw_wtou() (Context SWitch Windows to UNIX), are
+ * external to this module. This is done simply because it's easier
+ * to manipulate data structures in C rather than assembly.
+ */
+
+ENTRY(x86_getldt)
+ movl 4(%esp),%eax
+ sgdtl (%eax)
+ movl 8(%esp),%eax
+ sldt (%eax)
+ xor %eax,%eax
+ ret
+
+ENTRY(x86_setldt)
+ movl 4(%esp),%eax
+ lgdt (%eax)
+ jmp 1f
+ nop
+1:
+ movl 8(%esp),%eax
+ lldt %ax
+ xor %eax,%eax
+ ret
+
+ENTRY(x86_getfs)
+ mov %fs,%ax
+ ret
+
+ENTRY(x86_setfs)
+ mov 4(%esp),%fs
+ ret
+
+ENTRY(x86_gettid)
+ mov %fs:12,%eax
+ ret
+
+ENTRY(x86_critical_enter)
+ cli
+ ret
+
+ENTRY(x86_critical_exit)
+ sti
+ ret
diff --git a/sys/compat/ndis/winx64_wrap.S b/sys/compat/ndis/winx64_wrap.S
new file mode 100644
index 0000000..3e5d994
--- /dev/null
+++ b/sys/compat/ndis/winx64_wrap.S
@@ -0,0 +1,179 @@
+/*-
+ * Copyright (c) 2005
+ * Bill Paul <wpaul@windriver.com>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The x86_64 callback routines were written and graciously submitted
+ * by Ville-Pertti Keinonen <will@exomi.com>.
+ *
+ * $FreeBSD$
+ */
+
+#include <machine/asmacros.h>
+
+/*
+ * Wrapper for handling up to 16 arguments. We can't really
+ * know how many arguments the caller will pass us. I'm taking an
+ * educated guess that we'll never get over 16. Handling too
+ * few arguments is bad. Handling too many is inefficient, but
+ * not fatal. If someone can think of a way to handle an arbitrary
+ * number of arguments with more elegant code, freel free to let
+ * me know.
+ *
+ * Standard amd64 calling conventions specify the following registers
+ * to be used for passing the first 6 arguments:
+ *
+ * %rdi, %rsi, %rdx, %rcx, %r8, %r9
+ *
+ * Further arguments are passed on the stack (the 7th argument is
+ * located immediately after the return address).
+ *
+ * Windows x86_64 calling conventions only pass the first 4
+ * arguments in registers:
+ *
+ * %rcx, %rdx, %r8, %r9
+ *
+ * Even when arguments are passed in registers, the stack must have
+ * space reserved for those arguments. Thus the 5th argument (the
+ * first non-register argument) is placed 32 bytes after the return
+ * address. Additionally, %rdi and %rsi must be preserved. (These
+ * two registers are not scratch registers in the standard convention.)
+ *
+ * Note that in this template, we load a contrived 64 bit address into
+ * %r11 to represent our jump address. This is to guarantee that the
+ * assembler leaves enough room to patch in an absolute 64-bit address
+ * later. The idea behind this code is that we want to avoid having to
+ * manually create all the wrapper functions at compile time with
+ * a bunch of macros. This is doable, but a) messy and b) requires
+ * us to maintain two separate tables (one for the UNIX function
+ * pointers and another with the wrappers). This means I'd have to
+ * update two different tables each time I added a function.
+ *
+ * To avoid this, we create the wrappers at runtime instead. The
+ * image patch tables now contain two pointers: one two the normal
+ * routine, and a blank one for the wrapper. To construct a wrapper,
+ * we allocate some memory and copy the template function into it,
+ * then patch the function pointer for the routine we want to wrap
+ * into the newly created wrapper. The subr_pe module can then
+ * simply patch the wrapper routine into the jump table into the
+ * windows image. As a bonus, the wrapper pointer not only serves
+ * as the wrapper entry point address, it's also a data pointer
+ * that we can pass to free() later when we unload the module.
+ */
+
+ .globl x86_64_wrap_call
+ .globl x86_64_wrap_end
+
+ENTRY(x86_64_wrap)
+ push %rbp # insure that the stack
+ mov %rsp,%rbp # is 16-byte aligned
+ and $-16,%rsp #
+ subq $96,%rsp # allocate space on stack
+ mov %rsi,96-8(%rsp) # save %rsi
+ mov %rdi,96-16(%rsp)# save %rdi
+ mov %rcx,%r10 # temporarily save %rcx in scratch
+ lea 56+8(%rbp),%rsi # source == old stack top (stack+56)
+ mov %rsp,%rdi # destination == new stack top
+ mov $10,%rcx # count == 10 quadwords
+ rep
+ movsq # copy old stack contents to new location
+ mov %r10,%rdi # set up arg0 (%rcx -> %rdi)
+ mov %rdx,%rsi # set up arg1 (%rdx -> %rsi)
+ mov %r8,%rdx # set up arg2 (%r8 -> %rdx)
+ mov %r9,%rcx # set up arg3 (%r9 -> %rcx)
+ mov 40+8(%rbp),%r8 # set up arg4 (stack+40 -> %r8)
+ mov 48+8(%rbp),%r9 # set up arg5 (stack+48 -> %r9)
+ xor %rax,%rax # clear return value
+x86_64_wrap_call:
+ mov $0xFF00FF00FF00FF00,%r11
+ callq *%r11 # call routine
+ mov 96-16(%rsp),%rdi# restore %rdi
+ mov 96-8(%rsp),%rsi # restore %rsi
+ leave # delete space on stack
+ ret
+x86_64_wrap_end:
+
+/*
+ * Functions for invoking x86_64 callbacks. In each case, the first
+ * argument is a pointer to the function.
+ */
+
+ENTRY(x86_64_call1)
+ subq $40,%rsp
+ mov %rsi,%rcx
+ call *%rdi
+ addq $40,%rsp
+ ret
+
+ENTRY(x86_64_call2)
+ subq $40,%rsp
+ mov %rsi,%rcx
+ /* %rdx is already correct */
+ call *%rdi
+ addq $40,%rsp
+ ret
+
+ENTRY(x86_64_call3)
+ subq $40,%rsp
+ mov %rcx,%r8
+ mov %rsi,%rcx
+ call *%rdi
+ addq $40,%rsp
+ ret
+
+ENTRY(x86_64_call4)
+ subq $40,%rsp
+ mov %r8,%r9
+ mov %rcx,%r8
+ mov %rsi,%rcx
+ call *%rdi
+ addq $40,%rsp
+ ret
+
+ENTRY(x86_64_call5)
+ subq $48,%rsp
+ mov %r9,32(%rsp)
+ mov %r8,%r9
+ mov %rcx,%r8
+ mov %rsi,%rcx
+ call *%rdi
+ addq $48,%rsp
+ ret
+
+ENTRY(x86_64_call6)
+ subq $56,%rsp
+ mov 56+8(%rsp),%rax
+ mov %r9,32(%rsp)
+ mov %rax,40(%rsp)
+ mov %r8,%r9
+ mov %rcx,%r8
+ mov %rsi,%rcx
+ call *%rdi
+ addq $56,%rsp
+ ret
diff --git a/sys/compat/netbsd/dvcfg.h b/sys/compat/netbsd/dvcfg.h
new file mode 100644
index 0000000..817ab3d
--- /dev/null
+++ b/sys/compat/netbsd/dvcfg.h
@@ -0,0 +1,65 @@
+/* $FreeBSD$ */
+/* $NetBSD$ */
+/*-
+ * [NetBSD for NEC PC98 series]
+ * Copyright (c) 1996 NetBSD/pc98 porting staff.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1996 Naofumi HONDA. All rights reserved.
+ */
+
+#ifndef _COMPAT_NETBSD_DVCFG_H_
+#define _COMPAT_NETBSD_DVCFG_H_
+
+typedef void *dvcfg_hw_t;
+
+struct dvcfg_hwsel {
+ int cfg_max;
+
+ dvcfg_hw_t *cfg_sel;
+};
+
+#define DVCFG_MAJOR(dvcfg) (((u_int)(dvcfg)) >> 16)
+#define DVCFG_MINOR(dvcfg) (((u_int)(dvcfg)) & 0xffff)
+
+#define DVCFG_MKCFG(major, minor) ((((u_int)(major)) << 16) | ((minor) & 0xffff))
+
+#define DVCFG_HWSEL_SZ(array) (sizeof(array) / sizeof(dvcfg_hw_t))
+
+static __inline dvcfg_hw_t dvcfg_hw(struct dvcfg_hwsel *, u_int);
+
+static __inline dvcfg_hw_t
+dvcfg_hw(selp, num)
+ struct dvcfg_hwsel *selp;
+ u_int num;
+{
+
+ return ((num >= selp->cfg_max) ? 0 : selp->cfg_sel[num]);
+}
+
+#define DVCFG_HW(SELP, NUM) dvcfg_hw((SELP), (NUM))
+#endif /* _COMPAT_NETBSD_DVCFG_H_ */
diff --git a/sys/compat/svr4/Makefile b/sys/compat/svr4/Makefile
new file mode 100644
index 0000000..a90cd55
--- /dev/null
+++ b/sys/compat/svr4/Makefile
@@ -0,0 +1,17 @@
+# Makefile for syscall tables
+#
+# $FreeBSD$
+
+all:
+ @echo "make sysent only"
+
+sysent: svr4_sysent.c svr4_syscall.h svr4_proto.h
+
+svr4_syscallnames.c svr4_sysent.c svr4_syscall.h svr4_proto.h: \
+ ../../kern/makesyscalls.sh syscalls.master syscalls.conf
+ -mv -f svr4_syscallnames.c svr4_syscallnames.c.bak
+ -mv -f svr4_sysent.c svr4_sysent.c.bak
+ -mv -f svr4_syscall.h svr4_syscall.h.bak
+ -mv -f svr4_proto.h svr4_proto.h.bak
+ sh ../../kern/makesyscalls.sh syscalls.master syscalls.conf
+
diff --git a/sys/compat/svr4/imgact_svr4.c b/sys/compat/svr4/imgact_svr4.c
new file mode 100644
index 0000000..69e8890
--- /dev/null
+++ b/sys/compat/svr4/imgact_svr4.c
@@ -0,0 +1,238 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994-1996 Søren Schmidt
+ * All rights reserved.
+ *
+ * Based heavily on /sys/kern/imgact_aout.c which is:
+ * Copyright (c) 1993, David Greenman
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/exec.h>
+#include <sys/imgact.h>
+#include <sys/imgact_aout.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mman.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/racct.h>
+#include <sys/resourcevar.h>
+#include <sys/vnode.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_extern.h>
+
+#include <compat/svr4/svr4.h>
+
+static int exec_svr4_imgact(struct image_params *iparams);
+
+static int
+exec_svr4_imgact(imgp)
+ struct image_params *imgp;
+{
+ const struct exec *a_out = (const struct exec *) imgp->image_header;
+ struct vmspace *vmspace;
+ vm_offset_t vmaddr;
+ unsigned long virtual_offset, file_offset;
+ unsigned long bss_size;
+ ssize_t aresid;
+ int error;
+
+ if (((a_out->a_magic >> 16) & 0xff) != 0x64)
+ return -1;
+
+ /*
+ * Set file/virtual offset based on a.out variant.
+ */
+ switch ((int)(a_out->a_magic & 0xffff)) {
+ case 0413:
+ virtual_offset = 0;
+ file_offset = 1024;
+ break;
+ case 0314:
+ virtual_offset = 4096;
+ file_offset = 0;
+ break;
+ default:
+ return (-1);
+ }
+ bss_size = round_page(a_out->a_bss);
+#ifdef DEBUG
+ printf("imgact: text: %08lx, data: %08lx, bss: %08lx\n", (u_long)a_out->a_text, (u_long)a_out->a_data, bss_size);
+#endif
+
+ /*
+ * Check various fields in header for validity/bounds.
+ */
+ if (a_out->a_entry < virtual_offset ||
+ a_out->a_entry >= virtual_offset + a_out->a_text ||
+ a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK)
+ return (-1);
+
+ /* text + data can't exceed file size */
+ if (a_out->a_data + a_out->a_text > imgp->attr->va_size)
+ return (EFAULT);
+ /*
+ * text/data/bss must not exceed limits
+ */
+ PROC_LOCK(imgp->proc);
+ if (a_out->a_text > maxtsiz ||
+ a_out->a_data + bss_size > lim_cur(imgp->proc, RLIMIT_DATA) ||
+ racct_set(imgp->proc, RACCT_DATA, a_out->a_data + bss_size) != 0) {
+ PROC_UNLOCK(imgp->proc);
+ return (ENOMEM);
+ }
+ PROC_UNLOCK(imgp->proc);
+
+ VOP_UNLOCK(imgp->vp, 0);
+
+ /*
+ * Destroy old process VM and create a new one (with a new stack)
+ */
+ error = exec_new_vmspace(imgp, &svr4_sysvec);
+ if (error)
+ goto fail;
+ vmspace = imgp->proc->p_vmspace;
+
+ /*
+ * Check if file_offset page aligned,.
+ * Currently we cannot handle misalinged file offsets,
+ * and so we read in the entire image (what a waste).
+ */
+ if (file_offset & PAGE_MASK) {
+#ifdef DEBUG
+ printf("imgact: Non page aligned binary %lu\n", file_offset);
+#endif
+ /*
+ * Map text+data+bss read/write/execute
+ */
+ vmaddr = virtual_offset;
+ error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr,
+ a_out->a_text + a_out->a_data + bss_size, FALSE,
+ VM_PROT_ALL, VM_PROT_ALL, 0);
+ if (error)
+ goto fail;
+
+ error = vn_rdwr(UIO_READ, imgp->vp, (void *)vmaddr, file_offset,
+ a_out->a_text + a_out->a_data, UIO_USERSPACE, 0,
+ curthread->td_ucred, NOCRED, &aresid, curthread);
+ if (error != 0)
+ goto fail;
+ if (aresid != 0) {
+ error = ENOEXEC;
+ goto fail;
+ }
+
+ /*
+ * remove write enable on the 'text' part
+ */
+ error = vm_map_protect(&vmspace->vm_map,
+ vmaddr,
+ vmaddr + a_out->a_text,
+ VM_PROT_EXECUTE|VM_PROT_READ,
+ TRUE);
+ if (error)
+ goto fail;
+ }
+ else {
+#ifdef DEBUG
+ printf("imgact: Page aligned binary %lu\n", file_offset);
+#endif
+ /*
+ * Map text+data read/execute
+ */
+ vmaddr = virtual_offset;
+ error = vm_mmap(&vmspace->vm_map, &vmaddr,
+ a_out->a_text + a_out->a_data,
+ VM_PROT_READ | VM_PROT_EXECUTE,
+ VM_PROT_ALL,
+ MAP_PRIVATE | MAP_FIXED,
+ OBJT_VNODE, imgp->vp, file_offset);
+ if (error)
+ goto fail;
+
+#ifdef DEBUG
+ printf("imgact: startaddr=%08lx, length=%08lx\n", (u_long)vmaddr,
+ (u_long)a_out->a_text + a_out->a_data);
+#endif
+ /*
+ * allow read/write of data
+ */
+ error = vm_map_protect(&vmspace->vm_map,
+ vmaddr + a_out->a_text,
+ vmaddr + a_out->a_text + a_out->a_data,
+ VM_PROT_ALL,
+ FALSE);
+ if (error)
+ goto fail;
+
+ /*
+ * Allocate anon demand-zeroed area for uninitialized data
+ */
+ if (bss_size != 0) {
+ vmaddr = virtual_offset + a_out->a_text + a_out->a_data;
+ error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr,
+ bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0);
+ if (error)
+ goto fail;
+#ifdef DEBUG
+ printf("imgact: bssaddr=%08lx, length=%08lx\n",
+ (u_long)vmaddr, bss_size);
+#endif
+
+ }
+ }
+ /* Fill in process VM information */
+ vmspace->vm_tsize = round_page(a_out->a_text) >> PAGE_SHIFT;
+ vmspace->vm_dsize = round_page(a_out->a_data + bss_size) >> PAGE_SHIFT;
+ vmspace->vm_taddr = (caddr_t)virtual_offset;
+ vmspace->vm_daddr = (caddr_t)virtual_offset + a_out->a_text;
+
+ /* Fill in image_params */
+ imgp->interpreted = 0;
+ imgp->entry_addr = a_out->a_entry;
+
+ imgp->proc->p_sysent = &svr4_sysvec;
+fail:
+ vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
+ return (error);
+}
+
+/*
+ * Tell kern_execve.c about it, with a little help from the linker.
+ */
+struct execsw svr4_execsw = { exec_svr4_imgact, "svr4 ELF" };
+EXEC_SET(execsw_set, svr4_execsw);
+
diff --git a/sys/compat/svr4/svr4.h b/sys/compat/svr4/svr4.h
new file mode 100644
index 0000000..84ee720
--- /dev/null
+++ b/sys/compat/svr4/svr4.h
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "opt_svr4.h"
+
+#if !defined(_SVR4_H)
+#define _SVR4_H
+
+extern struct sysentvec svr4_sysvec;
+
+#define COMPAT_SVR4_SOLARIS2
+
+#endif
diff --git a/sys/compat/svr4/svr4_acl.h b/sys/compat/svr4/svr4_acl.h
new file mode 100644
index 0000000..ef2da1a
--- /dev/null
+++ b/sys/compat/svr4/svr4_acl.h
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1996 Christos Zoulas.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christos Zoulas.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SVR4_ACL_H_
+#define _SVR4_ACL_H_
+
+typedef struct svr4_aclent {
+ int a_type;
+ svr4_uid_t a_id;
+ svr4_o_mode_t a_perm;
+} svr4_aclent_t;
+
+#define SVR4_SYS_GETACL 1
+#define SVR4_SYS_SETACL 2
+#define SVR4_SYS_GETACLCNT 3
+
+#endif /* !_SVR4_ACL_H_ */
diff --git a/sys/compat/svr4/svr4_dirent.h b/sys/compat/svr4/svr4_dirent.h
new file mode 100644
index 0000000..9ce7bf8
--- /dev/null
+++ b/sys/compat/svr4/svr4_dirent.h
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_DIRENT_H_
+#define _SVR4_DIRENT_H_
+
+#define SVR4_MAXNAMLEN 512
+
+struct svr4_dirent {
+ svr4_ino_t d_ino;
+ svr4_off_t d_off;
+ u_short d_reclen;
+ char d_name[SVR4_MAXNAMLEN + 1];
+};
+
+struct svr4_dirent64 {
+ svr4_ino64_t d_ino;
+ svr4_off64_t d_off;
+ u_short d_reclen;
+ char d_name[SVR4_MAXNAMLEN + 1];
+};
+
+#define SVR4_NAMEOFF(dp) ((char *)&(dp)->d_name - (char *)dp)
+#define SVR4_RECLEN(de,namlen) ALIGN((SVR4_NAMEOFF(de) + (namlen) + 1))
+
+#endif /* !_SVR4_DIRENT_H_ */
diff --git a/sys/compat/svr4/svr4_errno.h b/sys/compat/svr4/svr4_errno.h
new file mode 100644
index 0000000..b5fa274
--- /dev/null
+++ b/sys/compat/svr4/svr4_errno.h
@@ -0,0 +1,172 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_ERRNO_H_
+#define _SVR4_ERRNO_H_
+
+#define SVR4_EPERM 1
+#define SVR4_ENOENT 2
+#define SVR4_ESRCH 3
+#define SVR4_EINTR 4
+#define SVR4_EIO 5
+#define SVR4_ENXIO 6
+#define SVR4_E2BIG 7
+#define SVR4_ENOEXEC 8
+#define SVR4_EBADF 9
+#define SVR4_ECHILD 10
+#define SVR4_EAGAIN 11
+#define SVR4_ENOMEM 12
+#define SVR4_EACCES 13
+#define SVR4_EFAULT 14
+#define SVR4_ENOTBLK 15
+#define SVR4_EBUSY 16
+#define SVR4_EEXIST 17
+#define SVR4_EXDEV 18
+#define SVR4_ENODEV 19
+#define SVR4_ENOTDIR 20
+#define SVR4_EISDIR 21
+#define SVR4_EINVAL 22
+#define SVR4_ENFILE 23
+#define SVR4_EMFILE 24
+#define SVR4_ENOTTY 25
+#define SVR4_ETXTBSY 26
+#define SVR4_EFBIG 27
+#define SVR4_ENOSPC 28
+#define SVR4_ESPIPE 29
+#define SVR4_EROFS 30
+#define SVR4_EMLINK 31
+#define SVR4_EPIPE 32
+#define SVR4_EDOM 33
+#define SVR4_ERANGE 34
+#define SVR4_ENOMSG 35
+#define SVR4_EIDRM 36
+#define SVR4_ECHRNG 37
+#define SVR4_EL2NSYNC 38
+#define SVR4_EL3HLT 39
+#define SVR4_EL3RST 40
+#define SVR4_ELNRNG 41
+#define SVR4_EUNATCH 42
+#define SVR4_ENOCSI 43
+#define SVR4_EL2HLT 44
+#define SVR4_EDEADLK 45
+#define SVR4_ENOLCK 46
+#define SVR4_EBADE 50
+#define SVR4_EBADR 51
+#define SVR4_EXFULL 52
+#define SVR4_ENOANO 53
+#define SVR4_EBADRQC 54
+#define SVR4_EBADSLT 55
+#define SVR4_EDEADLOCK 56
+#define SVR4_EBFONT 57
+#define SVR4_ENOSTR 60
+#define SVR4_ENODATA 61
+#define SVR4_ETIME 62
+#define SVR4_ENOSR 63
+#define SVR4_ENONET 64
+#define SVR4_ENOPKG 65
+#define SVR4_EREMOTE 66
+#define SVR4_ENOLINK 67
+#define SVR4_EADV 68
+#define SVR4_ESRMNT 69
+#define SVR4_ECOMM 70
+#define SVR4_EPROTO 71
+#define SVR4_EMULTIHOP 74
+#define SVR4_EBADMSG 77
+#define SVR4_ENAMETOOLONG 78
+#define SVR4_EOVERFLOW 79
+#define SVR4_ENOTUNIQ 80
+#define SVR4_EBADFD 81
+#define SVR4_EREMCHG 82
+#define SVR4_ELIBACC 83
+#define SVR4_ELIBBAD 84
+#define SVR4_ELIBSCN 85
+#define SVR4_ELIBMAX 86
+#define SVR4_ELIBEXEC 87
+#define SVR4_EILSEQ 88
+#define SVR4_ENOSYS 89
+#define SVR4_ELOOP 90
+#define SVR4_ERESTART 91
+#define SVR4_ESTRPIPE 92
+#define SVR4_ENOTEMPTY 93
+#define SVR4_EUSERS 94
+#define SVR4_ENOTSOCK 95
+#define SVR4_EDESTADDRREQ 96
+#define SVR4_EMSGSIZE 97
+#define SVR4_EPROTOTYPE 98
+#define SVR4_ENOPROTOOPT 99
+#define SVR4_EPROTONOSUPPORT 120
+#define SVR4_ESOCKTNOSUPPORT 121
+#define SVR4_EOPNOTSUPP 122
+#define SVR4_EPFNOSUPPORT 123
+#define SVR4_EAFNOSUPPORT 124
+#define SVR4_EADDRINUSE 125
+#define SVR4_EADDRNOTAVAIL 126
+#define SVR4_ENETDOWN 127
+#define SVR4_ENETUNREACH 128
+#define SVR4_ENETRESET 129
+#define SVR4_ECONNABORTED 130
+#define SVR4_ECONNRESET 131
+#define SVR4_ENOBUFS 132
+#define SVR4_EISCONN 133
+#define SVR4_ENOTCONN 134
+#define SVR4_EUCLEAN 135
+#define SVR4_ENOTNAM 137
+#define SVR4_ENAVAIL 138
+#define SVR4_EISNAM 139
+#define SVR4_EREMOTEIO 140
+#define SVR4_EINIT 141
+#define SVR4_EREMDEV 142
+#define SVR4_ESHUTDOWN 143
+#define SVR4_ETOOMANYREFS 144
+#define SVR4_ETIMEDOUT 145
+#define SVR4_ECONNREFUSED 146
+#define SVR4_EHOSTDOWN 147
+#define SVR4_EHOSTUNREACH 148
+#define SVR4_EWOULDBLOCK SVR4_EAGAIN
+#define SVR4_EALREADY 149
+#define SVR4_EINPROGRESS 150
+#define SVR4_ESTALE 151
+#define SVR4_EIORESID 500
+
+/*
+ * These ones are not translated...
+ */
+#define SVR4_EPROCLIM SVR4_ENOSYS
+#define SVR4_EDQUOT SVR4_ENOSYS
+#define SVR4_EBADRPC SVR4_ENOSYS
+#define SVR4_ERPCMISMATCH SVR4_ENOSYS
+#define SVR4_EPROGUNAVAIL SVR4_ENOSYS
+#define SVR4_EPROGMISMATCH SVR4_ENOSYS
+#define SVR4_EPROCUNAVAIL SVR4_ENOSYS
+#define SVR4_EFTYPE SVR4_ENOSYS
+#define SVR4_EAUTH SVR4_ENOSYS
+#define SVR4_ENEEDAUTH SVR4_ENOSYS
+
+#endif /* !_SVR4_ERRNO_H_ */
diff --git a/sys/compat/svr4/svr4_exec.h b/sys/compat/svr4/svr4_exec.h
new file mode 100644
index 0000000..adab956
--- /dev/null
+++ b/sys/compat/svr4/svr4_exec.h
@@ -0,0 +1,70 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_EXEC_H_
+#define _SVR4_EXEC_H_
+
+#ifdef SVR4_COMPAT_SOLARIS2
+# define SVR4_AUX_ARGSIZ (sizeof(AuxInfo) * 12 / sizeof(char *))
+#else
+# define SVR4_AUX_ARGSIZ (sizeof(AuxInfo) * 8 / sizeof(char *))
+#endif
+
+#if 0
+/* Don't think we need all this NetBSD stuff */
+/*
+ * The following is horrible; there must be a better way. I need to
+ * play with brk(2) a bit more.
+ */
+#ifdef __i386__
+/*
+ * I cannot load the interpreter after the data segment because brk(2)
+ * breaks. I have to load it somewhere before. Programs start at
+ * 0x08000000 so I load the interpreter far before.
+ */
+#define SVR4_INTERP_ADDR 0x01000000
+#endif
+
+#ifdef sparc
+/*
+ * Here programs load at 0x00010000, so I load the interpreter far after
+ * the end of the data segment.
+ */
+#define SVR4_INTERP_ADDR 0x10000000
+#endif
+
+#ifndef SVR4_INTERP_ADDR
+# define SVR4_INTERP_ADDR 0
+#endif
+#endif
+
+/*void svr4_setregs(struct thread *, struct exec_package *, u_long);*/
+
+#endif /* !_SVR4_EXEC_H_ */
diff --git a/sys/compat/svr4/svr4_fcntl.c b/sys/compat/svr4/svr4_fcntl.c
new file mode 100644
index 0000000..86fab78
--- /dev/null
+++ b/sys/compat/svr4/svr4_fcntl.c
@@ -0,0 +1,724 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994, 1997 Christos Zoulas.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christos Zoulas.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/capability.h>
+#include <sys/systm.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+/*#include <sys/ioctl.h>*/
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/mutex.h>
+#include <sys/namei.h>
+#include <sys/priv.h>
+#include <sys/proc.h>
+#include <sys/stat.h>
+#include <sys/syscallsubr.h>
+#include <sys/unistd.h>
+#include <sys/vnode.h>
+
+#include <sys/sysproto.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_proto.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_fcntl.h>
+
+#include <security/mac/mac_framework.h>
+
+static int svr4_to_bsd_flags(int);
+static u_long svr4_to_bsd_cmd(u_long);
+static int fd_revoke(struct thread *, int);
+static int fd_truncate(struct thread *, int, struct flock *);
+static int bsd_to_svr4_flags(int);
+static void bsd_to_svr4_flock(struct flock *, struct svr4_flock *);
+static void svr4_to_bsd_flock(struct svr4_flock *, struct flock *);
+static void bsd_to_svr4_flock64(struct flock *, struct svr4_flock64 *);
+static void svr4_to_bsd_flock64(struct svr4_flock64 *, struct flock *);
+
+static u_long
+svr4_to_bsd_cmd(cmd)
+ u_long cmd;
+{
+ switch (cmd) {
+ case SVR4_F_DUPFD:
+ return F_DUPFD;
+ case SVR4_F_DUP2FD:
+ return F_DUP2FD;
+ case SVR4_F_GETFD:
+ return F_GETFD;
+ case SVR4_F_SETFD:
+ return F_SETFD;
+ case SVR4_F_GETFL:
+ return F_GETFL;
+ case SVR4_F_SETFL:
+ return F_SETFL;
+ case SVR4_F_GETLK:
+ return F_GETLK;
+ case SVR4_F_SETLK:
+ return F_SETLK;
+ case SVR4_F_SETLKW:
+ return F_SETLKW;
+ default:
+ return -1;
+ }
+}
+
+static int
+svr4_to_bsd_flags(l)
+ int l;
+{
+ int r = 0;
+ r |= (l & SVR4_O_RDONLY) ? O_RDONLY : 0;
+ r |= (l & SVR4_O_WRONLY) ? O_WRONLY : 0;
+ r |= (l & SVR4_O_RDWR) ? O_RDWR : 0;
+ r |= (l & SVR4_O_NDELAY) ? O_NONBLOCK : 0;
+ r |= (l & SVR4_O_APPEND) ? O_APPEND : 0;
+ r |= (l & SVR4_O_SYNC) ? O_FSYNC : 0;
+ r |= (l & SVR4_O_NONBLOCK) ? O_NONBLOCK : 0;
+ r |= (l & SVR4_O_PRIV) ? O_EXLOCK : 0;
+ r |= (l & SVR4_O_CREAT) ? O_CREAT : 0;
+ r |= (l & SVR4_O_TRUNC) ? O_TRUNC : 0;
+ r |= (l & SVR4_O_EXCL) ? O_EXCL : 0;
+ r |= (l & SVR4_O_NOCTTY) ? O_NOCTTY : 0;
+ return r;
+}
+
+static int
+bsd_to_svr4_flags(l)
+ int l;
+{
+ int r = 0;
+ r |= (l & O_RDONLY) ? SVR4_O_RDONLY : 0;
+ r |= (l & O_WRONLY) ? SVR4_O_WRONLY : 0;
+ r |= (l & O_RDWR) ? SVR4_O_RDWR : 0;
+ r |= (l & O_NDELAY) ? SVR4_O_NONBLOCK : 0;
+ r |= (l & O_APPEND) ? SVR4_O_APPEND : 0;
+ r |= (l & O_FSYNC) ? SVR4_O_SYNC : 0;
+ r |= (l & O_NONBLOCK) ? SVR4_O_NONBLOCK : 0;
+ r |= (l & O_EXLOCK) ? SVR4_O_PRIV : 0;
+ r |= (l & O_CREAT) ? SVR4_O_CREAT : 0;
+ r |= (l & O_TRUNC) ? SVR4_O_TRUNC : 0;
+ r |= (l & O_EXCL) ? SVR4_O_EXCL : 0;
+ r |= (l & O_NOCTTY) ? SVR4_O_NOCTTY : 0;
+ return r;
+}
+
+
+static void
+bsd_to_svr4_flock(iflp, oflp)
+ struct flock *iflp;
+ struct svr4_flock *oflp;
+{
+ switch (iflp->l_type) {
+ case F_RDLCK:
+ oflp->l_type = SVR4_F_RDLCK;
+ break;
+ case F_WRLCK:
+ oflp->l_type = SVR4_F_WRLCK;
+ break;
+ case F_UNLCK:
+ oflp->l_type = SVR4_F_UNLCK;
+ break;
+ default:
+ oflp->l_type = -1;
+ break;
+ }
+
+ oflp->l_whence = (short) iflp->l_whence;
+ oflp->l_start = (svr4_off_t) iflp->l_start;
+ oflp->l_len = (svr4_off_t) iflp->l_len;
+ oflp->l_sysid = 0;
+ oflp->l_pid = (svr4_pid_t) iflp->l_pid;
+}
+
+
+static void
+svr4_to_bsd_flock(iflp, oflp)
+ struct svr4_flock *iflp;
+ struct flock *oflp;
+{
+ switch (iflp->l_type) {
+ case SVR4_F_RDLCK:
+ oflp->l_type = F_RDLCK;
+ break;
+ case SVR4_F_WRLCK:
+ oflp->l_type = F_WRLCK;
+ break;
+ case SVR4_F_UNLCK:
+ oflp->l_type = F_UNLCK;
+ break;
+ default:
+ oflp->l_type = -1;
+ break;
+ }
+
+ oflp->l_whence = iflp->l_whence;
+ oflp->l_start = (off_t) iflp->l_start;
+ oflp->l_len = (off_t) iflp->l_len;
+ oflp->l_pid = (pid_t) iflp->l_pid;
+ oflp->l_sysid = iflp->l_sysid;
+}
+
+static void
+bsd_to_svr4_flock64(iflp, oflp)
+ struct flock *iflp;
+ struct svr4_flock64 *oflp;
+{
+ switch (iflp->l_type) {
+ case F_RDLCK:
+ oflp->l_type = SVR4_F_RDLCK;
+ break;
+ case F_WRLCK:
+ oflp->l_type = SVR4_F_WRLCK;
+ break;
+ case F_UNLCK:
+ oflp->l_type = SVR4_F_UNLCK;
+ break;
+ default:
+ oflp->l_type = -1;
+ break;
+ }
+
+ oflp->l_whence = (short) iflp->l_whence;
+ oflp->l_start = (svr4_off64_t) iflp->l_start;
+ oflp->l_len = (svr4_off64_t) iflp->l_len;
+ oflp->l_sysid = iflp->l_sysid;
+ oflp->l_pid = (svr4_pid_t) iflp->l_pid;
+}
+
+
+static void
+svr4_to_bsd_flock64(iflp, oflp)
+ struct svr4_flock64 *iflp;
+ struct flock *oflp;
+{
+ switch (iflp->l_type) {
+ case SVR4_F_RDLCK:
+ oflp->l_type = F_RDLCK;
+ break;
+ case SVR4_F_WRLCK:
+ oflp->l_type = F_WRLCK;
+ break;
+ case SVR4_F_UNLCK:
+ oflp->l_type = F_UNLCK;
+ break;
+ default:
+ oflp->l_type = -1;
+ break;
+ }
+
+ oflp->l_whence = iflp->l_whence;
+ oflp->l_start = (off_t) iflp->l_start;
+ oflp->l_len = (off_t) iflp->l_len;
+ oflp->l_pid = (pid_t) iflp->l_pid;
+
+}
+
+
+static int
+fd_revoke(td, fd)
+ struct thread *td;
+ int fd;
+{
+ struct vnode *vp;
+ struct mount *mp;
+ struct vattr vattr;
+ int error, *retval;
+
+ retval = td->td_retval;
+ /*
+ * If we ever want to support Capsicum on SVR4 processes (unlikely)
+ * or FreeBSD grows a native frevoke() (more likely), we will need a
+ * CAP_FREVOKE here.
+ *
+ * In the meantime, use CAP_ALL: if a SVR4 process wants to
+ * do an frevoke(), it needs to do it on either a regular file
+ * descriptor or a fully-privileged capability (which is effectively
+ * the same as a non-capability-restricted file descriptor).
+ */
+ if ((error = fgetvp(td, fd, CAP_ALL, &vp)) != 0)
+ return (error);
+
+ if (vp->v_type != VCHR && vp->v_type != VBLK) {
+ error = EINVAL;
+ goto out;
+ }
+
+#ifdef MAC
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ error = mac_vnode_check_revoke(td->td_ucred, vp);
+ VOP_UNLOCK(vp, 0);
+ if (error)
+ goto out;
+#endif
+
+ if ((error = VOP_GETATTR(vp, &vattr, td->td_ucred)) != 0)
+ goto out;
+
+ if (td->td_ucred->cr_uid != vattr.va_uid &&
+ (error = priv_check(td, PRIV_VFS_ADMIN)) != 0)
+ goto out;
+
+ if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
+ goto out;
+ if (vcount(vp) > 1)
+ VOP_REVOKE(vp, REVOKEALL);
+ vn_finished_write(mp);
+out:
+ vrele(vp);
+ return error;
+}
+
+
+static int
+fd_truncate(td, fd, flp)
+ struct thread *td;
+ int fd;
+ struct flock *flp;
+{
+ off_t start, length;
+ struct file *fp;
+ struct vnode *vp;
+ struct vattr vattr;
+ int error, *retval;
+ struct ftruncate_args ft;
+
+ retval = td->td_retval;
+
+ /*
+ * We only support truncating the file.
+ */
+ if ((error = fget(td, fd, CAP_FTRUNCATE, &fp)) != 0)
+ return (error);
+
+ vp = fp->f_vnode;
+
+ if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
+ fdrop(fp, td);
+ return ESPIPE;
+ }
+
+ if ((error = VOP_GETATTR(vp, &vattr, td->td_ucred)) != 0) {
+ fdrop(fp, td);
+ return error;
+ }
+
+ length = vattr.va_size;
+
+ switch (flp->l_whence) {
+ case SEEK_CUR:
+ start = fp->f_offset + flp->l_start;
+ break;
+
+ case SEEK_END:
+ start = flp->l_start + length;
+ break;
+
+ case SEEK_SET:
+ start = flp->l_start;
+ break;
+
+ default:
+ fdrop(fp, td);
+ return EINVAL;
+ }
+
+ if (start + flp->l_len < length) {
+ /* We don't support free'ing in the middle of the file */
+ fdrop(fp, td);
+ return EINVAL;
+ }
+
+ ft.fd = fd;
+ ft.length = start;
+
+ error = sys_ftruncate(td, &ft);
+
+ fdrop(fp, td);
+ return (error);
+}
+
+int
+svr4_sys_open(td, uap)
+ struct thread *td;
+ struct svr4_sys_open_args *uap;
+{
+ struct proc *p = td->td_proc;
+ char *newpath;
+ int bsd_flags, error, retval;
+
+ CHECKALTEXIST(td, uap->path, &newpath);
+
+ bsd_flags = svr4_to_bsd_flags(uap->flags);
+ error = kern_open(td, newpath, UIO_SYSSPACE, bsd_flags, uap->mode);
+ free(newpath, M_TEMP);
+
+ if (error) {
+ /* uprintf("svr4_open(%s, 0x%0x, 0%o): %d\n", uap->path,
+ uap->flags, uap->mode, error);*/
+ return error;
+ }
+
+ retval = td->td_retval[0];
+
+ PROC_LOCK(p);
+ if (!(bsd_flags & O_NOCTTY) && SESS_LEADER(p) &&
+ !(p->p_flag & P_CONTROLT)) {
+#if defined(NOTYET)
+ struct file *fp;
+
+ error = fget(td, retval, CAP_IOCTL, &fp);
+ PROC_UNLOCK(p);
+ /*
+ * we may have lost a race the above open() and
+ * another thread issuing a close()
+ */
+ if (error)
+ return (EBADF); /* XXX: correct errno? */
+ /* ignore any error, just give it a try */
+ if (fp->f_type == DTYPE_VNODE)
+ fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td->td_ucred,
+ td);
+ fdrop(fp, td);
+ } else {
+ PROC_UNLOCK(p);
+ }
+#else
+ }
+ PROC_UNLOCK(p);
+#endif
+ return error;
+}
+
+int
+svr4_sys_open64(td, uap)
+ struct thread *td;
+ struct svr4_sys_open64_args *uap;
+{
+ return svr4_sys_open(td, (struct svr4_sys_open_args *)uap);
+}
+
+int
+svr4_sys_creat(td, uap)
+ struct thread *td;
+ struct svr4_sys_creat_args *uap;
+{
+ char *newpath;
+ int error;
+
+ CHECKALTEXIST(td, uap->path, &newpath);
+
+ error = kern_open(td, newpath, UIO_SYSSPACE, O_WRONLY | O_CREAT |
+ O_TRUNC, uap->mode);
+ free(newpath, M_TEMP);
+ return (error);
+}
+
+int
+svr4_sys_creat64(td, uap)
+ struct thread *td;
+ struct svr4_sys_creat64_args *uap;
+{
+ return svr4_sys_creat(td, (struct svr4_sys_creat_args *)uap);
+}
+
+int
+svr4_sys_llseek(td, uap)
+ struct thread *td;
+ struct svr4_sys_llseek_args *uap;
+{
+ struct lseek_args ap;
+
+ ap.fd = uap->fd;
+
+#if BYTE_ORDER == BIG_ENDIAN
+ ap.offset = (((u_int64_t) uap->offset1) << 32) |
+ uap->offset2;
+#else
+ ap.offset = (((u_int64_t) uap->offset2) << 32) |
+ uap->offset1;
+#endif
+ ap.whence = uap->whence;
+
+ return sys_lseek(td, &ap);
+}
+
+int
+svr4_sys_access(td, uap)
+ struct thread *td;
+ struct svr4_sys_access_args *uap;
+{
+ char *newpath;
+ int error;
+
+ CHECKALTEXIST(td, uap->path, &newpath);
+ error = kern_access(td, newpath, UIO_SYSSPACE, uap->amode);
+ free(newpath, M_TEMP);
+ return (error);
+}
+
+#if defined(NOTYET)
+int
+svr4_sys_pread(td, uap)
+ struct thread *td;
+ struct svr4_sys_pread_args *uap;
+{
+ struct pread_args pra;
+
+ /*
+ * Just translate the args structure and call the NetBSD
+ * pread(2) system call (offset type is 64-bit in NetBSD).
+ */
+ pra.fd = uap->fd;
+ pra.buf = uap->buf;
+ pra.nbyte = uap->nbyte;
+ pra.offset = uap->off;
+
+ return pread(td, &pra);
+}
+#endif
+
+#if defined(NOTYET)
+int
+svr4_sys_pread64(td, v, retval)
+ struct thread *td;
+ void *v;
+ register_t *retval;
+{
+
+ struct svr4_sys_pread64_args *uap = v;
+ struct sys_pread_args pra;
+
+ /*
+ * Just translate the args structure and call the NetBSD
+ * pread(2) system call (offset type is 64-bit in NetBSD).
+ */
+ pra.fd = uap->fd;
+ pra.buf = uap->buf;
+ pra.nbyte = uap->nbyte;
+ pra.offset = uap->off;
+
+ return (sys_pread(td, &pra, retval));
+}
+#endif /* NOTYET */
+
+#if defined(NOTYET)
+int
+svr4_sys_pwrite(td, uap)
+ struct thread *td;
+ struct svr4_sys_pwrite_args *uap;
+{
+ struct pwrite_args pwa;
+
+ /*
+ * Just translate the args structure and call the NetBSD
+ * pwrite(2) system call (offset type is 64-bit in NetBSD).
+ */
+ pwa.fd = uap->fd;
+ pwa.buf = uap->buf;
+ pwa.nbyte = uap->nbyte;
+ pwa.offset = uap->off;
+
+ return pwrite(td, &pwa);
+}
+#endif
+
+#if defined(NOTYET)
+int
+svr4_sys_pwrite64(td, v, retval)
+ struct thread *td;
+ void *v;
+ register_t *retval;
+{
+ struct svr4_sys_pwrite64_args *uap = v;
+ struct sys_pwrite_args pwa;
+
+ /*
+ * Just translate the args structure and call the NetBSD
+ * pwrite(2) system call (offset type is 64-bit in NetBSD).
+ */
+ pwa.fd = uap->fd;
+ pwa.buf = uap->buf;
+ pwa.nbyte = uap->nbyte;
+ pwa.offset = uap->off;
+
+ return (sys_pwrite(td, &pwa, retval));
+}
+#endif /* NOTYET */
+
+int
+svr4_sys_fcntl(td, uap)
+ struct thread *td;
+ struct svr4_sys_fcntl_args *uap;
+{
+ int cmd, error, *retval;
+
+ retval = td->td_retval;
+
+ cmd = svr4_to_bsd_cmd(uap->cmd);
+
+ switch (cmd) {
+ case F_DUPFD:
+ case F_DUP2FD:
+ case F_GETFD:
+ case F_SETFD:
+ return (kern_fcntl(td, uap->fd, cmd, (intptr_t)uap->arg));
+
+ case F_GETFL:
+ error = kern_fcntl(td, uap->fd, cmd, (intptr_t)uap->arg);
+ if (error)
+ return (error);
+ *retval = bsd_to_svr4_flags(*retval);
+ return (error);
+
+ case F_SETFL:
+ {
+ /*
+ * we must save the O_ASYNC flag, as that is
+ * handled by ioctl(_, I_SETSIG, _) emulation.
+ */
+ int flags;
+
+ DPRINTF(("Setting flags %p\n", uap->arg));
+
+ error = kern_fcntl(td, uap->fd, F_GETFL, 0);
+ if (error)
+ return (error);
+ flags = *retval;
+ flags &= O_ASYNC;
+ flags |= svr4_to_bsd_flags((u_long) uap->arg);
+ return (kern_fcntl(td, uap->fd, F_SETFL, flags));
+ }
+
+ case F_GETLK:
+ case F_SETLK:
+ case F_SETLKW:
+ {
+ struct svr4_flock ifl;
+ struct flock fl;
+
+ error = copyin(uap->arg, &ifl, sizeof (ifl));
+ if (error)
+ return (error);
+
+ svr4_to_bsd_flock(&ifl, &fl);
+
+ error = kern_fcntl(td, uap->fd, cmd, (intptr_t)&fl);
+ if (error || cmd != F_GETLK)
+ return (error);
+
+ bsd_to_svr4_flock(&fl, &ifl);
+
+ return (copyout(&ifl, uap->arg, sizeof (ifl)));
+ }
+ case -1:
+ switch (uap->cmd) {
+ case SVR4_F_FREESP:
+ {
+ struct svr4_flock ifl;
+ struct flock fl;
+
+ error = copyin(uap->arg, &ifl,
+ sizeof ifl);
+ if (error)
+ return error;
+ svr4_to_bsd_flock(&ifl, &fl);
+ return fd_truncate(td, uap->fd, &fl);
+ }
+
+ case SVR4_F_GETLK64:
+ case SVR4_F_SETLK64:
+ case SVR4_F_SETLKW64:
+ {
+ struct svr4_flock64 ifl;
+ struct flock fl;
+
+ switch (uap->cmd) {
+ case SVR4_F_GETLK64:
+ cmd = F_GETLK;
+ break;
+ case SVR4_F_SETLK64:
+ cmd = F_SETLK;
+ break;
+ case SVR4_F_SETLKW64:
+ cmd = F_SETLKW;
+ break;
+ }
+ error = copyin(uap->arg, &ifl,
+ sizeof (ifl));
+ if (error)
+ return (error);
+
+ svr4_to_bsd_flock64(&ifl, &fl);
+
+ error = kern_fcntl(td, uap->fd, cmd,
+ (intptr_t)&fl);
+ if (error || cmd != F_GETLK)
+ return (error);
+
+ bsd_to_svr4_flock64(&fl, &ifl);
+
+ return (copyout(&ifl, uap->arg,
+ sizeof (ifl)));
+ }
+
+ case SVR4_F_FREESP64:
+ {
+ struct svr4_flock64 ifl;
+ struct flock fl;
+
+ error = copyin(uap->arg, &ifl,
+ sizeof ifl);
+ if (error)
+ return error;
+ svr4_to_bsd_flock64(&ifl, &fl);
+ return fd_truncate(td, uap->fd, &fl);
+ }
+
+ case SVR4_F_REVOKE:
+ return fd_revoke(td, uap->fd);
+
+ default:
+ return ENOSYS;
+ }
+
+ default:
+ return ENOSYS;
+ }
+}
diff --git a/sys/compat/svr4/svr4_fcntl.h b/sys/compat/svr4/svr4_fcntl.h
new file mode 100644
index 0000000..1a354a7
--- /dev/null
+++ b/sys/compat/svr4/svr4_fcntl.h
@@ -0,0 +1,134 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_FCNTL_H_
+#define _SVR4_FCNTL_H_
+
+#include <compat/svr4/svr4_types.h>
+#include <sys/fcntl.h>
+
+#define SVR4_O_RDONLY 0x0000
+#define SVR4_O_WRONLY 0x0001
+#define SVR4_O_RDWR 0x0002
+#define SVR4_O_ACCMODE 0x0003
+#define SVR4_O_NDELAY 0x0004
+#define SVR4_O_APPEND 0x0008
+#define SVR4_O_SYNC 0x0010
+#define SVR4_O_NONBLOCK 0x0080
+#define SVR4_O_CREAT 0x0100
+#define SVR4_O_TRUNC 0x0200
+#define SVR4_O_EXCL 0x0400
+#define SVR4_O_NOCTTY 0x0800
+#define SVR4_O_PRIV 0x1000
+
+
+#define SVR4_FD_CLOEXEC 1
+
+#define SVR4_F_DUPFD 0
+#define SVR4_F_GETFD 1
+#define SVR4_F_SETFD 2
+#define SVR4_F_GETFL 3
+#define SVR4_F_SETFL 4
+#define SVR4_F_GETLK_SVR3 5
+#define SVR4_F_SETLK 6
+#define SVR4_F_SETLKW 7
+#define SVR4_F_CHKFL 8
+#define SVR4_F_DUP2FD 9
+#define SVR4_F_ALLOCSP 10
+#define SVR4_F_FREESP 11
+
+#define SVR4_F_ISSTREAM 13
+#define SVR4_F_GETLK 14
+#define SVR4_F_PRIV 15
+#define SVR4_F_NPRIV 16
+#define SVR4_F_QUOTACTL 17
+#define SVR4_F_BLOCKS 18
+#define SVR4_F_BLKSIZE 19
+#define SVR4_F_RSETLK 20
+#define SVR4_F_RGETLK 21
+#define SVR4_F_RSETLKW 22
+#define SVR4_F_GETOWN 23
+#define SVR4_F_SETOWN 24
+#define SVR4_F_REVOKE 25
+#define SVR4_F_HASREMOTELOCKS 26
+#define SVR4_F_FREESP64 27
+
+#define SVR4_F_GETLK64 33
+#define SVR4_F_SETLK64 34
+#define SVR4_F_SETLKW64 35
+
+#define SVR4_F_SHARE 40
+#define SVR4_F_UNSHARE 41
+
+#define SVR4_F_CHSIZE_XENIX 0x6000
+#define SVR4_F_RDCHK_XENIX 0x6001
+#define SVR4_F_LK_UNLCK_XENIX 0x6300
+#define SVR4_F_LK_LOCK_XENIX 0x7200
+#define SVR4_F_LK_NBLCK_XENIX 0x6200
+#define SVR4_F_LK_RLCK_XENIX 0x7100
+#define SVR4_F_LK_NBRLCK_XENIX 0x6100
+
+#define SVR4_LK_CMDTYPE(x) (((x) >> 12) & 0x7)
+#define SVR4_LK_LCKTYPE(x) (((x) >> 8) & 0x7)
+
+#define SVR4_F_RDLCK 1
+#define SVR4_F_WRLCK 2
+#define SVR4_F_UNLCK 3
+
+struct svr4_flock_svr3 {
+ short l_type;
+ short l_whence;
+ svr4_off_t l_start;
+ svr4_off_t l_len;
+ short l_sysid;
+ svr4_o_pid_t l_pid;
+};
+
+
+struct svr4_flock {
+ short l_type;
+ short l_whence;
+ svr4_off_t l_start;
+ svr4_off_t l_len;
+ long l_sysid;
+ svr4_pid_t l_pid;
+ long pad[4];
+};
+
+struct svr4_flock64 {
+ short l_type;
+ short l_whence;
+ svr4_off64_t l_start;
+ svr4_off64_t l_len;
+ long l_sysid;
+ svr4_pid_t l_pid;
+ long pad[4];
+};
+#endif /* !_SVR4_FCNTL_H_ */
diff --git a/sys/compat/svr4/svr4_filio.c b/sys/compat/svr4/svr4_filio.c
new file mode 100644
index 0000000..0fbba07
--- /dev/null
+++ b/sys/compat/svr4/svr4_filio.c
@@ -0,0 +1,251 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/capability.h>
+#include <sys/file.h>
+#include <sys/filio.h>
+#include <sys/lock.h>
+#include <sys/signal.h>
+#include <sys/filedesc.h>
+#include <sys/poll.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+
+#include <sys/sysproto.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_proto.h>
+#include <compat/svr4/svr4_ioctl.h>
+#include <compat/svr4/svr4_filio.h>
+
+/*#define GROTTY_READ_HACK*/
+
+int
+svr4_sys_poll(td, uap)
+ struct thread *td;
+ struct svr4_sys_poll_args *uap;
+{
+ int error;
+ struct poll_args pa;
+ struct pollfd *pfd;
+ int idx = 0, cerr;
+ u_long siz;
+
+ if (uap->nfds > maxfilesperproc && uap->nfds > FD_SETSIZE)
+ return (EINVAL);
+
+ pa.fds = uap->fds;
+ pa.nfds = uap->nfds;
+ pa.timeout = uap->timeout;
+
+ siz = uap->nfds * sizeof(struct pollfd);
+ pfd = (struct pollfd *)malloc(siz, M_TEMP, M_WAITOK);
+
+ error = sys_poll(td, (struct poll_args *)uap);
+
+ if ((cerr = copyin(uap->fds, pfd, siz)) != 0) {
+ error = cerr;
+ goto done;
+ }
+
+ for (idx = 0; idx < uap->nfds; idx++) {
+ /* POLLWRNORM already equals POLLOUT, so we don't worry about that */
+ if (pfd[idx].revents & (POLLOUT | POLLWRNORM | POLLWRBAND))
+ pfd[idx].revents |= (POLLOUT | POLLWRNORM | POLLWRBAND);
+ }
+ if ((cerr = copyout(pfd, uap->fds, siz)) != 0) {
+ error = cerr;
+ goto done; /* yeah, I know it's the next line, but this way I won't
+ forget to update it if I add more code */
+ }
+done:
+ free(pfd, M_TEMP);
+ return error;
+}
+
+#if defined(READ_TEST)
+int
+svr4_sys_read(td, uap)
+ struct thread *td;
+ struct svr4_sys_read_args *uap;
+{
+ struct read_args ra;
+ struct file *fp;
+ struct socket *so = NULL;
+ int so_state;
+ sigset_t sigmask;
+ int rv;
+
+ ra.fd = uap->fd;
+ ra.buf = uap->buf;
+ ra.nbyte = uap->nbyte;
+
+ if (fget(td, uap->fd, CAP_READ, &fp) != 0) {
+ DPRINTF(("Something fishy with the user-supplied file descriptor...\n"));
+ return EBADF;
+ }
+
+ if (fp->f_type == DTYPE_SOCKET) {
+ so = fp->f_data;
+ DPRINTF(("fd %d is a socket\n", uap->fd));
+ if (so->so_state & SS_ASYNC) {
+ DPRINTF(("fd %d is an ASYNC socket!\n", uap->fd));
+ }
+ DPRINTF(("Here are its flags: 0x%x\n", so->so_state));
+#if defined(GROTTY_READ_HACK)
+ so_state = so->so_state;
+ so->so_state &= ~SS_NBIO;
+#endif
+ }
+
+ rv = read(td, &ra);
+
+ DPRINTF(("svr4_read(%d, 0x%0x, %d) = %d\n",
+ uap->fd, uap->buf, uap->nbyte, rv));
+ if (rv == EAGAIN) {
+#ifdef DEBUG_SVR4
+ struct sigacts *ps;
+
+ PROC_LOCK(td->td_proc);
+ ps = td->td_proc->p_sigacts;
+ mtx_lock(&ps->ps_mtx);
+#endif
+ DPRINTF(("sigmask = 0x%x\n", td->td_sigmask));
+ DPRINTF(("sigignore = 0x%x\n", ps->ps_sigignore));
+ DPRINTF(("sigcaught = 0x%x\n", ps->ps_sigcatch));
+ DPRINTF(("siglist = 0x%x\n", td->td_siglist));
+#ifdef DEBUG_SVR4
+ mtx_unlock(&ps->ps_mtx);
+ PROC_UNLOCK(td->td_proc);
+#endif
+ }
+
+#if defined(GROTTY_READ_HACK)
+ if (so) { /* We've already checked to see if this is a socket */
+ so->so_state = so_state;
+ }
+#endif
+ fdrop(fp, td);
+
+ return(rv);
+}
+#endif /* READ_TEST */
+
+#if defined(BOGUS)
+int
+svr4_sys_write(td, uap)
+ struct thread *td;
+ struct svr4_sys_write_args *uap;
+{
+ struct write_args wa;
+ struct file *fp;
+ int rv;
+
+ wa.fd = uap->fd;
+ wa.buf = uap->buf;
+ wa.nbyte = uap->nbyte;
+
+ rv = write(td, &wa);
+
+ DPRINTF(("svr4_write(%d, 0x%0x, %d) = %d\n",
+ uap->fd, uap->buf, uap->nbyte, rv));
+
+ return(rv);
+}
+#endif /* BOGUS */
+
+int
+svr4_fil_ioctl(fp, td, retval, fd, cmd, data)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t data;
+{
+ struct filedesc *fdp = td->td_proc->p_fd;
+ struct filedescent *fde;
+ int error, num;
+
+ *retval = 0;
+
+ switch (cmd) {
+ case SVR4_FIOCLEX:
+ FILEDESC_XLOCK(fdp);
+ fde = &fdp->fd_ofiles[fd];
+ fde->fde_flags |= UF_EXCLOSE;
+ FILEDESC_XUNLOCK(fdp);
+ return 0;
+
+ case SVR4_FIONCLEX:
+ FILEDESC_XLOCK(fdp);
+ fde = &fdp->fd_ofiles[fd];
+ fde->fde_flags &= ~UF_EXCLOSE;
+ FILEDESC_XUNLOCK(fdp);
+ return 0;
+
+ case SVR4_FIOGETOWN:
+ case SVR4_FIOSETOWN:
+ case SVR4_FIOASYNC:
+ case SVR4_FIONBIO:
+ case SVR4_FIONREAD:
+ if ((error = copyin(data, &num, sizeof(num))) != 0)
+ return error;
+
+ switch (cmd) {
+ case SVR4_FIOGETOWN: cmd = FIOGETOWN; break;
+ case SVR4_FIOSETOWN: cmd = FIOSETOWN; break;
+ case SVR4_FIOASYNC: cmd = FIOASYNC; break;
+ case SVR4_FIONBIO: cmd = FIONBIO; break;
+ case SVR4_FIONREAD: cmd = FIONREAD; break;
+ }
+
+#ifdef SVR4_DEBUG
+ if (cmd == FIOASYNC) DPRINTF(("FIOASYNC\n"));
+#endif
+ error = fo_ioctl(fp, cmd, (caddr_t) &num, td->td_ucred, td);
+
+ if (error)
+ return error;
+
+ return copyout(&num, data, sizeof(num));
+
+ default:
+ DPRINTF(("Unknown svr4 filio %lx\n", cmd));
+ return 0; /* ENOSYS really */
+ }
+}
diff --git a/sys/compat/svr4/svr4_filio.h b/sys/compat/svr4/svr4_filio.h
new file mode 100644
index 0000000..baf81c7
--- /dev/null
+++ b/sys/compat/svr4/svr4_filio.h
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_FILIO_H_
+#define _SVR4_FILIO_H_
+
+#define SVR4_FIOC ('f' << 8)
+
+#define SVR4_FIOCLEX SVR4_IO('f', 1)
+#define SVR4_FIONCLEX SVR4_IO('f', 2)
+
+#define SVR4_FIOGETOWN SVR4_IOR('f', 123, int)
+#define SVR4_FIOSETOWN SVR4_IOW('f', 124, int)
+#define SVR4_FIOASYNC SVR4_IOW('f', 125, int)
+#define SVR4_FIONBIO SVR4_IOW('f', 126, int)
+#define SVR4_FIONREAD SVR4_IOR('f', 127, int)
+
+#endif /* !_SVR4_FILIO_H_ */
diff --git a/sys/compat/svr4/svr4_fuser.h b/sys/compat/svr4/svr4_fuser.h
new file mode 100644
index 0000000..df2db98
--- /dev/null
+++ b/sys/compat/svr4/svr4_fuser.h
@@ -0,0 +1,97 @@
+/*
+ * $FreeBSD$
+ * Derived from:
+ * $NetBSD: svr4_fuser.h,v 1.4 1998/09/04 19:54:38 christos Exp $ */
+
+/*-
+ * Original Copyright:
+ *
+ * Copyright (c) 1994 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Portions of this code have been derived from code contributed to the
+ * FreeBSD Project by Mark Newton.
+ *
+ * Copyright (c) 1999 Mark Newton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SVR4_FUSER_H_
+#define _SVR4_FUSER_H_
+
+#include <compat/svr4/svr4_types.h>
+
+struct svr4_f_user {
+ svr4_pid_t fu_pid;
+ int fu_flags;
+ uid_t fu_uid;
+};
+
+
+#define SVR4_F_FILE_ONLY 1
+#define SVR4_F_CONTAINED 2
+
+#define SVR4_F_CDIR 0x01
+#define SVR4_F_RDIR 0x02
+#define SVR4_F_TEXT 0x04
+#define SVR4_F_MAP 0x08
+#define SVR4_F_OPEN 0x10
+#define SVR4_F_TRACE 0x20
+#define SVR4_F_TTY 0x40
+
+#endif /* !_SVR4_FUSER_H_ */
diff --git a/sys/compat/svr4/svr4_hrt.h b/sys/compat/svr4/svr4_hrt.h
new file mode 100644
index 0000000..5a3bb67
--- /dev/null
+++ b/sys/compat/svr4/svr4_hrt.h
@@ -0,0 +1,87 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_HRT_H_
+#define _SVR4_HRT_H_
+
+#define SVR4_HRT_CNTL 0
+#define SVR4_HRT_CNTL_RES 0
+#define SVR4_HRT_CNTL_TOFD 1
+#define SVR4_HRT_CNTL_START 2
+#define SVR4_HRT_CNTL_GET 3
+
+#define SVR4_HRT_ALRM 1
+#define SVR4_HRT_ALRM_DO 4
+#define SVR4_HRT_ALRM_REP 5
+#define SVR4_HRT_ALRM_TOD 6
+#define SVR4_HRT_ALRM_FUTREP 7
+#define SVR4_HRT_ALRM_TODREP 8
+#define SVR4_HRT_ALRM_PEND 9
+
+#define SVR4_HRT_SLP 2
+#define SVR4_HRT_SLP_INT 10
+#define SVR4_HRT_SLP_TOD 11
+
+#define SVR4_HRT_BSD 12
+#define SVR4_HRT_BSD_PEND 13
+#define SVR4_HRT_BSD_REP1 14
+#define SVR4_HRT_BSD_REP2 15
+#define SVR4_HRT_BSD_CANCEL 16
+
+#define SVR4_HRT_CAN 3
+
+#define SVR4_HRT_SEC 1
+#define SVR4_HRT_MSEC 1000
+#define SVR4_HRT_USEC 1000000
+#define SVR4_HRT_NSEC 1000000000
+
+#define SVR4_HRT_TRUNC 0
+#define SVR4_HRT_RND 1
+
+typedef struct {
+ u_long i_word1;
+ u_long i_word2;
+ int i_clock;
+} svr4_hrt_interval_t;
+
+typedef struct {
+ u_long h_sec;
+ long h_rem;
+ u_long h_res;
+} svr4_hrt_time_t;
+
+#define SVR4_HRT_DONE 1
+#define SVR4_HRT_ERROR 2
+
+#define SVR4_HRT_CLK_STD 1
+#define SVR4_HRT_CLK_USERVIRT 2
+#define SVR4_HRT_CLK_PROCVIRT 4
+
+#endif /* !_SVR4_HRT_H_ */
diff --git a/sys/compat/svr4/svr4_ioctl.c b/sys/compat/svr4/svr4_ioctl.c
new file mode 100644
index 0000000..36b0580
--- /dev/null
+++ b/sys/compat/svr4/svr4_ioctl.c
@@ -0,0 +1,163 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/capability.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/fcntl.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/systm.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_proto.h>
+#include <compat/svr4/svr4_stropts.h>
+#include <compat/svr4/svr4_ioctl.h>
+#include <compat/svr4/svr4_termios.h>
+#include <compat/svr4/svr4_filio.h>
+#include <compat/svr4/svr4_sockio.h>
+
+#ifdef DEBUG_SVR4
+static void svr4_decode_cmd(u_long, char *, char *, int *, int *);
+/*
+ * Decode an ioctl command symbolically
+ */
+static void
+svr4_decode_cmd(cmd, dir, c, num, argsiz)
+ u_long cmd;
+ char *dir, *c;
+ int *num, *argsiz;
+{
+ if (cmd & SVR4_IOC_VOID)
+ *dir++ = 'V';
+ if (cmd & SVR4_IOC_IN)
+ *dir++ = 'R';
+ if (cmd & SVR4_IOC_OUT)
+ *dir++ = 'W';
+ *dir = '\0';
+ if (cmd & SVR4_IOC_INOUT)
+ *argsiz = (cmd >> 16) & 0xff;
+ else
+ *argsiz = -1;
+
+ *c = (cmd >> 8) & 0xff;
+ *num = cmd & 0xff;
+}
+#endif
+
+int
+svr4_sys_ioctl(td, uap)
+ struct thread *td;
+ struct svr4_sys_ioctl_args *uap;
+{
+ int *retval;
+ struct file *fp;
+ u_long cmd;
+ int (*fun)(struct file *, struct thread *, register_t *,
+ int, u_long, caddr_t);
+ int error;
+#ifdef DEBUG_SVR4
+ char dir[4];
+ char c;
+ int num;
+ int argsiz;
+
+ svr4_decode_cmd(uap->com, dir, &c, &num, &argsiz);
+
+ DPRINTF(("svr4_ioctl[%lx](%d, _IO%s(%c, %d, %d), %p);\n", uap->com, uap->fd,
+ dir, c, num, argsiz, uap->data));
+#endif
+ retval = td->td_retval;
+ cmd = uap->com;
+
+ if ((error = fget(td, uap->fd, CAP_IOCTL, &fp)) != 0)
+ return (error);
+
+ if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
+ fdrop(fp, td);
+ return EBADF;
+ }
+
+#if defined(DEBUG_SVR4)
+ if (fp->f_type == DTYPE_SOCKET) {
+ struct socket *so = fp->f_data;
+ DPRINTF(("<<< IN: so_state = 0x%x\n", so->so_state));
+ }
+#endif
+
+ switch (cmd & 0xff00) {
+ case SVR4_TIOC:
+ DPRINTF(("term\n"));
+ fun = svr4_term_ioctl;
+ break;
+
+ case SVR4_STR:
+ DPRINTF(("stream\n"));
+ fun = svr4_stream_ioctl;
+ break;
+
+ case SVR4_FIOC:
+ DPRINTF(("file\n"));
+ fun = svr4_fil_ioctl;
+ break;
+
+ case SVR4_SIOC:
+ DPRINTF(("socket\n"));
+ fun = svr4_sock_ioctl;
+ break;
+
+ case SVR4_XIOC:
+ /* We do not support those */
+ fdrop(fp, td);
+ return EINVAL;
+
+ default:
+ fdrop(fp, td);
+ DPRINTF(("Unimplemented ioctl %lx\n", cmd));
+ return 0; /* XXX: really ENOSYS */
+ }
+#if defined(DEBUG_SVR4)
+ if (fp->f_type == DTYPE_SOCKET) {
+ struct socket *so;
+
+ so = fp->f_data;
+ DPRINTF((">>> OUT: so_state = 0x%x\n", so->so_state));
+ }
+#endif
+ error = (*fun)(fp, td, retval, uap->fd, cmd, uap->data);
+ fdrop(fp, td);
+ return (error);
+}
diff --git a/sys/compat/svr4/svr4_ioctl.h b/sys/compat/svr4/svr4_ioctl.h
new file mode 100644
index 0000000..98b67a1
--- /dev/null
+++ b/sys/compat/svr4/svr4_ioctl.h
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_IOCTL_H_
+#define _SVR4_IOCTL_H_
+
+#define SVR4_IOC_VOID 0x20000000
+#define SVR4_IOC_OUT 0x40000000
+#define SVR4_IOC_IN 0x80000000
+#define SVR4_IOC_INOUT (SVR4_IOC_IN|SVR4_IOC_OUT)
+
+#define SVR4_IOC(inout,group,num,len) \
+ (inout | ((len & 0xff) << 16) | ((group) << 8) | (num))
+
+#define SVR4_XIOC ('X' << 8)
+
+#define SVR4_IO(g,n) SVR4_IOC(SVR4_IOC_VOID, (g), (n), 0)
+#define SVR4_IOR(g,n,t) SVR4_IOC(SVR4_IOC_OUT, (g), (n), sizeof(t))
+#define SVR4_IOW(g,n,t) SVR4_IOC(SVR4_IOC_IN, (g), (n), sizeof(t))
+#define SVR4_IOWR(g,n,t) SVR4_IOC(SVR4_IOC_INOUT,(g), (n), sizeof(t))
+
+int svr4_stream_ti_ioctl(struct file *, struct thread *, register_t *,
+ int, u_long, caddr_t);
+int svr4_stream_ioctl(struct file *, struct thread *, register_t *,
+ int, u_long, caddr_t);
+int svr4_term_ioctl(struct file *, struct thread *, register_t *,
+ int, u_long, caddr_t);
+int svr4_fil_ioctl (struct file *, struct thread *, register_t *,
+ int, u_long, caddr_t);
+int svr4_sock_ioctl (struct file *, struct thread *, register_t *,
+ int, u_long, caddr_t);
+
+#endif /* !_SVR4_IOCTL_H_ */
diff --git a/sys/compat/svr4/svr4_ipc.c b/sys/compat/svr4/svr4_ipc.c
new file mode 100644
index 0000000..f816cb0
--- /dev/null
+++ b/sys/compat/svr4/svr4_ipc.c
@@ -0,0 +1,707 @@
+/*-
+ * Copyright (c) 1995 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*-
+ * Portions of this code have been derived from software contributed
+ * to the FreeBSD Project by Mark Newton.
+ *
+ * Copyright (c) 1999 Mark Newton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * XXX- This code is presently a no-op on FreeBSD (and isn't compiled due
+ * to preprocessor conditionals). A nice project for a kernel hacking
+ * novice might be to MakeItGo, but I have more important fish to fry
+ * at present.
+ *
+ * Derived from: $NetBSD: svr4_ipc.c,v 1.7 1998/10/19 22:43:00 tron Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_sysvipc.h"
+
+#include <sys/param.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <sys/proc.h>
+#include <sys/sem.h>
+#include <sys/shm.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysproto.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_proto.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_ipc.h>
+
+#if defined(SYSVMSG) || defined(SYSVSHM) || defined(SYSVSEM)
+static void svr4_to_bsd_ipc_perm(const struct svr4_ipc_perm *,
+ struct ipc_perm *);
+static void bsd_to_svr4_ipc_perm(const struct ipc_perm *,
+ struct svr4_ipc_perm *);
+#endif
+
+#ifdef SYSVSEM
+static void bsd_to_svr4_semid_ds(const struct semid_ds *,
+ struct svr4_semid_ds *);
+static void svr4_to_bsd_semid_ds(const struct svr4_semid_ds *,
+ struct semid_ds *);
+static int svr4_semop(struct thread *, void *);
+static int svr4_semget(struct thread *, void *);
+static int svr4_semctl(struct thread *, void *);
+#endif
+
+#ifdef SYSVMSG
+static void bsd_to_svr4_msqid_ds(const struct msqid_ds *,
+ struct svr4_msqid_ds *);
+static void svr4_to_bsd_msqid_ds(const struct svr4_msqid_ds *,
+ struct msqid_ds *);
+static int svr4_msgsnd(struct thread *, void *);
+static int svr4_msgrcv(struct thread *, void *);
+static int svr4_msgget(struct thread *, void *);
+static int svr4_msgctl(struct thread *, void *);
+#endif
+
+#ifdef SYSVSHM
+static void bsd_to_svr4_shmid_ds(const struct shmid_ds *,
+ struct svr4_shmid_ds *);
+static void svr4_to_bsd_shmid_ds(const struct svr4_shmid_ds *,
+ struct shmid_ds *);
+static int svr4_shmat(struct thread *, void *);
+static int svr4_shmdt(struct thread *, void *);
+static int svr4_shmget(struct thread *, void *);
+static int svr4_shmctl(struct thread *, void *);
+#endif
+
+#if defined(SYSVMSG) || defined(SYSVSHM) || defined(SYSVSEM)
+
+static void
+svr4_to_bsd_ipc_perm(spp, bpp)
+ const struct svr4_ipc_perm *spp;
+ struct ipc_perm *bpp;
+{
+ bpp->key = spp->key;
+ bpp->uid = spp->uid;
+ bpp->gid = spp->gid;
+ bpp->cuid = spp->cuid;
+ bpp->cgid = spp->cgid;
+ bpp->mode = spp->mode;
+ bpp->seq = spp->seq;
+}
+
+static void
+bsd_to_svr4_ipc_perm(bpp, spp)
+ const struct ipc_perm *bpp;
+ struct svr4_ipc_perm *spp;
+{
+ spp->key = bpp->key;
+ spp->uid = bpp->uid;
+ spp->gid = bpp->gid;
+ spp->cuid = bpp->cuid;
+ spp->cgid = bpp->cgid;
+ spp->mode = bpp->mode;
+ spp->seq = bpp->seq;
+}
+#endif
+
+#ifdef SYSVSEM
+static void
+bsd_to_svr4_semid_ds(bds, sds)
+ const struct semid_ds *bds;
+ struct svr4_semid_ds *sds;
+{
+ bzero(sds, sizeof(*sds));
+ bsd_to_svr4_ipc_perm(&bds->sem_perm, &sds->sem_perm);
+ sds->sem_base = (struct svr4_sem *) bds->sem_base;
+ sds->sem_nsems = bds->sem_nsems;
+ sds->sem_otime = bds->sem_otime;
+ sds->sem_ctime = bds->sem_ctime;
+}
+
+static void
+svr4_to_bsd_semid_ds(sds, bds)
+ const struct svr4_semid_ds *sds;
+ struct semid_ds *bds;
+{
+ svr4_to_bsd_ipc_perm(&sds->sem_perm, &bds->sem_perm);
+ bds->sem_base = (struct sem *) bds->sem_base;
+ bds->sem_nsems = sds->sem_nsems;
+ bds->sem_otime = sds->sem_otime;
+ bds->sem_ctime = sds->sem_ctime;
+}
+
+struct svr4_sys_semctl_args {
+ int what;
+ int semid;
+ int semnum;
+ int cmd;
+ union semun arg;
+};
+
+static int
+svr4_semctl(td, v)
+ struct thread *td;
+ void *v;
+{
+ struct svr4_sys_semctl_args *uap = v;
+ struct svr4_semid_ds ss;
+ struct semid_ds bs;
+ union semun semun;
+ register_t rval;
+ int cmd, error;
+
+ switch (uap->cmd) {
+ case SVR4_SEM_GETZCNT:
+ cmd = GETZCNT;
+ break;
+
+ case SVR4_SEM_GETNCNT:
+ cmd = GETNCNT;
+ break;
+
+ case SVR4_SEM_GETPID:
+ cmd = GETPID;
+ break;
+
+ case SVR4_SEM_GETVAL:
+ cmd = GETVAL;
+ break;
+
+ case SVR4_SEM_SETVAL:
+ cmd = SETVAL;
+ break;
+
+ case SVR4_SEM_GETALL:
+ cmd = GETVAL;
+ break;
+
+ case SVR4_SEM_SETALL:
+ cmd = SETVAL;
+ break;
+
+ case SVR4_IPC_STAT:
+ cmd = IPC_STAT;
+ semun.buf = &bs;
+ error = kern_semctl(td, uap->semid, uap->semnum, cmd, &semun,
+ &rval);
+ if (error)
+ return (error);
+ bsd_to_svr4_semid_ds(&bs, &ss);
+ error = copyout(&ss, uap->arg.buf, sizeof(ss));
+ if (error == 0)
+ td->td_retval[0] = rval;
+ return (error);
+
+ case SVR4_IPC_SET:
+ cmd = IPC_SET;
+ error = copyin(uap->arg.buf, (caddr_t) &ss, sizeof ss);
+ if (error)
+ return (error);
+ svr4_to_bsd_semid_ds(&ss, &bs);
+ semun.buf = &bs;
+ return (kern_semctl(td, uap->semid, uap->semnum, cmd, &semun,
+ td->td_retval));
+
+ case SVR4_IPC_RMID:
+ cmd = IPC_RMID;
+ break;
+
+ default:
+ return EINVAL;
+ }
+
+ return (kern_semctl(td, uap->semid, uap->semnum, cmd, &uap->arg,
+ td->td_retval));
+}
+
+struct svr4_sys_semget_args {
+ int what;
+ svr4_key_t key;
+ int nsems;
+ int semflg;
+};
+
+static int
+svr4_semget(td, v)
+ struct thread *td;
+ void *v;
+{
+ struct svr4_sys_semget_args *uap = v;
+ struct semget_args ap;
+
+ ap.key = uap->key;
+ ap.nsems = uap->nsems;
+ ap.semflg = uap->semflg;
+
+ return sys_semget(td, &ap);
+}
+
+struct svr4_sys_semop_args {
+ int what;
+ int semid;
+ struct svr4_sembuf * sops;
+ u_int nsops;
+};
+
+static int
+svr4_semop(td, v)
+ struct thread *td;
+ void *v;
+{
+ struct svr4_sys_semop_args *uap = v;
+ struct semop_args ap;
+
+ ap.semid = uap->semid;
+ /* These are the same */
+ ap.sops = (struct sembuf *) uap->sops;
+ ap.nsops = uap->nsops;
+
+ return sys_semop(td, &ap);
+}
+
+int
+svr4_sys_semsys(td, uap)
+ struct thread *td;
+ struct svr4_sys_semsys_args *uap;
+{
+
+ DPRINTF(("svr4_semsys(%d)\n", uap->what));
+
+ switch (uap->what) {
+ case SVR4_semctl:
+ return svr4_semctl(td, uap);
+ case SVR4_semget:
+ return svr4_semget(td, uap);
+ case SVR4_semop:
+ return svr4_semop(td, uap);
+ default:
+ return EINVAL;
+ }
+}
+
+MODULE_DEPEND(svr4elf, sysvsem, 1, 1, 1);
+#endif
+
+#ifdef SYSVMSG
+static void
+bsd_to_svr4_msqid_ds(bds, sds)
+ const struct msqid_ds *bds;
+ struct svr4_msqid_ds *sds;
+{
+ bzero(sds, sizeof(*sds));
+ bsd_to_svr4_ipc_perm(&bds->msg_perm, &sds->msg_perm);
+ sds->msg_first = (struct svr4_msg *) bds->msg_first;
+ sds->msg_last = (struct svr4_msg *) bds->msg_last;
+ sds->msg_cbytes = bds->msg_cbytes;
+ sds->msg_qnum = bds->msg_qnum;
+ sds->msg_qbytes = bds->msg_qbytes;
+ sds->msg_lspid = bds->msg_lspid;
+ sds->msg_lrpid = bds->msg_lrpid;
+ sds->msg_stime = bds->msg_stime;
+ sds->msg_rtime = bds->msg_rtime;
+ sds->msg_ctime = bds->msg_ctime;
+}
+
+static void
+svr4_to_bsd_msqid_ds(sds, bds)
+ const struct svr4_msqid_ds *sds;
+ struct msqid_ds *bds;
+{
+ svr4_to_bsd_ipc_perm(&sds->msg_perm, &bds->msg_perm);
+ bds->msg_first = (struct msg *) sds->msg_first;
+ bds->msg_last = (struct msg *) sds->msg_last;
+ bds->msg_cbytes = sds->msg_cbytes;
+ bds->msg_qnum = sds->msg_qnum;
+ bds->msg_qbytes = sds->msg_qbytes;
+ bds->msg_lspid = sds->msg_lspid;
+ bds->msg_lrpid = sds->msg_lrpid;
+ bds->msg_stime = sds->msg_stime;
+ bds->msg_rtime = sds->msg_rtime;
+ bds->msg_ctime = sds->msg_ctime;
+}
+
+struct svr4_sys_msgsnd_args {
+ int what;
+ int msqid;
+ void * msgp;
+ size_t msgsz;
+ int msgflg;
+};
+
+static int
+svr4_msgsnd(td, v)
+ struct thread *td;
+ void *v;
+{
+ struct svr4_sys_msgsnd_args *uap = v;
+ struct msgsnd_args ap;
+
+ ap.msqid = uap->msqid;
+ ap.msgp = uap->msgp;
+ ap.msgsz = uap->msgsz;
+ ap.msgflg = uap->msgflg;
+
+ return sys_msgsnd(td, &ap);
+}
+
+struct svr4_sys_msgrcv_args {
+ int what;
+ int msqid;
+ void * msgp;
+ size_t msgsz;
+ long msgtyp;
+ int msgflg;
+};
+
+static int
+svr4_msgrcv(td, v)
+ struct thread *td;
+ void *v;
+{
+ struct svr4_sys_msgrcv_args *uap = v;
+ struct msgrcv_args ap;
+
+ ap.msqid = uap->msqid;
+ ap.msgp = uap->msgp;
+ ap.msgsz = uap->msgsz;
+ ap.msgtyp = uap->msgtyp;
+ ap.msgflg = uap->msgflg;
+
+ return sys_msgrcv(td, &ap);
+}
+
+struct svr4_sys_msgget_args {
+ int what;
+ svr4_key_t key;
+ int msgflg;
+};
+
+static int
+svr4_msgget(td, v)
+ struct thread *td;
+ void *v;
+{
+ struct svr4_sys_msgget_args *uap = v;
+ struct msgget_args ap;
+
+ ap.key = uap->key;
+ ap.msgflg = uap->msgflg;
+
+ return sys_msgget(td, &ap);
+}
+
+struct svr4_sys_msgctl_args {
+ int what;
+ int msqid;
+ int cmd;
+ struct svr4_msqid_ds * buf;
+};
+
+static int
+svr4_msgctl(td, v)
+ struct thread *td;
+ void *v;
+{
+ struct svr4_sys_msgctl_args *uap = v;
+ struct svr4_msqid_ds ss;
+ struct msqid_ds bs;
+ int error;
+
+ switch (uap->cmd) {
+ case SVR4_IPC_STAT:
+ error = kern_msgctl(td, uap->msqid, IPC_STAT, &bs);
+ if (error)
+ return error;
+ bsd_to_svr4_msqid_ds(&bs, &ss);
+ return copyout(&ss, uap->buf, sizeof ss);
+
+ case SVR4_IPC_SET:
+ error = copyin(uap->buf, &ss, sizeof ss);
+ if (error)
+ return error;
+ svr4_to_bsd_msqid_ds(&ss, &bs);
+ return (kern_msgctl(td, uap->msqid, IPC_SET, &bs));
+
+ case SVR4_IPC_RMID:
+ return (kern_msgctl(td, uap->msqid, IPC_RMID, NULL));
+
+ default:
+ return EINVAL;
+ }
+}
+
+int
+svr4_sys_msgsys(td, uap)
+ struct thread *td;
+ struct svr4_sys_msgsys_args *uap;
+{
+
+ DPRINTF(("svr4_msgsys(%d)\n", uap->what));
+
+ switch (uap->what) {
+ case SVR4_msgsnd:
+ return svr4_msgsnd(td, uap);
+ case SVR4_msgrcv:
+ return svr4_msgrcv(td, uap);
+ case SVR4_msgget:
+ return svr4_msgget(td, uap);
+ case SVR4_msgctl:
+ return svr4_msgctl(td, uap);
+ default:
+ return EINVAL;
+ }
+}
+
+MODULE_DEPEND(svr4elf, sysvmsg, 1, 1, 1);
+#endif
+
+#ifdef SYSVSHM
+
+static void
+bsd_to_svr4_shmid_ds(bds, sds)
+ const struct shmid_ds *bds;
+ struct svr4_shmid_ds *sds;
+{
+ bzero(sds, sizeof(*sds));
+ bsd_to_svr4_ipc_perm(&bds->shm_perm, &sds->shm_perm);
+ sds->shm_segsz = bds->shm_segsz;
+ sds->shm_lkcnt = 0;
+ sds->shm_lpid = bds->shm_lpid;
+ sds->shm_cpid = bds->shm_cpid;
+ sds->shm_amp = 0;
+ sds->shm_nattch = bds->shm_nattch;
+ sds->shm_cnattch = 0;
+ sds->shm_atime = bds->shm_atime;
+ sds->shm_dtime = bds->shm_dtime;
+ sds->shm_ctime = bds->shm_ctime;
+}
+
+static void
+svr4_to_bsd_shmid_ds(sds, bds)
+ const struct svr4_shmid_ds *sds;
+ struct shmid_ds *bds;
+{
+ svr4_to_bsd_ipc_perm(&sds->shm_perm, &bds->shm_perm);
+ bds->shm_segsz = sds->shm_segsz;
+ bds->shm_lpid = sds->shm_lpid;
+ bds->shm_cpid = sds->shm_cpid;
+ bds->shm_nattch = sds->shm_nattch;
+ bds->shm_atime = sds->shm_atime;
+ bds->shm_dtime = sds->shm_dtime;
+ bds->shm_ctime = sds->shm_ctime;
+}
+
+struct svr4_sys_shmat_args {
+ int what;
+ int shmid;
+ void * shmaddr;
+ int shmflg;
+};
+
+static int
+svr4_shmat(td, v)
+ struct thread *td;
+ void *v;
+{
+ struct svr4_sys_shmat_args *uap = v;
+ struct shmat_args ap;
+
+ ap.shmid = uap->shmid;
+ ap.shmaddr = uap->shmaddr;
+ ap.shmflg = uap->shmflg;
+
+ return sys_shmat(td, &ap);
+}
+
+struct svr4_sys_shmdt_args {
+ int what;
+ void * shmaddr;
+};
+
+static int
+svr4_shmdt(td, v)
+ struct thread *td;
+ void *v;
+{
+ struct svr4_sys_shmdt_args *uap = v;
+ struct shmdt_args ap;
+
+ ap.shmaddr = uap->shmaddr;
+
+ return sys_shmdt(td, &ap);
+}
+
+struct svr4_sys_shmget_args {
+ int what;
+ key_t key;
+ int size;
+ int shmflg;
+};
+
+static int
+svr4_shmget(td, v)
+ struct thread *td;
+ void *v;
+{
+ struct svr4_sys_shmget_args *uap = v;
+ struct shmget_args ap;
+
+ ap.key = uap->key;
+ ap.size = uap->size;
+ ap.shmflg = uap->shmflg;
+
+ return sys_shmget(td, &ap);
+}
+
+struct svr4_sys_shmctl_args {
+ int what;
+ int shmid;
+ int cmd;
+ struct svr4_shmid_ds * buf;
+};
+
+int
+svr4_shmctl(td, v)
+ struct thread *td;
+ void *v;
+{
+ struct svr4_sys_shmctl_args *uap = v;
+ struct shmid_ds bs;
+ struct svr4_shmid_ds ss;
+ size_t bufsize;
+ int cmd, error;
+
+ if (uap->buf != NULL) {
+ switch (uap->cmd) {
+ case SVR4_IPC_SET:
+ case SVR4_SHM_LOCK:
+ case SVR4_SHM_UNLOCK:
+ error = copyin(uap->buf, &ss, sizeof(ss));
+ if (error)
+ return (error);
+ svr4_to_bsd_shmid_ds(&ss, &bs);
+ break;
+ default:
+ return (EINVAL);
+ }
+ }
+
+ switch (uap->cmd) {
+ case SVR4_IPC_STAT:
+ cmd = IPC_STAT;
+ break;
+ case SVR4_IPC_SET:
+ cmd = IPC_SET;
+ break;
+ case SVR4_IPC_RMID:
+ cmd = IPC_RMID;
+ break;
+ case SVR4_SHM_LOCK:
+ cmd = SHM_LOCK;
+ break;
+ case SVR4_SHM_UNLOCK:
+ cmd = SHM_UNLOCK;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ error = kern_shmctl(td, uap->shmid, cmd, &bs, &bufsize);
+ if (error)
+ return (error);
+
+ switch (uap->cmd) {
+ case SVR4_IPC_STAT:
+ if (uap->buf != NULL) {
+ bsd_to_svr4_shmid_ds(&bs, &ss);
+ error = copyout(&ss, uap->buf, sizeof(ss));
+ }
+ break;
+ }
+
+ return (error);
+}
+
+int
+svr4_sys_shmsys(td, uap)
+ struct thread *td;
+ struct svr4_sys_shmsys_args *uap;
+{
+
+ DPRINTF(("svr4_shmsys(%d)\n", uap->what));
+
+ switch (uap->what) {
+ case SVR4_shmat:
+ return svr4_shmat(td, uap);
+ case SVR4_shmdt:
+ return svr4_shmdt(td, uap);
+ case SVR4_shmget:
+ return svr4_shmget(td, uap);
+ case SVR4_shmctl:
+ return svr4_shmctl(td, uap);
+ default:
+ return ENOSYS;
+ }
+}
+
+MODULE_DEPEND(svr4elf, sysvshm, 1, 1, 1);
+#endif /* SYSVSHM */
diff --git a/sys/compat/svr4/svr4_ipc.h b/sys/compat/svr4/svr4_ipc.h
new file mode 100644
index 0000000..36cf3dd
--- /dev/null
+++ b/sys/compat/svr4/svr4_ipc.h
@@ -0,0 +1,176 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1995 Christos Zoulas. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christos Zoulas.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_IPC_H_
+#define _SVR4_IPC_H_
+
+/*
+ * General IPC
+ */
+#define SVR4_IPC_RMID 10
+#define SVR4_IPC_SET 11
+#define SVR4_IPC_STAT 12
+
+struct svr4_ipc_perm {
+ svr4_uid_t uid;
+ svr4_gid_t gid;
+ svr4_uid_t cuid;
+ svr4_gid_t cgid;
+ svr4_mode_t mode;
+ u_long seq;
+ svr4_key_t key;
+ long pad[4];
+};
+
+/*
+ * Message queues
+ */
+#define SVR4_msgget 0
+#define SVR4_msgctl 1
+#define SVR4_msgrcv 2
+#define SVR4_msgsnd 3
+
+struct svr4_msg {
+ struct svr4_msg *msg_next;
+ long msg_type;
+ u_short msg_ts;
+ short msg_spot;
+};
+
+struct svr4_msqid_ds {
+ struct svr4_ipc_perm msg_perm;
+ struct svr4_msg *msg_first;
+ struct svr4_msg *msg_last;
+ u_long msg_cbytes;
+ u_long msg_qnum;
+ u_long msg_qbytes;
+ svr4_pid_t msg_lspid;
+ svr4_pid_t msg_lrpid;
+ svr4_time_t msg_stime;
+ long msg_pad1;
+ svr4_time_t msg_rtime;
+ long msg_pad2;
+ svr4_time_t msg_ctime;
+ long msg_pad3;
+ short msg_cv;
+ short msg_qnum_cv;
+ long msg_pad4[3];
+};
+
+struct svr4_msgbuf {
+ long mtype; /* message type */
+ char mtext[1]; /* message text */
+};
+
+struct svr4_msginfo {
+ int msgmap;
+ int msgmax;
+ int msgmnb;
+ int msgmni;
+ int msgssz;
+ int msgtql;
+ u_short msgseg;
+};
+
+/*
+ * Shared memory
+ */
+#define SVR4_shmat 0
+#define SVR4_shmctl 1
+#define SVR4_shmdt 2
+#define SVR4_shmget 3
+
+/* shmctl() operations */
+#define SVR4_SHM_LOCK 3
+#define SVR4_SHM_UNLOCK 4
+
+struct svr4_shmid_ds {
+ struct svr4_ipc_perm shm_perm;
+ int shm_segsz;
+ void *shm_amp;
+ u_short shm_lkcnt;
+ svr4_pid_t shm_lpid;
+ svr4_pid_t shm_cpid;
+ u_long shm_nattch;
+ u_long shm_cnattch;
+ svr4_time_t shm_atime;
+ long shm_pad1;
+ svr4_time_t shm_dtime;
+ long shm_pad2;
+ svr4_time_t shm_ctime;
+ long shm_pad3;
+ long shm_pad4[4];
+};
+
+/*
+ * Semaphores
+ */
+#define SVR4_semctl 0
+#define SVR4_semget 1
+#define SVR4_semop 2
+
+/* semctl() operations */
+#define SVR4_SEM_GETNCNT 3
+#define SVR4_SEM_GETPID 4
+#define SVR4_SEM_GETVAL 5
+#define SVR4_SEM_GETALL 6
+#define SVR4_SEM_GETZCNT 7
+#define SVR4_SEM_SETVAL 8
+#define SVR4_SEM_SETALL 9
+
+struct svr4_sem {
+ u_short semval;
+ svr4_pid_t sempid;
+ u_short semncnt;
+ u_short semzcnt;
+ u_short semncnt_cv;
+ u_short semzcnt_cv;
+};
+
+struct svr4_semid_ds {
+ struct svr4_ipc_perm sem_perm;
+ struct svr4_sem *sem_base;
+ u_short sem_nsems;
+ svr4_time_t sem_otime;
+ long sem_pad1;
+ svr4_time_t sem_ctime;
+ long sem_pad2;
+ long sem_pad3[4];
+};
+
+struct svr4_sembuf {
+ u_short sem_num;
+ short sem_op;
+ short sem_flg;
+};
+
+#endif /* _SVR4_IPC_H */
diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c
new file mode 100644
index 0000000..0cfaeae
--- /dev/null
+++ b/sys/compat/svr4/svr4_misc.c
@@ -0,0 +1,1658 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * SVR4 compatibility module.
+ *
+ * SVR4 system calls that are implemented differently in BSD are
+ * handled here.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/capability.h>
+#include <sys/dirent.h>
+#include <sys/fcntl.h>
+#include <sys/filedesc.h>
+#include <sys/imgact.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/file.h> /* Must come after sys/malloc.h */
+#include <sys/mman.h>
+#include <sys/mount.h>
+#include <sys/msg.h>
+#include <sys/mutex.h>
+#include <sys/namei.h>
+#include <sys/priv.h>
+#include <sys/proc.h>
+#include <sys/ptrace.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
+#include <sys/sem.h>
+#include <sys/signalvar.h>
+#include <sys/stat.h>
+#include <sys/sx.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysproto.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <sys/uio.h>
+#include <sys/vnode.h>
+#include <sys/wait.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_proto.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_sysconfig.h>
+#include <compat/svr4/svr4_dirent.h>
+#include <compat/svr4/svr4_acl.h>
+#include <compat/svr4/svr4_ulimit.h>
+#include <compat/svr4/svr4_statvfs.h>
+#include <compat/svr4/svr4_hrt.h>
+#include <compat/svr4/svr4_mman.h>
+#include <compat/svr4/svr4_wait.h>
+
+#include <security/mac/mac_framework.h>
+
+#include <machine/vmparam.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_map.h>
+#if defined(__FreeBSD__)
+#include <vm/uma.h>
+#include <vm/vm_extern.h>
+#endif
+
+#if defined(NetBSD)
+# if defined(UVM)
+# include <uvm/uvm_extern.h>
+# endif
+#endif
+
+#define BSD_DIRENT(cp) ((struct dirent *)(cp))
+
+static int svr4_mknod(struct thread *, register_t *, char *,
+ svr4_mode_t, svr4_dev_t);
+
+static __inline clock_t timeval_to_clock_t(struct timeval *);
+static int svr4_setinfo (pid_t , struct rusage *, int, svr4_siginfo_t *);
+
+struct svr4_hrtcntl_args;
+static int svr4_hrtcntl (struct thread *, struct svr4_hrtcntl_args *,
+ register_t *);
+static void bsd_statfs_to_svr4_statvfs(const struct statfs *,
+ struct svr4_statvfs *);
+static void bsd_statfs_to_svr4_statvfs64(const struct statfs *,
+ struct svr4_statvfs64 *);
+static struct proc *svr4_pfind(pid_t pid);
+
+/* BOGUS noop */
+#if defined(BOGUS)
+int
+svr4_sys_setitimer(td, uap)
+ struct thread *td;
+ struct svr4_sys_setitimer_args *uap;
+{
+ td->td_retval[0] = 0;
+ return 0;
+}
+#endif
+
+int
+svr4_sys_wait(td, uap)
+ struct thread *td;
+ struct svr4_sys_wait_args *uap;
+{
+ int error, st, sig;
+
+ error = kern_wait(td, WAIT_ANY, &st, 0, NULL);
+ if (error)
+ return (error);
+
+ if (WIFSIGNALED(st)) {
+ sig = WTERMSIG(st);
+ if (sig >= 0 && sig < NSIG)
+ st = (st & ~0177) | SVR4_BSD2SVR4_SIG(sig);
+ } else if (WIFSTOPPED(st)) {
+ sig = WSTOPSIG(st);
+ if (sig >= 0 && sig < NSIG)
+ st = (st & ~0xff00) | (SVR4_BSD2SVR4_SIG(sig) << 8);
+ }
+
+ /*
+ * It looks like wait(2) on svr4/solaris/2.4 returns
+ * the status in retval[1], and the pid on retval[0].
+ */
+ td->td_retval[1] = st;
+
+ if (uap->status)
+ error = copyout(&st, uap->status, sizeof(st));
+
+ return (error);
+}
+
+int
+svr4_sys_execv(td, uap)
+ struct thread *td;
+ struct svr4_sys_execv_args *uap;
+{
+ struct image_args eargs;
+ char *path;
+ int error;
+
+ CHECKALTEXIST(td, uap->path, &path);
+
+ error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, uap->argp, NULL);
+ free(path, M_TEMP);
+ if (error == 0)
+ error = kern_execve(td, &eargs, NULL);
+ return (error);
+}
+
+int
+svr4_sys_execve(td, uap)
+ struct thread *td;
+ struct svr4_sys_execve_args *uap;
+{
+ struct image_args eargs;
+ char *path;
+ int error;
+
+ CHECKALTEXIST(td, uap->path, &path);
+
+ error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, uap->argp,
+ uap->envp);
+ free(path, M_TEMP);
+ if (error == 0)
+ error = kern_execve(td, &eargs, NULL);
+ return (error);
+}
+
+int
+svr4_sys_time(td, v)
+ struct thread *td;
+ struct svr4_sys_time_args *v;
+{
+ struct svr4_sys_time_args *uap = v;
+ int error = 0;
+ struct timeval tv;
+
+ microtime(&tv);
+ if (uap->t)
+ error = copyout(&tv.tv_sec, uap->t,
+ sizeof(*(uap->t)));
+ td->td_retval[0] = (int) tv.tv_sec;
+
+ return error;
+}
+
+
+/*
+ * Read SVR4-style directory entries. We suck them into kernel space so
+ * that they can be massaged before being copied out to user code.
+ *
+ * This code is ported from the Linux emulator: Changes to the VFS interface
+ * between FreeBSD and NetBSD have made it simpler to port it from there than
+ * to adapt the NetBSD version.
+ */
+int
+svr4_sys_getdents64(td, uap)
+ struct thread *td;
+ struct svr4_sys_getdents64_args *uap;
+{
+ struct dirent *bdp;
+ struct vnode *vp;
+ caddr_t inp, buf; /* BSD-format */
+ int len, reclen; /* BSD-format */
+ caddr_t outp; /* SVR4-format */
+ int resid, svr4reclen=0; /* SVR4-format */
+ struct file *fp;
+ struct uio auio;
+ struct iovec aiov;
+ off_t off;
+ struct svr4_dirent64 svr4_dirent;
+ int buflen, error, eofflag, nbytes, justone;
+ u_long *cookies = NULL, *cookiep;
+ int ncookies;
+
+ DPRINTF(("svr4_sys_getdents64(%d, *, %d)\n",
+ uap->fd, uap->nbytes));
+ if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ, &fp)) != 0)
+ return (error);
+
+ if ((fp->f_flag & FREAD) == 0) {
+ fdrop(fp, td);
+ return (EBADF);
+ }
+
+ vp = fp->f_vnode;
+ if (vp->v_type != VDIR) {
+ fdrop(fp, td);
+ return (EINVAL);
+ }
+
+ nbytes = uap->nbytes;
+ if (nbytes == 1) {
+ nbytes = sizeof (struct svr4_dirent64);
+ justone = 1;
+ }
+ else
+ justone = 0;
+
+ off = fp->f_offset;
+#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */
+ buflen = max(DIRBLKSIZ, nbytes);
+ buflen = min(buflen, MAXBSIZE);
+ buf = malloc(buflen, M_TEMP, M_WAITOK);
+ vn_lock(vp, LK_SHARED | LK_RETRY);
+again:
+ aiov.iov_base = buf;
+ aiov.iov_len = buflen;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_rw = UIO_READ;
+ auio.uio_segflg = UIO_SYSSPACE;
+ auio.uio_td = td;
+ auio.uio_resid = buflen;
+ auio.uio_offset = off;
+
+ if (cookies) {
+ free(cookies, M_TEMP);
+ cookies = NULL;
+ }
+
+#ifdef MAC
+ error = mac_vnode_check_readdir(td->td_ucred, vp);
+ if (error)
+ goto out;
+#endif
+
+ error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
+ &ncookies, &cookies);
+ if (error) {
+ goto out;
+ }
+
+ inp = buf;
+ outp = (caddr_t) uap->dp;
+ resid = nbytes;
+ if ((len = buflen - auio.uio_resid) <= 0) {
+ goto eof;
+ }
+
+ cookiep = cookies;
+
+ if (cookies) {
+ /*
+ * When using cookies, the vfs has the option of reading from
+ * a different offset than that supplied (UFS truncates the
+ * offset to a block boundary to make sure that it never reads
+ * partway through a directory entry, even if the directory
+ * has been compacted).
+ */
+ while (len > 0 && ncookies > 0 && *cookiep <= off) {
+ bdp = (struct dirent *) inp;
+ len -= bdp->d_reclen;
+ inp += bdp->d_reclen;
+ cookiep++;
+ ncookies--;
+ }
+ }
+
+ while (len > 0) {
+ if (cookiep && ncookies == 0)
+ break;
+ bdp = (struct dirent *) inp;
+ reclen = bdp->d_reclen;
+ if (reclen & 3) {
+ DPRINTF(("svr4_readdir: reclen=%d\n", reclen));
+ error = EFAULT;
+ goto out;
+ }
+
+ if (bdp->d_fileno == 0) {
+ inp += reclen;
+ if (cookiep) {
+ off = *cookiep++;
+ ncookies--;
+ } else
+ off += reclen;
+ len -= reclen;
+ continue;
+ }
+ svr4reclen = SVR4_RECLEN(&svr4_dirent, bdp->d_namlen);
+ if (reclen > len || resid < svr4reclen) {
+ outp++;
+ break;
+ }
+ svr4_dirent.d_ino = (long) bdp->d_fileno;
+ if (justone) {
+ /*
+ * old svr4-style readdir usage.
+ */
+ svr4_dirent.d_off = (svr4_off_t) svr4reclen;
+ svr4_dirent.d_reclen = (u_short) bdp->d_namlen;
+ } else {
+ svr4_dirent.d_off = (svr4_off_t)(off + reclen);
+ svr4_dirent.d_reclen = (u_short) svr4reclen;
+ }
+ strlcpy(svr4_dirent.d_name, bdp->d_name, sizeof(svr4_dirent.d_name));
+ if ((error = copyout((caddr_t)&svr4_dirent, outp, svr4reclen)))
+ goto out;
+ inp += reclen;
+ if (cookiep) {
+ off = *cookiep++;
+ ncookies--;
+ } else
+ off += reclen;
+ outp += svr4reclen;
+ resid -= svr4reclen;
+ len -= reclen;
+ if (justone)
+ break;
+ }
+
+ if (outp == (caddr_t) uap->dp)
+ goto again;
+ fp->f_offset = off;
+
+ if (justone)
+ nbytes = resid + svr4reclen;
+
+eof:
+ td->td_retval[0] = nbytes - resid;
+out:
+ VOP_UNLOCK(vp, 0);
+ fdrop(fp, td);
+ if (cookies)
+ free(cookies, M_TEMP);
+ free(buf, M_TEMP);
+ return error;
+}
+
+
+int
+svr4_sys_getdents(td, uap)
+ struct thread *td;
+ struct svr4_sys_getdents_args *uap;
+{
+ struct dirent *bdp;
+ struct vnode *vp;
+ caddr_t inp, buf; /* BSD-format */
+ int len, reclen; /* BSD-format */
+ caddr_t outp; /* SVR4-format */
+ int resid, svr4_reclen; /* SVR4-format */
+ struct file *fp;
+ struct uio auio;
+ struct iovec aiov;
+ struct svr4_dirent idb;
+ off_t off; /* true file offset */
+ int buflen, error, eofflag;
+ u_long *cookiebuf = NULL, *cookie;
+ int ncookies = 0, *retval = td->td_retval;
+
+ if (uap->nbytes < 0)
+ return (EINVAL);
+
+ if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ, &fp)) != 0)
+ return (error);
+
+ if ((fp->f_flag & FREAD) == 0) {
+ fdrop(fp, td);
+ return (EBADF);
+ }
+
+ vp = fp->f_vnode;
+ if (vp->v_type != VDIR) {
+ fdrop(fp, td);
+ return (EINVAL);
+ }
+
+ buflen = min(MAXBSIZE, uap->nbytes);
+ buf = malloc(buflen, M_TEMP, M_WAITOK);
+ vn_lock(vp, LK_SHARED | LK_RETRY);
+ off = fp->f_offset;
+again:
+ aiov.iov_base = buf;
+ aiov.iov_len = buflen;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_rw = UIO_READ;
+ auio.uio_segflg = UIO_SYSSPACE;
+ auio.uio_td = td;
+ auio.uio_resid = buflen;
+ auio.uio_offset = off;
+
+#ifdef MAC
+ error = mac_vnode_check_readdir(td->td_ucred, vp);
+ if (error)
+ goto out;
+#endif
+
+ /*
+ * First we read into the malloc'ed buffer, then
+ * we massage it into user space, one record at a time.
+ */
+ error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies,
+ &cookiebuf);
+ if (error) {
+ goto out;
+ }
+
+ inp = buf;
+ outp = uap->buf;
+ resid = uap->nbytes;
+ if ((len = buflen - auio.uio_resid) == 0)
+ goto eof;
+
+ for (cookie = cookiebuf; len > 0; len -= reclen) {
+ bdp = (struct dirent *)inp;
+ reclen = bdp->d_reclen;
+ if (reclen & 3)
+ panic("svr4_sys_getdents64: bad reclen");
+ if (cookie)
+ off = *cookie++; /* each entry points to the next */
+ else
+ off += reclen;
+ if ((off >> 32) != 0) {
+ uprintf("svr4_sys_getdents64: dir offset too large for emulated program");
+ error = EINVAL;
+ goto out;
+ }
+ if (bdp->d_fileno == 0) {
+ inp += reclen; /* it is a hole; squish it out */
+ continue;
+ }
+ svr4_reclen = SVR4_RECLEN(&idb, bdp->d_namlen);
+ if (reclen > len || resid < svr4_reclen) {
+ /* entry too big for buffer, so just stop */
+ outp++;
+ break;
+ }
+ /*
+ * Massage in place to make a SVR4-shaped dirent (otherwise
+ * we have to worry about touching user memory outside of
+ * the copyout() call).
+ */
+ idb.d_ino = (svr4_ino_t)bdp->d_fileno;
+ idb.d_off = (svr4_off_t)off;
+ idb.d_reclen = (u_short)svr4_reclen;
+ strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
+ if ((error = copyout((caddr_t)&idb, outp, svr4_reclen)))
+ goto out;
+ /* advance past this real entry */
+ inp += reclen;
+ /* advance output past SVR4-shaped entry */
+ outp += svr4_reclen;
+ resid -= svr4_reclen;
+ }
+
+ /* if we squished out the whole block, try again */
+ if (outp == uap->buf)
+ goto again;
+ fp->f_offset = off; /* update the vnode offset */
+
+eof:
+ *retval = uap->nbytes - resid;
+out:
+ VOP_UNLOCK(vp, 0);
+ fdrop(fp, td);
+ if (cookiebuf)
+ free(cookiebuf, M_TEMP);
+ free(buf, M_TEMP);
+ return error;
+}
+
+
+int
+svr4_sys_mmap(td, uap)
+ struct thread *td;
+ struct svr4_sys_mmap_args *uap;
+{
+ struct mmap_args mm;
+ int *retval;
+
+ retval = td->td_retval;
+#define _MAP_NEW 0x80000000
+ /*
+ * Verify the arguments.
+ */
+ if (uap->prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
+ return EINVAL; /* XXX still needed? */
+
+ if (uap->len == 0)
+ return EINVAL;
+
+ mm.prot = uap->prot;
+ mm.len = uap->len;
+ mm.flags = uap->flags & ~_MAP_NEW;
+ mm.fd = uap->fd;
+ mm.addr = uap->addr;
+ mm.pos = uap->pos;
+
+ return sys_mmap(td, &mm);
+}
+
+int
+svr4_sys_mmap64(td, uap)
+ struct thread *td;
+ struct svr4_sys_mmap64_args *uap;
+{
+ struct mmap_args mm;
+ void *rp;
+
+#define _MAP_NEW 0x80000000
+ /*
+ * Verify the arguments.
+ */
+ if (uap->prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
+ return EINVAL; /* XXX still needed? */
+
+ if (uap->len == 0)
+ return EINVAL;
+
+ mm.prot = uap->prot;
+ mm.len = uap->len;
+ mm.flags = uap->flags & ~_MAP_NEW;
+ mm.fd = uap->fd;
+ mm.addr = uap->addr;
+ mm.pos = uap->pos;
+
+ rp = (void *) round_page((vm_offset_t)(td->td_proc->p_vmspace->vm_daddr + maxdsiz));
+ if ((mm.flags & MAP_FIXED) == 0 &&
+ mm.addr != 0 && (void *)mm.addr < rp)
+ mm.addr = rp;
+
+ return sys_mmap(td, &mm);
+}
+
+
+int
+svr4_sys_fchroot(td, uap)
+ struct thread *td;
+ struct svr4_sys_fchroot_args *uap;
+{
+ struct filedesc *fdp = td->td_proc->p_fd;
+ struct vnode *vp;
+ struct file *fp;
+ int error;
+
+ if ((error = priv_check(td, PRIV_VFS_FCHROOT)) != 0)
+ return error;
+ /* XXX: we have the chroot priv... what cap might we need? all? */
+ if ((error = getvnode(fdp, uap->fd, 0, &fp)) != 0)
+ return error;
+ vp = fp->f_vnode;
+ VREF(vp);
+ fdrop(fp, td);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ error = change_dir(vp, td);
+ if (error)
+ goto fail;
+#ifdef MAC
+ error = mac_vnode_check_chroot(td->td_ucred, vp);
+ if (error)
+ goto fail;
+#endif
+ VOP_UNLOCK(vp, 0);
+ error = change_root(vp, td);
+ vrele(vp);
+ return (error);
+fail:
+ vput(vp);
+ return (error);
+}
+
+
+static int
+svr4_mknod(td, retval, path, mode, dev)
+ struct thread *td;
+ register_t *retval;
+ char *path;
+ svr4_mode_t mode;
+ svr4_dev_t dev;
+{
+ char *newpath;
+ int error;
+
+ CHECKALTEXIST(td, path, &newpath);
+
+ if (S_ISFIFO(mode))
+ error = kern_mkfifo(td, newpath, UIO_SYSSPACE, mode);
+ else
+ error = kern_mknod(td, newpath, UIO_SYSSPACE, mode, dev);
+ free(newpath, M_TEMP);
+ return (error);
+}
+
+
+int
+svr4_sys_mknod(td, uap)
+ struct thread *td;
+ struct svr4_sys_mknod_args *uap;
+{
+ int *retval = td->td_retval;
+ return svr4_mknod(td, retval,
+ uap->path, uap->mode,
+ (svr4_dev_t)svr4_to_bsd_odev_t(uap->dev));
+}
+
+
+int
+svr4_sys_xmknod(td, uap)
+ struct thread *td;
+ struct svr4_sys_xmknod_args *uap;
+{
+ int *retval = td->td_retval;
+ return svr4_mknod(td, retval,
+ uap->path, uap->mode,
+ (svr4_dev_t)svr4_to_bsd_dev_t(uap->dev));
+}
+
+
+int
+svr4_sys_vhangup(td, uap)
+ struct thread *td;
+ struct svr4_sys_vhangup_args *uap;
+{
+ return 0;
+}
+
+
+int
+svr4_sys_sysconfig(td, uap)
+ struct thread *td;
+ struct svr4_sys_sysconfig_args *uap;
+{
+ int *retval;
+
+ retval = &(td->td_retval[0]);
+
+ switch (uap->name) {
+ case SVR4_CONFIG_NGROUPS:
+ *retval = ngroups_max;
+ break;
+ case SVR4_CONFIG_CHILD_MAX:
+ *retval = maxproc;
+ break;
+ case SVR4_CONFIG_OPEN_FILES:
+ *retval = maxfiles;
+ break;
+ case SVR4_CONFIG_POSIX_VER:
+ *retval = 198808;
+ break;
+ case SVR4_CONFIG_PAGESIZE:
+ *retval = PAGE_SIZE;
+ break;
+ case SVR4_CONFIG_CLK_TCK:
+ *retval = 60; /* should this be `hz', ie. 100? */
+ break;
+ case SVR4_CONFIG_XOPEN_VER:
+ *retval = 2; /* XXX: What should that be? */
+ break;
+ case SVR4_CONFIG_PROF_TCK:
+ *retval = 60; /* XXX: What should that be? */
+ break;
+ case SVR4_CONFIG_NPROC_CONF:
+ *retval = 1; /* Only one processor for now */
+ break;
+ case SVR4_CONFIG_NPROC_ONLN:
+ *retval = 1; /* And it better be online */
+ break;
+ case SVR4_CONFIG_AIO_LISTIO_MAX:
+ case SVR4_CONFIG_AIO_MAX:
+ case SVR4_CONFIG_AIO_PRIO_DELTA_MAX:
+ *retval = 0; /* No aio support */
+ break;
+ case SVR4_CONFIG_DELAYTIMER_MAX:
+ *retval = 0; /* No delaytimer support */
+ break;
+ case SVR4_CONFIG_MQ_OPEN_MAX:
+ *retval = msginfo.msgmni;
+ break;
+ case SVR4_CONFIG_MQ_PRIO_MAX:
+ *retval = 0; /* XXX: Don't know */
+ break;
+ case SVR4_CONFIG_RTSIG_MAX:
+ *retval = 0;
+ break;
+ case SVR4_CONFIG_SEM_NSEMS_MAX:
+ *retval = seminfo.semmni;
+ break;
+ case SVR4_CONFIG_SEM_VALUE_MAX:
+ *retval = seminfo.semvmx;
+ break;
+ case SVR4_CONFIG_SIGQUEUE_MAX:
+ *retval = 0; /* XXX: Don't know */
+ break;
+ case SVR4_CONFIG_SIGRT_MIN:
+ case SVR4_CONFIG_SIGRT_MAX:
+ *retval = 0; /* No real time signals */
+ break;
+ case SVR4_CONFIG_TIMER_MAX:
+ *retval = 3; /* XXX: real, virtual, profiling */
+ break;
+#if defined(NOTYET)
+ case SVR4_CONFIG_PHYS_PAGES:
+#if defined(UVM)
+ *retval = uvmexp.free; /* XXX: free instead of total */
+#else
+ *retval = cnt.v_free_count; /* XXX: free instead of total */
+#endif
+ break;
+ case SVR4_CONFIG_AVPHYS_PAGES:
+#if defined(UVM)
+ *retval = uvmexp.active; /* XXX: active instead of avg */
+#else
+ *retval = cnt.v_active_count; /* XXX: active instead of avg */
+#endif
+ break;
+#endif /* NOTYET */
+ case SVR4_CONFIG_COHERENCY:
+ *retval = 0; /* XXX */
+ break;
+ case SVR4_CONFIG_SPLIT_CACHE:
+ *retval = 0; /* XXX */
+ break;
+ case SVR4_CONFIG_ICACHESZ:
+ *retval = 256; /* XXX */
+ break;
+ case SVR4_CONFIG_DCACHESZ:
+ *retval = 256; /* XXX */
+ break;
+ case SVR4_CONFIG_ICACHELINESZ:
+ *retval = 64; /* XXX */
+ break;
+ case SVR4_CONFIG_DCACHELINESZ:
+ *retval = 64; /* XXX */
+ break;
+ case SVR4_CONFIG_ICACHEBLKSZ:
+ *retval = 64; /* XXX */
+ break;
+ case SVR4_CONFIG_DCACHEBLKSZ:
+ *retval = 64; /* XXX */
+ break;
+ case SVR4_CONFIG_DCACHETBLKSZ:
+ *retval = 64; /* XXX */
+ break;
+ case SVR4_CONFIG_ICACHE_ASSOC:
+ *retval = 1; /* XXX */
+ break;
+ case SVR4_CONFIG_DCACHE_ASSOC:
+ *retval = 1; /* XXX */
+ break;
+ case SVR4_CONFIG_MAXPID:
+ *retval = PID_MAX;
+ break;
+ case SVR4_CONFIG_STACK_PROT:
+ *retval = PROT_READ|PROT_WRITE|PROT_EXEC;
+ break;
+ default:
+ return EINVAL;
+ }
+ return 0;
+}
+
+/* ARGSUSED */
+int
+svr4_sys_break(td, uap)
+ struct thread *td;
+ struct svr4_sys_break_args *uap;
+{
+ struct obreak_args ap;
+
+ ap.nsize = uap->nsize;
+ return (sys_obreak(td, &ap));
+}
+
+static __inline clock_t
+timeval_to_clock_t(tv)
+ struct timeval *tv;
+{
+ return tv->tv_sec * hz + tv->tv_usec / (1000000 / hz);
+}
+
+
+int
+svr4_sys_times(td, uap)
+ struct thread *td;
+ struct svr4_sys_times_args *uap;
+{
+ struct timeval tv, utime, stime, cutime, cstime;
+ struct tms tms;
+ struct proc *p;
+ int error;
+
+ p = td->td_proc;
+ PROC_LOCK(p);
+ PROC_SLOCK(p);
+ calcru(p, &utime, &stime);
+ PROC_SUNLOCK(p);
+ calccru(p, &cutime, &cstime);
+ PROC_UNLOCK(p);
+
+ tms.tms_utime = timeval_to_clock_t(&utime);
+ tms.tms_stime = timeval_to_clock_t(&stime);
+
+ tms.tms_cutime = timeval_to_clock_t(&cutime);
+ tms.tms_cstime = timeval_to_clock_t(&cstime);
+
+ error = copyout(&tms, uap->tp, sizeof(tms));
+ if (error)
+ return (error);
+
+ microtime(&tv);
+ td->td_retval[0] = (int)timeval_to_clock_t(&tv);
+ return (0);
+}
+
+
+int
+svr4_sys_ulimit(td, uap)
+ struct thread *td;
+ struct svr4_sys_ulimit_args *uap;
+{
+ int *retval = td->td_retval;
+ int error;
+
+ switch (uap->cmd) {
+ case SVR4_GFILLIM:
+ PROC_LOCK(td->td_proc);
+ *retval = lim_cur(td->td_proc, RLIMIT_FSIZE) / 512;
+ PROC_UNLOCK(td->td_proc);
+ if (*retval == -1)
+ *retval = 0x7fffffff;
+ return 0;
+
+ case SVR4_SFILLIM:
+ {
+ struct rlimit krl;
+
+ krl.rlim_cur = uap->newlimit * 512;
+ PROC_LOCK(td->td_proc);
+ krl.rlim_max = lim_max(td->td_proc, RLIMIT_FSIZE);
+ PROC_UNLOCK(td->td_proc);
+
+ error = kern_setrlimit(td, RLIMIT_FSIZE, &krl);
+ if (error)
+ return error;
+
+ PROC_LOCK(td->td_proc);
+ *retval = lim_cur(td->td_proc, RLIMIT_FSIZE);
+ PROC_UNLOCK(td->td_proc);
+ if (*retval == -1)
+ *retval = 0x7fffffff;
+ return 0;
+ }
+
+ case SVR4_GMEMLIM:
+ {
+ struct vmspace *vm = td->td_proc->p_vmspace;
+ register_t r;
+
+ PROC_LOCK(td->td_proc);
+ r = lim_cur(td->td_proc, RLIMIT_DATA);
+ PROC_UNLOCK(td->td_proc);
+
+ if (r == -1)
+ r = 0x7fffffff;
+ r += (long) vm->vm_daddr;
+ if (r < 0)
+ r = 0x7fffffff;
+ *retval = r;
+ return 0;
+ }
+
+ case SVR4_GDESLIM:
+ PROC_LOCK(td->td_proc);
+ *retval = lim_cur(td->td_proc, RLIMIT_NOFILE);
+ PROC_UNLOCK(td->td_proc);
+ if (*retval == -1)
+ *retval = 0x7fffffff;
+ return 0;
+
+ default:
+ return EINVAL;
+ }
+}
+
+static struct proc *
+svr4_pfind(pid)
+ pid_t pid;
+{
+ struct proc *p;
+
+ /* look in the live processes */
+ if ((p = pfind(pid)) == NULL)
+ /* look in the zombies */
+ p = zpfind(pid);
+
+ return p;
+}
+
+
+int
+svr4_sys_pgrpsys(td, uap)
+ struct thread *td;
+ struct svr4_sys_pgrpsys_args *uap;
+{
+ int *retval = td->td_retval;
+ struct proc *p = td->td_proc;
+
+ switch (uap->cmd) {
+ case 1: /* setpgrp() */
+ /*
+ * SVR4 setpgrp() (which takes no arguments) has the
+ * semantics that the session ID is also created anew, so
+ * in almost every sense, setpgrp() is identical to
+ * setsid() for SVR4. (Under BSD, the difference is that
+ * a setpgid(0,0) will not create a new session.)
+ */
+ sys_setsid(td, NULL);
+ /*FALLTHROUGH*/
+
+ case 0: /* getpgrp() */
+ PROC_LOCK(p);
+ *retval = p->p_pgrp->pg_id;
+ PROC_UNLOCK(p);
+ return 0;
+
+ case 2: /* getsid(pid) */
+ if (uap->pid == 0)
+ PROC_LOCK(p);
+ else if ((p = svr4_pfind(uap->pid)) == NULL)
+ return ESRCH;
+ /*
+ * This has already been initialized to the pid of
+ * the session leader.
+ */
+ *retval = (register_t) p->p_session->s_sid;
+ PROC_UNLOCK(p);
+ return 0;
+
+ case 3: /* setsid() */
+ return sys_setsid(td, NULL);
+
+ case 4: /* getpgid(pid) */
+
+ if (uap->pid == 0)
+ PROC_LOCK(p);
+ else if ((p = svr4_pfind(uap->pid)) == NULL)
+ return ESRCH;
+
+ *retval = (int) p->p_pgrp->pg_id;
+ PROC_UNLOCK(p);
+ return 0;
+
+ case 5: /* setpgid(pid, pgid); */
+ {
+ struct setpgid_args sa;
+
+ sa.pid = uap->pid;
+ sa.pgid = uap->pgid;
+ return sys_setpgid(td, &sa);
+ }
+
+ default:
+ return EINVAL;
+ }
+}
+
+struct svr4_hrtcntl_args {
+ int cmd;
+ int fun;
+ int clk;
+ svr4_hrt_interval_t * iv;
+ svr4_hrt_time_t * ti;
+};
+
+
+static int
+svr4_hrtcntl(td, uap, retval)
+ struct thread *td;
+ struct svr4_hrtcntl_args *uap;
+ register_t *retval;
+{
+ switch (uap->fun) {
+ case SVR4_HRT_CNTL_RES:
+ DPRINTF(("htrcntl(RES)\n"));
+ *retval = SVR4_HRT_USEC;
+ return 0;
+
+ case SVR4_HRT_CNTL_TOFD:
+ DPRINTF(("htrcntl(TOFD)\n"));
+ {
+ struct timeval tv;
+ svr4_hrt_time_t t;
+ if (uap->clk != SVR4_HRT_CLK_STD) {
+ DPRINTF(("clk == %d\n", uap->clk));
+ return EINVAL;
+ }
+ if (uap->ti == NULL) {
+ DPRINTF(("ti NULL\n"));
+ return EINVAL;
+ }
+ microtime(&tv);
+ t.h_sec = tv.tv_sec;
+ t.h_rem = tv.tv_usec;
+ t.h_res = SVR4_HRT_USEC;
+ return copyout(&t, uap->ti, sizeof(t));
+ }
+
+ case SVR4_HRT_CNTL_START:
+ DPRINTF(("htrcntl(START)\n"));
+ return ENOSYS;
+
+ case SVR4_HRT_CNTL_GET:
+ DPRINTF(("htrcntl(GET)\n"));
+ return ENOSYS;
+ default:
+ DPRINTF(("Bad htrcntl command %d\n", uap->fun));
+ return ENOSYS;
+ }
+}
+
+
+int
+svr4_sys_hrtsys(td, uap)
+ struct thread *td;
+ struct svr4_sys_hrtsys_args *uap;
+{
+ int *retval = td->td_retval;
+
+ switch (uap->cmd) {
+ case SVR4_HRT_CNTL:
+ return svr4_hrtcntl(td, (struct svr4_hrtcntl_args *) uap,
+ retval);
+
+ case SVR4_HRT_ALRM:
+ DPRINTF(("hrtalarm\n"));
+ return ENOSYS;
+
+ case SVR4_HRT_SLP:
+ DPRINTF(("hrtsleep\n"));
+ return ENOSYS;
+
+ case SVR4_HRT_CAN:
+ DPRINTF(("hrtcancel\n"));
+ return ENOSYS;
+
+ default:
+ DPRINTF(("Bad hrtsys command %d\n", uap->cmd));
+ return EINVAL;
+ }
+}
+
+
+static int
+svr4_setinfo(pid, ru, st, s)
+ pid_t pid;
+ struct rusage *ru;
+ int st;
+ svr4_siginfo_t *s;
+{
+ svr4_siginfo_t i;
+ int sig;
+
+ memset(&i, 0, sizeof(i));
+
+ i.svr4_si_signo = SVR4_SIGCHLD;
+ i.svr4_si_errno = 0; /* XXX? */
+
+ i.svr4_si_pid = pid;
+ if (ru) {
+ i.svr4_si_stime = ru->ru_stime.tv_sec;
+ i.svr4_si_utime = ru->ru_utime.tv_sec;
+ }
+
+ if (WIFEXITED(st)) {
+ i.svr4_si_status = WEXITSTATUS(st);
+ i.svr4_si_code = SVR4_CLD_EXITED;
+ } else if (WIFSTOPPED(st)) {
+ sig = WSTOPSIG(st);
+ if (sig >= 0 && sig < NSIG)
+ i.svr4_si_status = SVR4_BSD2SVR4_SIG(sig);
+
+ if (i.svr4_si_status == SVR4_SIGCONT)
+ i.svr4_si_code = SVR4_CLD_CONTINUED;
+ else
+ i.svr4_si_code = SVR4_CLD_STOPPED;
+ } else {
+ sig = WTERMSIG(st);
+ if (sig >= 0 && sig < NSIG)
+ i.svr4_si_status = SVR4_BSD2SVR4_SIG(sig);
+
+ if (WCOREDUMP(st))
+ i.svr4_si_code = SVR4_CLD_DUMPED;
+ else
+ i.svr4_si_code = SVR4_CLD_KILLED;
+ }
+
+ DPRINTF(("siginfo [pid %ld signo %d code %d errno %d status %d]\n",
+ i.svr4_si_pid, i.svr4_si_signo, i.svr4_si_code, i.svr4_si_errno,
+ i.svr4_si_status));
+
+ return copyout(&i, s, sizeof(i));
+}
+
+
+int
+svr4_sys_waitsys(td, uap)
+ struct thread *td;
+ struct svr4_sys_waitsys_args *uap;
+{
+ struct rusage ru;
+ pid_t pid;
+ int nfound, status;
+ int error, *retval = td->td_retval;
+ struct proc *p, *q;
+
+ DPRINTF(("waitsys(%d, %d, %p, %x)\n",
+ uap->grp, uap->id,
+ uap->info, uap->options));
+
+ q = td->td_proc;
+ switch (uap->grp) {
+ case SVR4_P_PID:
+ pid = uap->id;
+ break;
+
+ case SVR4_P_PGID:
+ PROC_LOCK(q);
+ pid = -q->p_pgid;
+ PROC_UNLOCK(q);
+ break;
+
+ case SVR4_P_ALL:
+ pid = WAIT_ANY;
+ break;
+
+ default:
+ return EINVAL;
+ }
+
+ /* Hand off the easy cases to kern_wait(). */
+ if (!(uap->options & (SVR4_WNOWAIT)) &&
+ (uap->options & (SVR4_WEXITED | SVR4_WTRAPPED))) {
+ int options;
+
+ options = 0;
+ if (uap->options & SVR4_WSTOPPED)
+ options |= WUNTRACED;
+ if (uap->options & SVR4_WCONTINUED)
+ options |= WCONTINUED;
+ if (uap->options & SVR4_WNOHANG)
+ options |= WNOHANG;
+
+ error = kern_wait(td, pid, &status, options, &ru);
+ if (error)
+ return (error);
+ if (uap->options & SVR4_WNOHANG && *retval == 0)
+ error = svr4_setinfo(*retval, NULL, 0, uap->info);
+ else
+ error = svr4_setinfo(*retval, &ru, status, uap->info);
+ *retval = 0;
+ return (error);
+ }
+
+ /*
+ * Ok, handle the weird cases. Either WNOWAIT is set (meaning we
+ * just want to see if there is a process to harvest, we don't
+ * want to actually harvest it), or WEXIT and WTRAPPED are clear
+ * meaning we want to ignore zombies. Either way, we don't have
+ * to handle harvesting zombies here. We do have to duplicate the
+ * other portions of kern_wait() though, especially for WCONTINUED
+ * and WSTOPPED.
+ */
+loop:
+ nfound = 0;
+ sx_slock(&proctree_lock);
+ LIST_FOREACH(p, &q->p_children, p_sibling) {
+ PROC_LOCK(p);
+ if (pid != WAIT_ANY &&
+ p->p_pid != pid && p->p_pgid != -pid) {
+ PROC_UNLOCK(p);
+ DPRINTF(("pid %d pgid %d != %d\n", p->p_pid,
+ p->p_pgid, pid));
+ continue;
+ }
+ if (p_canwait(td, p)) {
+ PROC_UNLOCK(p);
+ continue;
+ }
+
+ nfound++;
+
+ PROC_SLOCK(p);
+ /*
+ * See if we have a zombie. If so, WNOWAIT should be set,
+ * as otherwise we should have called kern_wait() up above.
+ */
+ if ((p->p_state == PRS_ZOMBIE) &&
+ ((uap->options & (SVR4_WEXITED|SVR4_WTRAPPED)))) {
+ PROC_SUNLOCK(p);
+ KASSERT(uap->options & SVR4_WNOWAIT,
+ ("WNOWAIT is clear"));
+
+ /* Found a zombie, so cache info in local variables. */
+ pid = p->p_pid;
+ status = p->p_xstat;
+ ru = p->p_ru;
+ PROC_SLOCK(p);
+ calcru(p, &ru.ru_utime, &ru.ru_stime);
+ PROC_SUNLOCK(p);
+ PROC_UNLOCK(p);
+ sx_sunlock(&proctree_lock);
+
+ /* Copy the info out to userland. */
+ *retval = 0;
+ DPRINTF(("found %d\n", pid));
+ return (svr4_setinfo(pid, &ru, status, uap->info));
+ }
+
+ /*
+ * See if we have a stopped or continued process.
+ * XXX: This duplicates the same code in kern_wait().
+ */
+ if ((p->p_flag & P_STOPPED_SIG) &&
+ (p->p_suspcount == p->p_numthreads) &&
+ (p->p_flag & P_WAITED) == 0 &&
+ (p->p_flag & P_TRACED || uap->options & SVR4_WSTOPPED)) {
+ PROC_SUNLOCK(p);
+ if (((uap->options & SVR4_WNOWAIT)) == 0)
+ p->p_flag |= P_WAITED;
+ sx_sunlock(&proctree_lock);
+ pid = p->p_pid;
+ status = W_STOPCODE(p->p_xstat);
+ ru = p->p_ru;
+ PROC_SLOCK(p);
+ calcru(p, &ru.ru_utime, &ru.ru_stime);
+ PROC_SUNLOCK(p);
+ PROC_UNLOCK(p);
+
+ if (((uap->options & SVR4_WNOWAIT)) == 0) {
+ PROC_LOCK(q);
+ sigqueue_take(p->p_ksi);
+ PROC_UNLOCK(q);
+ }
+
+ *retval = 0;
+ DPRINTF(("jobcontrol %d\n", pid));
+ return (svr4_setinfo(pid, &ru, status, uap->info));
+ }
+ PROC_SUNLOCK(p);
+ if (uap->options & SVR4_WCONTINUED &&
+ (p->p_flag & P_CONTINUED)) {
+ sx_sunlock(&proctree_lock);
+ if (((uap->options & SVR4_WNOWAIT)) == 0)
+ p->p_flag &= ~P_CONTINUED;
+ pid = p->p_pid;
+ ru = p->p_ru;
+ status = SIGCONT;
+ PROC_SLOCK(p);
+ calcru(p, &ru.ru_utime, &ru.ru_stime);
+ PROC_SUNLOCK(p);
+ PROC_UNLOCK(p);
+
+ if (((uap->options & SVR4_WNOWAIT)) == 0) {
+ PROC_LOCK(q);
+ sigqueue_take(p->p_ksi);
+ PROC_UNLOCK(q);
+ }
+
+ *retval = 0;
+ DPRINTF(("jobcontrol %d\n", pid));
+ return (svr4_setinfo(pid, &ru, status, uap->info));
+ }
+ PROC_UNLOCK(p);
+ }
+
+ if (nfound == 0) {
+ sx_sunlock(&proctree_lock);
+ return (ECHILD);
+ }
+
+ if (uap->options & SVR4_WNOHANG) {
+ sx_sunlock(&proctree_lock);
+ *retval = 0;
+ return (svr4_setinfo(0, NULL, 0, uap->info));
+ }
+
+ PROC_LOCK(q);
+ sx_sunlock(&proctree_lock);
+ if (q->p_flag & P_STATCHILD) {
+ q->p_flag &= ~P_STATCHILD;
+ error = 0;
+ } else
+ error = msleep(q, &q->p_mtx, PWAIT | PCATCH, "svr4_wait", 0);
+ PROC_UNLOCK(q);
+ if (error)
+ return error;
+ goto loop;
+}
+
+
+static void
+bsd_statfs_to_svr4_statvfs(bfs, sfs)
+ const struct statfs *bfs;
+ struct svr4_statvfs *sfs;
+{
+ sfs->f_bsize = bfs->f_iosize; /* XXX */
+ sfs->f_frsize = bfs->f_bsize;
+ sfs->f_blocks = bfs->f_blocks;
+ sfs->f_bfree = bfs->f_bfree;
+ sfs->f_bavail = bfs->f_bavail;
+ sfs->f_files = bfs->f_files;
+ sfs->f_ffree = bfs->f_ffree;
+ sfs->f_favail = bfs->f_ffree;
+ sfs->f_fsid = bfs->f_fsid.val[0];
+ memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
+ sfs->f_flag = 0;
+ if (bfs->f_flags & MNT_RDONLY)
+ sfs->f_flag |= SVR4_ST_RDONLY;
+ if (bfs->f_flags & MNT_NOSUID)
+ sfs->f_flag |= SVR4_ST_NOSUID;
+ sfs->f_namemax = MAXNAMLEN;
+ memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
+ memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
+}
+
+
+static void
+bsd_statfs_to_svr4_statvfs64(bfs, sfs)
+ const struct statfs *bfs;
+ struct svr4_statvfs64 *sfs;
+{
+ sfs->f_bsize = bfs->f_iosize; /* XXX */
+ sfs->f_frsize = bfs->f_bsize;
+ sfs->f_blocks = bfs->f_blocks;
+ sfs->f_bfree = bfs->f_bfree;
+ sfs->f_bavail = bfs->f_bavail;
+ sfs->f_files = bfs->f_files;
+ sfs->f_ffree = bfs->f_ffree;
+ sfs->f_favail = bfs->f_ffree;
+ sfs->f_fsid = bfs->f_fsid.val[0];
+ memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
+ sfs->f_flag = 0;
+ if (bfs->f_flags & MNT_RDONLY)
+ sfs->f_flag |= SVR4_ST_RDONLY;
+ if (bfs->f_flags & MNT_NOSUID)
+ sfs->f_flag |= SVR4_ST_NOSUID;
+ sfs->f_namemax = MAXNAMLEN;
+ memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
+ memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
+}
+
+
+int
+svr4_sys_statvfs(td, uap)
+ struct thread *td;
+ struct svr4_sys_statvfs_args *uap;
+{
+ struct svr4_statvfs sfs;
+ struct statfs bfs;
+ char *path;
+ int error;
+
+ CHECKALTEXIST(td, uap->path, &path);
+
+ error = kern_statfs(td, path, UIO_SYSSPACE, &bfs);
+ free(path, M_TEMP);
+ if (error)
+ return (error);
+ bsd_statfs_to_svr4_statvfs(&bfs, &sfs);
+ return copyout(&sfs, uap->fs, sizeof(sfs));
+}
+
+
+int
+svr4_sys_fstatvfs(td, uap)
+ struct thread *td;
+ struct svr4_sys_fstatvfs_args *uap;
+{
+ struct svr4_statvfs sfs;
+ struct statfs bfs;
+ int error;
+
+ error = kern_fstatfs(td, uap->fd, &bfs);
+ if (error)
+ return (error);
+ bsd_statfs_to_svr4_statvfs(&bfs, &sfs);
+ return copyout(&sfs, uap->fs, sizeof(sfs));
+}
+
+
+int
+svr4_sys_statvfs64(td, uap)
+ struct thread *td;
+ struct svr4_sys_statvfs64_args *uap;
+{
+ struct svr4_statvfs64 sfs;
+ struct statfs bfs;
+ char *path;
+ int error;
+
+ CHECKALTEXIST(td, uap->path, &path);
+
+ error = kern_statfs(td, path, UIO_SYSSPACE, &bfs);
+ free(path, M_TEMP);
+ if (error)
+ return (error);
+ bsd_statfs_to_svr4_statvfs64(&bfs, &sfs);
+ return copyout(&sfs, uap->fs, sizeof(sfs));
+}
+
+
+int
+svr4_sys_fstatvfs64(td, uap)
+ struct thread *td;
+ struct svr4_sys_fstatvfs64_args *uap;
+{
+ struct svr4_statvfs64 sfs;
+ struct statfs bfs;
+ int error;
+
+ error = kern_fstatfs(td, uap->fd, &bfs);
+ if (error)
+ return (error);
+ bsd_statfs_to_svr4_statvfs64(&bfs, &sfs);
+ return copyout(&sfs, uap->fs, sizeof(sfs));
+}
+
+int
+svr4_sys_alarm(td, uap)
+ struct thread *td;
+ struct svr4_sys_alarm_args *uap;
+{
+ struct itimerval itv, oitv;
+ int error;
+
+ timevalclear(&itv.it_interval);
+ itv.it_value.tv_sec = uap->sec;
+ itv.it_value.tv_usec = 0;
+ error = kern_setitimer(td, ITIMER_REAL, &itv, &oitv);
+ if (error)
+ return (error);
+ if (oitv.it_value.tv_usec != 0)
+ oitv.it_value.tv_sec++;
+ td->td_retval[0] = oitv.it_value.tv_sec;
+ return (0);
+}
+
+int
+svr4_sys_gettimeofday(td, uap)
+ struct thread *td;
+ struct svr4_sys_gettimeofday_args *uap;
+{
+ if (uap->tp) {
+ struct timeval atv;
+
+ microtime(&atv);
+ return copyout(&atv, uap->tp, sizeof (atv));
+ }
+
+ return 0;
+}
+
+int
+svr4_sys_facl(td, uap)
+ struct thread *td;
+ struct svr4_sys_facl_args *uap;
+{
+ int *retval;
+
+ retval = td->td_retval;
+ *retval = 0;
+
+ switch (uap->cmd) {
+ case SVR4_SYS_SETACL:
+ /* We don't support acls on any filesystem */
+ return ENOSYS;
+
+ case SVR4_SYS_GETACL:
+ return copyout(retval, &uap->num,
+ sizeof(uap->num));
+
+ case SVR4_SYS_GETACLCNT:
+ return 0;
+
+ default:
+ return EINVAL;
+ }
+}
+
+
+int
+svr4_sys_acl(td, uap)
+ struct thread *td;
+ struct svr4_sys_acl_args *uap;
+{
+ /* XXX: for now the same */
+ return svr4_sys_facl(td, (struct svr4_sys_facl_args *)uap);
+}
+
+int
+svr4_sys_auditsys(td, uap)
+ struct thread *td;
+ struct svr4_sys_auditsys_args *uap;
+{
+ /*
+ * XXX: Big brother is *not* watching.
+ */
+ return 0;
+}
+
+int
+svr4_sys_memcntl(td, uap)
+ struct thread *td;
+ struct svr4_sys_memcntl_args *uap;
+{
+ switch (uap->cmd) {
+ case SVR4_MC_SYNC:
+ {
+ struct msync_args msa;
+
+ msa.addr = uap->addr;
+ msa.len = uap->len;
+ msa.flags = (int)uap->arg;
+
+ return sys_msync(td, &msa);
+ }
+ case SVR4_MC_ADVISE:
+ {
+ struct madvise_args maa;
+
+ maa.addr = uap->addr;
+ maa.len = uap->len;
+ maa.behav = (int)uap->arg;
+
+ return sys_madvise(td, &maa);
+ }
+ case SVR4_MC_LOCK:
+ case SVR4_MC_UNLOCK:
+ case SVR4_MC_LOCKAS:
+ case SVR4_MC_UNLOCKAS:
+ return EOPNOTSUPP;
+ default:
+ return ENOSYS;
+ }
+}
+
+
+int
+svr4_sys_nice(td, uap)
+ struct thread *td;
+ struct svr4_sys_nice_args *uap;
+{
+ struct setpriority_args ap;
+ int error;
+
+ ap.which = PRIO_PROCESS;
+ ap.who = 0;
+ ap.prio = uap->prio;
+
+ if ((error = sys_setpriority(td, &ap)) != 0)
+ return error;
+
+ /* the cast is stupid, but the structures are the same */
+ if ((error = sys_getpriority(td, (struct getpriority_args *)&ap)) != 0)
+ return error;
+
+ return 0;
+}
+
+int
+svr4_sys_resolvepath(td, uap)
+ struct thread *td;
+ struct svr4_sys_resolvepath_args *uap;
+{
+ struct nameidata nd;
+ int error, *retval = td->td_retval;
+ unsigned int ncopy;
+
+ NDINIT(&nd, LOOKUP, NOFOLLOW | SAVENAME, UIO_USERSPACE,
+ uap->path, td);
+
+ if ((error = namei(&nd)) != 0)
+ return (error);
+ NDFREE(&nd, NDF_NO_FREE_PNBUF);
+
+ ncopy = min(uap->bufsiz, strlen(nd.ni_cnd.cn_pnbuf) + 1);
+ if ((error = copyout(nd.ni_cnd.cn_pnbuf, uap->buf, ncopy)) != 0)
+ goto bad;
+
+ *retval = ncopy;
+bad:
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ return error;
+}
diff --git a/sys/compat/svr4/svr4_mman.h b/sys/compat/svr4/svr4_mman.h
new file mode 100644
index 0000000..e30e492
--- /dev/null
+++ b/sys/compat/svr4/svr4_mman.h
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1997 Todd Vierling
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_MMAN_H_
+#define _SVR4_MMAN_H_
+
+/*
+ * Commands and flags passed to memcntl().
+ * Most of them are the same as <sys/mman.h>, but we need the MC_
+ * memcntl command definitions.
+ */
+
+#define SVR4_MC_SYNC 1
+#define SVR4_MC_LOCK 2
+#define SVR4_MC_UNLOCK 3
+#define SVR4_MC_ADVISE 4
+#define SVR4_MC_LOCKAS 5
+#define SVR4_MC_UNLOCKAS 6
+
+#endif /* !_SVR4_MMAN_H */
diff --git a/sys/compat/svr4/svr4_proto.h b/sys/compat/svr4/svr4_proto.h
new file mode 100644
index 0000000..0478d3c
--- /dev/null
+++ b/sys/compat/svr4/svr4_proto.h
@@ -0,0 +1,596 @@
+/*
+ * System call prototypes.
+ *
+ * DO NOT EDIT-- this file is automatically generated.
+ * $FreeBSD$
+ * created from FreeBSD: head/sys/compat/svr4/syscalls.master 227691 2011-11-19 06:35:15Z ed
+ */
+
+#ifndef _SVR4_SYSPROTO_H_
+#define _SVR4_SYSPROTO_H_
+
+#include <sys/signal.h>
+#include <sys/acl.h>
+#include <sys/cpuset.h>
+#include <sys/_semaphore.h>
+#include <sys/ucontext.h>
+
+#include <bsm/audit_kevents.h>
+
+struct proc;
+
+struct thread;
+
+#define PAD_(t) (sizeof(register_t) <= sizeof(t) ? \
+ 0 : sizeof(register_t) - sizeof(t))
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define PADL_(t) 0
+#define PADR_(t) PAD_(t)
+#else
+#define PADL_(t) PAD_(t)
+#define PADR_(t) 0
+#endif
+
+struct svr4_sys_open_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+ char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)];
+};
+struct svr4_sys_wait_args {
+ char status_l_[PADL_(int *)]; int * status; char status_r_[PADR_(int *)];
+};
+struct svr4_sys_creat_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)];
+};
+struct svr4_sys_execv_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char argp_l_[PADL_(char **)]; char ** argp; char argp_r_[PADR_(char **)];
+};
+struct svr4_sys_time_args {
+ char t_l_[PADL_(time_t *)]; time_t * t; char t_r_[PADR_(time_t *)];
+};
+struct svr4_sys_mknod_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)];
+ char dev_l_[PADL_(int)]; int dev; char dev_r_[PADR_(int)];
+};
+struct svr4_sys_break_args {
+ char nsize_l_[PADL_(caddr_t)]; caddr_t nsize; char nsize_r_[PADR_(caddr_t)];
+};
+struct svr4_sys_stat_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char ub_l_[PADL_(struct svr4_stat *)]; struct svr4_stat * ub; char ub_r_[PADR_(struct svr4_stat *)];
+};
+struct svr4_sys_alarm_args {
+ char sec_l_[PADL_(unsigned)]; unsigned sec; char sec_r_[PADR_(unsigned)];
+};
+struct svr4_sys_fstat_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char sb_l_[PADL_(struct svr4_stat *)]; struct svr4_stat * sb; char sb_r_[PADR_(struct svr4_stat *)];
+};
+struct svr4_sys_pause_args {
+ register_t dummy;
+};
+struct svr4_sys_utime_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char ubuf_l_[PADL_(struct svr4_utimbuf *)]; struct svr4_utimbuf * ubuf; char ubuf_r_[PADR_(struct svr4_utimbuf *)];
+};
+struct svr4_sys_access_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char amode_l_[PADL_(int)]; int amode; char amode_r_[PADR_(int)];
+};
+struct svr4_sys_nice_args {
+ char prio_l_[PADL_(int)]; int prio; char prio_r_[PADR_(int)];
+};
+struct svr4_sys_kill_args {
+ char pid_l_[PADL_(int)]; int pid; char pid_r_[PADR_(int)];
+ char signum_l_[PADL_(int)]; int signum; char signum_r_[PADR_(int)];
+};
+struct svr4_sys_pgrpsys_args {
+ char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)];
+ char pid_l_[PADL_(int)]; int pid; char pid_r_[PADR_(int)];
+ char pgid_l_[PADL_(int)]; int pgid; char pgid_r_[PADR_(int)];
+};
+struct svr4_sys_times_args {
+ char tp_l_[PADL_(struct tms *)]; struct tms * tp; char tp_r_[PADR_(struct tms *)];
+};
+struct svr4_sys_signal_args {
+ char signum_l_[PADL_(int)]; int signum; char signum_r_[PADR_(int)];
+ char handler_l_[PADL_(svr4_sig_t)]; svr4_sig_t handler; char handler_r_[PADR_(svr4_sig_t)];
+};
+struct svr4_sys_msgsys_args {
+ char what_l_[PADL_(int)]; int what; char what_r_[PADR_(int)];
+ char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)];
+ char a3_l_[PADL_(int)]; int a3; char a3_r_[PADR_(int)];
+ char a4_l_[PADL_(int)]; int a4; char a4_r_[PADR_(int)];
+ char a5_l_[PADL_(int)]; int a5; char a5_r_[PADR_(int)];
+};
+struct svr4_sys_sysarch_args {
+ char op_l_[PADL_(int)]; int op; char op_r_[PADR_(int)];
+ char a1_l_[PADL_(void *)]; void * a1; char a1_r_[PADR_(void *)];
+};
+struct svr4_sys_shmsys_args {
+ char what_l_[PADL_(int)]; int what; char what_r_[PADR_(int)];
+ char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)];
+ char a3_l_[PADL_(int)]; int a3; char a3_r_[PADR_(int)];
+ char a4_l_[PADL_(int)]; int a4; char a4_r_[PADR_(int)];
+ char a5_l_[PADL_(int)]; int a5; char a5_r_[PADR_(int)];
+};
+struct svr4_sys_semsys_args {
+ char what_l_[PADL_(int)]; int what; char what_r_[PADR_(int)];
+ char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)];
+ char a3_l_[PADL_(int)]; int a3; char a3_r_[PADR_(int)];
+ char a4_l_[PADL_(int)]; int a4; char a4_r_[PADR_(int)];
+ char a5_l_[PADL_(int)]; int a5; char a5_r_[PADR_(int)];
+};
+struct svr4_sys_ioctl_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char com_l_[PADL_(u_long)]; u_long com; char com_r_[PADR_(u_long)];
+ char data_l_[PADL_(caddr_t)]; caddr_t data; char data_r_[PADR_(caddr_t)];
+};
+struct svr4_sys_utssys_args {
+ char a1_l_[PADL_(void *)]; void * a1; char a1_r_[PADR_(void *)];
+ char a2_l_[PADL_(void *)]; void * a2; char a2_r_[PADR_(void *)];
+ char sel_l_[PADL_(int)]; int sel; char sel_r_[PADR_(int)];
+ char a3_l_[PADL_(void *)]; void * a3; char a3_r_[PADR_(void *)];
+};
+struct svr4_sys_execve_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char argp_l_[PADL_(char **)]; char ** argp; char argp_r_[PADR_(char **)];
+ char envp_l_[PADL_(char **)]; char ** envp; char envp_r_[PADR_(char **)];
+};
+struct svr4_sys_fcntl_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)];
+ char arg_l_[PADL_(char *)]; char * arg; char arg_r_[PADR_(char *)];
+};
+struct svr4_sys_ulimit_args {
+ char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)];
+ char newlimit_l_[PADL_(long)]; long newlimit; char newlimit_r_[PADR_(long)];
+};
+struct svr4_sys_getdents_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)];
+ char nbytes_l_[PADL_(int)]; int nbytes; char nbytes_r_[PADR_(int)];
+};
+struct svr4_sys_getmsg_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char ctl_l_[PADL_(struct svr4_strbuf *)]; struct svr4_strbuf * ctl; char ctl_r_[PADR_(struct svr4_strbuf *)];
+ char dat_l_[PADL_(struct svr4_strbuf *)]; struct svr4_strbuf * dat; char dat_r_[PADR_(struct svr4_strbuf *)];
+ char flags_l_[PADL_(int *)]; int * flags; char flags_r_[PADR_(int *)];
+};
+struct svr4_sys_putmsg_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char ctl_l_[PADL_(struct svr4_strbuf *)]; struct svr4_strbuf * ctl; char ctl_r_[PADR_(struct svr4_strbuf *)];
+ char dat_l_[PADL_(struct svr4_strbuf *)]; struct svr4_strbuf * dat; char dat_r_[PADR_(struct svr4_strbuf *)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+};
+struct svr4_sys_poll_args {
+ char fds_l_[PADL_(struct pollfd *)]; struct pollfd * fds; char fds_r_[PADR_(struct pollfd *)];
+ char nfds_l_[PADL_(unsigned int)]; unsigned int nfds; char nfds_r_[PADR_(unsigned int)];
+ char timeout_l_[PADL_(int)]; int timeout; char timeout_r_[PADR_(int)];
+};
+struct svr4_sys_lstat_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char ub_l_[PADL_(struct svr4_stat *)]; struct svr4_stat * ub; char ub_r_[PADR_(struct svr4_stat *)];
+};
+struct svr4_sys_sigprocmask_args {
+ char how_l_[PADL_(int)]; int how; char how_r_[PADR_(int)];
+ char set_l_[PADL_(svr4_sigset_t *)]; svr4_sigset_t * set; char set_r_[PADR_(svr4_sigset_t *)];
+ char oset_l_[PADL_(svr4_sigset_t *)]; svr4_sigset_t * oset; char oset_r_[PADR_(svr4_sigset_t *)];
+};
+struct svr4_sys_sigsuspend_args {
+ char ss_l_[PADL_(svr4_sigset_t *)]; svr4_sigset_t * ss; char ss_r_[PADR_(svr4_sigset_t *)];
+};
+struct svr4_sys_sigaltstack_args {
+ char nss_l_[PADL_(struct svr4_sigaltstack *)]; struct svr4_sigaltstack * nss; char nss_r_[PADR_(struct svr4_sigaltstack *)];
+ char oss_l_[PADL_(struct svr4_sigaltstack *)]; struct svr4_sigaltstack * oss; char oss_r_[PADR_(struct svr4_sigaltstack *)];
+};
+struct svr4_sys_sigaction_args {
+ char signum_l_[PADL_(int)]; int signum; char signum_r_[PADR_(int)];
+ char nsa_l_[PADL_(struct svr4_sigaction *)]; struct svr4_sigaction * nsa; char nsa_r_[PADR_(struct svr4_sigaction *)];
+ char osa_l_[PADL_(struct svr4_sigaction *)]; struct svr4_sigaction * osa; char osa_r_[PADR_(struct svr4_sigaction *)];
+};
+struct svr4_sys_sigpending_args {
+ char what_l_[PADL_(int)]; int what; char what_r_[PADR_(int)];
+ char mask_l_[PADL_(svr4_sigset_t *)]; svr4_sigset_t * mask; char mask_r_[PADR_(svr4_sigset_t *)];
+};
+struct svr4_sys_context_args {
+ char func_l_[PADL_(int)]; int func; char func_r_[PADR_(int)];
+ char uc_l_[PADL_(struct svr4_ucontext *)]; struct svr4_ucontext * uc; char uc_r_[PADR_(struct svr4_ucontext *)];
+};
+struct svr4_sys_statvfs_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char fs_l_[PADL_(struct svr4_statvfs *)]; struct svr4_statvfs * fs; char fs_r_[PADR_(struct svr4_statvfs *)];
+};
+struct svr4_sys_fstatvfs_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char fs_l_[PADL_(struct svr4_statvfs *)]; struct svr4_statvfs * fs; char fs_r_[PADR_(struct svr4_statvfs *)];
+};
+struct svr4_sys_waitsys_args {
+ char grp_l_[PADL_(int)]; int grp; char grp_r_[PADR_(int)];
+ char id_l_[PADL_(int)]; int id; char id_r_[PADR_(int)];
+ char info_l_[PADL_(union svr4_siginfo *)]; union svr4_siginfo * info; char info_r_[PADR_(union svr4_siginfo *)];
+ char options_l_[PADL_(int)]; int options; char options_r_[PADR_(int)];
+};
+struct svr4_sys_hrtsys_args {
+ char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)];
+ char fun_l_[PADL_(int)]; int fun; char fun_r_[PADR_(int)];
+ char sub_l_[PADL_(int)]; int sub; char sub_r_[PADR_(int)];
+ char rv1_l_[PADL_(void *)]; void * rv1; char rv1_r_[PADR_(void *)];
+ char rv2_l_[PADL_(void *)]; void * rv2; char rv2_r_[PADR_(void *)];
+};
+struct svr4_sys_pathconf_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char name_l_[PADL_(int)]; int name; char name_r_[PADR_(int)];
+};
+struct svr4_sys_mmap_args {
+ char addr_l_[PADL_(caddr_t)]; caddr_t addr; char addr_r_[PADR_(caddr_t)];
+ char len_l_[PADL_(svr4_size_t)]; svr4_size_t len; char len_r_[PADR_(svr4_size_t)];
+ char prot_l_[PADL_(int)]; int prot; char prot_r_[PADR_(int)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char pos_l_[PADL_(svr4_off_t)]; svr4_off_t pos; char pos_r_[PADR_(svr4_off_t)];
+};
+struct svr4_sys_fpathconf_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char name_l_[PADL_(int)]; int name; char name_r_[PADR_(int)];
+};
+struct svr4_sys_xstat_args {
+ char two_l_[PADL_(int)]; int two; char two_r_[PADR_(int)];
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char ub_l_[PADL_(struct svr4_xstat *)]; struct svr4_xstat * ub; char ub_r_[PADR_(struct svr4_xstat *)];
+};
+struct svr4_sys_lxstat_args {
+ char two_l_[PADL_(int)]; int two; char two_r_[PADR_(int)];
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char ub_l_[PADL_(struct svr4_xstat *)]; struct svr4_xstat * ub; char ub_r_[PADR_(struct svr4_xstat *)];
+};
+struct svr4_sys_fxstat_args {
+ char two_l_[PADL_(int)]; int two; char two_r_[PADR_(int)];
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char sb_l_[PADL_(struct svr4_xstat *)]; struct svr4_xstat * sb; char sb_r_[PADR_(struct svr4_xstat *)];
+};
+struct svr4_sys_xmknod_args {
+ char two_l_[PADL_(int)]; int two; char two_r_[PADR_(int)];
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char mode_l_[PADL_(svr4_mode_t)]; svr4_mode_t mode; char mode_r_[PADR_(svr4_mode_t)];
+ char dev_l_[PADL_(svr4_dev_t)]; svr4_dev_t dev; char dev_r_[PADR_(svr4_dev_t)];
+};
+struct svr4_sys_setrlimit_args {
+ char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)];
+ char rlp_l_[PADL_(const struct svr4_rlimit *)]; const struct svr4_rlimit * rlp; char rlp_r_[PADR_(const struct svr4_rlimit *)];
+};
+struct svr4_sys_getrlimit_args {
+ char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)];
+ char rlp_l_[PADL_(struct svr4_rlimit *)]; struct svr4_rlimit * rlp; char rlp_r_[PADR_(struct svr4_rlimit *)];
+};
+struct svr4_sys_memcntl_args {
+ char addr_l_[PADL_(void *)]; void * addr; char addr_r_[PADR_(void *)];
+ char len_l_[PADL_(svr4_size_t)]; svr4_size_t len; char len_r_[PADR_(svr4_size_t)];
+ char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)];
+ char arg_l_[PADL_(void *)]; void * arg; char arg_r_[PADR_(void *)];
+ char attr_l_[PADL_(int)]; int attr; char attr_r_[PADR_(int)];
+ char mask_l_[PADL_(int)]; int mask; char mask_r_[PADR_(int)];
+};
+struct svr4_sys_uname_args {
+ char name_l_[PADL_(struct svr4_utsname *)]; struct svr4_utsname * name; char name_r_[PADR_(struct svr4_utsname *)];
+ char dummy_l_[PADL_(int)]; int dummy; char dummy_r_[PADR_(int)];
+};
+struct svr4_sys_sysconfig_args {
+ char name_l_[PADL_(int)]; int name; char name_r_[PADR_(int)];
+};
+struct svr4_sys_systeminfo_args {
+ char what_l_[PADL_(int)]; int what; char what_r_[PADR_(int)];
+ char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)];
+ char len_l_[PADL_(long)]; long len; char len_r_[PADR_(long)];
+};
+struct svr4_sys_fchroot_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+};
+struct svr4_sys_utimes_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char tptr_l_[PADL_(struct timeval *)]; struct timeval * tptr; char tptr_r_[PADR_(struct timeval *)];
+};
+struct svr4_sys_vhangup_args {
+ register_t dummy;
+};
+struct svr4_sys_gettimeofday_args {
+ char tp_l_[PADL_(struct timeval *)]; struct timeval * tp; char tp_r_[PADR_(struct timeval *)];
+};
+struct svr4_sys_llseek_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char offset1_l_[PADL_(long)]; long offset1; char offset1_r_[PADR_(long)];
+ char offset2_l_[PADL_(long)]; long offset2; char offset2_r_[PADR_(long)];
+ char whence_l_[PADL_(int)]; int whence; char whence_r_[PADR_(int)];
+};
+struct svr4_sys_acl_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)];
+ char num_l_[PADL_(int)]; int num; char num_r_[PADR_(int)];
+ char buf_l_[PADL_(struct svr4_aclent *)]; struct svr4_aclent * buf; char buf_r_[PADR_(struct svr4_aclent *)];
+};
+struct svr4_sys_auditsys_args {
+ char code_l_[PADL_(int)]; int code; char code_r_[PADR_(int)];
+ char a1_l_[PADL_(int)]; int a1; char a1_r_[PADR_(int)];
+ char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)];
+ char a3_l_[PADL_(int)]; int a3; char a3_r_[PADR_(int)];
+ char a4_l_[PADL_(int)]; int a4; char a4_r_[PADR_(int)];
+ char a5_l_[PADL_(int)]; int a5; char a5_r_[PADR_(int)];
+};
+struct svr4_sys_facl_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char cmd_l_[PADL_(int)]; int cmd; char cmd_r_[PADR_(int)];
+ char num_l_[PADL_(int)]; int num; char num_r_[PADR_(int)];
+ char buf_l_[PADL_(struct svr4_aclent *)]; struct svr4_aclent * buf; char buf_r_[PADR_(struct svr4_aclent *)];
+};
+struct svr4_sys_resolvepath_args {
+ char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)];
+ char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)];
+ char bufsiz_l_[PADL_(size_t)]; size_t bufsiz; char bufsiz_r_[PADR_(size_t)];
+};
+struct svr4_sys_getdents64_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char dp_l_[PADL_(struct svr4_dirent64 *)]; struct svr4_dirent64 * dp; char dp_r_[PADR_(struct svr4_dirent64 *)];
+ char nbytes_l_[PADL_(int)]; int nbytes; char nbytes_r_[PADR_(int)];
+};
+struct svr4_sys_mmap64_args {
+ char addr_l_[PADL_(void *)]; void * addr; char addr_r_[PADR_(void *)];
+ char len_l_[PADL_(svr4_size_t)]; svr4_size_t len; char len_r_[PADR_(svr4_size_t)];
+ char prot_l_[PADL_(int)]; int prot; char prot_r_[PADR_(int)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char pos_l_[PADL_(svr4_off64_t)]; svr4_off64_t pos; char pos_r_[PADR_(svr4_off64_t)];
+};
+struct svr4_sys_stat64_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char sb_l_[PADL_(struct svr4_stat64 *)]; struct svr4_stat64 * sb; char sb_r_[PADR_(struct svr4_stat64 *)];
+};
+struct svr4_sys_lstat64_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char sb_l_[PADL_(struct svr4_stat64 *)]; struct svr4_stat64 * sb; char sb_r_[PADR_(struct svr4_stat64 *)];
+};
+struct svr4_sys_fstat64_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char sb_l_[PADL_(struct svr4_stat64 *)]; struct svr4_stat64 * sb; char sb_r_[PADR_(struct svr4_stat64 *)];
+};
+struct svr4_sys_statvfs64_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char fs_l_[PADL_(struct svr4_statvfs64 *)]; struct svr4_statvfs64 * fs; char fs_r_[PADR_(struct svr4_statvfs64 *)];
+};
+struct svr4_sys_fstatvfs64_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char fs_l_[PADL_(struct svr4_statvfs64 *)]; struct svr4_statvfs64 * fs; char fs_r_[PADR_(struct svr4_statvfs64 *)];
+};
+struct svr4_sys_setrlimit64_args {
+ char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)];
+ char rlp_l_[PADL_(const struct svr4_rlimit64 *)]; const struct svr4_rlimit64 * rlp; char rlp_r_[PADR_(const struct svr4_rlimit64 *)];
+};
+struct svr4_sys_getrlimit64_args {
+ char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)];
+ char rlp_l_[PADL_(struct svr4_rlimit64 *)]; struct svr4_rlimit64 * rlp; char rlp_r_[PADR_(struct svr4_rlimit64 *)];
+};
+struct svr4_sys_creat64_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)];
+};
+struct svr4_sys_open64_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+ char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)];
+};
+struct svr4_sys_socket_args {
+ char domain_l_[PADL_(int)]; int domain; char domain_r_[PADR_(int)];
+ char type_l_[PADL_(int)]; int type; char type_r_[PADR_(int)];
+ char protocol_l_[PADL_(int)]; int protocol; char protocol_r_[PADR_(int)];
+};
+struct svr4_sys_recv_args {
+ char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
+ char buf_l_[PADL_(caddr_t)]; caddr_t buf; char buf_r_[PADR_(caddr_t)];
+ char len_l_[PADL_(int)]; int len; char len_r_[PADR_(int)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+};
+struct svr4_sys_send_args {
+ char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
+ char buf_l_[PADL_(caddr_t)]; caddr_t buf; char buf_r_[PADR_(caddr_t)];
+ char len_l_[PADL_(int)]; int len; char len_r_[PADR_(int)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+};
+struct svr4_sys_sendto_args {
+ char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
+ char buf_l_[PADL_(void *)]; void * buf; char buf_r_[PADR_(void *)];
+ char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+ char to_l_[PADL_(struct sockaddr *)]; struct sockaddr * to; char to_r_[PADR_(struct sockaddr *)];
+ char tolen_l_[PADL_(int)]; int tolen; char tolen_r_[PADR_(int)];
+};
+int svr4_sys_open(struct thread *, struct svr4_sys_open_args *);
+int svr4_sys_wait(struct thread *, struct svr4_sys_wait_args *);
+int svr4_sys_creat(struct thread *, struct svr4_sys_creat_args *);
+int svr4_sys_execv(struct thread *, struct svr4_sys_execv_args *);
+int svr4_sys_time(struct thread *, struct svr4_sys_time_args *);
+int svr4_sys_mknod(struct thread *, struct svr4_sys_mknod_args *);
+int svr4_sys_break(struct thread *, struct svr4_sys_break_args *);
+int svr4_sys_stat(struct thread *, struct svr4_sys_stat_args *);
+int svr4_sys_alarm(struct thread *, struct svr4_sys_alarm_args *);
+int svr4_sys_fstat(struct thread *, struct svr4_sys_fstat_args *);
+int svr4_sys_pause(struct thread *, struct svr4_sys_pause_args *);
+int svr4_sys_utime(struct thread *, struct svr4_sys_utime_args *);
+int svr4_sys_access(struct thread *, struct svr4_sys_access_args *);
+int svr4_sys_nice(struct thread *, struct svr4_sys_nice_args *);
+int svr4_sys_kill(struct thread *, struct svr4_sys_kill_args *);
+int svr4_sys_pgrpsys(struct thread *, struct svr4_sys_pgrpsys_args *);
+int svr4_sys_times(struct thread *, struct svr4_sys_times_args *);
+int svr4_sys_signal(struct thread *, struct svr4_sys_signal_args *);
+int svr4_sys_msgsys(struct thread *, struct svr4_sys_msgsys_args *);
+int svr4_sys_sysarch(struct thread *, struct svr4_sys_sysarch_args *);
+int svr4_sys_shmsys(struct thread *, struct svr4_sys_shmsys_args *);
+int svr4_sys_semsys(struct thread *, struct svr4_sys_semsys_args *);
+int svr4_sys_ioctl(struct thread *, struct svr4_sys_ioctl_args *);
+int svr4_sys_utssys(struct thread *, struct svr4_sys_utssys_args *);
+int svr4_sys_execve(struct thread *, struct svr4_sys_execve_args *);
+int svr4_sys_fcntl(struct thread *, struct svr4_sys_fcntl_args *);
+int svr4_sys_ulimit(struct thread *, struct svr4_sys_ulimit_args *);
+int svr4_sys_getdents(struct thread *, struct svr4_sys_getdents_args *);
+int svr4_sys_getmsg(struct thread *, struct svr4_sys_getmsg_args *);
+int svr4_sys_putmsg(struct thread *, struct svr4_sys_putmsg_args *);
+int svr4_sys_poll(struct thread *, struct svr4_sys_poll_args *);
+int svr4_sys_lstat(struct thread *, struct svr4_sys_lstat_args *);
+int svr4_sys_sigprocmask(struct thread *, struct svr4_sys_sigprocmask_args *);
+int svr4_sys_sigsuspend(struct thread *, struct svr4_sys_sigsuspend_args *);
+int svr4_sys_sigaltstack(struct thread *, struct svr4_sys_sigaltstack_args *);
+int svr4_sys_sigaction(struct thread *, struct svr4_sys_sigaction_args *);
+int svr4_sys_sigpending(struct thread *, struct svr4_sys_sigpending_args *);
+int svr4_sys_context(struct thread *, struct svr4_sys_context_args *);
+int svr4_sys_statvfs(struct thread *, struct svr4_sys_statvfs_args *);
+int svr4_sys_fstatvfs(struct thread *, struct svr4_sys_fstatvfs_args *);
+int svr4_sys_waitsys(struct thread *, struct svr4_sys_waitsys_args *);
+int svr4_sys_hrtsys(struct thread *, struct svr4_sys_hrtsys_args *);
+int svr4_sys_pathconf(struct thread *, struct svr4_sys_pathconf_args *);
+int svr4_sys_mmap(struct thread *, struct svr4_sys_mmap_args *);
+int svr4_sys_fpathconf(struct thread *, struct svr4_sys_fpathconf_args *);
+int svr4_sys_xstat(struct thread *, struct svr4_sys_xstat_args *);
+int svr4_sys_lxstat(struct thread *, struct svr4_sys_lxstat_args *);
+int svr4_sys_fxstat(struct thread *, struct svr4_sys_fxstat_args *);
+int svr4_sys_xmknod(struct thread *, struct svr4_sys_xmknod_args *);
+int svr4_sys_setrlimit(struct thread *, struct svr4_sys_setrlimit_args *);
+int svr4_sys_getrlimit(struct thread *, struct svr4_sys_getrlimit_args *);
+int svr4_sys_memcntl(struct thread *, struct svr4_sys_memcntl_args *);
+int svr4_sys_uname(struct thread *, struct svr4_sys_uname_args *);
+int svr4_sys_sysconfig(struct thread *, struct svr4_sys_sysconfig_args *);
+int svr4_sys_systeminfo(struct thread *, struct svr4_sys_systeminfo_args *);
+int svr4_sys_fchroot(struct thread *, struct svr4_sys_fchroot_args *);
+int svr4_sys_utimes(struct thread *, struct svr4_sys_utimes_args *);
+int svr4_sys_vhangup(struct thread *, struct svr4_sys_vhangup_args *);
+int svr4_sys_gettimeofday(struct thread *, struct svr4_sys_gettimeofday_args *);
+int svr4_sys_llseek(struct thread *, struct svr4_sys_llseek_args *);
+int svr4_sys_acl(struct thread *, struct svr4_sys_acl_args *);
+int svr4_sys_auditsys(struct thread *, struct svr4_sys_auditsys_args *);
+int svr4_sys_facl(struct thread *, struct svr4_sys_facl_args *);
+int svr4_sys_resolvepath(struct thread *, struct svr4_sys_resolvepath_args *);
+int svr4_sys_getdents64(struct thread *, struct svr4_sys_getdents64_args *);
+int svr4_sys_mmap64(struct thread *, struct svr4_sys_mmap64_args *);
+int svr4_sys_stat64(struct thread *, struct svr4_sys_stat64_args *);
+int svr4_sys_lstat64(struct thread *, struct svr4_sys_lstat64_args *);
+int svr4_sys_fstat64(struct thread *, struct svr4_sys_fstat64_args *);
+int svr4_sys_statvfs64(struct thread *, struct svr4_sys_statvfs64_args *);
+int svr4_sys_fstatvfs64(struct thread *, struct svr4_sys_fstatvfs64_args *);
+int svr4_sys_setrlimit64(struct thread *, struct svr4_sys_setrlimit64_args *);
+int svr4_sys_getrlimit64(struct thread *, struct svr4_sys_getrlimit64_args *);
+int svr4_sys_creat64(struct thread *, struct svr4_sys_creat64_args *);
+int svr4_sys_open64(struct thread *, struct svr4_sys_open64_args *);
+int svr4_sys_socket(struct thread *, struct svr4_sys_socket_args *);
+int svr4_sys_recv(struct thread *, struct svr4_sys_recv_args *);
+int svr4_sys_send(struct thread *, struct svr4_sys_send_args *);
+int svr4_sys_sendto(struct thread *, struct svr4_sys_sendto_args *);
+
+#ifdef COMPAT_43
+
+
+#endif /* COMPAT_43 */
+
+
+#ifdef COMPAT_FREEBSD4
+
+
+#endif /* COMPAT_FREEBSD4 */
+
+
+#ifdef COMPAT_FREEBSD6
+
+
+#endif /* COMPAT_FREEBSD6 */
+
+
+#ifdef COMPAT_FREEBSD7
+
+
+#endif /* COMPAT_FREEBSD7 */
+
+#define SVR4_SYS_AUE_svr4_sys_open AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_wait AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_creat AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_execv AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_time AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_mknod AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_break AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_stat AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_alarm AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_fstat AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_pause AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_utime AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_access AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_nice AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_kill AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_pgrpsys AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_times AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_signal AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_msgsys AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_sysarch AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_shmsys AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_semsys AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_ioctl AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_utssys AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_execve AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_fcntl AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_ulimit AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_getdents AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_getmsg AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_putmsg AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_poll AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_lstat AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_sigprocmask AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_sigsuspend AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_sigaltstack AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_sigaction AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_sigpending AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_context AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_statvfs AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_fstatvfs AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_waitsys AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_hrtsys AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_pathconf AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_mmap AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_fpathconf AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_xstat AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_lxstat AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_fxstat AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_xmknod AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_setrlimit AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_getrlimit AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_memcntl AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_uname AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_sysconfig AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_systeminfo AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_fchroot AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_utimes AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_vhangup AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_gettimeofday AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_llseek AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_acl AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_auditsys AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_facl AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_resolvepath AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_getdents64 AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_mmap64 AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_stat64 AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_lstat64 AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_fstat64 AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_statvfs64 AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_fstatvfs64 AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_setrlimit64 AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_getrlimit64 AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_creat64 AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_open64 AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_socket AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_recv AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_send AUE_NULL
+#define SVR4_SYS_AUE_svr4_sys_sendto AUE_NULL
+
+#undef PAD_
+#undef PADL_
+#undef PADR_
+
+#endif /* !_SVR4_SYSPROTO_H_ */
diff --git a/sys/compat/svr4/svr4_resource.c b/sys/compat/svr4/svr4_resource.c
new file mode 100644
index 0000000..7dd692a
--- /dev/null
+++ b/sys/compat/svr4/svr4_resource.c
@@ -0,0 +1,321 @@
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*-
+ * Portions of this software have been derived from software contributed
+ * to the FreeBSD Project by Mark Newton.
+ *
+ * Copyright (c) 1999 Mark Newton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Derived from: $NetBSD: svr4_resource.c,v 1.3 1998/12/13 18:00:52 christos Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/file.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
+#include <sys/syscallsubr.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_resource.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_proto.h>
+#include <compat/svr4/svr4_util.h>
+
+static __inline int svr4_to_native_rl(int);
+
+static __inline int
+svr4_to_native_rl(rl)
+ int rl;
+{
+ switch (rl) {
+ case SVR4_RLIMIT_CPU:
+ return RLIMIT_CPU;
+ case SVR4_RLIMIT_FSIZE:
+ return RLIMIT_FSIZE;
+ case SVR4_RLIMIT_DATA:
+ return RLIMIT_DATA;
+ case SVR4_RLIMIT_STACK:
+ return RLIMIT_STACK;
+ case SVR4_RLIMIT_CORE:
+ return RLIMIT_CORE;
+ case SVR4_RLIMIT_NOFILE:
+ return RLIMIT_NOFILE;
+ case SVR4_RLIMIT_VMEM:
+ return RLIMIT_VMEM;
+ default:
+ return -1;
+ }
+}
+
+/*
+ * Check if the resource limit fits within the BSD range and it is not
+ * one of the magic SVR4 limit values
+ */
+#define OKLIMIT(l) (((int32_t)(l)) >= 0 && ((int32_t)(l)) < 0x7fffffff && \
+ ((svr4_rlim_t)(l)) != SVR4_RLIM_INFINITY && \
+ ((svr4_rlim_t)(l)) != SVR4_RLIM_SAVED_CUR && \
+ ((svr4_rlim_t)(l)) != SVR4_RLIM_SAVED_MAX)
+
+#define OKLIMIT64(l) (((rlim_t)(l)) >= 0 && ((rlim_t)(l)) < RLIM_INFINITY && \
+ ((svr4_rlim64_t)(l)) != SVR4_RLIM64_INFINITY && \
+ ((svr4_rlim64_t)(l)) != SVR4_RLIM64_SAVED_CUR && \
+ ((svr4_rlim64_t)(l)) != SVR4_RLIM64_SAVED_MAX)
+
+int
+svr4_sys_getrlimit(td, uap)
+ struct thread *td;
+ struct svr4_sys_getrlimit_args *uap;
+{
+ int rl = svr4_to_native_rl(uap->which);
+ struct rlimit blim;
+ struct svr4_rlimit slim;
+
+ if (rl == -1)
+ return EINVAL;
+
+ PROC_LOCK(td->td_proc);
+ lim_rlimit(td->td_proc, rl, &blim);
+ PROC_UNLOCK(td->td_proc);
+
+ /*
+ * Our infinity, is their maxfiles.
+ */
+ if (rl == RLIMIT_NOFILE && blim.rlim_max == RLIM_INFINITY)
+ blim.rlim_max = maxfiles;
+
+ /*
+ * If the limit can be be represented, it is returned.
+ * Otherwise, if rlim_cur == rlim_max, return RLIM_SAVED_MAX
+ * else return RLIM_SAVED_CUR
+ */
+ if (blim.rlim_max == RLIM_INFINITY)
+ slim.rlim_max = SVR4_RLIM_INFINITY;
+ else if (OKLIMIT(blim.rlim_max))
+ slim.rlim_max = (svr4_rlim_t) blim.rlim_max;
+ else
+ slim.rlim_max = SVR4_RLIM_SAVED_MAX;
+
+ if (blim.rlim_cur == RLIM_INFINITY)
+ slim.rlim_cur = SVR4_RLIM_INFINITY;
+ else if (OKLIMIT(blim.rlim_cur))
+ slim.rlim_cur = (svr4_rlim_t) blim.rlim_cur;
+ else if (blim.rlim_max == blim.rlim_cur)
+ slim.rlim_cur = SVR4_RLIM_SAVED_MAX;
+ else
+ slim.rlim_cur = SVR4_RLIM_SAVED_CUR;
+
+ return copyout(&slim, uap->rlp, sizeof(*uap->rlp));
+}
+
+
+int
+svr4_sys_setrlimit(td, uap)
+ struct thread *td;
+ struct svr4_sys_setrlimit_args *uap;
+{
+ int rl = svr4_to_native_rl(uap->which);
+ struct rlimit blim, curlim;
+ struct svr4_rlimit slim;
+ int error;
+
+ if (rl == -1)
+ return EINVAL;
+
+ if ((error = copyin(uap->rlp, &slim, sizeof(slim))) != 0)
+ return error;
+
+ PROC_LOCK(td->td_proc);
+ lim_rlimit(td->td_proc, rl, &curlim);
+ PROC_UNLOCK(td->td_proc);
+
+ /*
+ * if the limit is SVR4_RLIM_INFINITY, then we set it to our
+ * unlimited.
+ * We should also: If it is SVR4_RLIM_SAVED_MAX, we should set the
+ * new limit to the corresponding saved hard limit, and if
+ * it is equal to SVR4_RLIM_SAVED_CUR, we should set it to the
+ * corresponding saved soft limit.
+ *
+ */
+ if (slim.rlim_max == SVR4_RLIM_INFINITY)
+ blim.rlim_max = RLIM_INFINITY;
+ else if (OKLIMIT(slim.rlim_max))
+ blim.rlim_max = (rlim_t) slim.rlim_max;
+ else if (slim.rlim_max == SVR4_RLIM_SAVED_MAX)
+ blim.rlim_max = curlim.rlim_max;
+ else if (slim.rlim_max == SVR4_RLIM_SAVED_CUR)
+ blim.rlim_max = curlim.rlim_cur;
+
+ if (slim.rlim_cur == SVR4_RLIM_INFINITY)
+ blim.rlim_cur = RLIM_INFINITY;
+ else if (OKLIMIT(slim.rlim_cur))
+ blim.rlim_cur = (rlim_t) slim.rlim_cur;
+ else if (slim.rlim_cur == SVR4_RLIM_SAVED_MAX)
+ blim.rlim_cur = curlim.rlim_max;
+ else if (slim.rlim_cur == SVR4_RLIM_SAVED_CUR)
+ blim.rlim_cur = curlim.rlim_cur;
+
+ return (kern_setrlimit(td, rl, &blim));
+}
+
+
+int
+svr4_sys_getrlimit64(td, uap)
+ struct thread *td;
+ struct svr4_sys_getrlimit64_args *uap;
+{
+ int rl = svr4_to_native_rl(uap->which);
+ struct rlimit blim;
+ struct svr4_rlimit64 slim;
+
+ if (rl == -1)
+ return EINVAL;
+
+ PROC_LOCK(td->td_proc);
+ lim_rlimit(td->td_proc, rl, &blim);
+ PROC_UNLOCK(td->td_proc);
+
+ /*
+ * Our infinity, is their maxfiles.
+ */
+ if (rl == RLIMIT_NOFILE && blim.rlim_max == RLIM_INFINITY)
+ blim.rlim_max = maxfiles;
+
+ /*
+ * If the limit can be be represented, it is returned.
+ * Otherwise, if rlim_cur == rlim_max, return SVR4_RLIM_SAVED_MAX
+ * else return SVR4_RLIM_SAVED_CUR
+ */
+ if (blim.rlim_max == RLIM_INFINITY)
+ slim.rlim_max = SVR4_RLIM64_INFINITY;
+ else if (OKLIMIT64(blim.rlim_max))
+ slim.rlim_max = (svr4_rlim64_t) blim.rlim_max;
+ else
+ slim.rlim_max = SVR4_RLIM64_SAVED_MAX;
+
+ if (blim.rlim_cur == RLIM_INFINITY)
+ slim.rlim_cur = SVR4_RLIM64_INFINITY;
+ else if (OKLIMIT64(blim.rlim_cur))
+ slim.rlim_cur = (svr4_rlim64_t) blim.rlim_cur;
+ else if (blim.rlim_max == blim.rlim_cur)
+ slim.rlim_cur = SVR4_RLIM64_SAVED_MAX;
+ else
+ slim.rlim_cur = SVR4_RLIM64_SAVED_CUR;
+
+ return copyout(&slim, uap->rlp, sizeof(*uap->rlp));
+}
+
+
+int
+svr4_sys_setrlimit64(td, uap)
+ struct thread *td;
+ struct svr4_sys_setrlimit64_args *uap;
+{
+ int rl = svr4_to_native_rl(uap->which);
+ struct rlimit blim, curlim;
+ struct svr4_rlimit64 slim;
+ int error;
+
+ if (rl == -1)
+ return EINVAL;
+
+ if ((error = copyin(uap->rlp, &slim, sizeof(slim))) != 0)
+ return error;
+
+ PROC_LOCK(td->td_proc);
+ lim_rlimit(td->td_proc, rl, &curlim);
+ PROC_UNLOCK(td->td_proc);
+
+ /*
+ * if the limit is SVR4_RLIM64_INFINITY, then we set it to our
+ * unlimited.
+ * We should also: If it is SVR4_RLIM64_SAVED_MAX, we should set the
+ * new limit to the corresponding saved hard limit, and if
+ * it is equal to SVR4_RLIM64_SAVED_CUR, we should set it to the
+ * corresponding saved soft limit.
+ *
+ */
+ if (slim.rlim_max == SVR4_RLIM64_INFINITY)
+ blim.rlim_max = RLIM_INFINITY;
+ else if (OKLIMIT64(slim.rlim_max))
+ blim.rlim_max = (rlim_t) slim.rlim_max;
+ else if (slim.rlim_max == SVR4_RLIM64_SAVED_MAX)
+ blim.rlim_max = curlim.rlim_max;
+ else if (slim.rlim_max == SVR4_RLIM64_SAVED_CUR)
+ blim.rlim_max = curlim.rlim_cur;
+
+ if (slim.rlim_cur == SVR4_RLIM64_INFINITY)
+ blim.rlim_cur = RLIM_INFINITY;
+ else if (OKLIMIT64(slim.rlim_cur))
+ blim.rlim_cur = (rlim_t) slim.rlim_cur;
+ else if (slim.rlim_cur == SVR4_RLIM64_SAVED_MAX)
+ blim.rlim_cur = curlim.rlim_max;
+ else if (slim.rlim_cur == SVR4_RLIM64_SAVED_CUR)
+ blim.rlim_cur = curlim.rlim_cur;
+
+ return (kern_setrlimit(td, rl, &blim));
+}
diff --git a/sys/compat/svr4/svr4_resource.h b/sys/compat/svr4/svr4_resource.h
new file mode 100644
index 0000000..4b93e9a
--- /dev/null
+++ b/sys/compat/svr4/svr4_resource.h
@@ -0,0 +1,109 @@
+/* Derived from:
+ * $NetBSD: svr4_resource.h,v 1.1 1998/11/28 21:53:02 christos Exp $ */
+
+/*-
+ * Original copyright:
+ *
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*-
+ * Portions of this code derived from software contributed to the
+ * FreeBSD Project by Mark Newton.
+ *
+ * Copyright (c) 1999 Mark Newton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SVR4_RESOURCE_H_
+#define _SVR4_RESOURCE_H_
+
+#define SVR4_RLIMIT_CPU 0
+#define SVR4_RLIMIT_FSIZE 1
+#define SVR4_RLIMIT_DATA 2
+#define SVR4_RLIMIT_STACK 3
+#define SVR4_RLIMIT_CORE 4
+#define SVR4_RLIMIT_NOFILE 5
+#define SVR4_RLIMIT_VMEM 6
+#define SVR4_RLIMIT_AS SVR4_RLIMIT_VMEM
+#define SVR4_RLIM_NLIMITS 7
+
+typedef u_int32_t svr4_rlim_t;
+
+#define SVR4_RLIM_SAVED_CUR 0x7ffffffd
+#define SVR4_RLIM_SAVED_MAX 0x7ffffffe
+#define SVR4_RLIM_INFINITY 0x7fffffff
+
+struct svr4_rlimit {
+ svr4_rlim_t rlim_cur;
+ svr4_rlim_t rlim_max;
+};
+
+typedef u_int64_t svr4_rlim64_t;
+
+#define SVR4_RLIM64_SAVED_CUR ((svr4_rlim64_t) -1)
+#define SVR4_RLIM64_SAVED_MAX ((svr4_rlim64_t) -2)
+#define SVR4_RLIM64_INFINITY ((svr4_rlim64_t) -3)
+
+struct svr4_rlimit64 {
+ svr4_rlim64_t rlim_cur;
+ svr4_rlim64_t rlim_max;
+};
+
+#endif /* !_SVR4_RESOURCE_H_ */
diff --git a/sys/compat/svr4/svr4_siginfo.h b/sys/compat/svr4/svr4_siginfo.h
new file mode 100644
index 0000000..35e653b
--- /dev/null
+++ b/sys/compat/svr4/svr4_siginfo.h
@@ -0,0 +1,111 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_SIGINFO_H_
+#define _SVR4_SIGINFO_H_
+
+#define SVR4_ILL_ILLOPC 1
+#define SVR4_ILL_ILLOPN 2
+#define SVR4_ILL_ILLADR 3
+#define SVR4_ILL_ILLTRP 4
+#define SVR4_ILL_PRVOPC 5
+#define SVR4_ILL_PRVREG 6
+#define SVR4_ILL_COPROC 7
+#define SVR4_ILL_BADSTK 8
+
+#define SVR4_FPE_INTDIV 1
+#define SVR4_FPE_INTOVF 2
+#define SVR4_FPE_FLTDIV 3
+#define SVR4_FPE_FLTOVF 4
+#define SVR4_FPE_FLTUND 5
+#define SVR4_FPE_FLTRES 6
+#define SVR4_FPE_FLTINV 7
+#define SVR4_FPE_FLTSUB 8
+
+#define SVR4_SEGV_MAPERR 1
+#define SVR4_SEGV_ACCERR 2
+
+#define SVR4_BUS_ADRALN 1
+#define SVR4_BUS_ADRERR 2
+#define SVR4_BUS_OBJERR 3
+
+#define SVR4_TRAP_BRKPT 1
+#define SVR4_TRAP_TRACE 2
+
+#define SVR4_POLL_IN 1
+#define SVR4_POLL_OUT 2
+#define SVR4_POLL_MSG 3
+#define SVR4_POLL_ERR 4
+#define SVR4_POLL_PRI 5
+
+#define SVR4_CLD_EXITED 1
+#define SVR4_CLD_KILLED 2
+#define SVR4_CLD_DUMPED 3
+#define SVR4_CLD_TRAPPED 4
+#define SVR4_CLD_STOPPED 5
+#define SVR4_CLD_CONTINUED 6
+
+#define SVR4_EMT_TAGOVF 1
+
+typedef union svr4_siginfo {
+ char si_pad[128]; /* Total size; for future expansion */
+ struct {
+ int _signo;
+ int _code;
+ int _errno;
+ union {
+ struct {
+ svr4_pid_t _pid;
+ svr4_clock_t _utime;
+ int _status;
+ svr4_clock_t _stime;
+ } _child;
+
+ struct {
+ caddr_t _addr;
+ int _trap;
+ } _fault;
+ } _reason;
+ } _info;
+} svr4_siginfo_t;
+
+#define svr4_si_signo _info._signo
+#define svr4_si_code _info._code
+#define svr4_si_errno _info._errno
+
+#define svr4_si_pid _info._reason._child._pid
+#define svr4_si_stime _info._reason._child._stime
+#define svr4_si_status _info._reason._child._status
+#define svr4_si_utime _info._reason._child._utime
+
+#define svr4_si_addr _info._reason._fault._addr
+#define svr4_si_trap _info._reason._fault._trap
+
+#endif /* !_SVR4_SIGINFO_H_ */
diff --git a/sys/compat/svr4/svr4_signal.c b/sys/compat/svr4/svr4_signal.c
new file mode 100644
index 0000000..3791c05
--- /dev/null
+++ b/sys/compat/svr4/svr4_signal.c
@@ -0,0 +1,577 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/filedesc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/signal.h>
+#include <sys/signalvar.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysproto.h>
+
+#include <machine/cpu.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_proto.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_ucontext.h>
+
+#define svr4_sigmask(n) (1 << (((n) - 1) & 31))
+#define svr4_sigword(n) (((n) - 1) >> 5)
+#define svr4_sigemptyset(s) memset((s), 0, sizeof(*(s)))
+#define svr4_sigismember(s, n) ((s)->bits[svr4_sigword(n)] & svr4_sigmask(n))
+#define svr4_sigaddset(s, n) ((s)->bits[svr4_sigword(n)] |= svr4_sigmask(n))
+
+void svr4_to_bsd_sigaction(const struct svr4_sigaction *, struct sigaction *);
+void bsd_to_svr4_sigaction(const struct sigaction *, struct svr4_sigaction *);
+void svr4_sigfillset(svr4_sigset_t *);
+
+int bsd_to_svr4_sig[SVR4_NSIG] = {
+ 0,
+ SVR4_SIGHUP,
+ SVR4_SIGINT,
+ SVR4_SIGQUIT,
+ SVR4_SIGILL,
+ SVR4_SIGTRAP,
+ SVR4_SIGABRT,
+ SVR4_SIGEMT,
+ SVR4_SIGFPE,
+ SVR4_SIGKILL,
+ SVR4_SIGBUS,
+ SVR4_SIGSEGV,
+ SVR4_SIGSYS,
+ SVR4_SIGPIPE,
+ SVR4_SIGALRM,
+ SVR4_SIGTERM,
+ SVR4_SIGURG,
+ SVR4_SIGSTOP,
+ SVR4_SIGTSTP,
+ SVR4_SIGCONT,
+ SVR4_SIGCHLD,
+ SVR4_SIGTTIN,
+ SVR4_SIGTTOU,
+ SVR4_SIGIO,
+ SVR4_SIGXCPU,
+ SVR4_SIGXFSZ,
+ SVR4_SIGVTALRM,
+ SVR4_SIGPROF,
+ SVR4_SIGWINCH,
+ 0, /* SIGINFO */
+ SVR4_SIGUSR1,
+ SVR4_SIGUSR2,
+};
+
+int svr4_to_bsd_sig[SVR4_NSIG] = {
+ 0,
+ SIGHUP,
+ SIGINT,
+ SIGQUIT,
+ SIGILL,
+ SIGTRAP,
+ SIGABRT,
+ SIGEMT,
+ SIGFPE,
+ SIGKILL,
+ SIGBUS,
+ SIGSEGV,
+ SIGSYS,
+ SIGPIPE,
+ SIGALRM,
+ SIGTERM,
+ SIGUSR1,
+ SIGUSR2,
+ SIGCHLD,
+ 0, /* XXX NetBSD uses SIGPWR here, but we don't seem to have one */
+ SIGWINCH,
+ SIGURG,
+ SIGIO,
+ SIGSTOP,
+ SIGTSTP,
+ SIGCONT,
+ SIGTTIN,
+ SIGTTOU,
+ SIGVTALRM,
+ SIGPROF,
+ SIGXCPU,
+ SIGXFSZ,
+};
+
+void
+svr4_sigfillset(s)
+ svr4_sigset_t *s;
+{
+ int i;
+
+ svr4_sigemptyset(s);
+ for (i = 1; i < SVR4_NSIG; i++)
+ if (svr4_to_bsd_sig[i] != 0)
+ svr4_sigaddset(s, i);
+}
+
+void
+svr4_to_bsd_sigset(sss, bss)
+ const svr4_sigset_t *sss;
+ sigset_t *bss;
+{
+ int i, newsig;
+
+ SIGEMPTYSET(*bss);
+ for (i = 1; i < SVR4_NSIG; i++)
+ if (svr4_sigismember(sss, i)) {
+ newsig = svr4_to_bsd_sig[i];
+ if (newsig)
+ SIGADDSET(*bss, newsig);
+ }
+}
+
+void
+bsd_to_svr4_sigset(bss, sss)
+ const sigset_t *bss;
+ svr4_sigset_t *sss;
+{
+ int i, newsig;
+
+ svr4_sigemptyset(sss);
+ for (i = 1; i < SVR4_NSIG; i++) {
+ if (SIGISMEMBER(*bss, i)) {
+ newsig = bsd_to_svr4_sig[i];
+ if (newsig)
+ svr4_sigaddset(sss, newsig);
+ }
+ }
+}
+
+/*
+ * XXX: Only a subset of the flags is currently implemented.
+ */
+void
+svr4_to_bsd_sigaction(ssa, bsa)
+ const struct svr4_sigaction *ssa;
+ struct sigaction *bsa;
+{
+
+ bsa->sa_handler = (sig_t) ssa->ssa_handler;
+ svr4_to_bsd_sigset(&ssa->ssa_mask, &bsa->sa_mask);
+ bsa->sa_flags = 0;
+ if ((ssa->ssa_flags & SVR4_SA_ONSTACK) != 0)
+ bsa->sa_flags |= SA_ONSTACK;
+ if ((ssa->ssa_flags & SVR4_SA_RESETHAND) != 0)
+ bsa->sa_flags |= SA_RESETHAND;
+ if ((ssa->ssa_flags & SVR4_SA_RESTART) != 0)
+ bsa->sa_flags |= SA_RESTART;
+ if ((ssa->ssa_flags & SVR4_SA_SIGINFO) != 0)
+ DPRINTF(("svr4_to_bsd_sigaction: SA_SIGINFO ignored\n"));
+ if ((ssa->ssa_flags & SVR4_SA_NOCLDSTOP) != 0)
+ bsa->sa_flags |= SA_NOCLDSTOP;
+ if ((ssa->ssa_flags & SVR4_SA_NODEFER) != 0)
+ bsa->sa_flags |= SA_NODEFER;
+ if ((ssa->ssa_flags & SVR4_SA_NOCLDWAIT) != 0)
+ bsa->sa_flags |= SA_NOCLDWAIT;
+ if ((ssa->ssa_flags & ~SVR4_SA_ALLBITS) != 0)
+ DPRINTF(("svr4_to_bsd_sigaction: extra bits ignored\n"));
+}
+
+void
+bsd_to_svr4_sigaction(bsa, ssa)
+ const struct sigaction *bsa;
+ struct svr4_sigaction *ssa;
+{
+
+ ssa->ssa_handler = (svr4_sig_t) bsa->sa_handler;
+ bsd_to_svr4_sigset(&bsa->sa_mask, &ssa->ssa_mask);
+ ssa->ssa_flags = 0;
+ if ((bsa->sa_flags & SA_ONSTACK) != 0)
+ ssa->ssa_flags |= SVR4_SA_ONSTACK;
+ if ((bsa->sa_flags & SA_RESETHAND) != 0)
+ ssa->ssa_flags |= SVR4_SA_RESETHAND;
+ if ((bsa->sa_flags & SA_RESTART) != 0)
+ ssa->ssa_flags |= SVR4_SA_RESTART;
+ if ((bsa->sa_flags & SA_NODEFER) != 0)
+ ssa->ssa_flags |= SVR4_SA_NODEFER;
+ if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
+ ssa->ssa_flags |= SVR4_SA_NOCLDSTOP;
+}
+
+void
+svr4_to_bsd_sigaltstack(sss, bss)
+ const struct svr4_sigaltstack *sss;
+ struct sigaltstack *bss;
+{
+
+ bss->ss_sp = sss->ss_sp;
+ bss->ss_size = sss->ss_size;
+ bss->ss_flags = 0;
+ if ((sss->ss_flags & SVR4_SS_DISABLE) != 0)
+ bss->ss_flags |= SS_DISABLE;
+ if ((sss->ss_flags & SVR4_SS_ONSTACK) != 0)
+ bss->ss_flags |= SS_ONSTACK;
+ if ((sss->ss_flags & ~SVR4_SS_ALLBITS) != 0)
+ /*XXX*/ uprintf("svr4_to_bsd_sigaltstack: extra bits ignored\n");
+}
+
+void
+bsd_to_svr4_sigaltstack(bss, sss)
+ const struct sigaltstack *bss;
+ struct svr4_sigaltstack *sss;
+{
+
+ sss->ss_sp = bss->ss_sp;
+ sss->ss_size = bss->ss_size;
+ sss->ss_flags = 0;
+ if ((bss->ss_flags & SS_DISABLE) != 0)
+ sss->ss_flags |= SVR4_SS_DISABLE;
+ if ((bss->ss_flags & SS_ONSTACK) != 0)
+ sss->ss_flags |= SVR4_SS_ONSTACK;
+}
+
+int
+svr4_sys_sigaction(td, uap)
+ struct thread *td;
+ struct svr4_sys_sigaction_args *uap;
+{
+ struct svr4_sigaction isa;
+ struct sigaction nbsa, obsa;
+ struct sigaction *nbsap;
+ int error;
+
+ if (uap->signum < 0 || uap->signum >= SVR4_NSIG)
+ return (EINVAL);
+
+ DPRINTF(("@@@ svr4_sys_sigaction(%d, %d, %d)\n", td->td_proc->p_pid,
+ uap->signum,
+ SVR4_SVR42BSD_SIG(uap->signum)));
+
+ if (uap->nsa != NULL) {
+ if ((error = copyin(uap->nsa, &isa, sizeof(isa))) != 0)
+ return (error);
+ svr4_to_bsd_sigaction(&isa, &nbsa);
+ nbsap = &nbsa;
+ } else
+ nbsap = NULL;
+#if defined(DEBUG_SVR4)
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ DPRINTF(("\tssa_mask[%d] = %lx\n", i,
+ isa.ssa_mask.bits[i]));
+ DPRINTF(("\tssa_handler = %p\n", isa.ssa_handler));
+ }
+#endif
+ error = kern_sigaction(td, SVR4_SVR42BSD_SIG(uap->signum), nbsap, &obsa,
+ 0);
+ if (error == 0 && uap->osa != NULL) {
+ bsd_to_svr4_sigaction(&obsa, &isa);
+ error = copyout(&isa, uap->osa, sizeof(isa));
+ }
+ return (error);
+}
+
+int
+svr4_sys_sigaltstack(td, uap)
+ struct thread *td;
+ struct svr4_sys_sigaltstack_args *uap;
+{
+ struct svr4_sigaltstack sss;
+ struct sigaltstack nbss, obss, *nbssp;
+ int error;
+
+ if (uap->nss != NULL) {
+ if ((error = copyin(uap->nss, &sss, sizeof(sss))) != 0)
+ return (error);
+ svr4_to_bsd_sigaltstack(&sss, &nbss);
+ nbssp = &nbss;
+ } else
+ nbssp = NULL;
+ error = kern_sigaltstack(td, nbssp, &obss);
+ if (error == 0 && uap->oss != NULL) {
+ bsd_to_svr4_sigaltstack(&obss, &sss);
+ error = copyout(&sss, uap->oss, sizeof(sss));
+ }
+ return (error);
+}
+
+/*
+ * Stolen from the ibcs2 one
+ */
+int
+svr4_sys_signal(td, uap)
+ struct thread *td;
+ struct svr4_sys_signal_args *uap;
+{
+ struct proc *p;
+ int signum;
+ int error;
+
+ p = td->td_proc;
+ DPRINTF(("@@@ svr4_sys_signal(%d)\n", p->p_pid));
+
+ signum = SVR4_SIGNO(uap->signum);
+ if (signum < 0 || signum >= SVR4_NSIG) {
+ if (SVR4_SIGCALL(uap->signum) == SVR4_SIGNAL_MASK ||
+ SVR4_SIGCALL(uap->signum) == SVR4_SIGDEFER_MASK)
+ td->td_retval[0] = (int)SVR4_SIG_ERR;
+ return (EINVAL);
+ }
+ signum = SVR4_SVR42BSD_SIG(signum);
+
+ switch (SVR4_SIGCALL(uap->signum)) {
+ case SVR4_SIGDEFER_MASK:
+ if (uap->handler == SVR4_SIG_HOLD)
+ goto sighold;
+ /* FALLTHROUGH */
+
+ case SVR4_SIGNAL_MASK:
+ {
+ struct sigaction nbsa, obsa;
+
+ nbsa.sa_handler = (sig_t) uap->handler;
+ SIGEMPTYSET(nbsa.sa_mask);
+ nbsa.sa_flags = 0;
+ if (signum != SIGALRM)
+ nbsa.sa_flags = SA_RESTART;
+ error = kern_sigaction(td, signum, &nbsa, &obsa, 0);
+ if (error != 0) {
+ DPRINTF(("signal: sigaction failed: %d\n",
+ error));
+ td->td_retval[0] = (int)SVR4_SIG_ERR;
+ return (error);
+ }
+ td->td_retval[0] = (int)obsa.sa_handler;
+ return (0);
+ }
+
+ case SVR4_SIGHOLD_MASK:
+sighold:
+ {
+ sigset_t set;
+
+ SIGEMPTYSET(set);
+ SIGADDSET(set, signum);
+ return (kern_sigprocmask(td, SIG_BLOCK, &set, NULL, 0));
+ }
+
+ case SVR4_SIGRELSE_MASK:
+ {
+ sigset_t set;
+
+ SIGEMPTYSET(set);
+ SIGADDSET(set, signum);
+ return (kern_sigprocmask(td, SIG_UNBLOCK, &set, NULL,
+ 0));
+ }
+
+ case SVR4_SIGIGNORE_MASK:
+ {
+ struct sigaction sa;
+
+ sa.sa_handler = SIG_IGN;
+ SIGEMPTYSET(sa.sa_mask);
+ sa.sa_flags = 0;
+ error = kern_sigaction(td, signum, &sa, NULL, 0);
+ if (error != 0)
+ DPRINTF(("sigignore: sigaction failed\n"));
+ return (error);
+ }
+
+ case SVR4_SIGPAUSE_MASK:
+ {
+ sigset_t mask;
+
+ PROC_LOCK(p);
+ mask = td->td_sigmask;
+ PROC_UNLOCK(p);
+ SIGDELSET(mask, signum);
+ return kern_sigsuspend(td, mask);
+ }
+
+ default:
+ return (ENOSYS);
+ }
+}
+
+
+int
+svr4_sys_sigprocmask(td, uap)
+ struct thread *td;
+ struct svr4_sys_sigprocmask_args *uap;
+{
+ svr4_sigset_t sss;
+ sigset_t oss, nss;
+ sigset_t *nssp;
+ int error;
+
+ if (uap->set != NULL) {
+ if ((error = copyin(uap->set, &sss, sizeof(sss))) != 0)
+ return error;
+ svr4_to_bsd_sigset(&sss, &nss);
+ nssp = &nss;
+ } else
+ nssp = NULL;
+
+ /* SVR/4 sigprocmask flag values are the same as the FreeBSD values. */
+ error = kern_sigprocmask(td, uap->how, nssp, &oss, 0);
+ if (error == 0 && uap->oset != NULL) {
+ bsd_to_svr4_sigset(&oss, &sss);
+ error = copyout(&sss, uap->oset, sizeof(sss));
+ }
+ return (error);
+}
+
+int
+svr4_sys_sigpending(td, uap)
+ struct thread *td;
+ struct svr4_sys_sigpending_args *uap;
+{
+ struct proc *p;
+ sigset_t bss;
+ svr4_sigset_t sss;
+
+ p = td->td_proc;
+ DPRINTF(("@@@ svr4_sys_sigpending(%d)\n", p->p_pid));
+ switch (uap->what) {
+ case 1: /* sigpending */
+ if (uap->mask == NULL)
+ return 0;
+ PROC_LOCK(p);
+ bss = p->p_siglist;
+ SIGSETOR(bss, td->td_siglist);
+ SIGSETAND(bss, td->td_sigmask);
+ PROC_UNLOCK(p);
+ bsd_to_svr4_sigset(&bss, &sss);
+ break;
+
+ case 2: /* sigfillset */
+ svr4_sigfillset(&sss);
+#if defined(DEBUG_SVR4)
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ DPRINTF(("new sigset[%d] = %lx\n", i, (long)sss.bits[i]));
+ }
+#endif
+ break;
+
+ default:
+ return EINVAL;
+ }
+
+ return copyout(&sss, uap->mask, sizeof(sss));
+}
+
+int
+svr4_sys_sigsuspend(td, uap)
+ struct thread *td;
+ struct svr4_sys_sigsuspend_args *uap;
+{
+ svr4_sigset_t sss;
+ sigset_t bss;
+ int error;
+
+ if ((error = copyin(uap->ss, &sss, sizeof(sss))) != 0)
+ return error;
+
+ svr4_to_bsd_sigset(&sss, &bss);
+ return kern_sigsuspend(td, bss);
+}
+
+
+int
+svr4_sys_kill(td, uap)
+ struct thread *td;
+ struct svr4_sys_kill_args *uap;
+{
+ struct kill_args ka;
+
+ if (uap->signum < 0 || uap->signum >= SVR4_NSIG)
+ return (EINVAL);
+ ka.pid = uap->pid;
+ ka.signum = SVR4_SVR42BSD_SIG(uap->signum);
+ return sys_kill(td, &ka);
+}
+
+
+int
+svr4_sys_context(td, uap)
+ struct thread *td;
+ struct svr4_sys_context_args *uap;
+{
+ struct svr4_ucontext uc;
+ int error, onstack;
+
+ switch (uap->func) {
+ case 0:
+ DPRINTF(("getcontext(%p)\n", uap->uc));
+ PROC_LOCK(td->td_proc);
+ onstack = sigonstack(cpu_getstack(td));
+ PROC_UNLOCK(td->td_proc);
+ svr4_getcontext(td, &uc, &td->td_sigmask, onstack);
+ return copyout(&uc, uap->uc, sizeof(uc));
+
+ case 1:
+ DPRINTF(("setcontext(%p)\n", uap->uc));
+ if ((error = copyin(uap->uc, &uc, sizeof(uc))) != 0)
+ return error;
+ DPRINTF(("uc_flags = %lx\n", uc.uc_flags));
+#if defined(DEBUG_SVR4)
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ DPRINTF(("uc_sigmask[%d] = %lx\n", i,
+ uc.uc_sigmask.bits[i]));
+ }
+#endif
+ return svr4_setcontext(td, &uc);
+
+ default:
+ DPRINTF(("context(%d, %p)\n", uap->func,
+ uap->uc));
+ return ENOSYS;
+ }
+ return 0;
+}
+
+int
+svr4_sys_pause(td, uap)
+ struct thread *td;
+ struct svr4_sys_pause_args *uap;
+{
+ sigset_t mask;
+
+ PROC_LOCK(td->td_proc);
+ mask = td->td_sigmask;
+ PROC_UNLOCK(td->td_proc);
+ return kern_sigsuspend(td, mask);
+}
diff --git a/sys/compat/svr4/svr4_signal.h b/sys/compat/svr4/svr4_signal.h
new file mode 100644
index 0000000..218236d
--- /dev/null
+++ b/sys/compat/svr4/svr4_signal.h
@@ -0,0 +1,144 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_SIGNAL_H_
+#define _SVR4_SIGNAL_H_
+
+#include <i386/svr4/svr4_machdep.h>
+#include <compat/svr4/svr4_siginfo.h>
+
+#define SVR4_SIGHUP 1
+#define SVR4_SIGINT 2
+#define SVR4_SIGQUIT 3
+#define SVR4_SIGILL 4
+#define SVR4_SIGTRAP 5
+#define SVR4_SIGIOT 6
+#define SVR4_SIGABRT 6
+#define SVR4_SIGEMT 7
+#define SVR4_SIGFPE 8
+#define SVR4_SIGKILL 9
+#define SVR4_SIGBUS 10
+#define SVR4_SIGSEGV 11
+#define SVR4_SIGSYS 12
+#define SVR4_SIGPIPE 13
+#define SVR4_SIGALRM 14
+#define SVR4_SIGTERM 15
+#define SVR4_SIGUSR1 16
+#define SVR4_SIGUSR2 17
+#define SVR4_SIGCLD 18
+#define SVR4_SIGCHLD 18
+#define SVR4_SIGPWR 19
+#define SVR4_SIGWINCH 20
+#define SVR4_SIGURG 21
+#define SVR4_SIGPOLL 22
+#define SVR4_SIGIO 22
+#define SVR4_SIGSTOP 23
+#define SVR4_SIGTSTP 24
+#define SVR4_SIGCONT 25
+#define SVR4_SIGTTIN 26
+#define SVR4_SIGTTOU 27
+#define SVR4_SIGVTALRM 28
+#define SVR4_SIGPROF 29
+#define SVR4_SIGXCPU 30
+#define SVR4_SIGXFSZ 31
+#define SVR4_NSIG 32
+
+#define SVR4_SIGNO_MASK 0x00FF
+#define SVR4_SIGNAL_MASK 0x0000
+#define SVR4_SIGDEFER_MASK 0x0100
+#define SVR4_SIGHOLD_MASK 0x0200
+#define SVR4_SIGRELSE_MASK 0x0400
+#define SVR4_SIGIGNORE_MASK 0x0800
+#define SVR4_SIGPAUSE_MASK 0x1000
+
+typedef void (*svr4_sig_t)(int, svr4_siginfo_t *, void *);
+#define SVR4_SIG_DFL (svr4_sig_t) 0
+#define SVR4_SIG_ERR (svr4_sig_t) -1
+#define SVR4_SIG_IGN (svr4_sig_t) 1
+#define SVR4_SIG_HOLD (svr4_sig_t) 2
+
+#define SVR4_SIGNO(a) ((a) & SVR4_SIGNO_MASK)
+#define SVR4_SIGCALL(a) ((a) & ~SVR4_SIGNO_MASK)
+
+#define SVR4_SIG_BLOCK 1
+#define SVR4_SIG_UNBLOCK 2
+#define SVR4_SIG_SETMASK 3
+
+extern int bsd_to_svr4_sig[SVR4_NSIG];
+extern int svr4_to_bsd_sig[SVR4_NSIG];
+
+#define SVR4_BSD2SVR4_SIG(sig) \
+ (((sig) < SVR4_NSIG) ? bsd_to_svr4_sig[sig] : sig)
+#define SVR4_SVR42BSD_SIG(sig) \
+ (((sig) < SVR4_NSIG) ? svr4_to_bsd_sig[sig] : sig)
+
+typedef struct {
+ u_long bits[4];
+} svr4_sigset_t;
+
+struct svr4_sigaction {
+ int ssa_flags;
+ svr4_sig_t ssa_handler;
+ svr4_sigset_t ssa_mask;
+ int ssa_reserved[2];
+};
+
+struct svr4_sigaltstack {
+ char *ss_sp;
+ int ss_size;
+ int ss_flags;
+};
+
+/* sa_flags */
+#define SVR4_SA_ONSTACK 0x00000001
+#define SVR4_SA_RESETHAND 0x00000002
+#define SVR4_SA_RESTART 0x00000004
+#define SVR4_SA_SIGINFO 0x00000008
+#define SVR4_SA_NODEFER 0x00000010
+#define SVR4_SA_NOCLDWAIT 0x00010000 /* No zombies */
+#define SVR4_SA_NOCLDSTOP 0x00020000 /* No jcl */
+#define SVR4_SA_ALLBITS 0x0003001f
+
+/* ss_flags */
+#define SVR4_SS_ONSTACK 0x00000001
+#define SVR4_SS_DISABLE 0x00000002
+#define SVR4_SS_ALLBITS 0x00000003
+
+#define SVR4_MINSIGSTKSZ 8192
+
+struct ksiginfo;
+
+void bsd_to_svr4_sigaltstack(const struct sigaltstack *, struct svr4_sigaltstack *);
+void bsd_to_svr4_sigset(const sigset_t *, svr4_sigset_t *);
+void svr4_to_bsd_sigaltstack(const struct svr4_sigaltstack *, struct sigaltstack *);
+void svr4_to_bsd_sigset(const svr4_sigset_t *, sigset_t *);
+void svr4_sendsig(sig_t, struct ksiginfo *, sigset_t *);
+
+#endif /* !_SVR4_SIGNAL_H_ */
diff --git a/sys/compat/svr4/svr4_socket.c b/sys/compat/svr4/svr4_socket.c
new file mode 100644
index 0000000..038267c
--- /dev/null
+++ b/sys/compat/svr4/svr4_socket.c
@@ -0,0 +1,242 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1996 Christos Zoulas.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christos Zoulas.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * In SVR4 unix domain sockets are referenced sometimes
+ * (in putmsg(2) for example) as a [device, inode] pair instead of a pathname.
+ * Since there is no iname() routine in the kernel, and we need access to
+ * a mapping from inode to pathname, we keep our own table. This is a simple
+ * linked list that contains the pathname, the [device, inode] pair, the
+ * file corresponding to that socket and the process. When the
+ * socket gets closed we remove the item from the list. The list gets loaded
+ * every time a stat(2) call finds a socket.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/queue.h>
+#include <sys/eventhandler.h>
+#include <sys/file.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysproto.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_socket.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_sockmod.h>
+#include <compat/svr4/svr4_proto.h>
+
+struct svr4_sockcache_entry {
+ struct proc *p; /* Process for the socket */
+ void *cookie; /* Internal cookie used for matching */
+ struct sockaddr_un sock;/* Pathname for the socket */
+ dev_t dev; /* Device where the socket lives on */
+ ino_t ino; /* Inode where the socket lives on */
+ TAILQ_ENTRY(svr4_sockcache_entry) entries;
+};
+
+static TAILQ_HEAD(, svr4_sockcache_entry) svr4_head;
+static struct mtx svr4_sockcache_lock;
+static eventhandler_tag svr4_sockcache_exit_tag, svr4_sockcache_exec_tag;
+
+static void svr4_purge_sockcache(void *arg, struct proc *p);
+
+int
+svr4_find_socket(td, fp, dev, ino, saun)
+ struct thread *td;
+ struct file *fp;
+ dev_t dev;
+ ino_t ino;
+ struct sockaddr_un *saun;
+{
+ struct svr4_sockcache_entry *e;
+ void *cookie = ((struct socket *)fp->f_data)->so_emuldata;
+
+ DPRINTF(("svr4_find_socket: [%p,%d,%d]: ", td, dev, ino));
+ mtx_lock(&svr4_sockcache_lock);
+ TAILQ_FOREACH(e, &svr4_head, entries)
+ if (e->p == td->td_proc && e->dev == dev && e->ino == ino) {
+#ifdef DIAGNOSTIC
+ if (e->cookie != NULL && e->cookie != cookie)
+ panic("svr4 socket cookie mismatch");
+#endif
+ e->cookie = cookie;
+ DPRINTF(("%s\n", e->sock.sun_path));
+ *saun = e->sock;
+ mtx_unlock(&svr4_sockcache_lock);
+ return (0);
+ }
+
+ mtx_unlock(&svr4_sockcache_lock);
+ DPRINTF(("not found\n"));
+ return (ENOENT);
+}
+
+int
+svr4_add_socket(td, path, st)
+ struct thread *td;
+ const char *path;
+ struct stat *st;
+{
+ struct svr4_sockcache_entry *e;
+ size_t len;
+ int error;
+
+ e = malloc(sizeof(*e), M_TEMP, M_WAITOK);
+ e->cookie = NULL;
+ e->dev = st->st_dev;
+ e->ino = st->st_ino;
+ e->p = td->td_proc;
+
+ if ((error = copyinstr(path, e->sock.sun_path,
+ sizeof(e->sock.sun_path), &len)) != 0) {
+ DPRINTF(("svr4_add_socket: copyinstr failed %d\n", error));
+ free(e, M_TEMP);
+ return error;
+ }
+
+ e->sock.sun_family = AF_LOCAL;
+ e->sock.sun_len = len;
+
+ mtx_lock(&svr4_sockcache_lock);
+ TAILQ_INSERT_HEAD(&svr4_head, e, entries);
+ mtx_unlock(&svr4_sockcache_lock);
+ DPRINTF(("svr4_add_socket: %s [%p,%d,%d]\n", e->sock.sun_path,
+ td->td_proc, e->dev, e->ino));
+ return 0;
+}
+
+void
+svr4_delete_socket(p, fp)
+ struct proc *p;
+ struct file *fp;
+{
+ struct svr4_sockcache_entry *e;
+ void *cookie = ((struct socket *)fp->f_data)->so_emuldata;
+
+ mtx_lock(&svr4_sockcache_lock);
+ TAILQ_FOREACH(e, &svr4_head, entries)
+ if (e->p == p && e->cookie == cookie) {
+ TAILQ_REMOVE(&svr4_head, e, entries);
+ mtx_unlock(&svr4_sockcache_lock);
+ DPRINTF(("svr4_delete_socket: %s [%p,%d,%d]\n",
+ e->sock.sun_path, p, (int)e->dev, e->ino));
+ free(e, M_TEMP);
+ return;
+ }
+ mtx_unlock(&svr4_sockcache_lock);
+}
+
+void
+svr4_purge_sockcache(arg, p)
+ void *arg;
+ struct proc *p;
+{
+ struct svr4_sockcache_entry *e, *ne;
+
+ mtx_lock(&svr4_sockcache_lock);
+ TAILQ_FOREACH_SAFE(e, &svr4_head, entries, ne) {
+ if (e->p == p) {
+ TAILQ_REMOVE(&svr4_head, e, entries);
+ DPRINTF(("svr4_purge_sockcache: %s [%p,%d,%d]\n",
+ e->sock.sun_path, p, (int)e->dev, e->ino));
+ free(e, M_TEMP);
+ }
+ }
+ mtx_unlock(&svr4_sockcache_lock);
+}
+
+void
+svr4_sockcache_init(void)
+{
+
+ TAILQ_INIT(&svr4_head);
+ mtx_init(&svr4_sockcache_lock, "svr4 socket cache", NULL, MTX_DEF);
+ svr4_sockcache_exit_tag = EVENTHANDLER_REGISTER(process_exit,
+ svr4_purge_sockcache, NULL, EVENTHANDLER_PRI_ANY);
+ svr4_sockcache_exec_tag = EVENTHANDLER_REGISTER(process_exec,
+ svr4_purge_sockcache, NULL, EVENTHANDLER_PRI_ANY);
+}
+
+void
+svr4_sockcache_destroy(void)
+{
+
+ KASSERT(TAILQ_EMPTY(&svr4_head),
+ ("%s: sockcache entries still around", __func__));
+ EVENTHANDLER_DEREGISTER(process_exec, svr4_sockcache_exec_tag);
+ EVENTHANDLER_DEREGISTER(process_exit, svr4_sockcache_exit_tag);
+ mtx_destroy(&svr4_sockcache_lock);
+}
+
+int
+svr4_sys_socket(td, uap)
+ struct thread *td;
+ struct svr4_sys_socket_args *uap;
+{
+ switch (uap->type) {
+ case SVR4_SOCK_DGRAM:
+ uap->type = SOCK_DGRAM;
+ break;
+
+ case SVR4_SOCK_STREAM:
+ uap->type = SOCK_STREAM;
+ break;
+
+ case SVR4_SOCK_RAW:
+ uap->type = SOCK_RAW;
+ break;
+
+ case SVR4_SOCK_RDM:
+ uap->type = SOCK_RDM;
+ break;
+
+ case SVR4_SOCK_SEQPACKET:
+ uap->type = SOCK_SEQPACKET;
+ break;
+ default:
+ return EINVAL;
+ }
+ return sys_socket(td, (struct socket_args *)uap);
+}
diff --git a/sys/compat/svr4/svr4_socket.h b/sys/compat/svr4/svr4_socket.h
new file mode 100644
index 0000000..cbe7401
--- /dev/null
+++ b/sys/compat/svr4/svr4_socket.h
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1996 Christos Zoulas.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christos Zoulas.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_SOCKET_H_
+#define _SVR4_SOCKET_H_
+
+#include <netinet/in.h>
+
+struct sockaddr_un;
+struct proc;
+struct thread;
+struct file;
+
+struct svr4_sockaddr_in {
+ u_char sin_family;
+ u_short sin_port;
+ struct in_addr sin_addr;
+ u_char sin_zero[8];
+};
+
+int svr4_add_socket(struct thread *, const char *, struct stat *);
+void svr4_delete_socket(struct proc *, struct file *);
+int svr4_find_socket(struct thread *, struct file *, dev_t, ino_t,
+ struct sockaddr_un *);
+void svr4_sockcache_init(void);
+void svr4_sockcache_destroy(void);
+
+#endif /* _SVR4_SOCKET_H_ */
diff --git a/sys/compat/svr4/svr4_sockio.c b/sys/compat/svr4/svr4_sockio.c
new file mode 100644
index 0000000..afb3cfe
--- /dev/null
+++ b/sys/compat/svr4/svr4_sockio.c
@@ -0,0 +1,168 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1995 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/sockio.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/vnet.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_ioctl.h>
+#include <compat/svr4/svr4_sockio.h>
+
+static int bsd_to_svr4_flags(int);
+
+#define bsd_to_svr4_flag(a) \
+ if (bf & __CONCAT(I,a)) sf |= __CONCAT(SVR4_I,a)
+
+static int
+bsd_to_svr4_flags(bf)
+ int bf;
+{
+ int sf = 0;
+ bsd_to_svr4_flag(FF_UP);
+ bsd_to_svr4_flag(FF_BROADCAST);
+ bsd_to_svr4_flag(FF_DEBUG);
+ bsd_to_svr4_flag(FF_LOOPBACK);
+ bsd_to_svr4_flag(FF_POINTOPOINT);
+#if defined(IFF_NOTRAILERS)
+ bsd_to_svr4_flag(FF_NOTRAILERS);
+#endif
+ if (bf & IFF_DRV_RUNNING)
+ sf |= SVR4_IFF_RUNNING;
+ bsd_to_svr4_flag(FF_NOARP);
+ bsd_to_svr4_flag(FF_PROMISC);
+ bsd_to_svr4_flag(FF_ALLMULTI);
+ bsd_to_svr4_flag(FF_MULTICAST);
+ return sf;
+}
+
+int
+svr4_sock_ioctl(fp, td, retval, fd, cmd, data)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t data;
+{
+ int error;
+
+ *retval = 0;
+
+ switch (cmd) {
+ case SVR4_SIOCGIFNUM:
+ {
+ struct ifnet *ifp;
+ struct ifaddr *ifa;
+ int ifnum = 0;
+
+ /*
+ * This does not return the number of physical
+ * interfaces (if_index), but the number of interfaces
+ * + addresses like ifconf() does, because this number
+ * is used by code that will call SVR4_SIOCGIFCONF to
+ * find the space needed for SVR4_SIOCGIFCONF. So we
+ * count the number of ifreq entries that the next
+ * SVR4_SIOCGIFCONF will return. Maybe a more correct
+ * fix is to make SVR4_SIOCGIFCONF return only one
+ * entry per physical interface?
+ */
+ IFNET_RLOCK();
+ TAILQ_FOREACH(ifp, &V_ifnet, if_link)
+ if (TAILQ_EMPTY(&ifp->if_addrhead))
+ ifnum++;
+ else
+ TAILQ_FOREACH(ifa, &ifp->if_addrhead,
+ ifa_link)
+ ifnum++;
+ IFNET_RUNLOCK();
+ DPRINTF(("SIOCGIFNUM %d\n", ifnum));
+ return copyout(&ifnum, data, sizeof(ifnum));
+ }
+
+ case SVR4_SIOCGIFFLAGS:
+ {
+ struct ifreq br;
+ struct svr4_ifreq sr;
+
+ if ((error = copyin(data, &sr, sizeof(sr))) != 0)
+ return error;
+
+ (void) strlcpy(br.ifr_name, sr.svr4_ifr_name,
+ sizeof(br.ifr_name));
+ if ((error = fo_ioctl(fp, SIOCGIFFLAGS,
+ (caddr_t) &br, td->td_ucred,
+ td)) != 0) {
+ DPRINTF(("SIOCGIFFLAGS (%s) %s: error %d\n",
+ br.ifr_name, sr.svr4_ifr_name, error));
+ return error;
+ }
+
+ sr.svr4_ifr_flags = bsd_to_svr4_flags(br.ifr_flags);
+ DPRINTF(("SIOCGIFFLAGS %s = %x\n",
+ sr.svr4_ifr_name, sr.svr4_ifr_flags));
+ return copyout(&sr, data, sizeof(sr));
+ }
+
+ case SVR4_SIOCGIFCONF:
+ {
+ struct svr4_ifconf sc;
+
+ if ((error = copyin(data, &sc, sizeof(sc))) != 0)
+ return error;
+
+ DPRINTF(("ifreq %d svr4_ifreq %d ifc_len %d\n",
+ sizeof(struct ifreq), sizeof(struct svr4_ifreq),
+ sc.svr4_ifc_len));
+
+ if ((error = fo_ioctl(fp, OSIOCGIFCONF,
+ (caddr_t) &sc, td->td_ucred,
+ td)) != 0)
+ return error;
+
+ DPRINTF(("SIOCGIFCONF\n"));
+ return 0;
+ }
+
+
+ default:
+ DPRINTF(("Unknown svr4 sockio %lx\n", cmd));
+ return 0; /* ENOSYS really */
+ }
+}
diff --git a/sys/compat/svr4/svr4_sockio.h b/sys/compat/svr4/svr4_sockio.h
new file mode 100644
index 0000000..6160aa3
--- /dev/null
+++ b/sys/compat/svr4/svr4_sockio.h
@@ -0,0 +1,93 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1995 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_SOCKIO_H_
+#define _SVR4_SOCKIO_H_
+
+#define SVR4_IFF_UP 0x0001
+#define SVR4_IFF_BROADCAST 0x0002
+#define SVR4_IFF_DEBUG 0x0004
+#define SVR4_IFF_LOOPBACK 0x0008
+#define SVR4_IFF_POINTOPOINT 0x0010
+#define SVR4_IFF_NOTRAILERS 0x0020
+#define SVR4_IFF_RUNNING 0x0040
+#define SVR4_IFF_NOARP 0x0080
+#define SVR4_IFF_PROMISC 0x0100
+#define SVR4_IFF_ALLMULTI 0x0200
+#define SVR4_IFF_INTELLIGENT 0x0400
+#define SVR4_IFF_MULTICAST 0x0800
+#define SVR4_IFF_MULTI_BCAST 0x1000
+#define SVR4_IFF_UNNUMBERED 0x2000
+#define SVR4_IFF_PRIVATE 0x8000
+
+struct svr4_ifreq {
+#define SVR4_IFNAMSIZ 16
+ char svr4_ifr_name[SVR4_IFNAMSIZ];
+ union {
+ struct osockaddr ifru_addr;
+ struct osockaddr ifru_dstaddr;
+ struct osockaddr ifru_broadaddr;
+ short ifru_flags;
+ int ifru_metric;
+ char ifru_data;
+ char ifru_enaddr[6];
+ int if_muxid[2];
+
+ } ifr_ifru;
+
+#define svr4_ifr_addr ifr_ifru.ifru_addr
+#define svr4_ifr_dstaddr ifr_ifru.ifru_dstaddr
+#define svr4_ifr_broadaddr ifr_ifru.ifru_broadaddr
+#define svr4_ifr_flags ifr_ifru.ifru_flags
+#define svr4_ifr_metric ifr_ifru.ifru_metric
+#define svr4_ifr_data ifr_ifru.ifru_data
+#define svr4_ifr_enaddr ifr_ifru.ifru_enaddr
+#define svr4_ifr_muxid ifr_ifru.ifru_muxid
+
+};
+
+struct svr4_ifconf {
+ int svr4_ifc_len;
+ union {
+ caddr_t ifcu_buf;
+ struct svr4_ifreq *ifcu_req;
+ } ifc_ifcu;
+
+#define svr4_ifc_buf ifc_ifcu.ifcu_buf
+#define svr4_ifc_req ifc_ifcu.ifcu_req
+};
+
+#define SVR4_SIOC ('i' << 8)
+
+#define SVR4_SIOCGIFFLAGS SVR4_IOWR('i', 17, struct svr4_ifreq)
+#define SVR4_SIOCGIFCONF SVR4_IOWR('i', 20, struct svr4_ifconf)
+#define SVR4_SIOCGIFNUM SVR4_IOR('i', 87, int)
+
+#endif /* !_SVR4_SOCKIO_H_ */
diff --git a/sys/compat/svr4/svr4_sockmod.h b/sys/compat/svr4/svr4_sockmod.h
new file mode 100644
index 0000000..622ff6f
--- /dev/null
+++ b/sys/compat/svr4/svr4_sockmod.h
@@ -0,0 +1,83 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_SOCKMOD_H_
+#define _SVR4_SOCKMOD_H_
+
+#define SVR4_SIMOD ('I' << 8)
+
+#define SVR4_SI_OGETUDATA (SVR4_SIMOD|101)
+#define SVR4_SI_SHUTDOWN (SVR4_SIMOD|102)
+#define SVR4_SI_LISTEN (SVR4_SIMOD|103)
+#define SVR4_SI_SETMYNAME (SVR4_SIMOD|104)
+#define SVR4_SI_SETPEERNAME (SVR4_SIMOD|105)
+#define SVR4_SI_GETINTRANSIT (SVR4_SIMOD|106)
+#define SVR4_SI_TCL_LINK (SVR4_SIMOD|107)
+#define SVR4_SI_TCL_UNLINK (SVR4_SIMOD|108)
+#define SVR4_SI_SOCKPARAMS (SVR4_SIMOD|109)
+#define SVR4_SI_GETUDATA (SVR4_SIMOD|110)
+
+
+#define SVR4_SOCK_DGRAM 1
+#define SVR4_SOCK_STREAM 2
+#define SVR4_SOCK_STREAM_ORD 3
+#define SVR4_SOCK_RAW 4
+#define SVR4_SOCK_RDM 5
+#define SVR4_SOCK_SEQPACKET 6
+
+struct svr4_si_sockparms {
+ int family;
+ int type;
+ int protocol;
+};
+
+struct svr4_si_oudata {
+ int tidusize;
+ int addrsize;
+ int optsize;
+ int etsdusize;
+ int servtype;
+ int so_state;
+ int so_options;
+ int tsdusize;
+};
+
+struct svr4_si_udata {
+ int tidusize;
+ int addrsize;
+ int optsize;
+ int etsdusize;
+ int servtype;
+ int so_state;
+ int so_options;
+ int tsdusize;
+ struct svr4_si_sockparms sockparms;
+};
+#endif /* !_SVR4_SOCKMOD_H_ */
diff --git a/sys/compat/svr4/svr4_stat.c b/sys/compat/svr4/svr4_stat.c
new file mode 100644
index 0000000..b686642
--- /dev/null
+++ b/sys/compat/svr4/svr4_stat.c
@@ -0,0 +1,699 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/stat.h>
+#include <sys/filedesc.h>
+#include <sys/jail.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/namei.h>
+#include <sys/unistd.h>
+#include <sys/time.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysctl.h>
+#include <sys/sysproto.h>
+#include <sys/un.h>
+
+#include <vm/vm.h>
+
+#include <netinet/in.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_proto.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_stat.h>
+#include <compat/svr4/svr4_ustat.h>
+#include <compat/svr4/svr4_utsname.h>
+#include <compat/svr4/svr4_systeminfo.h>
+#include <compat/svr4/svr4_socket.h>
+#include <compat/svr4/svr4_time.h>
+#if defined(NOTYET)
+#include "svr4_fuser.h"
+#endif
+
+#ifdef sparc
+/*
+ * Solaris-2.4 on the sparc has the old stat call using the new
+ * stat data structure...
+ */
+# define SVR4_NO_OSTAT
+#endif
+
+struct svr4_ustat_args {
+ svr4_dev_t dev;
+ struct svr4_ustat * name;
+};
+
+static void bsd_to_svr4_xstat(struct stat *, struct svr4_xstat *);
+static void bsd_to_svr4_stat64(struct stat *, struct svr4_stat64 *);
+int svr4_ustat(struct thread *, struct svr4_ustat_args *);
+static int svr4_to_bsd_pathconf(int);
+
+/*
+ * SVR4 uses named pipes as named sockets, so we tell programs
+ * that sockets are named pipes with mode 0
+ */
+#define BSD_TO_SVR4_MODE(mode) (S_ISSOCK(mode) ? S_IFIFO : (mode))
+
+
+#ifndef SVR4_NO_OSTAT
+static void bsd_to_svr4_stat(struct stat *, struct svr4_stat *);
+
+static void
+bsd_to_svr4_stat(st, st4)
+ struct stat *st;
+ struct svr4_stat *st4;
+{
+ memset(st4, 0, sizeof(*st4));
+ st4->st_dev = bsd_to_svr4_odev_t(st->st_dev);
+ st4->st_ino = st->st_ino;
+ st4->st_mode = BSD_TO_SVR4_MODE(st->st_mode);
+ st4->st_nlink = st->st_nlink;
+ st4->st_uid = st->st_uid;
+ st4->st_gid = st->st_gid;
+ st4->st_rdev = bsd_to_svr4_odev_t(st->st_rdev);
+ st4->st_size = st->st_size;
+ st4->st_atim = st->st_atim.tv_sec;
+ st4->st_mtim = st->st_mtim.tv_sec;
+ st4->st_ctim = st->st_ctim.tv_sec;
+}
+#endif
+
+
+static void
+bsd_to_svr4_xstat(st, st4)
+ struct stat *st;
+ struct svr4_xstat *st4;
+{
+ memset(st4, 0, sizeof(*st4));
+ st4->st_dev = bsd_to_svr4_dev_t(st->st_dev);
+ st4->st_ino = st->st_ino;
+ st4->st_mode = BSD_TO_SVR4_MODE(st->st_mode);
+ st4->st_nlink = st->st_nlink;
+ st4->st_uid = st->st_uid;
+ st4->st_gid = st->st_gid;
+ st4->st_rdev = bsd_to_svr4_dev_t(st->st_rdev);
+ st4->st_size = st->st_size;
+ st4->st_atim = st->st_atim;
+ st4->st_mtim = st->st_mtim;
+ st4->st_ctim = st->st_ctim;
+ st4->st_blksize = st->st_blksize;
+ st4->st_blocks = st->st_blocks;
+ strcpy(st4->st_fstype, "unknown");
+}
+
+
+static void
+bsd_to_svr4_stat64(st, st4)
+ struct stat *st;
+ struct svr4_stat64 *st4;
+{
+ memset(st4, 0, sizeof(*st4));
+ st4->st_dev = bsd_to_svr4_dev_t(st->st_dev);
+ st4->st_ino = st->st_ino;
+ st4->st_mode = BSD_TO_SVR4_MODE(st->st_mode);
+ st4->st_nlink = st->st_nlink;
+ st4->st_uid = st->st_uid;
+ st4->st_gid = st->st_gid;
+ st4->st_rdev = bsd_to_svr4_dev_t(st->st_rdev);
+ st4->st_size = st->st_size;
+ st4->st_atim = st->st_atim;
+ st4->st_mtim = st->st_mtim;
+ st4->st_ctim = st->st_ctim;
+ st4->st_blksize = st->st_blksize;
+ st4->st_blocks = st->st_blocks;
+ strcpy(st4->st_fstype, "unknown");
+}
+
+int
+svr4_sys_stat(td, uap)
+ struct thread *td;
+ struct svr4_sys_stat_args *uap;
+{
+ struct svr4_stat svr4_st;
+ struct stat st;
+ char *path;
+ int error;
+
+ CHECKALTEXIST(td, uap->path, &path);
+
+ error = kern_stat(td, path, UIO_SYSSPACE, &st);
+ free(path, M_TEMP);
+ if (error)
+ return (error);
+ bsd_to_svr4_stat(&st, &svr4_st);
+
+ if (S_ISSOCK(st.st_mode))
+ (void) svr4_add_socket(td, uap->path, &st);
+
+ return (copyout(&svr4_st, uap->ub, sizeof svr4_st));
+}
+
+
+int
+svr4_sys_lstat(td, uap)
+ struct thread *td;
+ struct svr4_sys_lstat_args *uap;
+{
+ struct svr4_stat svr4_st;
+ struct stat st;
+ char *path;
+ int error;
+
+ CHECKALTEXIST(td, uap->path, &path);
+
+ error = kern_lstat(td, path, UIO_SYSSPACE, &st);
+ free(path, M_TEMP);
+ if (error)
+ return (error);
+ bsd_to_svr4_stat(&st, &svr4_st);
+
+ if (S_ISSOCK(st.st_mode))
+ (void) svr4_add_socket(td, uap->path, &st);
+
+ return (copyout(&svr4_st, uap->ub, sizeof svr4_st));
+}
+
+
+int
+svr4_sys_fstat(td, uap)
+ struct thread *td;
+ struct svr4_sys_fstat_args *uap;
+{
+ struct svr4_stat svr4_st;
+ struct stat st;
+ int error;
+
+
+ error = kern_fstat(td, uap->fd, &st);
+ if (error)
+ return (error);
+ bsd_to_svr4_stat(&st, &svr4_st);
+ return (copyout(&svr4_st, uap->sb, sizeof svr4_st));
+}
+
+
+int
+svr4_sys_xstat(td, uap)
+ struct thread *td;
+ struct svr4_sys_xstat_args *uap;
+{
+ struct svr4_xstat svr4_st;
+ struct stat st;
+ char *path;
+ int error;
+
+ CHECKALTEXIST(td, uap->path, &path);
+
+ error = kern_stat(td, path, UIO_SYSSPACE, &st);
+ free(path, M_TEMP);
+ if (error)
+ return (error);
+
+ bsd_to_svr4_xstat(&st, &svr4_st);
+
+#if defined(SOCKET_NOTYET)
+ if (S_ISSOCK(st.st_mode))
+ (void) svr4_add_socket(td, uap->path, &st);
+#endif
+
+ return (copyout(&svr4_st, uap->ub, sizeof svr4_st));
+}
+
+int
+svr4_sys_lxstat(td, uap)
+ struct thread *td;
+ struct svr4_sys_lxstat_args *uap;
+{
+ struct svr4_xstat svr4_st;
+ struct stat st;
+ char *path;
+ int error;
+
+ CHECKALTEXIST(td, uap->path, &path);
+
+ error = kern_lstat(td, path, UIO_SYSSPACE, &st);
+ free(path, M_TEMP);
+ if (error)
+ return (error);
+
+ bsd_to_svr4_xstat(&st, &svr4_st);
+
+#if defined(SOCKET_NOTYET)
+ if (S_ISSOCK(st.st_mode))
+ (void) svr4_add_socket(td, uap->path, &st);
+#endif
+ return (copyout(&svr4_st, uap->ub, sizeof svr4_st));
+}
+
+
+int
+svr4_sys_fxstat(td, uap)
+ struct thread *td;
+ struct svr4_sys_fxstat_args *uap;
+{
+ struct svr4_xstat svr4_st;
+ struct stat st;
+ int error;
+
+
+ error = kern_fstat(td, uap->fd, &st);
+ if (error)
+ return (error);
+ bsd_to_svr4_xstat(&st, &svr4_st);
+ return (copyout(&svr4_st, uap->sb, sizeof svr4_st));
+}
+
+int
+svr4_sys_stat64(td, uap)
+ struct thread *td;
+ struct svr4_sys_stat64_args *uap;
+{
+ struct svr4_stat64 svr4_st;
+ struct stat st;
+ char *path;
+ int error;
+
+ CHECKALTEXIST(td, uap->path, &path);
+
+ error = kern_stat(td, path, UIO_SYSSPACE, &st);
+ free(path, M_TEMP);
+ if (error)
+ return (error);
+
+ bsd_to_svr4_stat64(&st, &svr4_st);
+
+ if (S_ISSOCK(st.st_mode))
+ (void) svr4_add_socket(td, uap->path, &st);
+
+ return (copyout(&svr4_st, uap->sb, sizeof svr4_st));
+}
+
+
+int
+svr4_sys_lstat64(td, uap)
+ struct thread *td;
+ struct svr4_sys_lstat64_args *uap;
+{
+ struct svr4_stat64 svr4_st;
+ struct stat st;
+ char *path;
+ int error;
+
+ CHECKALTEXIST(td, uap->path, &path);
+
+ error = kern_lstat(td, path, UIO_SYSSPACE, &st);
+ free(path, M_TEMP);
+ if (error)
+ return (error);
+
+ bsd_to_svr4_stat64(&st, &svr4_st);
+
+ if (S_ISSOCK(st.st_mode))
+ (void) svr4_add_socket(td, uap->path, &st);
+
+ return (copyout(&svr4_st, uap->sb, sizeof svr4_st));
+}
+
+
+int
+svr4_sys_fstat64(td, uap)
+ struct thread *td;
+ struct svr4_sys_fstat64_args *uap;
+{
+ struct svr4_stat64 svr4_st;
+ struct stat st;
+ int error;
+
+ error = kern_fstat(td, uap->fd, &st);
+ if (error)
+ return (error);
+ bsd_to_svr4_stat64(&st, &svr4_st);
+ return (copyout(&svr4_st, uap->sb, sizeof svr4_st));
+}
+
+
+int
+svr4_ustat(td, uap)
+ struct thread *td;
+ struct svr4_ustat_args *uap;
+{
+ struct svr4_ustat us;
+ int error;
+
+ memset(&us, 0, sizeof us);
+
+ /*
+ * XXX: should set f_tfree and f_tinode at least
+ * How do we translate dev -> fstat? (and then to svr4_ustat)
+ */
+ if ((error = copyout(&us, uap->name, sizeof us)) != 0)
+ return (error);
+
+ return 0;
+}
+
+/*extern char ostype[], osrelease[], version[], machine[];*/
+
+int
+svr4_sys_uname(td, uap)
+ struct thread *td;
+ struct svr4_sys_uname_args *uap;
+{
+ struct svr4_utsname sut;
+
+ memset(&sut, 0, sizeof(sut));
+
+ strlcpy(sut.sysname, ostype, sizeof(sut.sysname));
+ getcredhostname(td->td_ucred, sut.nodename, sizeof(sut.nodename));
+ strlcpy(sut.release, osrelease, sizeof(sut.release));
+ strlcpy(sut.version, version, sizeof(sut.version));
+ strlcpy(sut.machine, machine, sizeof(sut.machine));
+
+ return copyout((caddr_t) &sut, (caddr_t) uap->name,
+ sizeof(struct svr4_utsname));
+}
+
+int
+svr4_sys_systeminfo(td, uap)
+ struct thread *td;
+ struct svr4_sys_systeminfo_args *uap;
+{
+ char *str = NULL;
+ int error = 0;
+ register_t *retval = td->td_retval;
+ u_long hostid;
+ size_t len = 0;
+ char buf[MAXHOSTNAMELEN];
+ u_int rlen = uap->len;
+
+ switch (uap->what) {
+ case SVR4_SI_SYSNAME:
+ str = ostype;
+ break;
+
+ case SVR4_SI_HOSTNAME:
+ getcredhostname(td->td_ucred, buf, sizeof(buf));
+ str = buf;
+ break;
+
+ case SVR4_SI_RELEASE:
+ str = osrelease;
+ break;
+
+ case SVR4_SI_VERSION:
+ str = version;
+ break;
+
+ case SVR4_SI_MACHINE:
+ str = machine;
+ break;
+
+ case SVR4_SI_ARCHITECTURE:
+ str = machine;
+ break;
+
+ case SVR4_SI_ISALIST:
+#if defined(__sparc__)
+ str = "sparcv9 sparcv9-fsmuld sparcv8 sparcv8-fsmuld sparcv7 sparc";
+#elif defined(__i386__)
+ str = "i386";
+#elif defined(__amd64__)
+ str = "amd64";
+#else
+ str = "unknown";
+#endif
+ break;
+
+ case SVR4_SI_HW_SERIAL:
+ getcredhostid(td->td_ucred, &hostid);
+ snprintf(buf, sizeof(buf), "%lu", hostid);
+ str = buf;
+ break;
+
+ case SVR4_SI_HW_PROVIDER:
+ str = ostype;
+ break;
+
+ case SVR4_SI_SRPC_DOMAIN:
+ getcreddomainname(td->td_ucred, buf, sizeof(buf));
+ str = buf;
+ break;
+
+ case SVR4_SI_PLATFORM:
+#if defined(__i386__)
+ str = "i86pc";
+#else
+ str = "unknown";
+#endif
+ break;
+
+ case SVR4_SI_KERB_REALM:
+ str = "unsupported";
+ break;
+#if defined(WHY_DOES_AN_EMULATOR_WANT_TO_SET_HOSTNAMES)
+ case SVR4_SI_SET_HOSTNAME:
+ name = KERN_HOSTNAME;
+ return kern_sysctl(&name, 1, 0, 0, uap->buf, rlen, td);
+
+ case SVR4_SI_SET_SRPC_DOMAIN:
+ name = KERN_NISDOMAINNAME;
+ return kern_sysctl(&name, 1, 0, 0, uap->buf, rlen, td);
+#else
+ case SVR4_SI_SET_HOSTNAME:
+ case SVR4_SI_SET_SRPC_DOMAIN:
+ /* FALLTHROUGH */
+#endif
+ case SVR4_SI_SET_KERB_REALM:
+ return 0;
+
+ default:
+ DPRINTF(("Bad systeminfo command %d\n", uap->what));
+ return ENOSYS;
+ }
+
+ if (str) {
+ len = strlen(str) + 1;
+ if (len > rlen)
+ len = rlen;
+
+ if (uap->buf) {
+ error = copyout(str, uap->buf, len);
+ if (error)
+ return error;
+ /* make sure we are NULL terminated */
+ buf[0] = '\0';
+ error = copyout(buf, &(uap->buf[len - 1]), 1);
+ }
+ else
+ error = 0;
+ }
+ /* XXX NetBSD has hostname setting stuff here. Why would an emulator
+ want to do that? */
+
+ *retval = len;
+ return error;
+}
+
+int
+svr4_sys_utssys(td, uap)
+ struct thread *td;
+ struct svr4_sys_utssys_args *uap;
+{
+ switch (uap->sel) {
+ case 0: /* uname(2) */
+ {
+ struct svr4_sys_uname_args ua;
+ ua.name = uap->a1;
+ return svr4_sys_uname(td, &ua);
+ }
+
+ case 2: /* ustat(2) */
+ {
+ struct svr4_ustat_args ua;
+ ua.dev = (svr4_dev_t) uap->a2;
+ ua.name = uap->a1;
+ return svr4_ustat(td, &ua);
+ }
+
+ case 3: /* fusers(2) */
+ return ENOSYS;
+
+ default:
+ return ENOSYS;
+ }
+ return ENOSYS;
+}
+
+
+int
+svr4_sys_utime(td, uap)
+ struct thread *td;
+ struct svr4_sys_utime_args *uap;
+{
+ struct svr4_utimbuf ub;
+ struct timeval tbuf[2], *tp;
+ char *path;
+ int error;
+
+ if (uap->ubuf != NULL) {
+ error = copyin(uap->ubuf, &ub, sizeof(ub));
+ if (error)
+ return (error);
+ tbuf[0].tv_sec = ub.actime;
+ tbuf[0].tv_usec = 0;
+ tbuf[1].tv_sec = ub.modtime;
+ tbuf[1].tv_usec = 0;
+ tp = tbuf;
+ } else
+ tp = NULL;
+
+ CHECKALTEXIST(td, uap->path, &path);
+ error = kern_utimes(td, path, UIO_SYSSPACE, tp, UIO_SYSSPACE);
+ free(path, M_TEMP);
+ return (error);
+}
+
+
+int
+svr4_sys_utimes(td, uap)
+ struct thread *td;
+ struct svr4_sys_utimes_args *uap;
+{
+ char *path;
+ int error;
+
+ CHECKALTEXIST(td, uap->path, &path);
+ error = kern_utimes(td, path, UIO_SYSSPACE, uap->tptr, UIO_USERSPACE);
+ free(path, M_TEMP);
+ return (error);
+}
+
+static int
+svr4_to_bsd_pathconf(name)
+ int name;
+{
+ switch (name) {
+ case SVR4_PC_LINK_MAX:
+ return _PC_LINK_MAX;
+
+ case SVR4_PC_MAX_CANON:
+ return _PC_MAX_CANON;
+
+ case SVR4_PC_MAX_INPUT:
+ return _PC_MAX_INPUT;
+
+ case SVR4_PC_NAME_MAX:
+ return _PC_NAME_MAX;
+
+ case SVR4_PC_PATH_MAX:
+ return _PC_PATH_MAX;
+
+ case SVR4_PC_PIPE_BUF:
+ return _PC_PIPE_BUF;
+
+ case SVR4_PC_NO_TRUNC:
+ return _PC_NO_TRUNC;
+
+ case SVR4_PC_VDISABLE:
+ return _PC_VDISABLE;
+
+ case SVR4_PC_CHOWN_RESTRICTED:
+ return _PC_CHOWN_RESTRICTED;
+ case SVR4_PC_SYNC_IO:
+#if defined(_PC_SYNC_IO)
+ return _PC_SYNC_IO;
+#else
+ return 0;
+#endif
+ case SVR4_PC_ASYNC_IO:
+ case SVR4_PC_PRIO_IO:
+ /* Not supported */
+ return 0;
+
+ default:
+ /* Invalid */
+ return -1;
+ }
+}
+
+
+int
+svr4_sys_pathconf(td, uap)
+ struct thread *td;
+ struct svr4_sys_pathconf_args *uap;
+{
+ char *path;
+ int error, name;
+
+ name = svr4_to_bsd_pathconf(uap->name);
+
+ switch (name) {
+ case -1:
+ td->td_retval[0] = -1;
+ return (EINVAL);
+ case 0:
+ td->td_retval[0] = 0;
+ return (0);
+ default:
+ CHECKALTEXIST(td, uap->path, &path);
+ error = kern_pathconf(td, path, UIO_SYSSPACE, name, FOLLOW);
+ free(path, M_TEMP);
+ return (error);
+ }
+}
+
+
+int
+svr4_sys_fpathconf(td, uap)
+ struct thread *td;
+ struct svr4_sys_fpathconf_args *uap;
+{
+ register_t *retval = td->td_retval;
+
+ uap->name = svr4_to_bsd_pathconf(uap->name);
+
+ switch (uap->name) {
+ case -1:
+ *retval = -1;
+ return EINVAL;
+ case 0:
+ *retval = 0;
+ return 0;
+ default:
+ return sys_fpathconf(td, (struct fpathconf_args *)uap);
+ }
+}
diff --git a/sys/compat/svr4/svr4_stat.h b/sys/compat/svr4/svr4_stat.h
new file mode 100644
index 0000000..03d6e3c
--- /dev/null
+++ b/sys/compat/svr4/svr4_stat.h
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_STAT_H_
+#define _SVR4_STAT_H_
+
+#include <compat/svr4/svr4_types.h>
+#include <sys/stat.h>
+
+struct svr4_stat {
+ svr4_o_dev_t st_dev;
+ svr4_o_ino_t st_ino;
+ svr4_o_mode_t st_mode;
+ svr4_o_nlink_t st_nlink;
+ svr4_o_uid_t st_uid;
+ svr4_o_gid_t st_gid;
+ svr4_o_dev_t st_rdev;
+ svr4_off_t st_size;
+ svr4_time_t st_atim;
+ svr4_time_t st_mtim;
+ svr4_time_t st_ctim;
+};
+
+struct svr4_xstat {
+ svr4_dev_t st_dev;
+ long st_pad1[3];
+ svr4_ino_t st_ino;
+ svr4_mode_t st_mode;
+ svr4_nlink_t st_nlink;
+ svr4_uid_t st_uid;
+ svr4_gid_t st_gid;
+ svr4_dev_t st_rdev;
+ long st_pad2[2];
+ svr4_off_t st_size;
+ long st_pad3;
+ svr4_timestruc_t st_atim;
+ svr4_timestruc_t st_mtim;
+ svr4_timestruc_t st_ctim;
+ long st_blksize;
+ svr4_blkcnt_t st_blocks;
+ char st_fstype[16];
+ long st_pad4[8];
+};
+
+struct svr4_stat64 {
+ svr4_dev_t st_dev;
+ long st_pad1[3];
+ svr4_ino64_t st_ino;
+ svr4_mode_t st_mode;
+ svr4_nlink_t st_nlink;
+ svr4_uid_t st_uid;
+ svr4_gid_t st_gid;
+ svr4_dev_t st_rdev;
+ long st_pad2[2];
+ svr4_off64_t st_size;
+ svr4_timestruc_t st_atim;
+ svr4_timestruc_t st_mtim;
+ svr4_timestruc_t st_ctim;
+ long st_blksize;
+ svr4_blkcnt64_t st_blocks;
+ char st_fstype[16];
+ long st_pad4[8];
+};
+
+#define SVR4_PC_LINK_MAX 1
+#define SVR4_PC_MAX_CANON 2
+#define SVR4_PC_MAX_INPUT 3
+#define SVR4_PC_NAME_MAX 4
+#define SVR4_PC_PATH_MAX 5
+#define SVR4_PC_PIPE_BUF 6
+#define SVR4_PC_NO_TRUNC 7
+#define SVR4_PC_VDISABLE 8
+#define SVR4_PC_CHOWN_RESTRICTED 9
+#define SVR4_PC_ASYNC_IO 10
+#define SVR4_PC_PRIO_IO 11
+#define SVR4_PC_SYNC_IO 12
+
+#endif /* !_SVR4_STAT_H_ */
diff --git a/sys/compat/svr4/svr4_statvfs.h b/sys/compat/svr4/svr4_statvfs.h
new file mode 100644
index 0000000..7db9655
--- /dev/null
+++ b/sys/compat/svr4/svr4_statvfs.h
@@ -0,0 +1,72 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_STATVFS_H_
+#define _SVR4_STATVFS_H_
+
+typedef struct svr4_statvfs {
+ u_long f_bsize;
+ u_long f_frsize;
+ svr4_fsblkcnt_t f_blocks;
+ svr4_fsblkcnt_t f_bfree;
+ svr4_fsblkcnt_t f_bavail;
+ svr4_fsblkcnt_t f_files;
+ svr4_fsblkcnt_t f_ffree;
+ svr4_fsblkcnt_t f_favail;
+ u_long f_fsid;
+ char f_basetype[16];
+ u_long f_flag;
+ u_long f_namemax;
+ char f_fstr[32];
+ u_long f_filler[16];
+} svr4_statvfs_t;
+
+typedef struct svr4_statvfs64 {
+ u_long f_bsize;
+ u_long f_frsize;
+ svr4_fsblkcnt64_t f_blocks;
+ svr4_fsblkcnt64_t f_bfree;
+ svr4_fsblkcnt64_t f_bavail;
+ svr4_fsblkcnt64_t f_files;
+ svr4_fsblkcnt64_t f_ffree;
+ svr4_fsblkcnt64_t f_favail;
+ u_long f_fsid;
+ char f_basetype[16];
+ u_long f_flag;
+ u_long f_namemax;
+ char f_fstr[32];
+ u_long f_filler[16];
+} svr4_statvfs64_t;
+
+#define SVR4_ST_RDONLY 0x01
+#define SVR4_ST_NOSUID 0x02
+#define SVR4_ST_NOTRUNC 0x04
+
+#endif /* !_SVR4_STATVFS_H_ */
diff --git a/sys/compat/svr4/svr4_stream.c b/sys/compat/svr4/svr4_stream.c
new file mode 100644
index 0000000..1c7e83e
--- /dev/null
+++ b/sys/compat/svr4/svr4_stream.c
@@ -0,0 +1,2038 @@
+/*-
+ * Copyright (c) 1998 Mark Newton. All rights reserved.
+ * Copyright (c) 1994, 1996 Christos Zoulas. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christos Zoulas.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Pretend that we have streams...
+ * Yes, this is gross.
+ *
+ * ToDo: The state machine for getmsg needs re-thinking
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_compat.h"
+#include "opt_ktrace.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/capability.h>
+#include <sys/fcntl.h>
+#include <sys/filedesc.h>
+#include <sys/filio.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/file.h> /* Must come after sys/malloc.h */
+#include <sys/mbuf.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/protosw.h>
+#include <sys/signal.h>
+#include <sys/signalvar.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/stat.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysproto.h>
+#include <sys/uio.h>
+#include <sys/ktrace.h> /* Must come after sys/uio.h */
+#include <sys/un.h>
+
+#include <netinet/in.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_proto.h>
+#include <compat/svr4/svr4_stropts.h>
+#include <compat/svr4/svr4_timod.h>
+#include <compat/svr4/svr4_sockmod.h>
+#include <compat/svr4/svr4_ioctl.h>
+#include <compat/svr4/svr4_socket.h>
+
+/* Utils */
+static int clean_pipe(struct thread *, char *);
+static void getparm(struct file *, struct svr4_si_sockparms *);
+static int svr4_do_putmsg(struct thread *, struct svr4_sys_putmsg_args *,
+ struct file *);
+static int svr4_do_getmsg(struct thread *, struct svr4_sys_getmsg_args *,
+ struct file *);
+
+/* Address Conversions */
+static void sockaddr_to_netaddr_in(struct svr4_strmcmd *,
+ const struct sockaddr_in *);
+static void sockaddr_to_netaddr_un(struct svr4_strmcmd *,
+ const struct sockaddr_un *);
+static void netaddr_to_sockaddr_in(struct sockaddr_in *,
+ const struct svr4_strmcmd *);
+static void netaddr_to_sockaddr_un(struct sockaddr_un *,
+ const struct svr4_strmcmd *);
+
+/* stream ioctls */
+static int i_nread(struct file *, struct thread *, register_t *, int,
+ u_long, caddr_t);
+static int i_fdinsert(struct file *, struct thread *, register_t *, int,
+ u_long, caddr_t);
+static int i_str(struct file *, struct thread *, register_t *, int,
+ u_long, caddr_t);
+static int i_setsig(struct file *, struct thread *, register_t *, int,
+ u_long, caddr_t);
+static int i_getsig(struct file *, struct thread *, register_t *, int,
+ u_long, caddr_t);
+static int _i_bind_rsvd(struct file *, struct thread *, register_t *, int,
+ u_long, caddr_t);
+static int _i_rele_rsvd(struct file *, struct thread *, register_t *, int,
+ u_long, caddr_t);
+
+/* i_str sockmod calls */
+static int sockmod(struct file *, int, struct svr4_strioctl *,
+ struct thread *);
+static int si_listen(struct file *, int, struct svr4_strioctl *,
+ struct thread *);
+static int si_ogetudata(struct file *, int, struct svr4_strioctl *,
+ struct thread *);
+static int si_sockparams(struct file *, int, struct svr4_strioctl *,
+ struct thread *);
+static int si_shutdown (struct file *, int, struct svr4_strioctl *,
+ struct thread *);
+static int si_getudata(struct file *, int, struct svr4_strioctl *,
+ struct thread *);
+
+/* i_str timod calls */
+static int timod(struct file *, int, struct svr4_strioctl *, struct thread *);
+static int ti_getinfo(struct file *, int, struct svr4_strioctl *,
+ struct thread *);
+static int ti_bind(struct file *, int, struct svr4_strioctl *, struct thread *);
+
+#ifdef DEBUG_SVR4
+static void bufprint(u_char *, size_t);
+static int show_ioc(const char *, struct svr4_strioctl *);
+static int show_strbuf(struct svr4_strbuf *);
+static void show_msg(const char *, int, struct svr4_strbuf *,
+ struct svr4_strbuf *, int);
+
+static void
+bufprint(buf, len)
+ u_char *buf;
+ size_t len;
+{
+ size_t i;
+
+ uprintf("\n\t");
+ for (i = 0; i < len; i++) {
+ uprintf("%x ", buf[i]);
+ if (i && (i % 16) == 0)
+ uprintf("\n\t");
+ }
+}
+
+static int
+show_ioc(str, ioc)
+ const char *str;
+ struct svr4_strioctl *ioc;
+{
+ u_char *ptr = NULL;
+ int len;
+ int error;
+
+ len = ioc->len;
+ if (len > 1024)
+ len = 1024;
+
+ if (len > 0) {
+ ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK);
+ if ((error = copyin(ioc->buf, ptr, len)) != 0) {
+ free((char *) ptr, M_TEMP);
+ return error;
+ }
+ }
+
+ uprintf("%s cmd = %ld, timeout = %d, len = %d, buf = %p { ",
+ str, ioc->cmd, ioc->timeout, ioc->len, ioc->buf);
+
+ if (ptr != NULL)
+ bufprint(ptr, len);
+
+ uprintf("}\n");
+
+ if (ptr != NULL)
+ free((char *) ptr, M_TEMP);
+ return 0;
+}
+
+
+static int
+show_strbuf(str)
+ struct svr4_strbuf *str;
+{
+ int error;
+ u_char *ptr = NULL;
+ int maxlen = str->maxlen;
+ int len = str->len;
+
+ if (maxlen > 8192)
+ maxlen = 8192;
+
+ if (maxlen < 0)
+ maxlen = 0;
+
+ if (len >= maxlen)
+ len = maxlen;
+
+ if (len > 0) {
+ ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK);
+
+ if ((error = copyin(str->buf, ptr, len)) != 0) {
+ free((char *) ptr, M_TEMP);
+ return error;
+ }
+ }
+
+ uprintf(", { %d, %d, %p=[ ", str->maxlen, str->len, str->buf);
+
+ if (ptr)
+ bufprint(ptr, len);
+
+ uprintf("]}");
+
+ if (ptr)
+ free((char *) ptr, M_TEMP);
+
+ return 0;
+}
+
+
+static void
+show_msg(str, fd, ctl, dat, flags)
+ const char *str;
+ int fd;
+ struct svr4_strbuf *ctl;
+ struct svr4_strbuf *dat;
+ int flags;
+{
+ struct svr4_strbuf buf;
+ int error;
+
+ uprintf("%s(%d", str, fd);
+ if (ctl != NULL) {
+ if ((error = copyin(ctl, &buf, sizeof(buf))) != 0)
+ return;
+ show_strbuf(&buf);
+ }
+ else
+ uprintf(", NULL");
+
+ if (dat != NULL) {
+ if ((error = copyin(dat, &buf, sizeof(buf))) != 0)
+ return;
+ show_strbuf(&buf);
+ }
+ else
+ uprintf(", NULL");
+
+ uprintf(", %x);\n", flags);
+}
+
+#endif /* DEBUG_SVR4 */
+
+/*
+ * We are faced with an interesting situation. On svr4 unix sockets
+ * are really pipes. But we really have sockets, and we might as
+ * well use them. At the point where svr4 calls TI_BIND, it has
+ * already created a named pipe for the socket using mknod(2).
+ * We need to create a socket with the same name when we bind,
+ * so we need to remove the pipe before, otherwise we'll get address
+ * already in use. So we *carefully* remove the pipe, to avoid
+ * using this as a random file removal tool. We use system calls
+ * to avoid code duplication.
+ */
+static int
+clean_pipe(td, path)
+ struct thread *td;
+ char *path;
+{
+ struct stat st;
+ int error;
+
+ error = kern_lstat(td, path, UIO_SYSSPACE, &st);
+
+ /*
+ * Make sure we are dealing with a mode 0 named pipe.
+ */
+ if ((st.st_mode & S_IFMT) != S_IFIFO)
+ return (0);
+
+ if ((st.st_mode & ALLPERMS) != 0)
+ return (0);
+
+ error = kern_unlink(td, path, UIO_SYSSPACE);
+ if (error)
+ DPRINTF(("clean_pipe: unlink failed %d\n", error));
+ return (error);
+}
+
+
+static void
+sockaddr_to_netaddr_in(sc, sain)
+ struct svr4_strmcmd *sc;
+ const struct sockaddr_in *sain;
+{
+ struct svr4_netaddr_in *na;
+ na = SVR4_ADDROF(sc);
+
+ na->family = sain->sin_family;
+ na->port = sain->sin_port;
+ na->addr = sain->sin_addr.s_addr;
+ DPRINTF(("sockaddr_in -> netaddr %d %d %lx\n", na->family, na->port,
+ na->addr));
+}
+
+
+static void
+sockaddr_to_netaddr_un(sc, saun)
+ struct svr4_strmcmd *sc;
+ const struct sockaddr_un *saun;
+{
+ struct svr4_netaddr_un *na;
+ char *dst, *edst = ((char *) sc) + sc->offs + sizeof(na->family) + 1 -
+ sizeof(*sc);
+ const char *src;
+
+ na = SVR4_ADDROF(sc);
+ na->family = saun->sun_family;
+ for (src = saun->sun_path, dst = na->path; (*dst++ = *src++) != '\0'; )
+ if (dst == edst)
+ break;
+ DPRINTF(("sockaddr_un -> netaddr %d %s\n", na->family, na->path));
+}
+
+
+static void
+netaddr_to_sockaddr_in(sain, sc)
+ struct sockaddr_in *sain;
+ const struct svr4_strmcmd *sc;
+{
+ const struct svr4_netaddr_in *na;
+
+
+ na = SVR4_C_ADDROF(sc);
+ memset(sain, 0, sizeof(*sain));
+ sain->sin_len = sizeof(*sain);
+ sain->sin_family = na->family;
+ sain->sin_port = na->port;
+ sain->sin_addr.s_addr = na->addr;
+ DPRINTF(("netaddr -> sockaddr_in %d %d %x\n", sain->sin_family,
+ sain->sin_port, sain->sin_addr.s_addr));
+}
+
+
+static void
+netaddr_to_sockaddr_un(saun, sc)
+ struct sockaddr_un *saun;
+ const struct svr4_strmcmd *sc;
+{
+ const struct svr4_netaddr_un *na;
+ char *dst, *edst = &saun->sun_path[sizeof(saun->sun_path) - 1];
+ const char *src;
+
+ na = SVR4_C_ADDROF(sc);
+ memset(saun, 0, sizeof(*saun));
+ saun->sun_family = na->family;
+ for (src = na->path, dst = saun->sun_path; (*dst++ = *src++) != '\0'; )
+ if (dst == edst)
+ break;
+ saun->sun_len = dst - saun->sun_path;
+ DPRINTF(("netaddr -> sockaddr_un %d %s\n", saun->sun_family,
+ saun->sun_path));
+}
+
+
+static void
+getparm(fp, pa)
+ struct file *fp;
+ struct svr4_si_sockparms *pa;
+{
+ struct svr4_strm *st;
+ struct socket *so;
+
+ st = svr4_stream_get(fp);
+ if (st == NULL)
+ return;
+
+ so = fp->f_data;
+
+ pa->family = st->s_family;
+
+ switch (so->so_type) {
+ case SOCK_DGRAM:
+ pa->type = SVR4_T_CLTS;
+ pa->protocol = IPPROTO_UDP;
+ DPRINTF(("getparm(dgram)\n"));
+ return;
+
+ case SOCK_STREAM:
+ pa->type = SVR4_T_COTS; /* What about T_COTS_ORD? XXX */
+ pa->protocol = IPPROTO_IP;
+ DPRINTF(("getparm(stream)\n"));
+ return;
+
+ case SOCK_RAW:
+ pa->type = SVR4_T_CLTS;
+ pa->protocol = IPPROTO_RAW;
+ DPRINTF(("getparm(raw)\n"));
+ return;
+
+ default:
+ pa->type = 0;
+ pa->protocol = 0;
+ DPRINTF(("getparm(type %d?)\n", so->so_type));
+ return;
+ }
+}
+
+
+static int
+si_ogetudata(fp, fd, ioc, td)
+ struct file *fp;
+ int fd;
+ struct svr4_strioctl *ioc;
+ struct thread *td;
+{
+ int error;
+ struct svr4_si_oudata ud;
+ struct svr4_si_sockparms pa;
+
+ if (ioc->len != sizeof(ud) && ioc->len != sizeof(ud) - sizeof(int)) {
+ DPRINTF(("SI_OGETUDATA: Wrong size %d != %d\n",
+ sizeof(ud), ioc->len));
+ return EINVAL;
+ }
+
+ if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
+ return error;
+
+ getparm(fp, &pa);
+
+ switch (pa.family) {
+ case AF_INET:
+ ud.tidusize = 16384;
+ ud.addrsize = sizeof(struct svr4_sockaddr_in);
+ if (pa.type == SVR4_SOCK_STREAM)
+ ud.etsdusize = 1;
+ else
+ ud.etsdusize = 0;
+ break;
+
+ case AF_LOCAL:
+ ud.tidusize = 65536;
+ ud.addrsize = 128;
+ ud.etsdusize = 128;
+ break;
+
+ default:
+ DPRINTF(("SI_OGETUDATA: Unsupported address family %d\n",
+ pa.family));
+ return ENOSYS;
+ }
+
+ /* I have no idea what these should be! */
+ ud.optsize = 128;
+ ud.tsdusize = 128;
+
+ ud.servtype = pa.type;
+
+ /* XXX: Fixme */
+ ud.so_state = 0;
+ ud.so_options = 0;
+ return copyout(&ud, ioc->buf, ioc->len);
+}
+
+
+static int
+si_sockparams(fp, fd, ioc, td)
+ struct file *fp;
+ int fd;
+ struct svr4_strioctl *ioc;
+ struct thread *td;
+{
+ struct svr4_si_sockparms pa;
+
+ getparm(fp, &pa);
+ return copyout(&pa, ioc->buf, sizeof(pa));
+}
+
+
+static int
+si_listen(fp, fd, ioc, td)
+ struct file *fp;
+ int fd;
+ struct svr4_strioctl *ioc;
+ struct thread *td;
+{
+ int error;
+ struct svr4_strm *st = svr4_stream_get(fp);
+ struct svr4_strmcmd lst;
+ struct listen_args la;
+
+ if (st == NULL)
+ return EINVAL;
+
+ if (ioc->len < 0 || ioc->len > sizeof(lst))
+ return EINVAL;
+
+ if ((error = copyin(ioc->buf, &lst, ioc->len)) != 0)
+ return error;
+
+ if (lst.cmd != SVR4_TI_OLD_BIND_REQUEST) {
+ DPRINTF(("si_listen: bad request %ld\n", lst.cmd));
+ return EINVAL;
+ }
+
+ /*
+ * We are making assumptions again...
+ */
+ la.s = fd;
+ DPRINTF(("SI_LISTEN: fileno %d backlog = %d\n", fd, 5));
+ la.backlog = 5;
+
+ if ((error = sys_listen(td, &la)) != 0) {
+ DPRINTF(("SI_LISTEN: listen failed %d\n", error));
+ return error;
+ }
+
+ st->s_cmd = SVR4_TI__ACCEPT_WAIT;
+ lst.cmd = SVR4_TI_BIND_REPLY;
+
+ switch (st->s_family) {
+ case AF_INET:
+ /* XXX: Fill the length here */
+ break;
+
+ case AF_LOCAL:
+ lst.len = 140;
+ lst.pad[28] = 0x00000000; /* magic again */
+ lst.pad[29] = 0x00000800; /* magic again */
+ lst.pad[30] = 0x80001400; /* magic again */
+ break;
+
+ default:
+ DPRINTF(("SI_LISTEN: Unsupported address family %d\n",
+ st->s_family));
+ return ENOSYS;
+ }
+
+
+ if ((error = copyout(&lst, ioc->buf, ioc->len)) != 0)
+ return error;
+
+ return 0;
+}
+
+
+static int
+si_getudata(fp, fd, ioc, td)
+ struct file *fp;
+ int fd;
+ struct svr4_strioctl *ioc;
+ struct thread *td;
+{
+ int error;
+ struct svr4_si_udata ud;
+
+ if (sizeof(ud) != ioc->len) {
+ DPRINTF(("SI_GETUDATA: Wrong size %d != %d\n",
+ sizeof(ud), ioc->len));
+ return EINVAL;
+ }
+
+ if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
+ return error;
+
+ getparm(fp, &ud.sockparms);
+
+ switch (ud.sockparms.family) {
+ case AF_INET:
+ DPRINTF(("getudata_inet\n"));
+ ud.tidusize = 16384;
+ ud.tsdusize = 16384;
+ ud.addrsize = sizeof(struct svr4_sockaddr_in);
+ if (ud.sockparms.type == SVR4_SOCK_STREAM)
+ ud.etsdusize = 1;
+ else
+ ud.etsdusize = 0;
+ ud.optsize = 0;
+ break;
+
+ case AF_LOCAL:
+ DPRINTF(("getudata_local\n"));
+ ud.tidusize = 65536;
+ ud.tsdusize = 128;
+ ud.addrsize = 128;
+ ud.etsdusize = 128;
+ ud.optsize = 128;
+ break;
+
+ default:
+ DPRINTF(("SI_GETUDATA: Unsupported address family %d\n",
+ ud.sockparms.family));
+ return ENOSYS;
+ }
+
+
+ ud.servtype = ud.sockparms.type;
+ DPRINTF(("ud.servtype = %d\n", ud.servtype));
+ /* XXX: Fixme */
+ ud.so_state = 0;
+ ud.so_options = 0;
+ return copyout(&ud, ioc->buf, sizeof(ud));
+}
+
+
+static int
+si_shutdown(fp, fd, ioc, td)
+ struct file *fp;
+ int fd;
+ struct svr4_strioctl *ioc;
+ struct thread *td;
+{
+ int error;
+ struct shutdown_args ap;
+
+ if (ioc->len != sizeof(ap.how)) {
+ DPRINTF(("SI_SHUTDOWN: Wrong size %d != %d\n",
+ sizeof(ap.how), ioc->len));
+ return EINVAL;
+ }
+
+ if ((error = copyin(ioc->buf, &ap.how, ioc->len)) != 0)
+ return error;
+
+ ap.s = fd;
+
+ return sys_shutdown(td, &ap);
+}
+
+
+static int
+sockmod(fp, fd, ioc, td)
+ struct file *fp;
+ int fd;
+ struct svr4_strioctl *ioc;
+ struct thread *td;
+{
+ switch (ioc->cmd) {
+ case SVR4_SI_OGETUDATA:
+ DPRINTF(("SI_OGETUDATA\n"));
+ return si_ogetudata(fp, fd, ioc, td);
+
+ case SVR4_SI_SHUTDOWN:
+ DPRINTF(("SI_SHUTDOWN\n"));
+ return si_shutdown(fp, fd, ioc, td);
+
+ case SVR4_SI_LISTEN:
+ DPRINTF(("SI_LISTEN\n"));
+ return si_listen(fp, fd, ioc, td);
+
+ case SVR4_SI_SETMYNAME:
+ DPRINTF(("SI_SETMYNAME\n"));
+ return 0;
+
+ case SVR4_SI_SETPEERNAME:
+ DPRINTF(("SI_SETPEERNAME\n"));
+ return 0;
+
+ case SVR4_SI_GETINTRANSIT:
+ DPRINTF(("SI_GETINTRANSIT\n"));
+ return 0;
+
+ case SVR4_SI_TCL_LINK:
+ DPRINTF(("SI_TCL_LINK\n"));
+ return 0;
+
+ case SVR4_SI_TCL_UNLINK:
+ DPRINTF(("SI_TCL_UNLINK\n"));
+ return 0;
+
+ case SVR4_SI_SOCKPARAMS:
+ DPRINTF(("SI_SOCKPARAMS\n"));
+ return si_sockparams(fp, fd, ioc, td);
+
+ case SVR4_SI_GETUDATA:
+ DPRINTF(("SI_GETUDATA\n"));
+ return si_getudata(fp, fd, ioc, td);
+
+ default:
+ DPRINTF(("Unknown sockmod ioctl %lx\n", ioc->cmd));
+ return 0;
+
+ }
+}
+
+
+static int
+ti_getinfo(fp, fd, ioc, td)
+ struct file *fp;
+ int fd;
+ struct svr4_strioctl *ioc;
+ struct thread *td;
+{
+ int error;
+ struct svr4_infocmd info;
+
+ memset(&info, 0, sizeof(info));
+
+ if (ioc->len < 0 || ioc->len > sizeof(info))
+ return EINVAL;
+
+ if ((error = copyin(ioc->buf, &info, ioc->len)) != 0)
+ return error;
+
+ if (info.cmd != SVR4_TI_INFO_REQUEST)
+ return EINVAL;
+
+ info.cmd = SVR4_TI_INFO_REPLY;
+ info.tsdu = 0;
+ info.etsdu = 1;
+ info.cdata = -2;
+ info.ddata = -2;
+ info.addr = 16;
+ info.opt = -1;
+ info.tidu = 16384;
+ info.serv = 2;
+ info.current = 0;
+ info.provider = 2;
+
+ ioc->len = sizeof(info);
+ if ((error = copyout(&info, ioc->buf, ioc->len)) != 0)
+ return error;
+
+ return 0;
+}
+
+
+static int
+ti_bind(fp, fd, ioc, td)
+ struct file *fp;
+ int fd;
+ struct svr4_strioctl *ioc;
+ struct thread *td;
+{
+ int error;
+ struct svr4_strm *st = svr4_stream_get(fp);
+ struct sockaddr_in sain;
+ struct sockaddr_un saun;
+ struct sockaddr *skp;
+ int sasize;
+ struct svr4_strmcmd bnd;
+
+ if (st == NULL) {
+ DPRINTF(("ti_bind: bad file descriptor\n"));
+ return EINVAL;
+ }
+
+ if (ioc->len < 0 || ioc->len > sizeof(bnd))
+ return EINVAL;
+
+ if ((error = copyin(ioc->buf, &bnd, ioc->len)) != 0)
+ return error;
+
+ if (bnd.cmd != SVR4_TI_OLD_BIND_REQUEST) {
+ DPRINTF(("ti_bind: bad request %ld\n", bnd.cmd));
+ return EINVAL;
+ }
+
+ switch (st->s_family) {
+ case AF_INET:
+ skp = (struct sockaddr *)&sain;
+ sasize = sizeof(sain);
+
+ if (bnd.offs == 0)
+ goto error;
+
+ netaddr_to_sockaddr_in(&sain, &bnd);
+
+ DPRINTF(("TI_BIND: fam %d, port %d, addr %x\n",
+ sain.sin_family, sain.sin_port,
+ sain.sin_addr.s_addr));
+ break;
+
+ case AF_LOCAL:
+ skp = (struct sockaddr *)&saun;
+ sasize = sizeof(saun);
+ if (bnd.offs == 0)
+ goto error;
+
+ netaddr_to_sockaddr_un(&saun, &bnd);
+
+ if (saun.sun_path[0] == '\0')
+ goto error;
+
+ DPRINTF(("TI_BIND: fam %d, path %s\n",
+ saun.sun_family, saun.sun_path));
+
+ if ((error = clean_pipe(td, saun.sun_path)) != 0)
+ return error;
+
+ bnd.pad[28] = 0x00001000; /* magic again */
+ break;
+
+ default:
+ DPRINTF(("TI_BIND: Unsupported address family %d\n",
+ st->s_family));
+ return ENOSYS;
+ }
+
+ DPRINTF(("TI_BIND: fileno %d\n", fd));
+
+ if ((error = kern_bind(td, fd, skp)) != 0) {
+ DPRINTF(("TI_BIND: bind failed %d\n", error));
+ return error;
+ }
+ goto reply;
+
+error:
+ memset(&bnd, 0, sizeof(bnd));
+ bnd.len = sasize + 4;
+ bnd.offs = 0x10; /* XXX */
+
+reply:
+ bnd.cmd = SVR4_TI_BIND_REPLY;
+
+ if ((error = copyout(&bnd, ioc->buf, ioc->len)) != 0)
+ return error;
+
+ return 0;
+}
+
+
+static int
+timod(fp, fd, ioc, td)
+ struct file *fp;
+ int fd;
+ struct svr4_strioctl *ioc;
+ struct thread *td;
+{
+ switch (ioc->cmd) {
+ case SVR4_TI_GETINFO:
+ DPRINTF(("TI_GETINFO\n"));
+ return ti_getinfo(fp, fd, ioc, td);
+
+ case SVR4_TI_OPTMGMT:
+ DPRINTF(("TI_OPTMGMT\n"));
+ return 0;
+
+ case SVR4_TI_BIND:
+ DPRINTF(("TI_BIND\n"));
+ return ti_bind(fp, fd, ioc, td);
+
+ case SVR4_TI_UNBIND:
+ DPRINTF(("TI_UNBIND\n"));
+ return 0;
+
+ default:
+ DPRINTF(("Unknown timod ioctl %lx\n", ioc->cmd));
+ return 0;
+ }
+}
+
+
+int
+svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t dat;
+{
+ struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat;
+ struct svr4_strm *st = svr4_stream_get(fp);
+ int error;
+ struct sockaddr *sa;
+ socklen_t sasize, oldsasize;
+ struct svr4_strmcmd sc;
+
+ DPRINTF(("svr4_stream_ti_ioctl\n"));
+
+ if (st == NULL)
+ return EINVAL;
+
+ sc.offs = 0x10;
+
+ if ((error = copyin(sub, &skb, sizeof(skb))) != 0) {
+ DPRINTF(("ti_ioctl: error copying in strbuf\n"));
+ return error;
+ }
+
+ switch (st->s_family) {
+ case AF_INET:
+ sasize = sizeof(struct sockaddr_in);
+ break;
+
+ case AF_LOCAL:
+ sasize = sizeof(struct sockaddr_un);
+ break;
+
+ default:
+ DPRINTF(("ti_ioctl: Unsupported address family %d\n",
+ st->s_family));
+ return ENOSYS;
+ }
+ oldsasize = sasize;
+
+ switch (cmd) {
+ case SVR4_TI_GETMYNAME:
+ DPRINTF(("TI_GETMYNAME\n"));
+ {
+ error = kern_getsockname(td, fd, &sa, &sasize);
+ if (error) {
+ DPRINTF(("ti_ioctl: getsockname error\n"));
+ return error;
+ }
+ }
+ break;
+
+ case SVR4_TI_GETPEERNAME:
+ DPRINTF(("TI_GETPEERNAME\n"));
+ {
+ error = kern_getpeername(td, fd, &sa, &sasize);
+ if (error) {
+ DPRINTF(("ti_ioctl: getpeername error\n"));
+ return error;
+ }
+ }
+ break;
+
+ case SVR4_TI_SETMYNAME:
+ DPRINTF(("TI_SETMYNAME\n"));
+ return 0;
+
+ case SVR4_TI_SETPEERNAME:
+ DPRINTF(("TI_SETPEERNAME\n"));
+ return 0;
+ default:
+ DPRINTF(("ti_ioctl: Unknown ioctl %lx\n", cmd));
+ return ENOSYS;
+ }
+
+ if (sasize < 0 || sasize > oldsasize) {
+ free(sa, M_SONAME);
+ return EINVAL;
+ }
+
+ switch (st->s_family) {
+ case AF_INET:
+ sockaddr_to_netaddr_in(&sc, (struct sockaddr_in *)sa);
+ skb.len = sasize;
+ break;
+
+ case AF_LOCAL:
+ sockaddr_to_netaddr_un(&sc, (struct sockaddr_un *)sa);
+ skb.len = sasize + 4;
+ break;
+
+ default:
+ free(sa, M_SONAME);
+ return ENOSYS;
+ }
+ free(sa, M_SONAME);
+
+ if ((error = copyout(SVR4_ADDROF(&sc), skb.buf, sasize)) != 0) {
+ DPRINTF(("ti_ioctl: error copying out socket data\n"));
+ return error;
+ }
+
+
+ if ((error = copyout(&skb, sub, sizeof(skb))) != 0) {
+ DPRINTF(("ti_ioctl: error copying out strbuf\n"));
+ return error;
+ }
+
+ return error;
+}
+
+
+
+
+static int
+i_nread(fp, td, retval, fd, cmd, dat)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t dat;
+{
+ int error;
+ int nread = 0;
+
+ /*
+ * We are supposed to return the message length in nread, and the
+ * number of messages in retval. We don't have the notion of number
+ * of stream messages, so we just find out if we have any bytes waiting
+ * for us, and if we do, then we assume that we have at least one
+ * message waiting for us.
+ */
+ if ((error = fo_ioctl(fp, FIONREAD, (caddr_t) &nread, td->td_ucred,
+ td)) != 0)
+ return error;
+
+ if (nread != 0)
+ *retval = 1;
+ else
+ *retval = 0;
+
+ return copyout(&nread, dat, sizeof(nread));
+}
+
+static int
+i_fdinsert(fp, td, retval, fd, cmd, dat)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t dat;
+{
+ /*
+ * Major hack again here. We assume that we are using this to
+ * implement accept(2). If that is the case, we have already
+ * called accept, and we have stored the file descriptor in
+ * afd. We find the file descriptor that the code wants to use
+ * in fd insert, and then we dup2() our accepted file descriptor
+ * to it.
+ */
+ int error;
+ struct svr4_strm *st = svr4_stream_get(fp);
+ struct svr4_strfdinsert fdi;
+ struct dup2_args d2p;
+
+ if (st == NULL) {
+ DPRINTF(("fdinsert: bad file type\n"));
+ return EINVAL;
+ }
+
+ mtx_lock(&Giant);
+ if (st->s_afd == -1) {
+ DPRINTF(("fdinsert: accept fd not found\n"));
+ mtx_unlock(&Giant);
+ return ENOENT;
+ }
+
+ if ((error = copyin(dat, &fdi, sizeof(fdi))) != 0) {
+ DPRINTF(("fdinsert: copyin failed %d\n", error));
+ mtx_unlock(&Giant);
+ return error;
+ }
+
+ d2p.from = st->s_afd;
+ d2p.to = fdi.fd;
+
+ if ((error = sys_dup2(td, &d2p)) != 0) {
+ DPRINTF(("fdinsert: dup2(%d, %d) failed %d\n",
+ st->s_afd, fdi.fd, error));
+ mtx_unlock(&Giant);
+ return error;
+ }
+
+ if ((error = kern_close(td, st->s_afd)) != 0) {
+ DPRINTF(("fdinsert: close(%d) failed %d\n",
+ st->s_afd, error));
+ mtx_unlock(&Giant);
+ return error;
+ }
+
+ st->s_afd = -1;
+ mtx_unlock(&Giant);
+
+ *retval = 0;
+ return 0;
+}
+
+
+static int
+_i_bind_rsvd(fp, td, retval, fd, cmd, dat)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t dat;
+{
+ struct mkfifo_args ap;
+
+ /*
+ * This is a supposed to be a kernel and library only ioctl.
+ * It gets called before ti_bind, when we have a unix
+ * socket, to physically create the socket transport and
+ * ``reserve'' it. I don't know how this get reserved inside
+ * the kernel, but we are going to create it nevertheless.
+ */
+ ap.path = dat;
+ ap.mode = S_IFIFO;
+
+ return sys_mkfifo(td, &ap);
+}
+
+static int
+_i_rele_rsvd(fp, td, retval, fd, cmd, dat)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t dat;
+{
+ struct unlink_args ap;
+
+ /*
+ * This is a supposed to be a kernel and library only ioctl.
+ * I guess it is supposed to release the socket.
+ */
+ ap.path = dat;
+
+ return sys_unlink(td, &ap);
+}
+
+static int
+i_str(fp, td, retval, fd, cmd, dat)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t dat;
+{
+ int error;
+ struct svr4_strioctl ioc;
+
+ if ((error = copyin(dat, &ioc, sizeof(ioc))) != 0)
+ return error;
+
+#ifdef DEBUG_SVR4
+ if ((error = show_ioc(">", &ioc)) != 0)
+ return error;
+#endif /* DEBUG_SVR4 */
+
+ switch (ioc.cmd & 0xff00) {
+ case SVR4_SIMOD:
+ if ((error = sockmod(fp, fd, &ioc, td)) != 0)
+ return error;
+ break;
+
+ case SVR4_TIMOD:
+ if ((error = timod(fp, fd, &ioc, td)) != 0)
+ return error;
+ break;
+
+ default:
+ DPRINTF(("Unimplemented module %c %ld\n",
+ (char) (cmd >> 8), cmd & 0xff));
+ return 0;
+ }
+
+#ifdef DEBUG_SVR4
+ if ((error = show_ioc("<", &ioc)) != 0)
+ return error;
+#endif /* DEBUG_SVR4 */
+ return copyout(&ioc, dat, sizeof(ioc));
+}
+
+static int
+i_setsig(fp, td, retval, fd, cmd, dat)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t dat;
+{
+ /*
+ * This is the best we can do for now; we cannot generate
+ * signals only for specific events so the signal mask gets
+ * ignored; we save it just to pass it to a possible I_GETSIG...
+ *
+ * We alse have to fix the O_ASYNC fcntl bit, so the
+ * process will get SIGPOLLs.
+ */
+ int error;
+ register_t oflags, flags;
+ struct svr4_strm *st = svr4_stream_get(fp);
+
+ if (st == NULL) {
+ DPRINTF(("i_setsig: bad file descriptor\n"));
+ return EINVAL;
+ }
+ /* get old status flags */
+ error = kern_fcntl(td, fd, F_GETFL, 0);
+ if (error)
+ return (error);
+
+ oflags = td->td_retval[0];
+
+ /* update the flags */
+ mtx_lock(&Giant);
+ if (dat != NULL) {
+ int mask;
+
+ flags = oflags | O_ASYNC;
+ if ((error = copyin(dat, &mask, sizeof(mask))) != 0) {
+ DPRINTF(("i_setsig: bad eventmask pointer\n"));
+ return error;
+ }
+ if (mask & SVR4_S_ALLMASK) {
+ DPRINTF(("i_setsig: bad eventmask data %x\n", mask));
+ return EINVAL;
+ }
+ st->s_eventmask = mask;
+ }
+ else {
+ flags = oflags & ~O_ASYNC;
+ st->s_eventmask = 0;
+ }
+ mtx_unlock(&Giant);
+
+ /* set the new flags, if changed */
+ if (flags != oflags) {
+ error = kern_fcntl(td, fd, F_SETFL, flags);
+ if (error)
+ return (error);
+ flags = td->td_retval[0];
+ }
+
+ /* set up SIGIO receiver if needed */
+ if (dat != NULL)
+ return (kern_fcntl(td, fd, F_SETOWN, td->td_proc->p_pid));
+ return 0;
+}
+
+static int
+i_getsig(fp, td, retval, fd, cmd, dat)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t dat;
+{
+ int error, eventmask;
+
+ if (dat != NULL) {
+ struct svr4_strm *st = svr4_stream_get(fp);
+
+ if (st == NULL) {
+ DPRINTF(("i_getsig: bad file descriptor\n"));
+ return EINVAL;
+ }
+ mtx_lock(&Giant);
+ eventmask = st->s_eventmask;
+ mtx_unlock(&Giant);
+ if ((error = copyout(&eventmask, dat,
+ sizeof(eventmask))) != 0) {
+ DPRINTF(("i_getsig: bad eventmask pointer\n"));
+ return error;
+ }
+ }
+ return 0;
+}
+
+int
+svr4_stream_ioctl(fp, td, retval, fd, cmd, dat)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t dat;
+{
+ *retval = 0;
+
+ /*
+ * All the following stuff assumes "sockmod" is pushed...
+ */
+ switch (cmd) {
+ case SVR4_I_NREAD:
+ DPRINTF(("I_NREAD\n"));
+ return i_nread(fp, td, retval, fd, cmd, dat);
+
+ case SVR4_I_PUSH:
+ DPRINTF(("I_PUSH %p\n", dat));
+#if defined(DEBUG_SVR4)
+ show_strbuf((struct svr4_strbuf *)dat);
+#endif
+ return 0;
+
+ case SVR4_I_POP:
+ DPRINTF(("I_POP\n"));
+ return 0;
+
+ case SVR4_I_LOOK:
+ DPRINTF(("I_LOOK\n"));
+ return 0;
+
+ case SVR4_I_FLUSH:
+ DPRINTF(("I_FLUSH\n"));
+ return 0;
+
+ case SVR4_I_SRDOPT:
+ DPRINTF(("I_SRDOPT\n"));
+ return 0;
+
+ case SVR4_I_GRDOPT:
+ DPRINTF(("I_GRDOPT\n"));
+ return 0;
+
+ case SVR4_I_STR:
+ DPRINTF(("I_STR\n"));
+ return i_str(fp, td, retval, fd, cmd, dat);
+
+ case SVR4_I_SETSIG:
+ DPRINTF(("I_SETSIG\n"));
+ return i_setsig(fp, td, retval, fd, cmd, dat);
+
+ case SVR4_I_GETSIG:
+ DPRINTF(("I_GETSIG\n"));
+ return i_getsig(fp, td, retval, fd, cmd, dat);
+
+ case SVR4_I_FIND:
+ DPRINTF(("I_FIND\n"));
+ /*
+ * Here we are not pushing modules really, we just
+ * pretend all are present
+ */
+ *retval = 0;
+ return 0;
+
+ case SVR4_I_LINK:
+ DPRINTF(("I_LINK\n"));
+ return 0;
+
+ case SVR4_I_UNLINK:
+ DPRINTF(("I_UNLINK\n"));
+ return 0;
+
+ case SVR4_I_ERECVFD:
+ DPRINTF(("I_ERECVFD\n"));
+ return 0;
+
+ case SVR4_I_PEEK:
+ DPRINTF(("I_PEEK\n"));
+ return 0;
+
+ case SVR4_I_FDINSERT:
+ DPRINTF(("I_FDINSERT\n"));
+ return i_fdinsert(fp, td, retval, fd, cmd, dat);
+
+ case SVR4_I_SENDFD:
+ DPRINTF(("I_SENDFD\n"));
+ return 0;
+
+ case SVR4_I_RECVFD:
+ DPRINTF(("I_RECVFD\n"));
+ return 0;
+
+ case SVR4_I_SWROPT:
+ DPRINTF(("I_SWROPT\n"));
+ return 0;
+
+ case SVR4_I_GWROPT:
+ DPRINTF(("I_GWROPT\n"));
+ return 0;
+
+ case SVR4_I_LIST:
+ DPRINTF(("I_LIST\n"));
+ return 0;
+
+ case SVR4_I_PLINK:
+ DPRINTF(("I_PLINK\n"));
+ return 0;
+
+ case SVR4_I_PUNLINK:
+ DPRINTF(("I_PUNLINK\n"));
+ return 0;
+
+ case SVR4_I_SETEV:
+ DPRINTF(("I_SETEV\n"));
+ return 0;
+
+ case SVR4_I_GETEV:
+ DPRINTF(("I_GETEV\n"));
+ return 0;
+
+ case SVR4_I_STREV:
+ DPRINTF(("I_STREV\n"));
+ return 0;
+
+ case SVR4_I_UNSTREV:
+ DPRINTF(("I_UNSTREV\n"));
+ return 0;
+
+ case SVR4_I_FLUSHBAND:
+ DPRINTF(("I_FLUSHBAND\n"));
+ return 0;
+
+ case SVR4_I_CKBAND:
+ DPRINTF(("I_CKBAND\n"));
+ return 0;
+
+ case SVR4_I_GETBAND:
+ DPRINTF(("I_GETBANK\n"));
+ return 0;
+
+ case SVR4_I_ATMARK:
+ DPRINTF(("I_ATMARK\n"));
+ return 0;
+
+ case SVR4_I_SETCLTIME:
+ DPRINTF(("I_SETCLTIME\n"));
+ return 0;
+
+ case SVR4_I_GETCLTIME:
+ DPRINTF(("I_GETCLTIME\n"));
+ return 0;
+
+ case SVR4_I_CANPUT:
+ DPRINTF(("I_CANPUT\n"));
+ return 0;
+
+ case SVR4__I_BIND_RSVD:
+ DPRINTF(("_I_BIND_RSVD\n"));
+ return _i_bind_rsvd(fp, td, retval, fd, cmd, dat);
+
+ case SVR4__I_RELE_RSVD:
+ DPRINTF(("_I_RELE_RSVD\n"));
+ return _i_rele_rsvd(fp, td, retval, fd, cmd, dat);
+
+ default:
+ DPRINTF(("unimpl cmd = %lx\n", cmd));
+ break;
+ }
+
+ return 0;
+}
+
+
+
+int
+svr4_sys_putmsg(td, uap)
+ struct thread *td;
+ struct svr4_sys_putmsg_args *uap;
+{
+ struct file *fp;
+ int error;
+
+ if ((error = fget(td, uap->fd, CAP_SEND, &fp)) != 0) {
+#ifdef DEBUG_SVR4
+ uprintf("putmsg: bad fp\n");
+#endif
+ return EBADF;
+ }
+ error = svr4_do_putmsg(td, uap, fp);
+ fdrop(fp, td);
+ return (error);
+}
+
+static int
+svr4_do_putmsg(td, uap, fp)
+ struct thread *td;
+ struct svr4_sys_putmsg_args *uap;
+ struct file *fp;
+{
+ struct svr4_strbuf dat, ctl;
+ struct svr4_strmcmd sc;
+ struct sockaddr_in sain;
+ struct sockaddr_un saun;
+ struct sockaddr *sa;
+ int sasize, *retval;
+ struct svr4_strm *st;
+ int error;
+
+ retval = td->td_retval;
+
+#ifdef DEBUG_SVR4
+ show_msg(">putmsg", uap->fd, uap->ctl,
+ uap->dat, uap->flags);
+#endif /* DEBUG_SVR4 */
+
+ if (uap->ctl != NULL) {
+ if ((error = copyin(uap->ctl, &ctl, sizeof(ctl))) != 0) {
+#ifdef DEBUG_SVR4
+ uprintf("putmsg: copyin(): %d\n", error);
+#endif
+ return error;
+ }
+ }
+ else
+ ctl.len = -1;
+
+ if (uap->dat != NULL) {
+ if ((error = copyin(uap->dat, &dat, sizeof(dat))) != 0) {
+#ifdef DEBUG_SVR4
+ uprintf("putmsg: copyin(): %d (2)\n", error);
+#endif
+ return error;
+ }
+ }
+ else
+ dat.len = -1;
+
+ /*
+ * Only for sockets for now.
+ */
+ if ((st = svr4_stream_get(fp)) == NULL) {
+ DPRINTF(("putmsg: bad file type\n"));
+ return EINVAL;
+ }
+
+ if (ctl.len < 0 || ctl.len > sizeof(sc)) {
+ DPRINTF(("putmsg: Bad control size %d != %d\n", ctl.len,
+ sizeof(struct svr4_strmcmd)));
+ return EINVAL;
+ }
+
+ if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
+ return error;
+
+ switch (st->s_family) {
+ case AF_INET:
+ if (sc.len != sizeof(sain)) {
+ if (sc.cmd == SVR4_TI_DATA_REQUEST) {
+ struct write_args wa;
+
+ /* Solaris seems to use sc.cmd = 3 to
+ * send "expedited" data. telnet uses
+ * this for options processing, sending EOF,
+ * etc. I'm sure other things use it too.
+ * I don't have any documentation
+ * on it, so I'm making a guess that this
+ * is how it works. newton@atdot.dotat.org XXX
+ */
+ DPRINTF(("sending expedited data ??\n"));
+ wa.fd = uap->fd;
+ wa.buf = dat.buf;
+ wa.nbyte = dat.len;
+ return sys_write(td, &wa);
+ }
+ DPRINTF(("putmsg: Invalid inet length %ld\n", sc.len));
+ return EINVAL;
+ }
+ netaddr_to_sockaddr_in(&sain, &sc);
+ sa = (struct sockaddr *)&sain;
+ sasize = sizeof(sain);
+ if (sain.sin_family != st->s_family)
+ error = EINVAL;
+ break;
+
+ case AF_LOCAL:
+ if (ctl.len == 8) {
+ /* We are doing an accept; succeed */
+ DPRINTF(("putmsg: Do nothing\n"));
+ *retval = 0;
+ return 0;
+ }
+ else {
+ /* Maybe we've been given a device/inode pair */
+ dev_t *dev = SVR4_ADDROF(&sc);
+ ino_t *ino = (ino_t *) &dev[1];
+ if (svr4_find_socket(td, fp, *dev, *ino, &saun) != 0) {
+ /* I guess we have it by name */
+ netaddr_to_sockaddr_un(&saun, &sc);
+ }
+ sa = (struct sockaddr *)&saun;
+ sasize = sizeof(saun);
+ }
+ break;
+
+ default:
+ DPRINTF(("putmsg: Unsupported address family %d\n",
+ st->s_family));
+ return ENOSYS;
+ }
+
+ mtx_lock(&Giant);
+ st->s_cmd = sc.cmd;
+ mtx_unlock(&Giant);
+ switch (sc.cmd) {
+ case SVR4_TI_CONNECT_REQUEST: /* connect */
+ {
+
+ return (kern_connect(td, uap->fd, sa));
+ }
+
+ case SVR4_TI_SENDTO_REQUEST: /* sendto */
+ {
+ struct msghdr msg;
+ struct iovec aiov;
+
+ msg.msg_name = sa;
+ msg.msg_namelen = sasize;
+ msg.msg_iov = &aiov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = 0;
+ msg.msg_flags = 0;
+ aiov.iov_base = dat.buf;
+ aiov.iov_len = dat.len;
+ error = kern_sendit(td, uap->fd, &msg, uap->flags,
+ NULL, UIO_USERSPACE);
+ DPRINTF(("sendto_request error: %d\n", error));
+ *retval = 0;
+ return error;
+ }
+
+ default:
+ DPRINTF(("putmsg: Unimplemented command %lx\n", sc.cmd));
+ return ENOSYS;
+ }
+}
+
+int
+svr4_sys_getmsg(td, uap)
+ struct thread *td;
+ struct svr4_sys_getmsg_args *uap;
+{
+ struct file *fp;
+ int error;
+
+ if ((error = fget(td, uap->fd, CAP_RECV, &fp)) != 0) {
+#ifdef DEBUG_SVR4
+ uprintf("getmsg: bad fp\n");
+#endif
+ return EBADF;
+ }
+ error = svr4_do_getmsg(td, uap, fp);
+ fdrop(fp, td);
+ return (error);
+}
+
+int
+svr4_do_getmsg(td, uap, fp)
+ struct thread *td;
+ struct svr4_sys_getmsg_args *uap;
+ struct file *fp;
+{
+ struct svr4_strbuf dat, ctl;
+ struct svr4_strmcmd sc;
+ int error, *retval;
+ struct msghdr msg;
+ struct iovec aiov;
+ struct sockaddr_in sain;
+ struct sockaddr_un saun;
+ struct sockaddr *sa;
+ socklen_t sasize;
+ struct svr4_strm *st;
+ struct file *afp;
+ int fl;
+
+ retval = td->td_retval;
+ error = 0;
+ afp = NULL;
+
+ memset(&sc, 0, sizeof(sc));
+
+#ifdef DEBUG_SVR4
+ show_msg(">getmsg", uap->fd, uap->ctl,
+ uap->dat, 0);
+#endif /* DEBUG_SVR4 */
+
+ if (uap->ctl != NULL) {
+ if ((error = copyin(uap->ctl, &ctl, sizeof(ctl))) != 0)
+ return error;
+ if (ctl.len < 0)
+ return EINVAL;
+ }
+ else {
+ ctl.len = -1;
+ ctl.maxlen = 0;
+ }
+
+ if (uap->dat != NULL) {
+ if ((error = copyin(uap->dat, &dat, sizeof(dat))) != 0)
+ return error;
+ }
+ else {
+ dat.len = -1;
+ dat.maxlen = 0;
+ }
+
+ /*
+ * Only for sockets for now.
+ */
+ if ((st = svr4_stream_get(fp)) == NULL) {
+ DPRINTF(("getmsg: bad file type\n"));
+ return EINVAL;
+ }
+
+ if (ctl.maxlen == -1 || dat.maxlen == -1) {
+ DPRINTF(("getmsg: Cannot handle -1 maxlen (yet)\n"));
+ return ENOSYS;
+ }
+
+ switch (st->s_family) {
+ case AF_INET:
+ sasize = sizeof(sain);
+ break;
+
+ case AF_LOCAL:
+ sasize = sizeof(saun);
+ break;
+
+ default:
+ DPRINTF(("getmsg: Unsupported address family %d\n",
+ st->s_family));
+ return ENOSYS;
+ }
+
+ mtx_lock(&Giant);
+ switch (st->s_cmd) {
+ case SVR4_TI_CONNECT_REQUEST:
+ DPRINTF(("getmsg: TI_CONNECT_REQUEST\n"));
+ /*
+ * We do the connect in one step, so the putmsg should
+ * have gotten the error.
+ */
+ sc.cmd = SVR4_TI_OK_REPLY;
+ sc.len = 0;
+
+ ctl.len = 8;
+ dat.len = -1;
+ fl = 1;
+ st->s_cmd = sc.cmd;
+ break;
+
+ case SVR4_TI_OK_REPLY:
+ DPRINTF(("getmsg: TI_OK_REPLY\n"));
+ /*
+ * We are immediately after a connect reply, so we send
+ * a connect verification.
+ */
+
+ error = kern_getpeername(td, uap->fd, &sa, &sasize);
+ if (error) {
+ mtx_unlock(&Giant);
+ DPRINTF(("getmsg: getpeername failed %d\n", error));
+ return error;
+ }
+
+ sc.cmd = SVR4_TI_CONNECT_REPLY;
+ sc.pad[0] = 0x4;
+ sc.offs = 0x18;
+ sc.pad[1] = 0x14;
+ sc.pad[2] = 0x04000402;
+
+ switch (st->s_family) {
+ case AF_INET:
+ sc.len = sasize;
+ sockaddr_to_netaddr_in(&sc, (struct sockaddr_in *)sa);
+ break;
+
+ case AF_LOCAL:
+ sc.len = sasize + 4;
+ sockaddr_to_netaddr_un(&sc, (struct sockaddr_un *)sa);
+ break;
+
+ default:
+ mtx_unlock(&Giant);
+ free(sa, M_SONAME);
+ return ENOSYS;
+ }
+ free(sa, M_SONAME);
+
+ ctl.len = 40;
+ dat.len = -1;
+ fl = 0;
+ st->s_cmd = sc.cmd;
+ break;
+
+ case SVR4_TI__ACCEPT_OK:
+ DPRINTF(("getmsg: TI__ACCEPT_OK\n"));
+ /*
+ * We do the connect in one step, so the putmsg should
+ * have gotten the error.
+ */
+ sc.cmd = SVR4_TI_OK_REPLY;
+ sc.len = 1;
+
+ ctl.len = 8;
+ dat.len = -1;
+ fl = 1;
+ st->s_cmd = SVR4_TI__ACCEPT_WAIT;
+ break;
+
+ case SVR4_TI__ACCEPT_WAIT:
+ DPRINTF(("getmsg: TI__ACCEPT_WAIT\n"));
+ /*
+ * We are after a listen, so we try to accept...
+ */
+
+ error = kern_accept(td, uap->fd, &sa, &sasize, &afp);
+ if (error) {
+ mtx_unlock(&Giant);
+ DPRINTF(("getmsg: accept failed %d\n", error));
+ return error;
+ }
+
+ st->s_afd = *retval;
+
+ DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd));
+
+ sc.cmd = SVR4_TI_ACCEPT_REPLY;
+ sc.offs = 0x18;
+ sc.pad[0] = 0x0;
+
+ switch (st->s_family) {
+ case AF_INET:
+ sc.pad[1] = 0x28;
+ sockaddr_to_netaddr_in(&sc, (struct sockaddr_in *)&sa);
+ ctl.len = 40;
+ sc.len = sasize;
+ break;
+
+ case AF_LOCAL:
+ sc.pad[1] = 0x00010000;
+ sc.pad[2] = 0xf6bcdaa0; /* I don't know what that is */
+ sc.pad[3] = 0x00010000;
+ ctl.len = 134;
+ sc.len = sasize + 4;
+ break;
+
+ default:
+ fdclose(td->td_proc->p_fd, afp, st->s_afd, td);
+ fdrop(afp, td);
+ st->s_afd = -1;
+ mtx_unlock(&Giant);
+ free(sa, M_SONAME);
+ return ENOSYS;
+ }
+ free(sa, M_SONAME);
+
+ dat.len = -1;
+ fl = 0;
+ st->s_cmd = SVR4_TI__ACCEPT_OK;
+ break;
+
+ case SVR4_TI_SENDTO_REQUEST:
+ DPRINTF(("getmsg: TI_SENDTO_REQUEST\n"));
+ if (ctl.maxlen > 36 && ctl.len < 36)
+ ctl.len = 36;
+
+ if (ctl.len > sizeof(sc))
+ ctl.len = sizeof(sc);
+
+ if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0) {
+ mtx_unlock(&Giant);
+ return error;
+ }
+
+ switch (st->s_family) {
+ case AF_INET:
+ sa = (struct sockaddr *)&sain;
+ sockaddr_to_netaddr_in(&sc, &sain);
+ break;
+
+ case AF_LOCAL:
+ sa = (struct sockaddr *)&saun;
+ sockaddr_to_netaddr_un(&sc, &saun);
+ break;
+
+ default:
+ mtx_unlock(&Giant);
+ return ENOSYS;
+ }
+
+ msg.msg_name = sa;
+ msg.msg_namelen = sasize;
+ msg.msg_iov = &aiov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = 0;
+ aiov.iov_base = dat.buf;
+ aiov.iov_len = dat.maxlen;
+ msg.msg_flags = 0;
+
+ error = kern_recvit(td, uap->fd, &msg, UIO_SYSSPACE, NULL);
+
+ if (error) {
+ mtx_unlock(&Giant);
+ DPRINTF(("getmsg: recvit failed %d\n", error));
+ return error;
+ }
+
+ sc.cmd = SVR4_TI_RECVFROM_IND;
+
+ switch (st->s_family) {
+ case AF_INET:
+ sc.len = sasize;
+ sockaddr_to_netaddr_in(&sc, &sain);
+ break;
+
+ case AF_LOCAL:
+ sc.len = sasize + 4;
+ sockaddr_to_netaddr_un(&sc, &saun);
+ break;
+
+ default:
+ mtx_unlock(&Giant);
+ return ENOSYS;
+ }
+
+ dat.len = *retval;
+ fl = 0;
+ st->s_cmd = sc.cmd;
+ break;
+
+ default:
+ st->s_cmd = sc.cmd;
+ if (st->s_cmd == SVR4_TI_CONNECT_REQUEST) {
+ struct read_args ra;
+
+ /* More weirdness: Again, I can't find documentation
+ * to back this up, but when a process does a generic
+ * "getmsg()" call it seems that the command field is
+ * zero and the length of the data area is zero. I
+ * think processes expect getmsg() to fill in dat.len
+ * after reading at most dat.maxlen octets from the
+ * stream. Since we're using sockets I can let
+ * read() look after it and frob return values
+ * appropriately (or inappropriately :-)
+ * -- newton@atdot.dotat.org XXX
+ */
+ ra.fd = uap->fd;
+ ra.buf = dat.buf;
+ ra.nbyte = dat.maxlen;
+ if ((error = sys_read(td, &ra)) != 0) {
+ mtx_unlock(&Giant);
+ return error;
+ }
+ dat.len = *retval;
+ *retval = 0;
+ st->s_cmd = SVR4_TI_SENDTO_REQUEST;
+ break;
+ }
+ mtx_unlock(&Giant);
+ DPRINTF(("getmsg: Unknown state %x\n", st->s_cmd));
+ return EINVAL;
+ }
+
+ if (uap->ctl) {
+ if (ctl.len > sizeof(sc))
+ ctl.len = sizeof(sc);
+ if (ctl.len != -1)
+ error = copyout(&sc, ctl.buf, ctl.len);
+
+ if (error == 0)
+ error = copyout(&ctl, uap->ctl, sizeof(ctl));
+ }
+
+ if (uap->dat) {
+ if (error == 0)
+ error = copyout(&dat, uap->dat, sizeof(dat));
+ }
+
+ if (uap->flags) { /* XXX: Need translation */
+ if (error == 0)
+ error = copyout(&fl, uap->flags, sizeof(fl));
+ }
+
+ if (error) {
+ if (afp) {
+ fdclose(td->td_proc->p_fd, afp, st->s_afd, td);
+ fdrop(afp, td);
+ st->s_afd = -1;
+ }
+ mtx_unlock(&Giant);
+ return (error);
+ }
+ mtx_unlock(&Giant);
+ if (afp)
+ fdrop(afp, td);
+
+ *retval = 0;
+
+#ifdef DEBUG_SVR4
+ show_msg("<getmsg", uap->fd, uap->ctl,
+ uap->dat, fl);
+#endif /* DEBUG_SVR4 */
+ return error;
+}
+
+int svr4_sys_send(td, uap)
+ struct thread *td;
+ struct svr4_sys_send_args *uap;
+{
+ struct sendto_args sta;
+
+ sta.s = uap->s;
+ sta.buf = uap->buf;
+ sta.len = uap->len;
+ sta.flags = uap->flags;
+ sta.to = NULL;
+ sta.tolen = 0;
+
+ return (sys_sendto(td, &sta));
+}
+
+int svr4_sys_recv(td, uap)
+ struct thread *td;
+ struct svr4_sys_recv_args *uap;
+{
+ struct recvfrom_args rfa;
+
+ rfa.s = uap->s;
+ rfa.buf = uap->buf;
+ rfa.len = uap->len;
+ rfa.flags = uap->flags;
+ rfa.from = NULL;
+ rfa.fromlenaddr = NULL;
+
+ return (sys_recvfrom(td, &rfa));
+}
+
+/*
+ * XXX This isn't necessary, but it's handy for inserting debug code into
+ * sendto(). Let's leave it here for now...
+ */
+int
+svr4_sys_sendto(td, uap)
+ struct thread *td;
+ struct svr4_sys_sendto_args *uap;
+{
+ struct sendto_args sa;
+
+ sa.s = uap->s;
+ sa.buf = uap->buf;
+ sa.len = uap->len;
+ sa.flags = uap->flags;
+ sa.to = (caddr_t)uap->to;
+ sa.tolen = uap->tolen;
+
+ DPRINTF(("calling sendto()\n"));
+ return sys_sendto(td, &sa);
+}
+
diff --git a/sys/compat/svr4/svr4_stropts.h b/sys/compat/svr4/svr4_stropts.h
new file mode 100644
index 0000000..a96c24d
--- /dev/null
+++ b/sys/compat/svr4/svr4_stropts.h
@@ -0,0 +1,179 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_STROPTS_H_
+#define _SVR4_STROPTS_H_
+
+
+struct svr4_strbuf {
+ int maxlen;
+ int len;
+ char *buf;
+};
+
+#define SVR4_STR ('S' << 8)
+#define SVR4_I_NREAD (SVR4_STR| 1)
+#define SVR4_I_PUSH (SVR4_STR| 2)
+#define SVR4_I_POP (SVR4_STR| 3)
+#define SVR4_I_LOOK (SVR4_STR| 4)
+#define SVR4_I_FLUSH (SVR4_STR| 5)
+#define SVR4_I_SRDOPT (SVR4_STR| 6)
+#define SVR4_I_GRDOPT (SVR4_STR| 7)
+#define SVR4_I_STR (SVR4_STR| 8)
+#define SVR4_I_SETSIG (SVR4_STR| 9)
+#define SVR4_I_GETSIG (SVR4_STR|10)
+#define SVR4_I_FIND (SVR4_STR|11)
+#define SVR4_I_LINK (SVR4_STR|12)
+#define SVR4_I_UNLINK (SVR4_STR|13)
+#define SVR4_I_ERECVFD (SVR4_STR|14)
+#define SVR4_I_PEEK (SVR4_STR|15)
+#define SVR4_I_FDINSERT (SVR4_STR|16)
+#define SVR4_I_SENDFD (SVR4_STR|17)
+#define SVR4_I_RECVFD (SVR4_STR|18)
+#define SVR4_I_SWROPT (SVR4_STR|19)
+#define SVR4_I_GWROPT (SVR4_STR|20)
+#define SVR4_I_LIST (SVR4_STR|21)
+#define SVR4_I_PLINK (SVR4_STR|22)
+#define SVR4_I_PUNLINK (SVR4_STR|23)
+#define SVR4_I_SETEV (SVR4_STR|24)
+#define SVR4_I_GETEV (SVR4_STR|25)
+#define SVR4_I_STREV (SVR4_STR|26)
+#define SVR4_I_UNSTREV (SVR4_STR|27)
+#define SVR4_I_FLUSHBAND (SVR4_STR|28)
+#define SVR4_I_CKBAND (SVR4_STR|29)
+#define SVR4_I_GETBAND (SVR4_STR|30)
+#define SVR4_I_ATMARK (SVR4_STR|31)
+#define SVR4_I_SETCLTIME (SVR4_STR|32)
+#define SVR4_I_GETCLTIME (SVR4_STR|33)
+#define SVR4_I_CANPUT (SVR4_STR|34)
+
+/*
+ * The following two ioctls are OS specific and
+ * undocumented.
+ */
+#define SVR4__I_BIND_RSVD (SVR4_STR|242)
+#define SVR4__I_RELE_RSVD (SVR4_STR|243)
+
+/*
+ * Service type definitions
+ */
+#define SVR4_T_COTS 1 /* Connection-orieted */
+#define SVR4_T_COTS_ORD 2 /* Local connection-oriented */
+#define SVR4_T_CLTS 3 /* Connectionless */
+
+/* Struct passed for SVR4_I_STR */
+struct svr4_strioctl {
+ u_long cmd;
+ int timeout;
+ int len;
+ char *buf;
+};
+
+/*
+ * Bits for I_{G,S}ETSIG
+ */
+#define SVR4_S_INPUT 0x0001 /* any message on read queue no HIPRI */
+#define SVR4_S_HIPRI 0x0002 /* high prio message on read queue */
+#define SVR4_S_OUTPUT 0x0004 /* write queue has free space */
+#define SVR4_S_MSG 0x0008 /* signal message in read queue head */
+#define SVR4_S_ERROR 0x0010 /* error message in read queue head */
+#define SVR4_S_HANGUP 0x0020 /* hangup message in read queue head */
+#define SVR4_S_RDNORM 0x0040 /* normal message on read queue */
+#define SVR4_S_WRNORM S_OUTPUT /* write queue has free space */
+#define SVR4_S_RDBAND 0x0080 /* out of band message on read queue */
+#define SVR4_S_WRBAND 0x0100 /* write queue has free space for oob */
+#define SVR4_S_BANDURG 0x0200 /* generate SIGURG instead of SIGPOLL */
+#define SVR4_S_ALLMASK 0x03ff /* all events mask */
+
+/*
+ * Our internal state for the stream
+ * For now we keep almost nothing... In the future we can keep more
+ * streams state.
+ *
+ * Locking key:
+ * r - Read only field only set during creation
+ * G - Giant
+ */
+struct svr4_strm {
+ int s_family; /* (r) socket family */
+ int s_cmd; /* (G) last getmsg reply or putmsg request */
+ int s_afd; /* (G) last accepted fd; [for fd_insert] */
+ int s_eventmask; /* (G) state info from I_SETSIG et al */
+};
+
+/*
+ * The following structures are determined empirically.
+ */
+struct svr4_strmcmd {
+ long cmd; /* command ? */
+ long len; /* Address len */
+ long offs; /* Address offset */
+ long pad[61];
+};
+
+struct svr4_infocmd {
+ long cmd;
+ long tsdu;
+ long etsdu;
+ long cdata;
+ long ddata;
+ long addr;
+ long opt;
+ long tidu;
+ long serv;
+ long current;
+ long provider;
+};
+
+struct svr4_strfdinsert {
+ struct svr4_strbuf ctl;
+ struct svr4_strbuf data;
+ long flags;
+ int fd;
+ int offset;
+};
+
+struct svr4_netaddr_in {
+ u_short family;
+ u_short port;
+ u_long addr;
+};
+
+struct svr4_netaddr_un {
+ u_short family;
+ char path[1];
+};
+
+#define SVR4_ADDROF(sc) (void *) (((char *) (sc)) + (sc)->offs)
+#define SVR4_C_ADDROF(sc) (const void *) (((const char *) (sc)) + (sc)->offs)
+
+struct svr4_strm *svr4_stream_get(struct file *fp);
+
+#endif /* !_SVR4_STROPTS */
diff --git a/sys/compat/svr4/svr4_syscall.h b/sys/compat/svr4/svr4_syscall.h
new file mode 100644
index 0000000..1500591
--- /dev/null
+++ b/sys/compat/svr4/svr4_syscall.h
@@ -0,0 +1,147 @@
+/*
+ * System call numbers.
+ *
+ * DO NOT EDIT-- this file is automatically generated.
+ * $FreeBSD$
+ * created from FreeBSD: head/sys/compat/svr4/syscalls.master 227691 2011-11-19 06:35:15Z ed
+ */
+
+#define SVR4_SYS_exit 1
+#define SVR4_SYS_fork 2
+#define SVR4_SYS_read 3
+#define SVR4_SYS_write 4
+#define SVR4_SYS_svr4_sys_open 5
+#define SVR4_SYS_close 6
+#define SVR4_SYS_svr4_sys_wait 7
+#define SVR4_SYS_svr4_sys_creat 8
+#define SVR4_SYS_link 9
+#define SVR4_SYS_unlink 10
+#define SVR4_SYS_svr4_sys_execv 11
+#define SVR4_SYS_chdir 12
+#define SVR4_SYS_svr4_sys_time 13
+#define SVR4_SYS_svr4_sys_mknod 14
+#define SVR4_SYS_chmod 15
+#define SVR4_SYS_chown 16
+#define SVR4_SYS_svr4_sys_break 17
+#define SVR4_SYS_svr4_sys_stat 18
+#define SVR4_SYS_lseek 19
+#define SVR4_SYS_getpid 20
+#define SVR4_SYS_setuid 23
+#define SVR4_SYS_getuid 24
+#define SVR4_SYS_svr4_sys_alarm 27
+#define SVR4_SYS_svr4_sys_fstat 28
+#define SVR4_SYS_svr4_sys_pause 29
+#define SVR4_SYS_svr4_sys_utime 30
+#define SVR4_SYS_svr4_sys_access 33
+#define SVR4_SYS_svr4_sys_nice 34
+#define SVR4_SYS_sync 36
+#define SVR4_SYS_svr4_sys_kill 37
+#define SVR4_SYS_svr4_sys_pgrpsys 39
+#define SVR4_SYS_dup 41
+#define SVR4_SYS_pipe 42
+#define SVR4_SYS_svr4_sys_times 43
+#define SVR4_SYS_setgid 46
+#define SVR4_SYS_getgid 47
+#define SVR4_SYS_svr4_sys_signal 48
+#define SVR4_SYS_svr4_sys_msgsys 49
+#define SVR4_SYS_svr4_sys_sysarch 50
+#define SVR4_SYS_svr4_sys_shmsys 52
+#define SVR4_SYS_svr4_sys_semsys 53
+#define SVR4_SYS_svr4_sys_ioctl 54
+#define SVR4_SYS_svr4_sys_utssys 57
+#define SVR4_SYS_fsync 58
+#define SVR4_SYS_svr4_sys_execve 59
+#define SVR4_SYS_umask 60
+#define SVR4_SYS_chroot 61
+#define SVR4_SYS_svr4_sys_fcntl 62
+#define SVR4_SYS_svr4_sys_ulimit 63
+#define SVR4_SYS_rmdir 79
+#define SVR4_SYS_mkdir 80
+#define SVR4_SYS_svr4_sys_getdents 81
+#define SVR4_SYS_svr4_sys_getmsg 85
+#define SVR4_SYS_svr4_sys_putmsg 86
+#define SVR4_SYS_svr4_sys_poll 87
+#define SVR4_SYS_svr4_sys_lstat 88
+#define SVR4_SYS_symlink 89
+#define SVR4_SYS_readlink 90
+#define SVR4_SYS_getgroups 91
+#define SVR4_SYS_setgroups 92
+#define SVR4_SYS_fchmod 93
+#define SVR4_SYS_fchown 94
+#define SVR4_SYS_svr4_sys_sigprocmask 95
+#define SVR4_SYS_svr4_sys_sigsuspend 96
+#define SVR4_SYS_svr4_sys_sigaltstack 97
+#define SVR4_SYS_svr4_sys_sigaction 98
+#define SVR4_SYS_svr4_sys_sigpending 99
+#define SVR4_SYS_svr4_sys_context 100
+#define SVR4_SYS_svr4_sys_statvfs 103
+#define SVR4_SYS_svr4_sys_fstatvfs 104
+#define SVR4_SYS_svr4_sys_waitsys 107
+#define SVR4_SYS_svr4_sys_hrtsys 109
+#define SVR4_SYS_svr4_sys_pathconf 113
+#define SVR4_SYS_svr4_sys_mmap 115
+#define SVR4_SYS_mprotect 116
+#define SVR4_SYS_munmap 117
+#define SVR4_SYS_svr4_sys_fpathconf 118
+#define SVR4_SYS_vfork 119
+#define SVR4_SYS_fchdir 120
+#define SVR4_SYS_readv 121
+#define SVR4_SYS_writev 122
+#define SVR4_SYS_svr4_sys_xstat 123
+#define SVR4_SYS_svr4_sys_lxstat 124
+#define SVR4_SYS_svr4_sys_fxstat 125
+#define SVR4_SYS_svr4_sys_xmknod 126
+#define SVR4_SYS_svr4_sys_setrlimit 128
+#define SVR4_SYS_svr4_sys_getrlimit 129
+#define SVR4_SYS_lchown 130
+#define SVR4_SYS_svr4_sys_memcntl 131
+#define SVR4_SYS_rename 134
+#define SVR4_SYS_svr4_sys_uname 135
+#define SVR4_SYS_setegid 136
+#define SVR4_SYS_svr4_sys_sysconfig 137
+#define SVR4_SYS_adjtime 138
+#define SVR4_SYS_svr4_sys_systeminfo 139
+#define SVR4_SYS_seteuid 141
+#define SVR4_SYS_svr4_sys_fchroot 153
+#define SVR4_SYS_svr4_sys_utimes 154
+#define SVR4_SYS_svr4_sys_vhangup 155
+#define SVR4_SYS_svr4_sys_gettimeofday 156
+#define SVR4_SYS_getitimer 157
+#define SVR4_SYS_setitimer 158
+#define SVR4_SYS_svr4_sys_llseek 175
+#define SVR4_SYS_svr4_sys_acl 185
+#define SVR4_SYS_svr4_sys_auditsys 186
+#define SVR4_SYS_nanosleep 199
+#define SVR4_SYS_svr4_sys_facl 200
+#define SVR4_SYS_setreuid 202
+#define SVR4_SYS_setregid 203
+#define SVR4_SYS_svr4_sys_resolvepath 209
+#define SVR4_SYS_svr4_sys_getdents64 213
+#define SVR4_SYS_svr4_sys_mmap64 214
+#define SVR4_SYS_svr4_sys_stat64 215
+#define SVR4_SYS_svr4_sys_lstat64 216
+#define SVR4_SYS_svr4_sys_fstat64 217
+#define SVR4_SYS_svr4_sys_statvfs64 218
+#define SVR4_SYS_svr4_sys_fstatvfs64 219
+#define SVR4_SYS_svr4_sys_setrlimit64 220
+#define SVR4_SYS_svr4_sys_getrlimit64 221
+#define SVR4_SYS_svr4_sys_creat64 224
+#define SVR4_SYS_svr4_sys_open64 225
+#define SVR4_SYS_svr4_sys_socket 230
+#define SVR4_SYS_socketpair 231
+#define SVR4_SYS_bind 232
+#define SVR4_SYS_listen 233
+#define SVR4_SYS_accept 234
+#define SVR4_SYS_connect 235
+#define SVR4_SYS_shutdown 236
+#define SVR4_SYS_svr4_sys_recv 237
+#define SVR4_SYS_recvfrom 238
+#define SVR4_SYS_recvmsg 239
+#define SVR4_SYS_svr4_sys_send 240
+#define SVR4_SYS_sendmsg 241
+#define SVR4_SYS_svr4_sys_sendto 242
+#define SVR4_SYS_getpeername 243
+#define SVR4_SYS_getsockname 244
+#define SVR4_SYS_getsockopt 245
+#define SVR4_SYS_setsockopt 246
+#define SVR4_SYS_MAXSYSCALL 250
diff --git a/sys/compat/svr4/svr4_syscallnames.c b/sys/compat/svr4/svr4_syscallnames.c
new file mode 100644
index 0000000..dffc0cd
--- /dev/null
+++ b/sys/compat/svr4/svr4_syscallnames.c
@@ -0,0 +1,260 @@
+/*
+ * System call names.
+ *
+ * DO NOT EDIT-- this file is automatically generated.
+ * $FreeBSD$
+ * created from FreeBSD: head/sys/compat/svr4/syscalls.master 227691 2011-11-19 06:35:15Z ed
+ */
+
+const char *svr4_syscallnames[] = {
+ "#0", /* 0 = unused */
+ "exit", /* 1 = exit */
+ "fork", /* 2 = fork */
+ "read", /* 3 = read */
+ "write", /* 4 = write */
+ "svr4_sys_open", /* 5 = svr4_sys_open */
+ "close", /* 6 = close */
+ "svr4_sys_wait", /* 7 = svr4_sys_wait */
+ "svr4_sys_creat", /* 8 = svr4_sys_creat */
+ "link", /* 9 = link */
+ "unlink", /* 10 = unlink */
+ "svr4_sys_execv", /* 11 = svr4_sys_execv */
+ "chdir", /* 12 = chdir */
+ "svr4_sys_time", /* 13 = svr4_sys_time */
+ "svr4_sys_mknod", /* 14 = svr4_sys_mknod */
+ "chmod", /* 15 = chmod */
+ "chown", /* 16 = chown */
+ "svr4_sys_break", /* 17 = svr4_sys_break */
+ "svr4_sys_stat", /* 18 = svr4_sys_stat */
+ "lseek", /* 19 = lseek */
+ "getpid", /* 20 = getpid */
+ "#21", /* 21 = old_mount */
+ "#22", /* 22 = sysv_umount */
+ "setuid", /* 23 = setuid */
+ "getuid", /* 24 = getuid */
+ "#25", /* 25 = stime */
+ "#26", /* 26 = ptrace */
+ "svr4_sys_alarm", /* 27 = svr4_sys_alarm */
+ "svr4_sys_fstat", /* 28 = svr4_sys_fstat */
+ "svr4_sys_pause", /* 29 = svr4_sys_pause */
+ "svr4_sys_utime", /* 30 = svr4_sys_utime */
+ "#31", /* 31 = stty */
+ "#32", /* 32 = gtty */
+ "svr4_sys_access", /* 33 = svr4_sys_access */
+ "svr4_sys_nice", /* 34 = svr4_sys_nice */
+ "#35", /* 35 = statfs */
+ "sync", /* 36 = sync */
+ "svr4_sys_kill", /* 37 = svr4_sys_kill */
+ "#38", /* 38 = fstatfs */
+ "svr4_sys_pgrpsys", /* 39 = svr4_sys_pgrpsys */
+ "#40", /* 40 = xenix */
+ "dup", /* 41 = dup */
+ "pipe", /* 42 = pipe */
+ "svr4_sys_times", /* 43 = svr4_sys_times */
+ "#44", /* 44 = profil */
+ "#45", /* 45 = plock */
+ "setgid", /* 46 = setgid */
+ "getgid", /* 47 = getgid */
+ "svr4_sys_signal", /* 48 = svr4_sys_signal */
+ "svr4_sys_msgsys", /* 49 = svr4_sys_msgsys */
+ "svr4_sys_sysarch", /* 50 = svr4_sys_sysarch */
+ "#51", /* 51 = acct */
+ "svr4_sys_shmsys", /* 52 = svr4_sys_shmsys */
+ "svr4_sys_semsys", /* 53 = svr4_sys_semsys */
+ "svr4_sys_ioctl", /* 54 = svr4_sys_ioctl */
+ "#55", /* 55 = uadmin */
+ "#56", /* 56 = exch */
+ "svr4_sys_utssys", /* 57 = svr4_sys_utssys */
+ "fsync", /* 58 = fsync */
+ "svr4_sys_execve", /* 59 = svr4_sys_execve */
+ "umask", /* 60 = umask */
+ "chroot", /* 61 = chroot */
+ "svr4_sys_fcntl", /* 62 = svr4_sys_fcntl */
+ "svr4_sys_ulimit", /* 63 = svr4_sys_ulimit */
+ "#64", /* 64 = reserved */
+ "#65", /* 65 = reserved */
+ "#66", /* 66 = reserved */
+ "#67", /* 67 = reserved */
+ "#68", /* 68 = reserved */
+ "#69", /* 69 = reserved */
+ "#70", /* 70 = advfs */
+ "#71", /* 71 = unadvfs */
+ "#72", /* 72 = rmount */
+ "#73", /* 73 = rumount */
+ "#74", /* 74 = rfstart */
+ "#75", /* 75 = sigret */
+ "#76", /* 76 = rdebug */
+ "#77", /* 77 = rfstop */
+ "#78", /* 78 = rfsys */
+ "rmdir", /* 79 = rmdir */
+ "mkdir", /* 80 = mkdir */
+ "svr4_sys_getdents", /* 81 = svr4_sys_getdents */
+ "#82", /* 82 = libattach */
+ "#83", /* 83 = libdetach */
+ "#84", /* 84 = sysfs */
+ "svr4_sys_getmsg", /* 85 = svr4_sys_getmsg */
+ "svr4_sys_putmsg", /* 86 = svr4_sys_putmsg */
+ "svr4_sys_poll", /* 87 = svr4_sys_poll */
+ "svr4_sys_lstat", /* 88 = svr4_sys_lstat */
+ "symlink", /* 89 = symlink */
+ "readlink", /* 90 = readlink */
+ "getgroups", /* 91 = getgroups */
+ "setgroups", /* 92 = setgroups */
+ "fchmod", /* 93 = fchmod */
+ "fchown", /* 94 = fchown */
+ "svr4_sys_sigprocmask", /* 95 = svr4_sys_sigprocmask */
+ "svr4_sys_sigsuspend", /* 96 = svr4_sys_sigsuspend */
+ "svr4_sys_sigaltstack", /* 97 = svr4_sys_sigaltstack */
+ "svr4_sys_sigaction", /* 98 = svr4_sys_sigaction */
+ "svr4_sys_sigpending", /* 99 = svr4_sys_sigpending */
+ "svr4_sys_context", /* 100 = svr4_sys_context */
+ "#101", /* 101 = evsys */
+ "#102", /* 102 = evtrapret */
+ "svr4_sys_statvfs", /* 103 = svr4_sys_statvfs */
+ "svr4_sys_fstatvfs", /* 104 = svr4_sys_fstatvfs */
+ "#105", /* 105 = whoknows */
+ "#106", /* 106 = nfssvc */
+ "svr4_sys_waitsys", /* 107 = svr4_sys_waitsys */
+ "#108", /* 108 = sigsendsys */
+ "svr4_sys_hrtsys", /* 109 = svr4_sys_hrtsys */
+ "#110", /* 110 = acancel */
+ "#111", /* 111 = async */
+ "#112", /* 112 = priocntlsys */
+ "svr4_sys_pathconf", /* 113 = svr4_sys_pathconf */
+ "#114", /* 114 = mincore */
+ "svr4_sys_mmap", /* 115 = svr4_sys_mmap */
+ "mprotect", /* 116 = mprotect */
+ "munmap", /* 117 = munmap */
+ "svr4_sys_fpathconf", /* 118 = svr4_sys_fpathconf */
+ "vfork", /* 119 = vfork */
+ "fchdir", /* 120 = fchdir */
+ "readv", /* 121 = readv */
+ "writev", /* 122 = writev */
+ "svr4_sys_xstat", /* 123 = svr4_sys_xstat */
+ "svr4_sys_lxstat", /* 124 = svr4_sys_lxstat */
+ "svr4_sys_fxstat", /* 125 = svr4_sys_fxstat */
+ "svr4_sys_xmknod", /* 126 = svr4_sys_xmknod */
+ "#127", /* 127 = clocal */
+ "svr4_sys_setrlimit", /* 128 = svr4_sys_setrlimit */
+ "svr4_sys_getrlimit", /* 129 = svr4_sys_getrlimit */
+ "lchown", /* 130 = lchown */
+ "svr4_sys_memcntl", /* 131 = svr4_sys_memcntl */
+ "#132", /* 132 = getpmsg */
+ "#133", /* 133 = putpmsg */
+ "rename", /* 134 = rename */
+ "svr4_sys_uname", /* 135 = svr4_sys_uname */
+ "setegid", /* 136 = setegid */
+ "svr4_sys_sysconfig", /* 137 = svr4_sys_sysconfig */
+ "adjtime", /* 138 = adjtime */
+ "svr4_sys_systeminfo", /* 139 = svr4_sys_systeminfo */
+ "#140", /* 140 = notused */
+ "seteuid", /* 141 = seteuid */
+ "#142", /* 142 = vtrace */
+ "#143", /* 143 = { */
+ "#144", /* 144 = sigtimedwait */
+ "#145", /* 145 = lwp_info */
+ "#146", /* 146 = yield */
+ "#147", /* 147 = lwp_sema_wait */
+ "#148", /* 148 = lwp_sema_post */
+ "#149", /* 149 = lwp_sema_trywait */
+ "#150", /* 150 = notused */
+ "#151", /* 151 = notused */
+ "#152", /* 152 = modctl */
+ "svr4_sys_fchroot", /* 153 = svr4_sys_fchroot */
+ "svr4_sys_utimes", /* 154 = svr4_sys_utimes */
+ "svr4_sys_vhangup", /* 155 = svr4_sys_vhangup */
+ "svr4_sys_gettimeofday", /* 156 = svr4_sys_gettimeofday */
+ "getitimer", /* 157 = getitimer */
+ "setitimer", /* 158 = setitimer */
+ "#159", /* 159 = lwp_create */
+ "#160", /* 160 = lwp_exit */
+ "#161", /* 161 = lwp_suspend */
+ "#162", /* 162 = lwp_continue */
+ "#163", /* 163 = lwp_kill */
+ "#164", /* 164 = lwp_self */
+ "#165", /* 165 = lwp_getprivate */
+ "#166", /* 166 = lwp_setprivate */
+ "#167", /* 167 = lwp_wait */
+ "#168", /* 168 = lwp_mutex_unlock */
+ "#169", /* 169 = lwp_mutex_lock */
+ "#170", /* 170 = lwp_cond_wait */
+ "#171", /* 171 = lwp_cond_signal */
+ "#172", /* 172 = lwp_cond_broadcast */
+ "#173", /* 173 = { */
+ "#174", /* 174 = { */
+ "svr4_sys_llseek", /* 175 = svr4_sys_llseek */
+ "#176", /* 176 = inst_sync */
+ "#177", /* 177 = whoknows */
+ "#178", /* 178 = kaio */
+ "#179", /* 179 = whoknows */
+ "#180", /* 180 = whoknows */
+ "#181", /* 181 = whoknows */
+ "#182", /* 182 = whoknows */
+ "#183", /* 183 = whoknows */
+ "#184", /* 184 = tsolsys */
+ "svr4_sys_acl", /* 185 = svr4_sys_acl */
+ "svr4_sys_auditsys", /* 186 = svr4_sys_auditsys */
+ "#187", /* 187 = processor_bind */
+ "#188", /* 188 = processor_info */
+ "#189", /* 189 = p_online */
+ "#190", /* 190 = sigqueue */
+ "#191", /* 191 = clock_gettime */
+ "#192", /* 192 = clock_settime */
+ "#193", /* 193 = clock_getres */
+ "#194", /* 194 = timer_create */
+ "#195", /* 195 = timer_delete */
+ "#196", /* 196 = timer_settime */
+ "#197", /* 197 = timer_gettime */
+ "#198", /* 198 = timer_overrun */
+ "nanosleep", /* 199 = nanosleep */
+ "svr4_sys_facl", /* 200 = svr4_sys_facl */
+ "#201", /* 201 = door */
+ "setreuid", /* 202 = setreuid */
+ "setregid", /* 203 = setregid */
+ "#204", /* 204 = install_utrap */
+ "#205", /* 205 = signotify */
+ "#206", /* 206 = schedctl */
+ "#207", /* 207 = pset */
+ "#208", /* 208 = whoknows */
+ "svr4_sys_resolvepath", /* 209 = svr4_sys_resolvepath */
+ "#210", /* 210 = signotifywait */
+ "#211", /* 211 = lwp_sigredirect */
+ "#212", /* 212 = lwp_alarm */
+ "svr4_sys_getdents64", /* 213 = svr4_sys_getdents64 */
+ "svr4_sys_mmap64", /* 214 = svr4_sys_mmap64 */
+ "svr4_sys_stat64", /* 215 = svr4_sys_stat64 */
+ "svr4_sys_lstat64", /* 216 = svr4_sys_lstat64 */
+ "svr4_sys_fstat64", /* 217 = svr4_sys_fstat64 */
+ "svr4_sys_statvfs64", /* 218 = svr4_sys_statvfs64 */
+ "svr4_sys_fstatvfs64", /* 219 = svr4_sys_fstatvfs64 */
+ "svr4_sys_setrlimit64", /* 220 = svr4_sys_setrlimit64 */
+ "svr4_sys_getrlimit64", /* 221 = svr4_sys_getrlimit64 */
+ "#222", /* 222 = pread64 */
+ "#223", /* 223 = pwrite64 */
+ "svr4_sys_creat64", /* 224 = svr4_sys_creat64 */
+ "svr4_sys_open64", /* 225 = svr4_sys_open64 */
+ "#226", /* 226 = rpcsys */
+ "#227", /* 227 = whoknows */
+ "#228", /* 228 = whoknows */
+ "#229", /* 229 = whoknows */
+ "svr4_sys_socket", /* 230 = svr4_sys_socket */
+ "socketpair", /* 231 = socketpair */
+ "bind", /* 232 = bind */
+ "listen", /* 233 = listen */
+ "accept", /* 234 = accept */
+ "connect", /* 235 = connect */
+ "shutdown", /* 236 = shutdown */
+ "svr4_sys_recv", /* 237 = svr4_sys_recv */
+ "recvfrom", /* 238 = recvfrom */
+ "recvmsg", /* 239 = recvmsg */
+ "svr4_sys_send", /* 240 = svr4_sys_send */
+ "sendmsg", /* 241 = sendmsg */
+ "svr4_sys_sendto", /* 242 = svr4_sys_sendto */
+ "getpeername", /* 243 = getpeername */
+ "getsockname", /* 244 = getsockname */
+ "getsockopt", /* 245 = getsockopt */
+ "setsockopt", /* 246 = setsockopt */
+ "#247", /* 247 = sockconfig */
+ "#248", /* 248 = { */
+ "#249", /* 249 = { */
+};
diff --git a/sys/compat/svr4/svr4_sysconfig.h b/sys/compat/svr4/svr4_sysconfig.h
new file mode 100644
index 0000000..4a26545
--- /dev/null
+++ b/sys/compat/svr4/svr4_sysconfig.h
@@ -0,0 +1,78 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1995 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_SYSCONFIG_H_
+#define _SVR4_SYSCONFIG_H_
+
+#define SVR4_CONFIG_UNUSED_1 0x01
+#define SVR4_CONFIG_NGROUPS 0x02
+#define SVR4_CONFIG_CHILD_MAX 0x03
+#define SVR4_CONFIG_OPEN_FILES 0x04
+#define SVR4_CONFIG_POSIX_VER 0x05
+#define SVR4_CONFIG_PAGESIZE 0x06
+#define SVR4_CONFIG_CLK_TCK 0x07
+#define SVR4_CONFIG_XOPEN_VER 0x08
+#define SVR4_CONFIG_UNUSED_9 0x09
+#define SVR4_CONFIG_PROF_TCK 0x0a
+#define SVR4_CONFIG_NPROC_CONF 0x0b
+#define SVR4_CONFIG_NPROC_ONLN 0x0c
+#define SVR4_CONFIG_AIO_LISTIO_MAX 0x0d
+#define SVR4_CONFIG_AIO_MAX 0x0e
+#define SVR4_CONFIG_AIO_PRIO_DELTA_MAX 0x0f
+#define SVR4_CONFIG_DELAYTIMER_MAX 0x10
+#define SVR4_CONFIG_MQ_OPEN_MAX 0x11
+#define SVR4_CONFIG_MQ_PRIO_MAX 0x12
+#define SVR4_CONFIG_RTSIG_MAX 0x13
+#define SVR4_CONFIG_SEM_NSEMS_MAX 0x14
+#define SVR4_CONFIG_SEM_VALUE_MAX 0x15
+#define SVR4_CONFIG_SIGQUEUE_MAX 0x16
+#define SVR4_CONFIG_SIGRT_MIN 0x17
+#define SVR4_CONFIG_SIGRT_MAX 0x18
+#define SVR4_CONFIG_TIMER_MAX 0x19
+#define SVR4_CONFIG_PHYS_PAGES 0x1a
+#define SVR4_CONFIG_AVPHYS_PAGES 0x1b
+#define SVR4_CONFIG_COHERENCY 0x1c
+#define SVR4_CONFIG_SPLIT_CACHE 0x1d
+#define SVR4_CONFIG_ICACHESZ 0x1e
+#define SVR4_CONFIG_DCACHESZ 0x1f
+#define SVR4_CONFIG_ICACHELINESZ 0x20
+#define SVR4_CONFIG_DCACHELINESZ 0x21
+#define SVR4_CONFIG_ICACHEBLKSZ 0x22
+#define SVR4_CONFIG_DCACHEBLKSZ 0x23
+#define SVR4_CONFIG_DCACHETBLKSZ 0x24
+#define SVR4_CONFIG_ICACHE_ASSOC 0x25
+#define SVR4_CONFIG_DCACHE_ASSOC 0x26
+#define SVR4_CONFIG_UNUSED_2 0x27
+#define SVR4_CONFIG_UNUSED_3 0x28
+#define SVR4_CONFIG_UNUSED_4 0x29
+#define SVR4_CONFIG_MAXPID 0x2a
+#define SVR4_CONFIG_STACK_PROT 0x2b
+
+#endif /* !_SVR4_SYSCONFIG_H_ */
diff --git a/sys/compat/svr4/svr4_sysent.c b/sys/compat/svr4/svr4_sysent.c
new file mode 100644
index 0000000..1b18501
--- /dev/null
+++ b/sys/compat/svr4/svr4_sysent.c
@@ -0,0 +1,272 @@
+/*
+ * System call switch table.
+ *
+ * DO NOT EDIT-- this file is automatically generated.
+ * $FreeBSD$
+ * created from FreeBSD: head/sys/compat/svr4/syscalls.master 227691 2011-11-19 06:35:15Z ed
+ */
+
+#include <sys/types.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <netinet/in.h>
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_proto.h>
+
+#define AS(name) (sizeof(struct name) / sizeof(register_t))
+
+/* The casts are bogus but will do for now. */
+struct sysent svr4_sysent[] = {
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 0 = unused */
+ { AS(sys_exit_args), (sy_call_t *)sys_sys_exit, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 1 = exit */
+ { 0, (sy_call_t *)sys_fork, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 2 = fork */
+ { AS(read_args), (sy_call_t *)sys_read, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 3 = read */
+ { AS(write_args), (sy_call_t *)sys_write, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 4 = write */
+ { AS(svr4_sys_open_args), (sy_call_t *)svr4_sys_open, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 5 = svr4_sys_open */
+ { AS(close_args), (sy_call_t *)sys_close, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 6 = close */
+ { AS(svr4_sys_wait_args), (sy_call_t *)svr4_sys_wait, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 7 = svr4_sys_wait */
+ { AS(svr4_sys_creat_args), (sy_call_t *)svr4_sys_creat, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 8 = svr4_sys_creat */
+ { AS(link_args), (sy_call_t *)sys_link, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 9 = link */
+ { AS(unlink_args), (sy_call_t *)sys_unlink, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 10 = unlink */
+ { AS(svr4_sys_execv_args), (sy_call_t *)svr4_sys_execv, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 11 = svr4_sys_execv */
+ { AS(chdir_args), (sy_call_t *)sys_chdir, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 12 = chdir */
+ { AS(svr4_sys_time_args), (sy_call_t *)svr4_sys_time, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 13 = svr4_sys_time */
+ { AS(svr4_sys_mknod_args), (sy_call_t *)svr4_sys_mknod, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 14 = svr4_sys_mknod */
+ { AS(chmod_args), (sy_call_t *)sys_chmod, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 15 = chmod */
+ { AS(chown_args), (sy_call_t *)sys_chown, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 16 = chown */
+ { AS(svr4_sys_break_args), (sy_call_t *)svr4_sys_break, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 17 = svr4_sys_break */
+ { AS(svr4_sys_stat_args), (sy_call_t *)svr4_sys_stat, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 18 = svr4_sys_stat */
+ { AS(lseek_args), (sy_call_t *)sys_lseek, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 19 = lseek */
+ { 0, (sy_call_t *)sys_getpid, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 20 = getpid */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 21 = old_mount */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 22 = sysv_umount */
+ { AS(setuid_args), (sy_call_t *)sys_setuid, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 23 = setuid */
+ { 0, (sy_call_t *)sys_getuid, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 24 = getuid */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 25 = stime */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 26 = ptrace */
+ { AS(svr4_sys_alarm_args), (sy_call_t *)svr4_sys_alarm, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 27 = svr4_sys_alarm */
+ { AS(svr4_sys_fstat_args), (sy_call_t *)svr4_sys_fstat, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 28 = svr4_sys_fstat */
+ { 0, (sy_call_t *)svr4_sys_pause, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 29 = svr4_sys_pause */
+ { AS(svr4_sys_utime_args), (sy_call_t *)svr4_sys_utime, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 30 = svr4_sys_utime */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 31 = stty */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 32 = gtty */
+ { AS(svr4_sys_access_args), (sy_call_t *)svr4_sys_access, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 33 = svr4_sys_access */
+ { AS(svr4_sys_nice_args), (sy_call_t *)svr4_sys_nice, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 34 = svr4_sys_nice */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 35 = statfs */
+ { 0, (sy_call_t *)sys_sync, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 36 = sync */
+ { AS(svr4_sys_kill_args), (sy_call_t *)svr4_sys_kill, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 37 = svr4_sys_kill */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 38 = fstatfs */
+ { AS(svr4_sys_pgrpsys_args), (sy_call_t *)svr4_sys_pgrpsys, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 39 = svr4_sys_pgrpsys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 40 = xenix */
+ { AS(dup_args), (sy_call_t *)sys_dup, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 41 = dup */
+ { 0, (sy_call_t *)sys_pipe, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 42 = pipe */
+ { AS(svr4_sys_times_args), (sy_call_t *)svr4_sys_times, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 43 = svr4_sys_times */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 44 = profil */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 45 = plock */
+ { AS(setgid_args), (sy_call_t *)sys_setgid, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 46 = setgid */
+ { 0, (sy_call_t *)sys_getgid, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 47 = getgid */
+ { AS(svr4_sys_signal_args), (sy_call_t *)svr4_sys_signal, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 48 = svr4_sys_signal */
+ { AS(svr4_sys_msgsys_args), (sy_call_t *)svr4_sys_msgsys, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 49 = svr4_sys_msgsys */
+ { AS(svr4_sys_sysarch_args), (sy_call_t *)svr4_sys_sysarch, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 50 = svr4_sys_sysarch */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 51 = acct */
+ { AS(svr4_sys_shmsys_args), (sy_call_t *)svr4_sys_shmsys, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 52 = svr4_sys_shmsys */
+ { AS(svr4_sys_semsys_args), (sy_call_t *)svr4_sys_semsys, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 53 = svr4_sys_semsys */
+ { AS(svr4_sys_ioctl_args), (sy_call_t *)svr4_sys_ioctl, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 54 = svr4_sys_ioctl */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 55 = uadmin */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 56 = exch */
+ { AS(svr4_sys_utssys_args), (sy_call_t *)svr4_sys_utssys, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 57 = svr4_sys_utssys */
+ { AS(fsync_args), (sy_call_t *)sys_fsync, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 58 = fsync */
+ { AS(svr4_sys_execve_args), (sy_call_t *)svr4_sys_execve, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 59 = svr4_sys_execve */
+ { AS(umask_args), (sy_call_t *)sys_umask, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 60 = umask */
+ { AS(chroot_args), (sy_call_t *)sys_chroot, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 61 = chroot */
+ { AS(svr4_sys_fcntl_args), (sy_call_t *)svr4_sys_fcntl, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 62 = svr4_sys_fcntl */
+ { AS(svr4_sys_ulimit_args), (sy_call_t *)svr4_sys_ulimit, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 63 = svr4_sys_ulimit */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 64 = reserved */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 65 = reserved */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 66 = reserved */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 67 = reserved */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 68 = reserved */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 69 = reserved */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 70 = advfs */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 71 = unadvfs */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 72 = rmount */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 73 = rumount */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 74 = rfstart */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 75 = sigret */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 76 = rdebug */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 77 = rfstop */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 78 = rfsys */
+ { AS(rmdir_args), (sy_call_t *)sys_rmdir, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 79 = rmdir */
+ { AS(mkdir_args), (sy_call_t *)sys_mkdir, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 80 = mkdir */
+ { AS(svr4_sys_getdents_args), (sy_call_t *)svr4_sys_getdents, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 81 = svr4_sys_getdents */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 82 = libattach */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 83 = libdetach */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 84 = sysfs */
+ { AS(svr4_sys_getmsg_args), (sy_call_t *)svr4_sys_getmsg, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 85 = svr4_sys_getmsg */
+ { AS(svr4_sys_putmsg_args), (sy_call_t *)svr4_sys_putmsg, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 86 = svr4_sys_putmsg */
+ { AS(svr4_sys_poll_args), (sy_call_t *)svr4_sys_poll, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 87 = svr4_sys_poll */
+ { AS(svr4_sys_lstat_args), (sy_call_t *)svr4_sys_lstat, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 88 = svr4_sys_lstat */
+ { AS(symlink_args), (sy_call_t *)sys_symlink, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 89 = symlink */
+ { AS(readlink_args), (sy_call_t *)sys_readlink, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 90 = readlink */
+ { AS(getgroups_args), (sy_call_t *)sys_getgroups, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 91 = getgroups */
+ { AS(setgroups_args), (sy_call_t *)sys_setgroups, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 92 = setgroups */
+ { AS(fchmod_args), (sy_call_t *)sys_fchmod, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 93 = fchmod */
+ { AS(fchown_args), (sy_call_t *)sys_fchown, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 94 = fchown */
+ { AS(svr4_sys_sigprocmask_args), (sy_call_t *)svr4_sys_sigprocmask, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 95 = svr4_sys_sigprocmask */
+ { AS(svr4_sys_sigsuspend_args), (sy_call_t *)svr4_sys_sigsuspend, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 96 = svr4_sys_sigsuspend */
+ { AS(svr4_sys_sigaltstack_args), (sy_call_t *)svr4_sys_sigaltstack, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 97 = svr4_sys_sigaltstack */
+ { AS(svr4_sys_sigaction_args), (sy_call_t *)svr4_sys_sigaction, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 98 = svr4_sys_sigaction */
+ { AS(svr4_sys_sigpending_args), (sy_call_t *)svr4_sys_sigpending, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 99 = svr4_sys_sigpending */
+ { AS(svr4_sys_context_args), (sy_call_t *)svr4_sys_context, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 100 = svr4_sys_context */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 101 = evsys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 102 = evtrapret */
+ { AS(svr4_sys_statvfs_args), (sy_call_t *)svr4_sys_statvfs, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 103 = svr4_sys_statvfs */
+ { AS(svr4_sys_fstatvfs_args), (sy_call_t *)svr4_sys_fstatvfs, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 104 = svr4_sys_fstatvfs */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 105 = whoknows */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 106 = nfssvc */
+ { AS(svr4_sys_waitsys_args), (sy_call_t *)svr4_sys_waitsys, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 107 = svr4_sys_waitsys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 108 = sigsendsys */
+ { AS(svr4_sys_hrtsys_args), (sy_call_t *)svr4_sys_hrtsys, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 109 = svr4_sys_hrtsys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 110 = acancel */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 111 = async */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 112 = priocntlsys */
+ { AS(svr4_sys_pathconf_args), (sy_call_t *)svr4_sys_pathconf, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 113 = svr4_sys_pathconf */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 114 = mincore */
+ { AS(svr4_sys_mmap_args), (sy_call_t *)svr4_sys_mmap, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 115 = svr4_sys_mmap */
+ { AS(mprotect_args), (sy_call_t *)sys_mprotect, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 116 = mprotect */
+ { AS(munmap_args), (sy_call_t *)sys_munmap, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 117 = munmap */
+ { AS(svr4_sys_fpathconf_args), (sy_call_t *)svr4_sys_fpathconf, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 118 = svr4_sys_fpathconf */
+ { 0, (sy_call_t *)sys_vfork, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 119 = vfork */
+ { AS(fchdir_args), (sy_call_t *)sys_fchdir, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 120 = fchdir */
+ { AS(readv_args), (sy_call_t *)sys_readv, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 121 = readv */
+ { AS(writev_args), (sy_call_t *)sys_writev, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 122 = writev */
+ { AS(svr4_sys_xstat_args), (sy_call_t *)svr4_sys_xstat, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 123 = svr4_sys_xstat */
+ { AS(svr4_sys_lxstat_args), (sy_call_t *)svr4_sys_lxstat, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 124 = svr4_sys_lxstat */
+ { AS(svr4_sys_fxstat_args), (sy_call_t *)svr4_sys_fxstat, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 125 = svr4_sys_fxstat */
+ { AS(svr4_sys_xmknod_args), (sy_call_t *)svr4_sys_xmknod, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 126 = svr4_sys_xmknod */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 127 = clocal */
+ { AS(svr4_sys_setrlimit_args), (sy_call_t *)svr4_sys_setrlimit, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 128 = svr4_sys_setrlimit */
+ { AS(svr4_sys_getrlimit_args), (sy_call_t *)svr4_sys_getrlimit, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 129 = svr4_sys_getrlimit */
+ { AS(lchown_args), (sy_call_t *)sys_lchown, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 130 = lchown */
+ { AS(svr4_sys_memcntl_args), (sy_call_t *)svr4_sys_memcntl, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 131 = svr4_sys_memcntl */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 132 = getpmsg */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 133 = putpmsg */
+ { AS(rename_args), (sy_call_t *)sys_rename, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 134 = rename */
+ { AS(svr4_sys_uname_args), (sy_call_t *)svr4_sys_uname, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 135 = svr4_sys_uname */
+ { AS(setegid_args), (sy_call_t *)sys_setegid, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 136 = setegid */
+ { AS(svr4_sys_sysconfig_args), (sy_call_t *)svr4_sys_sysconfig, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 137 = svr4_sys_sysconfig */
+ { AS(adjtime_args), (sy_call_t *)sys_adjtime, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 138 = adjtime */
+ { AS(svr4_sys_systeminfo_args), (sy_call_t *)svr4_sys_systeminfo, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 139 = svr4_sys_systeminfo */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 140 = notused */
+ { AS(seteuid_args), (sy_call_t *)sys_seteuid, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 141 = seteuid */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 142 = vtrace */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 143 = { */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 144 = sigtimedwait */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 145 = lwp_info */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 146 = yield */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 147 = lwp_sema_wait */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 148 = lwp_sema_post */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 149 = lwp_sema_trywait */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 150 = notused */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 151 = notused */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 152 = modctl */
+ { AS(svr4_sys_fchroot_args), (sy_call_t *)svr4_sys_fchroot, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 153 = svr4_sys_fchroot */
+ { AS(svr4_sys_utimes_args), (sy_call_t *)svr4_sys_utimes, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 154 = svr4_sys_utimes */
+ { 0, (sy_call_t *)svr4_sys_vhangup, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 155 = svr4_sys_vhangup */
+ { AS(svr4_sys_gettimeofday_args), (sy_call_t *)svr4_sys_gettimeofday, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 156 = svr4_sys_gettimeofday */
+ { AS(getitimer_args), (sy_call_t *)sys_getitimer, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 157 = getitimer */
+ { AS(setitimer_args), (sy_call_t *)sys_setitimer, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 158 = setitimer */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 159 = lwp_create */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 160 = lwp_exit */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 161 = lwp_suspend */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 162 = lwp_continue */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 163 = lwp_kill */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 164 = lwp_self */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 165 = lwp_getprivate */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 166 = lwp_setprivate */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 167 = lwp_wait */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 168 = lwp_mutex_unlock */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 169 = lwp_mutex_lock */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 170 = lwp_cond_wait */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 171 = lwp_cond_signal */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 172 = lwp_cond_broadcast */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 173 = { */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 174 = { */
+ { AS(svr4_sys_llseek_args), (sy_call_t *)svr4_sys_llseek, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 175 = svr4_sys_llseek */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 176 = inst_sync */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 177 = whoknows */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 178 = kaio */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 179 = whoknows */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 180 = whoknows */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 181 = whoknows */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 182 = whoknows */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 183 = whoknows */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 184 = tsolsys */
+ { AS(svr4_sys_acl_args), (sy_call_t *)svr4_sys_acl, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 185 = svr4_sys_acl */
+ { AS(svr4_sys_auditsys_args), (sy_call_t *)svr4_sys_auditsys, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 186 = svr4_sys_auditsys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 187 = processor_bind */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 188 = processor_info */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 189 = p_online */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 190 = sigqueue */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 191 = clock_gettime */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 192 = clock_settime */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 193 = clock_getres */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 194 = timer_create */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 195 = timer_delete */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 196 = timer_settime */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 197 = timer_gettime */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 198 = timer_overrun */
+ { AS(nanosleep_args), (sy_call_t *)sys_nanosleep, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 199 = nanosleep */
+ { AS(svr4_sys_facl_args), (sy_call_t *)svr4_sys_facl, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 200 = svr4_sys_facl */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 201 = door */
+ { AS(setreuid_args), (sy_call_t *)sys_setreuid, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 202 = setreuid */
+ { AS(setregid_args), (sy_call_t *)sys_setregid, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 203 = setregid */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 204 = install_utrap */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 205 = signotify */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 206 = schedctl */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 207 = pset */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 208 = whoknows */
+ { AS(svr4_sys_resolvepath_args), (sy_call_t *)svr4_sys_resolvepath, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 209 = svr4_sys_resolvepath */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 210 = signotifywait */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 211 = lwp_sigredirect */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 212 = lwp_alarm */
+ { AS(svr4_sys_getdents64_args), (sy_call_t *)svr4_sys_getdents64, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 213 = svr4_sys_getdents64 */
+ { AS(svr4_sys_mmap64_args), (sy_call_t *)svr4_sys_mmap64, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 214 = svr4_sys_mmap64 */
+ { AS(svr4_sys_stat64_args), (sy_call_t *)svr4_sys_stat64, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 215 = svr4_sys_stat64 */
+ { AS(svr4_sys_lstat64_args), (sy_call_t *)svr4_sys_lstat64, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 216 = svr4_sys_lstat64 */
+ { AS(svr4_sys_fstat64_args), (sy_call_t *)svr4_sys_fstat64, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 217 = svr4_sys_fstat64 */
+ { AS(svr4_sys_statvfs64_args), (sy_call_t *)svr4_sys_statvfs64, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 218 = svr4_sys_statvfs64 */
+ { AS(svr4_sys_fstatvfs64_args), (sy_call_t *)svr4_sys_fstatvfs64, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 219 = svr4_sys_fstatvfs64 */
+ { AS(svr4_sys_setrlimit64_args), (sy_call_t *)svr4_sys_setrlimit64, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 220 = svr4_sys_setrlimit64 */
+ { AS(svr4_sys_getrlimit64_args), (sy_call_t *)svr4_sys_getrlimit64, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 221 = svr4_sys_getrlimit64 */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 222 = pread64 */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 223 = pwrite64 */
+ { AS(svr4_sys_creat64_args), (sy_call_t *)svr4_sys_creat64, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 224 = svr4_sys_creat64 */
+ { AS(svr4_sys_open64_args), (sy_call_t *)svr4_sys_open64, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 225 = svr4_sys_open64 */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 226 = rpcsys */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 227 = whoknows */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 228 = whoknows */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 229 = whoknows */
+ { AS(svr4_sys_socket_args), (sy_call_t *)svr4_sys_socket, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 230 = svr4_sys_socket */
+ { AS(socketpair_args), (sy_call_t *)sys_socketpair, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 231 = socketpair */
+ { AS(bind_args), (sy_call_t *)sys_bind, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 232 = bind */
+ { AS(listen_args), (sy_call_t *)sys_listen, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 233 = listen */
+ { AS(accept_args), (sy_call_t *)sys_accept, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 234 = accept */
+ { AS(connect_args), (sy_call_t *)sys_connect, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 235 = connect */
+ { AS(shutdown_args), (sy_call_t *)sys_shutdown, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 236 = shutdown */
+ { AS(svr4_sys_recv_args), (sy_call_t *)svr4_sys_recv, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 237 = svr4_sys_recv */
+ { AS(recvfrom_args), (sy_call_t *)sys_recvfrom, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 238 = recvfrom */
+ { AS(recvmsg_args), (sy_call_t *)sys_recvmsg, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 239 = recvmsg */
+ { AS(svr4_sys_send_args), (sy_call_t *)svr4_sys_send, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 240 = svr4_sys_send */
+ { AS(sendmsg_args), (sy_call_t *)sys_sendmsg, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 241 = sendmsg */
+ { AS(svr4_sys_sendto_args), (sy_call_t *)svr4_sys_sendto, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 242 = svr4_sys_sendto */
+ { AS(getpeername_args), (sy_call_t *)sys_getpeername, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 243 = getpeername */
+ { AS(getsockname_args), (sy_call_t *)sys_getsockname, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 244 = getsockname */
+ { AS(getsockopt_args), (sy_call_t *)sys_getsockopt, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 245 = getsockopt */
+ { AS(setsockopt_args), (sy_call_t *)sys_setsockopt, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 246 = setsockopt */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 247 = sockconfig */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 248 = { */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 249 = { */
+};
diff --git a/sys/compat/svr4/svr4_systeminfo.h b/sys/compat/svr4/svr4_systeminfo.h
new file mode 100644
index 0000000..2d5288e
--- /dev/null
+++ b/sys/compat/svr4/svr4_systeminfo.h
@@ -0,0 +1,50 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_SYSTEMINFO_H_
+#define _SVR4_SYSTEMINFO_H_
+
+#define SVR4_SI_SYSNAME 1
+#define SVR4_SI_HOSTNAME 2
+#define SVR4_SI_RELEASE 3
+#define SVR4_SI_VERSION 4
+#define SVR4_SI_MACHINE 5
+#define SVR4_SI_ARCHITECTURE 6
+#define SVR4_SI_HW_SERIAL 7
+#define SVR4_SI_HW_PROVIDER 8
+#define SVR4_SI_SRPC_DOMAIN 9
+#define SVR4_SI_SET_HOSTNAME 258
+#define SVR4_SI_SET_SRPC_DOMAIN 265
+#define SVR4_SI_SET_KERB_REALM 266
+#define SVR4_SI_KERB_REALM 267
+#define SVR4_SI_PLATFORM 513
+#define SVR4_SI_ISALIST 514
+
+#endif /* !_SVR4_SYSTEMINFO_H_ */
diff --git a/sys/compat/svr4/svr4_sysvec.c b/sys/compat/svr4/svr4_sysvec.c
new file mode 100644
index 0000000..561a838
--- /dev/null
+++ b/sys/compat/svr4/svr4_sysvec.c
@@ -0,0 +1,314 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christos Zoulas.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/* XXX we use functions that might not exist. */
+#include "opt_compat.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/sysent.h>
+#include <sys/imgact.h>
+#include <sys/imgact_elf.h>
+#include <sys/fcntl.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/namei.h>
+#include <sys/socket.h>
+#include <sys/syscallsubr.h>
+#include <sys/vnode.h>
+#include <vm/vm.h>
+#include <sys/exec.h>
+#include <sys/kernel.h>
+#include <machine/cpu.h>
+#include <netinet/in.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_syscall.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_socket.h>
+#include <compat/svr4/svr4_sockio.h>
+#include <compat/svr4/svr4_errno.h>
+#include <compat/svr4/svr4_proto.h>
+#include <compat/svr4/svr4_siginfo.h>
+#include <compat/svr4/svr4_util.h>
+
+int bsd_to_svr4_errno[ELAST+1] = {
+ 0,
+ SVR4_EPERM,
+ SVR4_ENOENT,
+ SVR4_ESRCH,
+ SVR4_EINTR,
+ SVR4_EIO,
+ SVR4_ENXIO,
+ SVR4_E2BIG,
+ SVR4_ENOEXEC,
+ SVR4_EBADF,
+ SVR4_ECHILD,
+ SVR4_EDEADLK,
+ SVR4_ENOMEM,
+ SVR4_EACCES,
+ SVR4_EFAULT,
+ SVR4_ENOTBLK,
+ SVR4_EBUSY,
+ SVR4_EEXIST,
+ SVR4_EXDEV,
+ SVR4_ENODEV,
+ SVR4_ENOTDIR,
+ SVR4_EISDIR,
+ SVR4_EINVAL,
+ SVR4_ENFILE,
+ SVR4_EMFILE,
+ SVR4_ENOTTY,
+ SVR4_ETXTBSY,
+ SVR4_EFBIG,
+ SVR4_ENOSPC,
+ SVR4_ESPIPE,
+ SVR4_EROFS,
+ SVR4_EMLINK,
+ SVR4_EPIPE,
+ SVR4_EDOM,
+ SVR4_ERANGE,
+ SVR4_EAGAIN,
+ SVR4_EINPROGRESS,
+ SVR4_EALREADY,
+ SVR4_ENOTSOCK,
+ SVR4_EDESTADDRREQ,
+ SVR4_EMSGSIZE,
+ SVR4_EPROTOTYPE,
+ SVR4_ENOPROTOOPT,
+ SVR4_EPROTONOSUPPORT,
+ SVR4_ESOCKTNOSUPPORT,
+ SVR4_EOPNOTSUPP,
+ SVR4_EPFNOSUPPORT,
+ SVR4_EAFNOSUPPORT,
+ SVR4_EADDRINUSE,
+ SVR4_EADDRNOTAVAIL,
+ SVR4_ENETDOWN,
+ SVR4_ENETUNREACH,
+ SVR4_ENETRESET,
+ SVR4_ECONNABORTED,
+ SVR4_ECONNRESET,
+ SVR4_ENOBUFS,
+ SVR4_EISCONN,
+ SVR4_ENOTCONN,
+ SVR4_ESHUTDOWN,
+ SVR4_ETOOMANYREFS,
+ SVR4_ETIMEDOUT,
+ SVR4_ECONNREFUSED,
+ SVR4_ELOOP,
+ SVR4_ENAMETOOLONG,
+ SVR4_EHOSTDOWN,
+ SVR4_EHOSTUNREACH,
+ SVR4_ENOTEMPTY,
+ SVR4_EPROCLIM,
+ SVR4_EUSERS,
+ SVR4_EDQUOT,
+ SVR4_ESTALE,
+ SVR4_EREMOTE,
+ SVR4_EBADRPC,
+ SVR4_ERPCMISMATCH,
+ SVR4_EPROGUNAVAIL,
+ SVR4_EPROGMISMATCH,
+ SVR4_EPROCUNAVAIL,
+ SVR4_ENOLCK,
+ SVR4_ENOSYS,
+ SVR4_EFTYPE,
+ SVR4_EAUTH,
+ SVR4_ENEEDAUTH,
+ SVR4_EIDRM,
+ SVR4_ENOMSG,
+};
+
+
+static int svr4_fixup(register_t **stack_base, struct image_params *imgp);
+
+extern struct sysent svr4_sysent[];
+#undef szsigcode
+#undef sigcode
+
+extern int svr4_szsigcode;
+extern char svr4_sigcode[];
+
+struct sysentvec svr4_sysvec = {
+ .sv_size = SVR4_SYS_MAXSYSCALL,
+ .sv_table = svr4_sysent,
+ .sv_mask = 0xff,
+ .sv_sigsize = SVR4_NSIG-1, /* NB: signal trans table indexed with signno-1 */
+ .sv_sigtbl = bsd_to_svr4_sig+1,
+ .sv_errsize = ELAST, /* ELAST */
+ .sv_errtbl = bsd_to_svr4_errno,
+ .sv_transtrap = NULL,
+ .sv_fixup = svr4_fixup,
+ .sv_sendsig = svr4_sendsig,
+ .sv_sigcode = svr4_sigcode,
+ .sv_szsigcode = &svr4_szsigcode,
+ .sv_prepsyscall = NULL,
+ .sv_name = "SVR4",
+ .sv_coredump = elf32_coredump,
+ .sv_imgact_try = NULL,
+ .sv_minsigstksz = SVR4_MINSIGSTKSZ,
+ .sv_pagesize = PAGE_SIZE,
+ .sv_minuser = VM_MIN_ADDRESS,
+ .sv_maxuser = VM_MAXUSER_ADDRESS,
+ .sv_usrstack = USRSTACK,
+ .sv_psstrings = PS_STRINGS,
+ .sv_stackprot = VM_PROT_ALL,
+ .sv_copyout_strings = exec_copyout_strings,
+ .sv_setregs = exec_setregs,
+ .sv_fixlimit = NULL,
+ .sv_maxssiz = NULL,
+ .sv_flags = SV_ABI_UNDEF | SV_IA32 | SV_ILP32,
+ .sv_set_syscall_retval = cpu_set_syscall_retval,
+ .sv_fetch_syscall_args = cpu_fetch_syscall_args,
+ .sv_syscallnames = NULL,
+ .sv_schedtail = NULL,
+};
+
+const char svr4_emul_path[] = "/compat/svr4";
+
+Elf32_Brandinfo svr4_brand = {
+ .brand = ELFOSABI_SYSV,
+ .machine = EM_386, /* XXX only implemented for x86 so far. */
+ .compat_3_brand = "SVR4",
+ .emul_path = svr4_emul_path,
+ .interp_path = "/lib/libc.so.1",
+ .sysvec = &svr4_sysvec,
+ .interp_newpath = NULL,
+ .brand_note = NULL,
+ .flags = 0
+};
+
+static int
+svr4_fixup(register_t **stack_base, struct image_params *imgp)
+{
+ Elf32_Auxargs *args;
+ register_t *pos;
+
+ KASSERT(curthread->td_proc == imgp->proc,
+ ("unsafe svr4_fixup(), should be curproc"));
+ args = (Elf32_Auxargs *)imgp->auxargs;
+ pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2);
+
+ if (args->execfd != -1)
+ AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
+ AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
+ AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
+ AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
+ AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
+ AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
+ AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
+ AUXARGS_ENTRY(pos, AT_BASE, args->base);
+ AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid);
+ AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid);
+ AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid);
+ AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid);
+ AUXARGS_ENTRY(pos, AT_NULL, 0);
+
+ free(imgp->auxargs, M_TEMP);
+ imgp->auxargs = NULL;
+
+ (*stack_base)--;
+ **stack_base = (register_t)imgp->args->argc;
+ return 0;
+}
+
+/*
+ * Search an alternate path before passing pathname arguments on
+ * to system calls. Useful for keeping a separate 'emulation tree'.
+ *
+ * If cflag is set, we check if an attempt can be made to create
+ * the named file, i.e. we check if the directory it should
+ * be in exists.
+ */
+int
+svr4_emul_find(struct thread *td, char *path, enum uio_seg pathseg,
+ char **pbuf, int create)
+{
+
+ return (kern_alternate_path(td, svr4_emul_path, path, pathseg, pbuf,
+ create, AT_FDCWD));
+}
+
+static int
+svr4_elf_modevent(module_t mod, int type, void *data)
+{
+ int error;
+
+ error = 0;
+
+ switch(type) {
+ case MOD_LOAD:
+ if (elf32_insert_brand_entry(&svr4_brand) < 0) {
+ printf("cannot insert svr4 elf brand handler\n");
+ error = EINVAL;
+ break;
+ }
+ if (bootverbose)
+ printf("svr4 ELF exec handler installed\n");
+ svr4_sockcache_init();
+ break;
+ case MOD_UNLOAD:
+ /* Only allow the emulator to be removed if it isn't in use. */
+ if (elf32_brand_inuse(&svr4_brand) != 0) {
+ error = EBUSY;
+ } else if (elf32_remove_brand_entry(&svr4_brand) < 0) {
+ error = EINVAL;
+ }
+
+ if (error) {
+ printf("Could not deinstall ELF interpreter entry (error %d)\n",
+ error);
+ break;
+ }
+ if (bootverbose)
+ printf("svr4 ELF exec handler removed\n");
+ svr4_sockcache_destroy();
+ break;
+ default:
+ return (EOPNOTSUPP);
+ break;
+ }
+ return error;
+}
+
+static moduledata_t svr4_elf_mod = {
+ "svr4elf",
+ svr4_elf_modevent,
+ 0
+};
+DECLARE_MODULE_TIED(svr4elf, svr4_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY);
+MODULE_DEPEND(svr4elf, streams, 1, 1, 1);
diff --git a/sys/compat/svr4/svr4_termios.c b/sys/compat/svr4/svr4_termios.c
new file mode 100644
index 0000000..8195a41
--- /dev/null
+++ b/sys/compat/svr4/svr4_termios.c
@@ -0,0 +1,612 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/tty.h>
+
+#include <sys/sysproto.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_ioctl.h>
+#include <compat/svr4/svr4_termios.h>
+
+#ifndef __CONCAT3
+# if __STDC__
+# define __CONCAT3(a,b,c) a ## b ## c
+# else
+# define __CONCAT3(a,b,c) a/**/b/**/c
+# endif
+#endif
+
+static u_long bsd_to_svr4_speed(u_long, u_long);
+static u_long svr4_to_bsd_speed(u_long, u_long);
+static void svr4_to_bsd_termios(const struct svr4_termios *,
+ struct termios *, int);
+static void bsd_to_svr4_termios(const struct termios *,
+ struct svr4_termios *);
+static void svr4_termio_to_termios(const struct svr4_termio *,
+ struct svr4_termios *);
+static void svr4_termios_to_termio(const struct svr4_termios *,
+ struct svr4_termio *);
+#ifdef DEBUG_SVR4
+static void print_svr4_termios(const struct svr4_termios *);
+static void print_bsd_termios(const struct termios *);
+#endif /* DEBUG_SVR4 */
+
+#define undefined_char(a,b) /**/
+#define undefined_flag1(f,a,b) /**/
+#define undefined_flag2(f,a,b,c1,t1,c2,t2) /**/
+#define undefined_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) /**/
+
+#define svr4_to_bsd_char(a,b) \
+ if (new || __CONCAT3(SVR4_,a,b) < SVR4_NCC) { \
+ if (st->c_cc[__CONCAT3(SVR4_,a,b)] == SVR4_POSIX_VDISABLE) \
+ bt->c_cc[__CONCAT(a,b)] = _POSIX_VDISABLE; \
+ else \
+ bt->c_cc[__CONCAT(a,b)] = st->c_cc[__CONCAT3(SVR4_,a,b)]; \
+ }
+
+#define svr4_to_bsd_flag1(f,a,b) \
+ if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \
+ if (st->f & __CONCAT3(SVR4_,a,b)) \
+ bt->f |= __CONCAT(a,b); \
+ else \
+ bt->f &= ~__CONCAT(a,b); \
+ }
+
+#define svr4_to_bsd_flag2(f,a,b,c1,t1,c2,t2) \
+ if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \
+ bt->f &= ~__CONCAT(a,b); \
+ switch (st->f & __CONCAT3(SVR4_,a,b)) { \
+ case __CONCAT3(SVR4_,c1,t1): bt->f |= __CONCAT(c1,t1); break; \
+ case __CONCAT3(SVR4_,c2,t2): bt->f |= __CONCAT(c2,t2); break; \
+ } \
+ }
+
+#define svr4_to_bsd_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) \
+ if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \
+ bt->f &= ~__CONCAT(a,b); \
+ switch (st->f & __CONCAT3(SVR4_,a,b)) { \
+ case __CONCAT3(SVR4_,c1,t1): bt->f |= __CONCAT(c1,t1); break; \
+ case __CONCAT3(SVR4_,c2,t2): bt->f |= __CONCAT(c2,t2); break; \
+ case __CONCAT3(SVR4_,c3,t3): bt->f |= __CONCAT(c3,t3); break; \
+ case __CONCAT3(SVR4_,c4,t4): bt->f |= __CONCAT(c4,t4); break; \
+ } \
+ }
+
+
+#define bsd_to_svr4_char(a,b) \
+ if (bt->c_cc[__CONCAT(a,b)] == _POSIX_VDISABLE) \
+ st->c_cc[__CONCAT3(SVR4_,a,b)] = SVR4_POSIX_VDISABLE; \
+ else \
+ st->c_cc[__CONCAT3(SVR4_,a,b)] = bt->c_cc[__CONCAT(a,b)]
+
+#define bsd_to_svr4_flag1(f,a,b) \
+ if (bt->f & __CONCAT(a,b)) \
+ st->f |= __CONCAT3(SVR4_,a,b); \
+ else \
+ st->f &= ~__CONCAT3(SVR4_,a,b)
+
+#define bsd_to_svr4_flag2(f,a,b,c1,t1,c2,t2) \
+ st->f &= ~__CONCAT(a,b); \
+ switch (bt->f & __CONCAT(a,b)) { \
+ case __CONCAT(c1,t1): st->f |= __CONCAT3(SVR4_,c1,t1); break; \
+ case __CONCAT(c2,t2): st->f |= __CONCAT3(SVR4_,c2,t2); break; \
+ }
+
+#define bsd_to_svr4_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) \
+ st->f &= ~__CONCAT(a,b); \
+ switch (bt->f & __CONCAT(a,b)) { \
+ case __CONCAT(c1,t1): st->f |= __CONCAT3(SVR4_,c1,t1); break; \
+ case __CONCAT(c2,t2): st->f |= __CONCAT3(SVR4_,c2,t2); break; \
+ case __CONCAT(c3,t3): st->f |= __CONCAT3(SVR4_,c3,t3); break; \
+ case __CONCAT(c4,t4): st->f |= __CONCAT3(SVR4_,c4,t4); break; \
+ }
+
+#ifdef DEBUG_SVR4
+static void
+print_svr4_termios(st)
+ const struct svr4_termios *st;
+{
+ int i;
+ DPRINTF(("SVR4\niflag=%lo oflag=%lo cflag=%lo lflag=%lo\n",
+ st->c_iflag, st->c_oflag, st->c_cflag, st->c_lflag));
+ DPRINTF(("cc: "));
+ for (i = 0; i < SVR4_NCCS; i++)
+ DPRINTF(("%o ", st->c_cc[i]));
+ DPRINTF(("\n"));
+}
+
+
+static void
+print_bsd_termios(bt)
+ const struct termios *bt;
+{
+ int i;
+ uprintf("BSD\niflag=%o oflag=%o cflag=%o lflag=%o\n",
+ bt->c_iflag, bt->c_oflag, bt->c_cflag, bt->c_lflag);
+ uprintf("cc: ");
+ for (i = 0; i < NCCS; i++)
+ uprintf("%o ", bt->c_cc[i]);
+ uprintf("\n");
+}
+#endif /* DEBUG_SVR4 */
+
+static u_long
+bsd_to_svr4_speed(sp, mask)
+ u_long sp;
+ u_long mask;
+{
+ switch (sp) {
+#undef getval
+#define getval(a,b) case __CONCAT(a,b): sp = __CONCAT3(SVR4_,a,b)
+ getval(B,0);
+ getval(B,50);
+ getval(B,75);
+ getval(B,110);
+ getval(B,134);
+ getval(B,150);
+ getval(B,200);
+ getval(B,300);
+ getval(B,600);
+ getval(B,1200);
+ getval(B,1800);
+ getval(B,2400);
+ getval(B,4800);
+ getval(B,9600);
+ getval(B,19200);
+ getval(B,38400);
+ getval(B,57600);
+ getval(B,115200);
+ default: sp = SVR4_B9600; /* XXX */
+ }
+
+ while ((mask & 1) == 0) {
+ mask >>= 1;
+ sp <<= 1;
+ }
+
+ return sp;
+}
+
+
+static u_long
+svr4_to_bsd_speed(sp, mask)
+ u_long sp;
+ u_long mask;
+{
+ while ((mask & 1) == 0) {
+ mask >>= 1;
+ sp >>= 1;
+ }
+
+ switch (sp & mask) {
+#undef getval
+#define getval(a,b) case __CONCAT3(SVR4_,a,b): return __CONCAT(a,b)
+ getval(B,0);
+ getval(B,50);
+ getval(B,75);
+ getval(B,110);
+ getval(B,134);
+ getval(B,150);
+ getval(B,200);
+ getval(B,300);
+ getval(B,600);
+ getval(B,1200);
+ getval(B,1800);
+ getval(B,2400);
+ getval(B,4800);
+ getval(B,9600);
+ getval(B,19200);
+ getval(B,38400);
+ getval(B,57600);
+ getval(B,115200);
+ default: return B9600; /* XXX */
+ }
+}
+
+
+static void
+svr4_to_bsd_termios(st, bt, new)
+ const struct svr4_termios *st;
+ struct termios *bt;
+ int new;
+{
+ /* control characters */
+ /*
+ * We process VMIN and VTIME first,
+ * because they are shared with VEOF and VEOL
+ */
+ svr4_to_bsd_char(V,MIN);
+ svr4_to_bsd_char(V,TIME);
+
+ svr4_to_bsd_char(V,INTR);
+ svr4_to_bsd_char(V,QUIT);
+ svr4_to_bsd_char(V,ERASE);
+ svr4_to_bsd_char(V,KILL);
+ svr4_to_bsd_char(V,EOF);
+ svr4_to_bsd_char(V,EOL);
+ svr4_to_bsd_char(V,EOL2);
+ undefined_char(V,SWTCH);
+ svr4_to_bsd_char(V,START);
+ svr4_to_bsd_char(V,STOP);
+ svr4_to_bsd_char(V,SUSP);
+ svr4_to_bsd_char(V,DSUSP);
+ svr4_to_bsd_char(V,REPRINT);
+ svr4_to_bsd_char(V,DISCARD);
+ svr4_to_bsd_char(V,WERASE);
+ svr4_to_bsd_char(V,LNEXT);
+
+ /* Input modes */
+ svr4_to_bsd_flag1(c_iflag,I,GNBRK);
+ svr4_to_bsd_flag1(c_iflag,B,RKINT);
+ svr4_to_bsd_flag1(c_iflag,I,GNPAR);
+ svr4_to_bsd_flag1(c_iflag,P,ARMRK);
+ svr4_to_bsd_flag1(c_iflag,I,NPCK);
+ svr4_to_bsd_flag1(c_iflag,I,STRIP);
+ svr4_to_bsd_flag1(c_iflag,I,NLCR);
+ svr4_to_bsd_flag1(c_iflag,I,GNCR);
+ svr4_to_bsd_flag1(c_iflag,I,CRNL);
+ undefined_flag1(c_iflag,I,UCLC);
+ svr4_to_bsd_flag1(c_iflag,I,XON);
+ svr4_to_bsd_flag1(c_iflag,I,XANY);
+ svr4_to_bsd_flag1(c_iflag,I,XOFF);
+ svr4_to_bsd_flag1(c_iflag,I,MAXBEL);
+ undefined_flag1(c_iflag,D,OSMODE);
+
+ /* Output modes */
+ svr4_to_bsd_flag1(c_oflag,O,POST);
+ undefined_flag1(c_oflag,O,LCUC);
+ svr4_to_bsd_flag1(c_oflag,O,NLCR);
+ undefined_flag1(c_oflag,O,CRNL);
+ undefined_flag1(c_oflag,O,NOCR);
+ undefined_flag1(c_oflag,O,NLRET);
+ undefined_flag1(c_oflag,O,FILL);
+ undefined_flag1(c_oflag,O,FDEL);
+ undefined_flag2(c_oflag,N,LDLY,N,L0,N,L1);
+ undefined_flag4(c_oflag,C,RDLY,C,R0,C,R1,C,R2,C,R3);
+ undefined_flag4(c_oflag,T,ABDLY,T,AB0,T,AB1,T,AB2,T,AB3);
+ undefined_flag2(c_oflag,B,SDLY,B,S0,B,S1);
+ undefined_flag2(c_oflag,V,TDLY,V,T0,V,T1);
+ undefined_flag2(c_oflag,F,FDLY,F,F0,F,F1);
+ undefined_flag1(c_oflag,P,AGEOUT);
+ undefined_flag1(c_oflag,W,RAP);
+
+ /* Control modes */
+ bt->c_ospeed = svr4_to_bsd_speed(st->c_cflag, SVR4_CBAUD);
+ svr4_to_bsd_flag4(c_cflag,C,SIZE,C,S5,C,S6,C,S7,C,S8)
+ svr4_to_bsd_flag1(c_cflag,C,STOPB);
+ svr4_to_bsd_flag1(c_cflag,C,READ);
+ svr4_to_bsd_flag1(c_cflag,P,ARENB);
+ svr4_to_bsd_flag1(c_cflag,P,ARODD);
+ svr4_to_bsd_flag1(c_cflag,H,UPCL);
+ svr4_to_bsd_flag1(c_cflag,C,LOCAL);
+ undefined_flag1(c_cflag,R,CV1EN);
+ undefined_flag1(c_cflag,X,MT1EN);
+ undefined_flag1(c_cflag,L,OBLK);
+ undefined_flag1(c_cflag,X,CLUDE);
+ bt->c_ispeed = svr4_to_bsd_speed(st->c_cflag, SVR4_CIBAUD);
+ undefined_flag1(c_cflag,P,AREXT);
+
+ /* line discipline modes */
+ svr4_to_bsd_flag1(c_lflag,I,SIG);
+ svr4_to_bsd_flag1(c_lflag,I,CANON);
+ undefined_flag1(c_lflag,X,CASE);
+ svr4_to_bsd_flag1(c_lflag,E,CHO);
+ svr4_to_bsd_flag1(c_lflag,E,CHOE);
+ svr4_to_bsd_flag1(c_lflag,E,CHOK);
+ svr4_to_bsd_flag1(c_lflag,E,CHONL);
+ svr4_to_bsd_flag1(c_lflag,N,OFLSH);
+ svr4_to_bsd_flag1(c_lflag,T,OSTOP);
+ svr4_to_bsd_flag1(c_lflag,E,CHOCTL);
+ svr4_to_bsd_flag1(c_lflag,E,CHOPRT);
+ svr4_to_bsd_flag1(c_lflag,E,CHOKE);
+ undefined_flag1(c_lflag,D,EFECHO);
+ svr4_to_bsd_flag1(c_lflag,F,LUSHO);
+ svr4_to_bsd_flag1(c_lflag,P,ENDIN);
+ svr4_to_bsd_flag1(c_lflag,I,EXTEN);
+}
+
+
+static void
+bsd_to_svr4_termios(bt, st)
+ const struct termios *bt;
+ struct svr4_termios *st;
+{
+ /* control characters */
+ /*
+ * We process VMIN and VTIME first,
+ * because they are shared with VEOF and VEOL
+ */
+ bsd_to_svr4_char(V,MIN);
+ bsd_to_svr4_char(V,TIME);
+ bsd_to_svr4_char(V,INTR);
+ bsd_to_svr4_char(V,QUIT);
+ bsd_to_svr4_char(V,ERASE);
+ bsd_to_svr4_char(V,KILL);
+ bsd_to_svr4_char(V,EOF);
+ bsd_to_svr4_char(V,EOL);
+ bsd_to_svr4_char(V,EOL2);
+ undefined_char(V,SWTCH);
+ bsd_to_svr4_char(V,START);
+ bsd_to_svr4_char(V,STOP);
+ bsd_to_svr4_char(V,SUSP);
+ bsd_to_svr4_char(V,DSUSP);
+ bsd_to_svr4_char(V,REPRINT);
+ bsd_to_svr4_char(V,DISCARD);
+ bsd_to_svr4_char(V,WERASE);
+ bsd_to_svr4_char(V,LNEXT);
+
+ /* Input modes */
+ bsd_to_svr4_flag1(c_iflag,I,GNBRK);
+ bsd_to_svr4_flag1(c_iflag,B,RKINT);
+ bsd_to_svr4_flag1(c_iflag,I,GNPAR);
+ bsd_to_svr4_flag1(c_iflag,P,ARMRK);
+ bsd_to_svr4_flag1(c_iflag,I,NPCK);
+ bsd_to_svr4_flag1(c_iflag,I,STRIP);
+ bsd_to_svr4_flag1(c_iflag,I,NLCR);
+ bsd_to_svr4_flag1(c_iflag,I,GNCR);
+ bsd_to_svr4_flag1(c_iflag,I,CRNL);
+ undefined_flag1(c_iflag,I,UCLC);
+ bsd_to_svr4_flag1(c_iflag,I,XON);
+ bsd_to_svr4_flag1(c_iflag,I,XANY);
+ bsd_to_svr4_flag1(c_iflag,I,XOFF);
+ bsd_to_svr4_flag1(c_iflag,I,MAXBEL);
+ undefined_flag1(c_iflag,D,OSMODE);
+
+ /* Output modes */
+ bsd_to_svr4_flag1(c_oflag,O,POST);
+ undefined_flag1(c_oflag,O,LCUC);
+ bsd_to_svr4_flag1(c_oflag,O,NLCR);
+ undefined_flag1(c_oflag,O,CRNL);
+ undefined_flag1(c_oflag,O,NOCR);
+ undefined_flag1(c_oflag,O,NLRET);
+ undefined_flag1(c_oflag,O,FILL);
+ undefined_flag1(c_oflag,O,FDEL);
+ undefined_flag2(c_oflag,N,LDLY,N,L0,N,L1);
+ undefined_flag4(c_oflag,C,RDLY,C,R0,C,R1,C,R2,C,R3);
+ undefined_flag4(c_oflag,T,ABDLY,T,AB0,T,AB1,T,AB2,T,AB3);
+ undefined_flag2(c_oflag,B,SDLY,B,S0,B,S1);
+ undefined_flag2(c_oflag,V,TDLY,V,T0,V,T1);
+ undefined_flag2(c_oflag,F,FDLY,F,F0,F,F1);
+ undefined_flag1(c_oflag,P,AGEOUT);
+ undefined_flag1(c_oflag,W,RAP);
+
+ /* Control modes */
+ st->c_cflag &= ~SVR4_CBAUD;
+ st->c_cflag |= bsd_to_svr4_speed(bt->c_ospeed, SVR4_CBAUD);
+ bsd_to_svr4_flag4(c_cflag,C,SIZE,C,S5,C,S6,C,S7,C,S8)
+ bsd_to_svr4_flag1(c_cflag,C,STOPB);
+ bsd_to_svr4_flag1(c_cflag,C,READ);
+ bsd_to_svr4_flag1(c_cflag,P,ARENB);
+ bsd_to_svr4_flag1(c_cflag,P,ARODD);
+ bsd_to_svr4_flag1(c_cflag,H,UPCL);
+ bsd_to_svr4_flag1(c_cflag,C,LOCAL);
+ undefined_flag1(c_cflag,R,CV1EN);
+ undefined_flag1(c_cflag,X,MT1EN);
+ undefined_flag1(c_cflag,L,OBLK);
+ undefined_flag1(c_cflag,X,CLUDE);
+ st->c_cflag &= ~SVR4_CIBAUD;
+ st->c_cflag |= bsd_to_svr4_speed(bt->c_ispeed, SVR4_CIBAUD);
+
+ undefined_flag1(c_oflag,P,AREXT);
+
+ /* line discipline modes */
+ bsd_to_svr4_flag1(c_lflag,I,SIG);
+ bsd_to_svr4_flag1(c_lflag,I,CANON);
+ undefined_flag1(c_lflag,X,CASE);
+ bsd_to_svr4_flag1(c_lflag,E,CHO);
+ bsd_to_svr4_flag1(c_lflag,E,CHOE);
+ bsd_to_svr4_flag1(c_lflag,E,CHOK);
+ bsd_to_svr4_flag1(c_lflag,E,CHONL);
+ bsd_to_svr4_flag1(c_lflag,N,OFLSH);
+ bsd_to_svr4_flag1(c_lflag,T,OSTOP);
+ bsd_to_svr4_flag1(c_lflag,E,CHOCTL);
+ bsd_to_svr4_flag1(c_lflag,E,CHOPRT);
+ bsd_to_svr4_flag1(c_lflag,E,CHOKE);
+ undefined_flag1(c_lflag,D,EFECHO);
+ bsd_to_svr4_flag1(c_lflag,F,LUSHO);
+ bsd_to_svr4_flag1(c_lflag,P,ENDIN);
+ bsd_to_svr4_flag1(c_lflag,I,EXTEN);
+}
+
+
+static void
+svr4_termio_to_termios(t, ts)
+ const struct svr4_termio *t;
+ struct svr4_termios *ts;
+{
+ int i;
+
+ ts->c_iflag = (svr4_tcflag_t) t->c_iflag;
+ ts->c_oflag = (svr4_tcflag_t) t->c_oflag;
+ ts->c_cflag = (svr4_tcflag_t) t->c_cflag;
+ ts->c_lflag = (svr4_tcflag_t) t->c_lflag;
+
+ for (i = 0; i < SVR4_NCC; i++)
+ ts->c_cc[i] = (svr4_cc_t) t->c_cc[i];
+}
+
+
+static void
+svr4_termios_to_termio(ts, t)
+ const struct svr4_termios *ts;
+ struct svr4_termio *t;
+{
+ int i;
+
+ t->c_iflag = (u_short) ts->c_iflag;
+ t->c_oflag = (u_short) ts->c_oflag;
+ t->c_cflag = (u_short) ts->c_cflag;
+ t->c_lflag = (u_short) ts->c_lflag;
+ t->c_line = 0; /* XXX */
+
+ for (i = 0; i < SVR4_NCC; i++)
+ t->c_cc[i] = (u_char) ts->c_cc[i];
+}
+
+int
+svr4_term_ioctl(fp, td, retval, fd, cmd, data)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t data;
+{
+ struct termios bt;
+ struct svr4_termios st;
+ struct svr4_termio t;
+ int error, new;
+
+ *retval = 0;
+
+ DPRINTF(("TERM ioctl %lx\n", cmd));
+
+ switch (cmd) {
+ case SVR4_TCGETA:
+ case SVR4_TCGETS:
+ DPRINTF(("ioctl(TCGET%c);\n", cmd == SVR4_TCGETA ? 'A' : 'S'));
+ if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t) &bt,
+ td->td_ucred, td)) != 0)
+ return error;
+
+ memset(&st, 0, sizeof(st));
+ bsd_to_svr4_termios(&bt, &st);
+
+#ifdef DEBUG_SVR4
+ print_bsd_termios(&bt);
+ print_svr4_termios(&st);
+#endif /* DEBUG_SVR4 */
+
+ if (cmd == SVR4_TCGETA) {
+ svr4_termios_to_termio(&st, &t);
+ return copyout(&t, data, sizeof(t));
+ }
+ else {
+ return copyout(&st, data, sizeof(st));
+ }
+
+ case SVR4_TCSETA:
+ case SVR4_TCSETS:
+ case SVR4_TCSETAW:
+ case SVR4_TCSETSW:
+ case SVR4_TCSETAF:
+ case SVR4_TCSETSF:
+ DPRINTF(("TCSET{A,S,AW,SW,AF,SF}\n"));
+ /* get full BSD termios so we don't lose information */
+ if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t) &bt,
+ td->td_ucred, td)) != 0)
+ return error;
+
+ switch (cmd) {
+ case SVR4_TCSETS:
+ case SVR4_TCSETSW:
+ case SVR4_TCSETSF:
+ if ((error = copyin(data, &st, sizeof(st))) != 0)
+ return error;
+ new = 1;
+ break;
+
+ case SVR4_TCSETA:
+ case SVR4_TCSETAW:
+ case SVR4_TCSETAF:
+ if ((error = copyin(data, &t, sizeof(t))) != 0)
+ return error;
+
+ svr4_termio_to_termios(&t, &st);
+ new = 0;
+ break;
+
+ default:
+ return EINVAL;
+ }
+
+ svr4_to_bsd_termios(&st, &bt, new);
+
+ switch (cmd) {
+ case SVR4_TCSETA:
+ case SVR4_TCSETS:
+ DPRINTF(("ioctl(TCSET[A|S]);\n"));
+ cmd = TIOCSETA;
+ break;
+ case SVR4_TCSETAW:
+ case SVR4_TCSETSW:
+ DPRINTF(("ioctl(TCSET[A|S]W);\n"));
+ cmd = TIOCSETAW;
+ break;
+ case SVR4_TCSETAF:
+ case SVR4_TCSETSF:
+ DPRINTF(("ioctl(TCSET[A|S]F);\n"));
+ cmd = TIOCSETAF;
+ break;
+ }
+
+#ifdef DEBUG_SVR4
+ print_bsd_termios(&bt);
+ print_svr4_termios(&st);
+#endif /* DEBUG_SVR4 */
+
+ return fo_ioctl(fp, cmd, (caddr_t) &bt, td->td_ucred, td);
+
+ case SVR4_TIOCGWINSZ:
+ DPRINTF(("TIOCGWINSZ\n"));
+ {
+ struct svr4_winsize ws;
+
+ error = fo_ioctl(fp, TIOCGWINSZ, (caddr_t) &ws,
+ td->td_ucred, td);
+ if (error)
+ return error;
+ return copyout(&ws, data, sizeof(ws));
+ }
+
+ case SVR4_TIOCSWINSZ:
+ DPRINTF(("TIOCSWINSZ\n"));
+ {
+ struct svr4_winsize ws;
+
+ if ((error = copyin(data, &ws, sizeof(ws))) != 0)
+ return error;
+ return fo_ioctl(fp, TIOCSWINSZ, (caddr_t) &ws,
+ td->td_ucred, td);
+ }
+
+ default:
+ DPRINTF(("teleport to STREAMS ioctls...\n"));
+ return svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, data);
+ }
+}
diff --git a/sys/compat/svr4/svr4_termios.h b/sys/compat/svr4/svr4_termios.h
new file mode 100644
index 0000000..c2b0c54
--- /dev/null
+++ b/sys/compat/svr4/svr4_termios.h
@@ -0,0 +1,224 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_TERMIOS_H_
+#define _SVR4_TERMIOS_H_
+
+#define SVR4_POSIX_VDISABLE 0
+#define SVR4_NCC 8
+#define SVR4_NCCS 19
+
+typedef u_long svr4_tcflag_t;
+typedef u_char svr4_cc_t;
+typedef u_long svr4_speed_t;
+
+struct svr4_termios {
+ svr4_tcflag_t c_iflag;
+ svr4_tcflag_t c_oflag;
+ svr4_tcflag_t c_cflag;
+ svr4_tcflag_t c_lflag;
+ svr4_cc_t c_cc[SVR4_NCCS];
+};
+
+struct svr4_termio {
+ u_short c_iflag;
+ u_short c_oflag;
+ u_short c_cflag;
+ u_short c_lflag;
+ char c_line;
+ u_char c_cc[SVR4_NCC];
+};
+
+/* control characters */
+#define SVR4_VINTR 0
+#define SVR4_VQUIT 1
+#define SVR4_VERASE 2
+#define SVR4_VKILL 3
+#define SVR4_VEOF 4
+#define SVR4_VEOL 5
+#define SVR4_VEOL2 6
+#define SVR4_VMIN 4
+#define SVR4_VTIME 5
+#define SVR4_VSWTCH 7
+#define SVR4_VSTART 8
+#define SVR4_VSTOP 9
+#define SVR4_VSUSP 10
+#define SVR4_VDSUSP 11
+#define SVR4_VREPRINT 12
+#define SVR4_VDISCARD 13
+#define SVR4_VWERASE 14
+#define SVR4_VLNEXT 15
+
+/* Input modes */
+#define SVR4_IGNBRK 00000001
+#define SVR4_BRKINT 00000002
+#define SVR4_IGNPAR 00000004
+#define SVR4_PARMRK 00000010
+#define SVR4_INPCK 00000020
+#define SVR4_ISTRIP 00000040
+#define SVR4_INLCR 00000100
+#define SVR4_IGNCR 00000200
+#define SVR4_ICRNL 00000400
+#define SVR4_IUCLC 00001000
+#define SVR4_IXON 00002000
+#define SVR4_IXANY 00004000
+#define SVR4_IXOFF 00010000
+#define SVR4_IMAXBEL 00020000
+#define SVR4_DOSMODE 00100000
+
+/* Output modes */
+#define SVR4_OPOST 00000001
+#define SVR4_OLCUC 00000002
+#define SVR4_ONLCR 00000004
+#define SVR4_OCRNL 00000010
+#define SVR4_ONOCR 00000020
+#define SVR4_ONLRET 00000040
+#define SVR4_OFILL 00000100
+#define SVR4_OFDEL 00000200
+#define SVR4_NLDLY 00000400
+#define SVR4_NL0 00000000
+#define SVR4_NL1 00000400
+#define SVR4_CRDLY 00003000
+#define SVR4_CR0 00000000
+#define SVR4_CR1 00001000
+#define SVR4_CR2 00002000
+#define SVR4_CR3 00003000
+#define SVR4_TABDLY 00014000
+#define SVR4_TAB0 00000000
+#define SVR4_TAB1 00004000
+#define SVR4_TAB2 00010000
+#define SVR4_TAB3 00014000
+#define SVR4_XTABS 00014000
+#define SVR4_BSDLY 00020000
+#define SVR4_BS0 00000000
+#define SVR4_BS1 00020000
+#define SVR4_VTDLY 00040000
+#define SVR4_VT0 00000000
+#define SVR4_VT1 00040000
+#define SVR4_FFDLY 00100000
+#define SVR4_FF0 00000000
+#define SVR4_FF1 00100000
+#define SVR4_PAGEOUT 00200000
+#define SVR4_WRAP 00400000
+
+/* Control modes */
+#define SVR4_CBAUD 00000017
+#define SVR4_CSIZE 00000060
+#define SVR4_CS5 00000000
+#define SVR4_CS6 00000200
+#define SVR4_CS7 00000040
+#define SVR4_CS8 00000006
+#define SVR4_CSTOPB 00000100
+#define SVR4_CREAD 00000200
+#define SVR4_PARENB 00000400
+#define SVR4_PARODD 00001000
+#define SVR4_HUPCL 00002000
+#define SVR4_CLOCAL 00004000
+#define SVR4_RCV1EN 00010000
+#define SVR4_XMT1EN 00020000
+#define SVR4_LOBLK 00040000
+#define SVR4_XCLUDE 00100000
+#define SVR4_CIBAUD 03600000
+#define SVR4_PAREXT 04000000
+
+/* line discipline modes */
+#define SVR4_ISIG 00000001
+#define SVR4_ICANON 00000002
+#define SVR4_XCASE 00000004
+#define SVR4_ECHO 00000010
+#define SVR4_ECHOE 00000020
+#define SVR4_ECHOK 00000040
+#define SVR4_ECHONL 00000100
+#define SVR4_NOFLSH 00000200
+#define SVR4_TOSTOP 00000400
+#define SVR4_ECHOCTL 00001000
+#define SVR4_ECHOPRT 00002000
+#define SVR4_ECHOKE 00004000
+#define SVR4_DEFECHO 00010000
+#define SVR4_FLUSHO 00020000
+#define SVR4_PENDIN 00040000
+#define SVR4_IEXTEN 00100000
+
+#define SVR4_TIOC ('T' << 8)
+
+#define SVR4_TCGETA (SVR4_TIOC| 1)
+#define SVR4_TCSETA (SVR4_TIOC| 2)
+#define SVR4_TCSETAW (SVR4_TIOC| 3)
+#define SVR4_TCSETAF (SVR4_TIOC| 4)
+#define SVR4_TCSBRK (SVR4_TIOC| 5)
+#define SVR4_TCXONC (SVR4_TIOC| 6)
+#define SVR4_TCFLSH (SVR4_TIOC| 7)
+#define SVR4_TIOCKBON (SVR4_TIOC| 8)
+#define SVR4_TIOCKBOF (SVR4_TIOC| 9)
+#define SVR4_KBENABLED (SVR4_TIOC|10)
+#define SVR4_TCGETS (SVR4_TIOC|13)
+#define SVR4_TCSETS (SVR4_TIOC|14)
+#define SVR4_TCSETSW (SVR4_TIOC|15)
+#define SVR4_TCSETSF (SVR4_TIOC|16)
+#define SVR4_TCDSET (SVR4_TIOC|32)
+#define SVR4_RTS_TOG (SVR4_TIOC|33)
+#define SVR4_TCGETSC (SVR4_TIOC|34)
+#define SVR4_TCSETSC (SVR4_TIOC|35)
+#define SVR4_TCMOUSE (SVR4_TIOC|36)
+#define SVR4_TIOCGWINSZ (SVR4_TIOC|104)
+#define SVR4_TIOCSWINSZ (SVR4_TIOC|103)
+
+struct svr4_winsize {
+ u_short ws_row;
+ u_short ws_col;
+ u_short ws_xpixel;
+ u_short ws_ypixel;
+};
+
+#define SVR4_B0 0
+#define SVR4_B50 1
+#define SVR4_B75 2
+#define SVR4_B110 3
+#define SVR4_B134 4
+#define SVR4_B150 5
+#define SVR4_B200 6
+#define SVR4_B300 7
+#define SVR4_B600 8
+#define SVR4_B1200 9
+#define SVR4_B1800 10
+#define SVR4_B2400 11
+#define SVR4_B4800 12
+#define SVR4_B9600 13
+#define SVR4_B19200 14
+#define SVR4_B38400 15
+#define SVR4_B57600 16
+#define SVR4_B76800 17
+#define SVR4_B115200 18
+#define SVR4_B153600 19
+#define SVR4_B230400 20
+#define SVR4_B307200 21
+#define SVR4_B460800 22
+
+#endif /* !_SVR4_TERMIOS_H_ */
diff --git a/sys/compat/svr4/svr4_time.h b/sys/compat/svr4/svr4_time.h
new file mode 100644
index 0000000..0be9823
--- /dev/null
+++ b/sys/compat/svr4/svr4_time.h
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_TIME_H_
+#define _SVR4_TIME_H_
+
+#include <sys/time.h>
+
+struct svr4_utimbuf {
+ time_t actime;
+ time_t modtime;
+};
+
+#endif /* !_SVR4_TIME_H_ */
diff --git a/sys/compat/svr4/svr4_timod.h b/sys/compat/svr4/svr4_timod.h
new file mode 100644
index 0000000..e295a4c
--- /dev/null
+++ b/sys/compat/svr4/svr4_timod.h
@@ -0,0 +1,87 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_TIMOD_H_
+#define _SVR4_TIMOD_H_
+
+#define SVR4_TIMOD ('T' << 8)
+#define SVR4_TI_GETINFO (SVR4_TIMOD|140)
+#define SVR4_TI_OPTMGMT (SVR4_TIMOD|141)
+#define SVR4_TI_BIND (SVR4_TIMOD|142)
+#define SVR4_TI_UNBIND (SVR4_TIMOD|143)
+#define SVR4_TI_GETMYNAME (SVR4_TIMOD|144)
+#define SVR4_TI_GETPEERNAME (SVR4_TIMOD|145)
+#define SVR4_TI_SETMYNAME (SVR4_TIMOD|146)
+#define SVR4_TI_SETPEERNAME (SVR4_TIMOD|147)
+#define SVR4_TI_SYNC (SVR4_TIMOD|148)
+#define SVR4_TI_GETADDRS (SVR4_TIMOD|149)
+
+#define SVR4_TI_CONNECT_REQUEST 0x00
+#define SVR4_TI_CONNECT_RESPONSE 0x01
+#define SVR4_TI_DISCONNECT_REQUEST 0x02
+#define SVR4_TI_DATA_REQUEST 0x03
+#define SVR4_TI_EXPDATA_REQUEST 0x04
+#define SVR4_TI_INFO_REQUEST 0x05
+#define SVR4_TI_OLD_BIND_REQUEST 0x06
+#define SVR4_TI_UNBIND_REQUEST 0x07
+#define SVR4_TI_SENDTO_REQUEST 0x08
+#define SVR4_TI_OLD_OPTMGMT_REQUEST 0x09
+#define SVR4_TI_ORDREL_REQUEST 0x0a
+
+#define SVR4_TI_ACCEPT_REPLY 0x0b
+#define SVR4_TI_CONNECT_REPLY 0x0c
+#define SVR4_TI_DISCONNECT_IND 0x0d
+#define SVR4_TI_DATA_IND 0x0e
+#define SVR4_TI_EXPDATA_IND 0x0f
+#define SVR4_TI_INFO_REPLY 0x10
+#define SVR4_TI_BIND_REPLY 0x11
+#define SVR4_TI_ERROR_REPLY 0x12
+#define SVR4_TI_OK_REPLY 0x13
+#define SVR4_TI_RECVFROM_IND 0x14
+#define SVR4_TI_RECVFROM_ERROR_IND 0x15
+#define SVR4_TI_OPTMGMT_REPLY 0x16
+#define SVR4_TI_ORDREL_IND 0x17
+
+#define SVR4_TI_ADDRESS_REQUEST 0x18
+#define SVR4_TI_ADDRESS_REPLY 0x19
+
+#define SVR4_TI_BIND_REQUEST 0x20
+#define SVR4_TI_OPTMGMT_REQUEST 0x21
+
+#define SVR4_TI__ACCEPT_WAIT 0x10000001
+#define SVR4_TI__ACCEPT_OK 0x10000002
+
+struct svr4_netbuf {
+ u_int maxlen;
+ u_int len;
+ char *buf;
+};
+
+#endif /* !_SVR4_TIMOD_H_ */
diff --git a/sys/compat/svr4/svr4_types.h b/sys/compat/svr4/svr4_types.h
new file mode 100644
index 0000000..e4f51b5
--- /dev/null
+++ b/sys/compat/svr4/svr4_types.h
@@ -0,0 +1,81 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_TYPES_H_
+#define _SVR4_TYPES_H_
+
+typedef u_quad_t svr4_ino64_t;
+typedef quad_t svr4_off64_t;
+typedef quad_t svr4_blkcnt64_t;
+typedef u_quad_t svr4_fsblkcnt64_t;
+
+typedef long svr4_off_t;
+typedef u_long svr4_dev_t;
+typedef u_long svr4_ino_t;
+typedef u_long svr4_mode_t;
+typedef u_long svr4_nlink_t;
+typedef long svr4_uid_t;
+typedef long svr4_gid_t;
+typedef long svr4_daddr_t;
+typedef long svr4_pid_t;
+typedef long svr4_time_t;
+typedef long svr4_blkcnt_t;
+typedef u_long svr4_fsblkcnt_t;
+typedef char *svr4_caddr_t;
+typedef u_int svr4_size_t;
+
+typedef short svr4_o_dev_t;
+typedef short svr4_o_pid_t;
+typedef u_short svr4_o_ino_t;
+typedef u_short svr4_o_mode_t;
+typedef short svr4_o_nlink_t;
+typedef u_short svr4_o_uid_t;
+typedef u_short svr4_o_gid_t;
+typedef long svr4_clock_t;
+typedef int svr4_key_t;
+
+typedef struct timespec svr4_timestruc_t;
+
+#define svr4_omajor(x) ((int32_t)((((x) & 0x7f00) >> 8)))
+#define svr4_ominor(x) ((int32_t)((((x) & 0x00ff) >> 0)))
+#define svr4_omakedev(x,y) ((svr4_o_dev_t)((((x) << 8) & 0x7f00) | \
+ (((y) << 0) & 0x00ff)))
+
+#define svr4_to_bsd_odev_t(d) makedev(svr4_omajor(d), svr4_ominor(d))
+#define bsd_to_svr4_odev_t(d) svr4_omakedev(major(d), minor(d))
+
+#define svr4_major(x) ((int32_t)((((x) & 0xfffc0000) >> 18)))
+#define svr4_minor(x) ((int32_t)((((x) & 0x0003ffff) >> 0)))
+#define svr4_makedev(x,y) ((svr4_dev_t)((((x) << 18) & 0xfffc0000) | \
+ (((y) << 0) & 0x0003ffff)))
+#define svr4_to_bsd_dev_t(d) makedev(svr4_major(d), svr4_minor(d))
+#define bsd_to_svr4_dev_t(d) svr4_makedev(major(d), minor(d))
+
+#endif /* !_SVR4_TYPES_H_ */
diff --git a/sys/compat/svr4/svr4_ucontext.h b/sys/compat/svr4/svr4_ucontext.h
new file mode 100644
index 0000000..24cb5a1
--- /dev/null
+++ b/sys/compat/svr4/svr4_ucontext.h
@@ -0,0 +1,74 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_UCONTEXT_H_
+#define _SVR4_UCONTEXT_H_
+
+/*
+ * Machine context
+ */
+
+#define SVR4_UC_SIGMASK 0x01
+#define SVR4_UC_STACK 0x02
+
+#define SVR4_UC_CPU 0x04
+#define SVR4_UC_FPU 0x08
+#define SVR4_UC_WEITEK 0x10
+
+#define SVR4_UC_MCONTEXT (SVR4_UC_CPU|SVR4_UC_FPU|SVR4_UC_WEITEK)
+
+#define SVR4_UC_ALL (SVR4_UC_SIGMASK|SVR4_UC_STACK|SVR4_UC_MCONTEXT)
+
+typedef struct svr4_ucontext {
+ u_long uc_flags;
+ /* struct svr4_ucontext *uc_link;*/
+ void *uc_link;
+ svr4_sigset_t uc_sigmask;
+ struct svr4_sigaltstack uc_stack;
+ svr4_mcontext_t uc_mcontext;
+ long uc_pad[5];
+} svr4_ucontext_t;
+
+#define SVR4_UC_GETREGSET 0
+#define SVR4_UC_SETREGSET 1
+
+/*
+ * Signal frame
+ */
+struct svr4_sigframe {
+ int sf_signum;
+ union svr4_siginfo *sf_sip;
+ struct svr4_ucontext *sf_ucp;
+ sig_t sf_handler;
+ struct svr4_ucontext sf_uc;
+ union svr4_siginfo sf_si;
+};
+
+#endif /* !_SVR4_UCONTEXT_H_ */
diff --git a/sys/compat/svr4/svr4_ulimit.h b/sys/compat/svr4/svr4_ulimit.h
new file mode 100644
index 0000000..d636c01
--- /dev/null
+++ b/sys/compat/svr4/svr4_ulimit.h
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_ULIMIT_H_
+#define _SVR4_ULIMIT_H_
+
+#define SVR4_GFILLIM 1
+#define SVR4_SFILLIM 2
+#define SVR4_GMEMLIM 3
+#define SVR4_GDESLIM 4
+#define SVR4_GTXTOFF 64
+
+
+#endif /* !_SVR4_ULIMIT_H_ */
diff --git a/sys/compat/svr4/svr4_ustat.h b/sys/compat/svr4/svr4_ustat.h
new file mode 100644
index 0000000..3b9ade1
--- /dev/null
+++ b/sys/compat/svr4/svr4_ustat.h
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_USTAT_H_
+#define _SVR4_USTAT_H_
+
+#include <compat/svr4/svr4_types.h>
+
+struct svr4_ustat {
+ svr4_daddr_t f_tfree;
+ svr4_ino_t f_tinode;
+ char f_fname[6];
+ char f_fpack[6];
+};
+
+#endif /* !_SVR4_USTAT_H_ */
diff --git a/sys/compat/svr4/svr4_util.h b/sys/compat/svr4/svr4_util.h
new file mode 100644
index 0000000..4cbf230
--- /dev/null
+++ b/sys/compat/svr4/svr4_util.h
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_UTIL_H_
+#define _SVR4_UTIL_H_
+
+/*#include <compat/common/compat_util.h>*/
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <machine/vmparam.h>
+#include <sys/exec.h>
+#include <sys/sysent.h>
+#include <sys/cdefs.h>
+#include <sys/uio.h>
+
+#ifdef DEBUG_SVR4
+#define DPRINTF(a) uprintf a;
+#else
+#define DPRINTF(a)
+#endif
+
+int svr4_emul_find(struct thread *, char *, enum uio_seg, char **, int);
+
+#define CHECKALT(td, upath, pathp, i) \
+ do { \
+ int _error; \
+ \
+ _error = svr4_emul_find(td, upath, UIO_USERSPACE, pathp, i); \
+ if (*(pathp) == NULL) \
+ return (_error); \
+ } while (0)
+
+#define CHECKALTEXIST(td, upath, pathp) CHECKALT(td, upath, pathp, 0)
+#define CHECKALTCREAT(td, upath, pathp) CHECKALT(td, upath, pathp, 1)
+
+#endif /* !_SVR4_UTIL_H_ */
diff --git a/sys/compat/svr4/svr4_utsname.h b/sys/compat/svr4/svr4_utsname.h
new file mode 100644
index 0000000..7179575
--- /dev/null
+++ b/sys/compat/svr4/svr4_utsname.h
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_UTSNAME_H_
+#define _SVR4_UTSNAME_H_
+
+#include <compat/svr4/svr4_types.h>
+
+struct svr4_utsname {
+ char sysname[257];
+ char nodename[257];
+ char release[257];
+ char version[257];
+ char machine[257];
+};
+
+#endif /* !_SVR4_UTSNAME_H_ */
diff --git a/sys/compat/svr4/svr4_wait.h b/sys/compat/svr4/svr4_wait.h
new file mode 100644
index 0000000..0ce5db7
--- /dev/null
+++ b/sys/compat/svr4/svr4_wait.h
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_WAIT_H_
+#define _SVR4_WAIT_H_
+
+
+#define SVR4_P_PID 0
+#define SVR4_P_PPID 1
+#define SVR4_P_PGID 2
+#define SVR4_P_SID 3
+#define SVR4_P_CID 4
+#define SVR4_P_UID 5
+#define SVR4_P_GID 6
+#define SVR4_P_ALL 7
+
+#define SVR4_WEXITED 0x01
+#define SVR4_WTRAPPED 0x02
+#define SVR4_WSTOPPED 0x04
+#define SVR4_WCONTINUED 0x08
+#define SVR4_WUNDEF1 0x10
+#define SVR4_WUNDEF2 0x20
+#define SVR4_WNOHANG 0x40
+#define SVR4_WNOWAIT 0x80
+
+#define SVR4_WOPTMASK (SVR4_WEXITED|SVR4_WTRAPPED|SVR4_WSTOPPED|\
+ SVR4_WCONTINUED|SVR4_WNOHANG|SVR4_WNOWAIT)
+
+#endif /* !_SVR4_WAIT_H_ */
diff --git a/sys/compat/svr4/syscalls.conf b/sys/compat/svr4/syscalls.conf
new file mode 100644
index 0000000..84e0783
--- /dev/null
+++ b/sys/compat/svr4/syscalls.conf
@@ -0,0 +1,11 @@
+# $FreeBSD$
+sysnames="svr4_syscallnames.c"
+sysproto="svr4_proto.h"
+sysproto_h=_SVR4_SYSPROTO_H_
+syshdr="svr4_syscall.h"
+syssw="svr4_sysent.c"
+sysmk="/dev/null"
+syscallprefix="SVR4_SYS_"
+switchname="svr4_sysent"
+namesname="svr4_syscallnames"
+systrace="/dev/null"
diff --git a/sys/compat/svr4/syscalls.master b/sys/compat/svr4/syscalls.master
new file mode 100644
index 0000000..0997ab7
--- /dev/null
+++ b/sys/compat/svr4/syscalls.master
@@ -0,0 +1,396 @@
+ $FreeBSD$
+; from: @(#)syscalls.master 8.1 (Berkeley) 7/19/93
+;
+; System call name/number master file (or rather, slave, from SVR4).
+; Processed to create svr4_sysent.c, svr4_syscalls.c and svr4_syscall.h.
+
+; Columns: number type nargs name alt{name,tag,rtyp}/comments
+; number system call number, must be in order
+; audit the audit event associated with the system call
+; A value of AUE_NULL means no auditing, but it also means that
+; there is no audit event for the call at this time. For the
+; case where the event exists, but we don't want auditing, the
+; event should be #defined to AUE_NULL in audit_kevents.h.
+; type one of STD, OBSOL, UNIMPL, COMPAT
+; name psuedo-prototype of syscall routine
+; If one of the following alts is different, then all appear:
+; altname name of system call if different
+; alttag name of args struct tag if different from [o]`name'"_args"
+; altrtyp return type if not int (bogus - syscalls always return int)
+; for UNIMPL/OBSOL, name continues with comments
+
+; types:
+; STD always included
+; COMPAT included on COMPAT #ifdef
+; OBSOL obsolete, not included in system, only specifies name
+; UNIMPL not implemented, placeholder only
+
+; #ifdef's, etc. may be included, and are copied to the output files.
+
+#include <sys/types.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <netinet/in.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_proto.h>
+
+0 AUE_NULL UNIMPL unused
+1 AUE_NULL NOPROTO { void sys_exit(int rval); } exit \
+ sys_exit_args void
+2 AUE_NULL NOPROTO { int fork(void); }
+3 AUE_NULL NOPROTO { int read(int fd, char *buf, u_int nbyte); }
+4 AUE_NULL NOPROTO { int write(int fd, char *buf, u_int nbyte); }
+5 AUE_NULL STD { int svr4_sys_open(char *path, int flags, \
+ int mode); }
+6 AUE_NULL NOPROTO { int close(int fd); }
+7 AUE_NULL STD { int svr4_sys_wait(int *status); }
+8 AUE_NULL STD { int svr4_sys_creat(char *path, int mode); }
+9 AUE_NULL NOPROTO { int link(char *path, char *link); }
+10 AUE_NULL NOPROTO { int unlink(char *path); }
+11 AUE_NULL STD { int svr4_sys_execv(char *path, char **argp); }
+12 AUE_NULL NOPROTO { int chdir(char *path); }
+13 AUE_NULL STD { int svr4_sys_time(time_t *t); }
+14 AUE_NULL STD { int svr4_sys_mknod(char* path, int mode, int dev); }
+15 AUE_NULL NOPROTO { int chmod(char *path, int mode); }
+16 AUE_NULL NOPROTO { int chown(char *path, uid_t uid, gid_t gid); }
+17 AUE_NULL STD { int svr4_sys_break(caddr_t nsize); }
+18 AUE_NULL STD { int svr4_sys_stat(char* path, \
+ struct svr4_stat* ub); }
+19 AUE_NULL NOPROTO { int lseek(int filedes, off_t *offset, \
+ int whence); }
+20 AUE_NULL NOPROTO { pid_t getpid(void); }
+21 AUE_NULL UNIMPL old_mount
+22 AUE_NULL UNIMPL sysv_umount
+23 AUE_NULL NOPROTO { int setuid(uid_t uid); }
+24 AUE_NULL NOPROTO { uid_t getuid(void); }
+25 AUE_NULL UNIMPL stime
+26 AUE_NULL UNIMPL ptrace
+27 AUE_NULL STD { int svr4_sys_alarm(unsigned sec); }
+28 AUE_NULL STD { int svr4_sys_fstat(int fd, \
+ struct svr4_stat *sb); }
+29 AUE_NULL STD { int svr4_sys_pause(void); }
+30 AUE_NULL STD { int svr4_sys_utime(char *path, \
+ struct svr4_utimbuf *ubuf); }
+31 AUE_NULL UNIMPL stty
+32 AUE_NULL UNIMPL gtty
+33 AUE_NULL STD { int svr4_sys_access(char *path, \
+ int amode); }
+34 AUE_NULL STD { int svr4_sys_nice(int prio); }
+35 AUE_NULL UNIMPL statfs
+36 AUE_NULL NOPROTO { int sync(void); }
+37 AUE_NULL STD { int svr4_sys_kill(int pid, int signum); }
+38 AUE_NULL UNIMPL fstatfs
+39 AUE_NULL STD { int svr4_sys_pgrpsys(int cmd, int pid, \
+ int pgid); }
+40 AUE_NULL UNIMPL xenix
+41 AUE_NULL NOPROTO { int dup(u_int fd); }
+42 AUE_NULL NOPROTO { int pipe(void); }
+43 AUE_NULL STD { int svr4_sys_times(struct tms *tp); }
+44 AUE_NULL UNIMPL profil
+45 AUE_NULL UNIMPL plock
+46 AUE_NULL NOPROTO { int setgid(gid_t gid); }
+47 AUE_NULL NOPROTO { gid_t getgid(void); }
+48 AUE_NULL STD { int svr4_sys_signal(int signum, \
+ svr4_sig_t handler); }
+49 AUE_NULL STD { int svr4_sys_msgsys(int what, int a2, \
+ int a3, int a4, int a5); }
+50 AUE_NULL STD { int svr4_sys_sysarch(int op, void *a1); }
+51 AUE_NULL UNIMPL acct
+52 AUE_NULL STD { int svr4_sys_shmsys(int what, int a2, \
+ int a3, int a4, int a5); }
+53 AUE_NULL STD { int svr4_sys_semsys(int what, int a2, \
+ int a3, int a4, int a5); }
+54 AUE_NULL STD { int svr4_sys_ioctl(int fd, u_long com, \
+ caddr_t data); }
+55 AUE_NULL UNIMPL uadmin
+56 AUE_NULL UNIMPL exch
+57 AUE_NULL STD { int svr4_sys_utssys(void *a1, void *a2, \
+ int sel, void *a3); }
+58 AUE_NULL NOPROTO { int fsync(int fd); }
+59 AUE_NULL STD { int svr4_sys_execve(char *path, \
+ char **argp, char **envp); }
+60 AUE_NULL NOPROTO { int umask(int newmask); }
+61 AUE_NULL NOPROTO { int chroot(char *path); }
+62 AUE_NULL STD { int svr4_sys_fcntl(int fd, int cmd, \
+ char *arg); }
+63 AUE_NULL STD { int svr4_sys_ulimit(int cmd, \
+ long newlimit); }
+64 AUE_NULL UNIMPL reserved
+65 AUE_NULL UNIMPL reserved
+66 AUE_NULL UNIMPL reserved
+67 AUE_NULL UNIMPL reserved
+68 AUE_NULL UNIMPL reserved
+69 AUE_NULL UNIMPL reserved
+70 AUE_NULL UNIMPL advfs
+71 AUE_NULL UNIMPL unadvfs
+72 AUE_NULL UNIMPL rmount
+73 AUE_NULL UNIMPL rumount
+74 AUE_NULL UNIMPL rfstart
+75 AUE_NULL UNIMPL sigret
+76 AUE_NULL UNIMPL rdebug
+77 AUE_NULL UNIMPL rfstop
+78 AUE_NULL UNIMPL rfsys
+79 AUE_NULL NOPROTO { int rmdir(char *path); }
+80 AUE_NULL NOPROTO { int mkdir(char *path, int mode); }
+81 AUE_NULL STD { int svr4_sys_getdents(int fd, char *buf, \
+ int nbytes); }
+82 AUE_NULL UNIMPL libattach
+83 AUE_NULL UNIMPL libdetach
+84 AUE_NULL UNIMPL sysfs
+85 AUE_NULL STD { int svr4_sys_getmsg(int fd, \
+ struct svr4_strbuf *ctl, \
+ struct svr4_strbuf *dat, int *flags); }
+86 AUE_NULL STD { int svr4_sys_putmsg(int fd, \
+ struct svr4_strbuf *ctl, \
+ struct svr4_strbuf *dat, int flags); }
+87 AUE_NULL STD { int svr4_sys_poll(struct pollfd *fds, \
+ unsigned int nfds, int timeout); }
+88 AUE_NULL STD { int svr4_sys_lstat(char *path, \
+ struct svr4_stat *ub); }
+89 AUE_NULL NOPROTO { int symlink(char *path, char *link); }
+90 AUE_NULL NOPROTO { int readlink(char *path, char *buf, \
+ int count); }
+91 AUE_NULL NOPROTO { int getgroups(u_int gidsetsize, \
+ gid_t *gidset); }
+92 AUE_NULL NOPROTO { int setgroups(u_int gidsetsize, \
+ gid_t *gidset); }
+93 AUE_NULL NOPROTO { int fchmod(int fd, int mode); }
+94 AUE_NULL NOPROTO { int fchown(int fd, int uid, int gid); }
+95 AUE_NULL STD { int svr4_sys_sigprocmask(int how, \
+ svr4_sigset_t *set, \
+ svr4_sigset_t *oset); }
+96 AUE_NULL STD { int svr4_sys_sigsuspend( \
+ svr4_sigset_t *ss); }
+97 AUE_NULL STD { int svr4_sys_sigaltstack( \
+ struct svr4_sigaltstack *nss, \
+ struct svr4_sigaltstack *oss); }
+98 AUE_NULL STD { int svr4_sys_sigaction(int signum, \
+ struct svr4_sigaction *nsa, \
+ struct svr4_sigaction *osa); }
+99 AUE_NULL STD { int svr4_sys_sigpending(int what, \
+ svr4_sigset_t *mask); }
+100 AUE_NULL STD { int svr4_sys_context(int func, \
+ struct svr4_ucontext *uc); }
+101 AUE_NULL UNIMPL evsys
+102 AUE_NULL UNIMPL evtrapret
+103 AUE_NULL STD { int svr4_sys_statvfs(char *path, \
+ struct svr4_statvfs *fs); }
+104 AUE_NULL STD { int svr4_sys_fstatvfs(int fd, \
+ struct svr4_statvfs *fs); }
+105 AUE_NULL UNIMPL whoknows
+106 AUE_NULL UNIMPL nfssvc
+107 AUE_NULL STD { int svr4_sys_waitsys(int grp, int id, \
+ union svr4_siginfo *info, int options); }
+108 AUE_NULL UNIMPL sigsendsys
+109 AUE_NULL STD { int svr4_sys_hrtsys(int cmd, int fun, \
+ int sub, void *rv1, void *rv2); }
+110 AUE_NULL UNIMPL acancel
+111 AUE_NULL UNIMPL async
+112 AUE_NULL UNIMPL priocntlsys
+113 AUE_NULL STD { int svr4_sys_pathconf(char *path, \
+ int name); }
+114 AUE_NULL UNIMPL mincore
+115 AUE_NULL STD { caddr_t svr4_sys_mmap(caddr_t addr, \
+ svr4_size_t len, int prot, int flags, \
+ int fd, svr4_off_t pos); }
+116 AUE_NULL NOPROTO { int mprotect(void *addr, int len, \
+ int prot); }
+117 AUE_NULL NOPROTO { int munmap(void *addr, int len); }
+118 AUE_NULL STD { int svr4_sys_fpathconf(int fd, int name); }
+119 AUE_NULL NOPROTO { int vfork(void); }
+120 AUE_NULL NOPROTO { int fchdir(int fd); }
+121 AUE_NULL NOPROTO { int readv(int fd, struct iovec *iovp, \
+ u_int iovcnt); }
+122 AUE_NULL NOPROTO { int writev(int fd, struct iovec *iovp, \
+ u_int iovcnt); }
+123 AUE_NULL STD { int svr4_sys_xstat(int two, char *path, \
+ struct svr4_xstat *ub); }
+124 AUE_NULL STD { int svr4_sys_lxstat(int two, char *path, \
+ struct svr4_xstat *ub); }
+125 AUE_NULL STD { int svr4_sys_fxstat(int two, int fd, \
+ struct svr4_xstat *sb); }
+126 AUE_NULL STD { int svr4_sys_xmknod(int two, char *path, \
+ svr4_mode_t mode, svr4_dev_t dev); }
+127 AUE_NULL UNIMPL clocal
+128 AUE_NULL STD { int svr4_sys_setrlimit(int which, \
+ const struct svr4_rlimit *rlp); }
+129 AUE_NULL STD { int svr4_sys_getrlimit(int which, \
+ struct svr4_rlimit *rlp); }
+130 AUE_NULL NOPROTO { int lchown(char *path, uid_t uid, \
+ gid_t gid); }
+131 AUE_NULL STD { int svr4_sys_memcntl(void * addr, \
+ svr4_size_t len, int cmd, void * arg, \
+ int attr, int mask); }
+132 AUE_NULL UNIMPL getpmsg
+133 AUE_NULL UNIMPL putpmsg
+134 AUE_NULL NOPROTO { int rename(char *from, char *to); }
+135 AUE_NULL STD { int svr4_sys_uname( \
+ struct svr4_utsname* name, int dummy); }
+136 AUE_NULL NOPROTO { int setegid(gid_t egid); }
+137 AUE_NULL STD { int svr4_sys_sysconfig(int name); }
+138 AUE_NULL NOPROTO { int adjtime(struct timeval *delta, \
+ struct timeval *olddelta); }
+139 AUE_NULL STD { long svr4_sys_systeminfo(int what, \
+ char *buf, long len); }
+140 AUE_NULL UNIMPL notused
+141 AUE_NULL NOPROTO { int seteuid(uid_t euid); }
+142 AUE_NULL UNIMPL vtrace
+; fork1
+143 AUE_NULL UNIMPL { int fork(void); }
+144 AUE_NULL UNIMPL sigtimedwait
+145 AUE_NULL UNIMPL lwp_info
+146 AUE_NULL UNIMPL yield
+147 AUE_NULL UNIMPL lwp_sema_wait
+148 AUE_NULL UNIMPL lwp_sema_post
+149 AUE_NULL UNIMPL lwp_sema_trywait
+150 AUE_NULL UNIMPL notused
+151 AUE_NULL UNIMPL notused
+152 AUE_NULL UNIMPL modctl
+153 AUE_NULL STD { int svr4_sys_fchroot(int fd); }
+154 AUE_NULL STD { int svr4_sys_utimes(char *path, \
+ struct timeval *tptr); }
+155 AUE_NULL STD { int svr4_sys_vhangup(void); }
+156 AUE_NULL STD { int svr4_sys_gettimeofday( \
+ struct timeval *tp); }
+157 AUE_NULL NOPROTO { int getitimer(u_int which, \
+ struct itimerval *itv); }
+158 AUE_NULL NOPROTO { int setitimer(u_int which, \
+ struct itimerval *itv, \
+ struct itimerval *oitv); }
+159 AUE_NULL UNIMPL lwp_create
+160 AUE_NULL UNIMPL lwp_exit
+161 AUE_NULL UNIMPL lwp_suspend
+162 AUE_NULL UNIMPL lwp_continue
+163 AUE_NULL UNIMPL lwp_kill
+164 AUE_NULL UNIMPL lwp_self
+165 AUE_NULL UNIMPL lwp_getprivate
+166 AUE_NULL UNIMPL lwp_setprivate
+167 AUE_NULL UNIMPL lwp_wait
+168 AUE_NULL UNIMPL lwp_mutex_unlock
+169 AUE_NULL UNIMPL lwp_mutex_lock
+170 AUE_NULL UNIMPL lwp_cond_wait
+171 AUE_NULL UNIMPL lwp_cond_signal
+172 AUE_NULL UNIMPL lwp_cond_broadcast
+173 AUE_NULL UNIMPL { ssize_t svr4_sys_pread(int fd, void *buf, \
+ size_t nbyte, svr4_off_t off); }
+174 AUE_NULL UNIMPL { ssize_t svr4_sys_pwrite(int fd, \
+ const void *buf, size_t nbyte, \
+ svr4_off_t off); }
+175 AUE_NULL STD { svr4_off64_t svr4_sys_llseek(int fd, \
+ long offset1, long offset2, int whence); }
+176 AUE_NULL UNIMPL inst_sync
+177 AUE_NULL UNIMPL whoknows
+178 AUE_NULL UNIMPL kaio
+179 AUE_NULL UNIMPL whoknows
+180 AUE_NULL UNIMPL whoknows
+181 AUE_NULL UNIMPL whoknows
+182 AUE_NULL UNIMPL whoknows
+183 AUE_NULL UNIMPL whoknows
+184 AUE_NULL UNIMPL tsolsys
+185 AUE_NULL STD { int svr4_sys_acl(char *path, int cmd, \
+ int num, struct svr4_aclent *buf); }
+186 AUE_NULL STD { int svr4_sys_auditsys(int code, int a1, \
+ int a2, int a3, int a4, int a5); }
+187 AUE_NULL UNIMPL processor_bind
+188 AUE_NULL UNIMPL processor_info
+189 AUE_NULL UNIMPL p_online
+190 AUE_NULL UNIMPL sigqueue
+191 AUE_NULL UNIMPL clock_gettime
+192 AUE_NULL UNIMPL clock_settime
+193 AUE_NULL UNIMPL clock_getres
+194 AUE_NULL UNIMPL timer_create
+195 AUE_NULL UNIMPL timer_delete
+196 AUE_NULL UNIMPL timer_settime
+197 AUE_NULL UNIMPL timer_gettime
+198 AUE_NULL UNIMPL timer_overrun
+199 AUE_NULL NOPROTO { int nanosleep( \
+ const struct timespec *rqtp, \
+ struct timespec *rmtp); }
+200 AUE_NULL STD { int svr4_sys_facl(int fd, int cmd, \
+ int num, struct svr4_aclent *buf); }
+201 AUE_NULL UNIMPL door
+202 AUE_NULL NOPROTO { int setreuid(int ruid, int euid); }
+203 AUE_NULL NOPROTO { int setregid(int rgid, int egid); }
+204 AUE_NULL UNIMPL install_utrap
+205 AUE_NULL UNIMPL signotify
+206 AUE_NULL UNIMPL schedctl
+207 AUE_NULL UNIMPL pset
+208 AUE_NULL UNIMPL whoknows
+209 AUE_NULL STD { int svr4_sys_resolvepath(const char *path, \
+ char *buf, size_t bufsiz); }
+210 AUE_NULL UNIMPL signotifywait
+211 AUE_NULL UNIMPL lwp_sigredirect
+212 AUE_NULL UNIMPL lwp_alarm
+213 AUE_NULL STD { int svr4_sys_getdents64(int fd, \
+ struct svr4_dirent64 *dp, int nbytes); }
+;213 AUE_NULL UNIMPL getdents64
+214 AUE_NULL STD { caddr_t svr4_sys_mmap64(void *addr, \
+ svr4_size_t len, int prot, int flags, \
+ int fd, svr4_off64_t pos); }
+215 AUE_NULL STD { int svr4_sys_stat64(char *path, \
+ struct svr4_stat64 *sb); }
+216 AUE_NULL STD { int svr4_sys_lstat64(char *path, \
+ struct svr4_stat64 *sb); }
+217 AUE_NULL STD { int svr4_sys_fstat64(int fd, \
+ struct svr4_stat64 *sb); }
+218 AUE_NULL STD { int svr4_sys_statvfs64(char *path, \
+ struct svr4_statvfs64 *fs); }
+219 AUE_NULL STD { int svr4_sys_fstatvfs64(int fd, \
+ struct svr4_statvfs64 *fs); }
+220 AUE_NULL STD { int svr4_sys_setrlimit64(int which, \
+ const struct svr4_rlimit64 *rlp); }
+221 AUE_NULL STD { int svr4_sys_getrlimit64(int which, \
+ struct svr4_rlimit64 *rlp); }
+222 AUE_NULL UNIMPL pread64
+223 AUE_NULL UNIMPL pwrite64
+224 AUE_NULL STD { int svr4_sys_creat64(char *path, \
+ int mode); }
+225 AUE_NULL STD { int svr4_sys_open64(char *path, int flags, \
+ int mode); }
+226 AUE_NULL UNIMPL rpcsys
+227 AUE_NULL UNIMPL whoknows
+228 AUE_NULL UNIMPL whoknows
+229 AUE_NULL UNIMPL whoknows
+230 AUE_NULL STD { int svr4_sys_socket(int domain, int type, \
+ int protocol); }
+231 AUE_NULL NOPROTO { int socketpair(int domain, int type, \
+ int protocol, int *rsv); }
+232 AUE_NULL NOPROTO { int bind(int s, \
+ const struct sockaddr *name, \
+ int namelen); }
+233 AUE_NULL NOPROTO { int listen(int s, int backlog); }
+234 AUE_NULL NOPROTO { int accept(int s, struct sockaddr *name, \
+ int *anamelen); }
+235 AUE_NULL NOPROTO { int connect(int s, \
+ const struct sockaddr *name, \
+ int namelen); }
+236 AUE_NULL NOPROTO { int shutdown(int s, int how); }
+237 AUE_NULL STD { int svr4_sys_recv(int s, caddr_t buf, \
+ int len, int flags); }
+238 AUE_NULL NOPROTO { ssize_t recvfrom(int s, void *buf, \
+ size_t len, int flags, \
+ struct sockaddr *from, \
+ int *fromlenaddr); }
+239 AUE_NULL NOPROTO { ssize_t recvmsg(int s, struct msghdr *msg, \
+ int flags); }
+240 AUE_NULL STD { int svr4_sys_send(int s, caddr_t buf, \
+ int len, int flags); }
+241 AUE_NULL NOPROTO { ssize_t sendmsg(int s, \
+ const struct msghdr *msg, int flags); }
+242 AUE_NULL STD { ssize_t svr4_sys_sendto(int s, void *buf, \
+ size_t len, int flags, \
+ struct sockaddr *to, int tolen); }
+243 AUE_NULL NOPROTO { int getpeername(int fdes, \
+ struct sockaddr *asa, int *alen); }
+244 AUE_NULL NOPROTO { int getsockname(int fdes, \
+ struct sockaddr *asa, int *alen); }
+245 AUE_NULL NOPROTO { int getsockopt(int s, int level, int name, \
+ void *val, int *avalsize); }
+246 AUE_NULL NOPROTO { int setsockopt(int s, int level, int name, \
+ const void *val, int valsize); }
+247 AUE_NULL UNIMPL sockconfig
+248 AUE_NULL UNIMPL { int ntp_gettime(struct ntptimeval *ntvp); }
+249 AUE_NULL UNIMPL { int ntp_adjtime(struct timex *tp); }
diff --git a/sys/compat/x86bios/x86bios.c b/sys/compat/x86bios/x86bios.c
new file mode 100644
index 0000000..32b9929
--- /dev/null
+++ b/sys/compat/x86bios/x86bios.c
@@ -0,0 +1,853 @@
+/*-
+ * Copyright (c) 2009 Alex Keda <admin@lissyara.su>
+ * Copyright (c) 2009-2010 Jung-uk Kim <jkim@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_x86bios.h"
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/sysctl.h>
+
+#include <contrib/x86emu/x86emu.h>
+#include <contrib/x86emu/x86emu_regs.h>
+#include <compat/x86bios/x86bios.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#ifdef __amd64__
+#define X86BIOS_NATIVE_ARCH
+#endif
+#ifdef __i386__
+#define X86BIOS_NATIVE_VM86
+#endif
+
+#define X86BIOS_MEM_SIZE 0x00100000 /* 1M */
+
+#define X86BIOS_TRACE(h, n, r) do { \
+ printf(__STRING(h) \
+ " (ax=0x%04x bx=0x%04x cx=0x%04x dx=0x%04x es=0x%04x di=0x%04x)\n",\
+ (n), (r)->R_AX, (r)->R_BX, (r)->R_CX, (r)->R_DX, \
+ (r)->R_ES, (r)->R_DI); \
+} while (0)
+
+static struct mtx x86bios_lock;
+
+static SYSCTL_NODE(_debug, OID_AUTO, x86bios, CTLFLAG_RD, NULL,
+ "x86bios debugging");
+static int x86bios_trace_call;
+TUNABLE_INT("debug.x86bios.call", &x86bios_trace_call);
+SYSCTL_INT(_debug_x86bios, OID_AUTO, call, CTLFLAG_RW, &x86bios_trace_call, 0,
+ "Trace far function calls");
+static int x86bios_trace_int;
+TUNABLE_INT("debug.x86bios.int", &x86bios_trace_int);
+SYSCTL_INT(_debug_x86bios, OID_AUTO, int, CTLFLAG_RW, &x86bios_trace_int, 0,
+ "Trace software interrupt handlers");
+
+#ifdef X86BIOS_NATIVE_VM86
+
+#include <machine/vm86.h>
+#include <machine/vmparam.h>
+#include <machine/pc/bios.h>
+
+struct vm86context x86bios_vmc;
+
+static void
+x86bios_emu2vmf(struct x86emu_regs *regs, struct vm86frame *vmf)
+{
+
+ vmf->vmf_ds = regs->R_DS;
+ vmf->vmf_es = regs->R_ES;
+ vmf->vmf_ax = regs->R_AX;
+ vmf->vmf_bx = regs->R_BX;
+ vmf->vmf_cx = regs->R_CX;
+ vmf->vmf_dx = regs->R_DX;
+ vmf->vmf_bp = regs->R_BP;
+ vmf->vmf_si = regs->R_SI;
+ vmf->vmf_di = regs->R_DI;
+}
+
+static void
+x86bios_vmf2emu(struct vm86frame *vmf, struct x86emu_regs *regs)
+{
+
+ regs->R_DS = vmf->vmf_ds;
+ regs->R_ES = vmf->vmf_es;
+ regs->R_FLG = vmf->vmf_flags;
+ regs->R_AX = vmf->vmf_ax;
+ regs->R_BX = vmf->vmf_bx;
+ regs->R_CX = vmf->vmf_cx;
+ regs->R_DX = vmf->vmf_dx;
+ regs->R_BP = vmf->vmf_bp;
+ regs->R_SI = vmf->vmf_si;
+ regs->R_DI = vmf->vmf_di;
+}
+
+void *
+x86bios_alloc(uint32_t *offset, size_t size, int flags)
+{
+ void *vaddr;
+ int i;
+
+ if (offset == NULL || size == 0)
+ return (NULL);
+ vaddr = contigmalloc(size, M_DEVBUF, flags, 0, X86BIOS_MEM_SIZE,
+ PAGE_SIZE, 0);
+ if (vaddr != NULL) {
+ *offset = vtophys(vaddr);
+ mtx_lock(&x86bios_lock);
+ for (i = 0; i < atop(round_page(size)); i++)
+ vm86_addpage(&x86bios_vmc, atop(*offset) + i,
+ (vm_offset_t)vaddr + ptoa(i));
+ mtx_unlock(&x86bios_lock);
+ }
+
+ return (vaddr);
+}
+
+void
+x86bios_free(void *addr, size_t size)
+{
+ vm_paddr_t paddr;
+ int i, nfree;
+
+ if (addr == NULL || size == 0)
+ return;
+ paddr = vtophys(addr);
+ if (paddr >= X86BIOS_MEM_SIZE || (paddr & PAGE_MASK) != 0)
+ return;
+ mtx_lock(&x86bios_lock);
+ for (i = 0; i < x86bios_vmc.npages; i++)
+ if (x86bios_vmc.pmap[i].kva == (vm_offset_t)addr)
+ break;
+ if (i >= x86bios_vmc.npages) {
+ mtx_unlock(&x86bios_lock);
+ return;
+ }
+ nfree = atop(round_page(size));
+ bzero(x86bios_vmc.pmap + i, sizeof(*x86bios_vmc.pmap) * nfree);
+ if (i + nfree == x86bios_vmc.npages) {
+ x86bios_vmc.npages -= nfree;
+ while (--i >= 0 && x86bios_vmc.pmap[i].kva == 0)
+ x86bios_vmc.npages--;
+ }
+ mtx_unlock(&x86bios_lock);
+ contigfree(addr, size, M_DEVBUF);
+}
+
+void
+x86bios_init_regs(struct x86regs *regs)
+{
+
+ bzero(regs, sizeof(*regs));
+}
+
+void
+x86bios_call(struct x86regs *regs, uint16_t seg, uint16_t off)
+{
+ struct vm86frame vmf;
+
+ if (x86bios_trace_call)
+ X86BIOS_TRACE(Calling 0x%06x, (seg << 4) + off, regs);
+
+ bzero(&vmf, sizeof(vmf));
+ x86bios_emu2vmf((struct x86emu_regs *)regs, &vmf);
+ vmf.vmf_cs = seg;
+ vmf.vmf_ip = off;
+ mtx_lock(&x86bios_lock);
+ vm86_datacall(-1, &vmf, &x86bios_vmc);
+ mtx_unlock(&x86bios_lock);
+ x86bios_vmf2emu(&vmf, (struct x86emu_regs *)regs);
+
+ if (x86bios_trace_call)
+ X86BIOS_TRACE(Exiting 0x%06x, (seg << 4) + off, regs);
+}
+
+uint32_t
+x86bios_get_intr(int intno)
+{
+
+ return (readl(BIOS_PADDRTOVADDR(intno * 4)));
+}
+
+void
+x86bios_set_intr(int intno, uint32_t saddr)
+{
+
+ writel(BIOS_PADDRTOVADDR(intno * 4), saddr);
+}
+
+void
+x86bios_intr(struct x86regs *regs, int intno)
+{
+ struct vm86frame vmf;
+
+ if (x86bios_trace_int)
+ X86BIOS_TRACE(Calling INT 0x%02x, intno, regs);
+
+ bzero(&vmf, sizeof(vmf));
+ x86bios_emu2vmf((struct x86emu_regs *)regs, &vmf);
+ mtx_lock(&x86bios_lock);
+ vm86_datacall(intno, &vmf, &x86bios_vmc);
+ mtx_unlock(&x86bios_lock);
+ x86bios_vmf2emu(&vmf, (struct x86emu_regs *)regs);
+
+ if (x86bios_trace_int)
+ X86BIOS_TRACE(Exiting INT 0x%02x, intno, regs);
+}
+
+void *
+x86bios_offset(uint32_t offset)
+{
+ vm_offset_t addr;
+
+ addr = vm86_getaddr(&x86bios_vmc, X86BIOS_PHYSTOSEG(offset),
+ X86BIOS_PHYSTOOFF(offset));
+ if (addr == 0)
+ addr = BIOS_PADDRTOVADDR(offset);
+
+ return ((void *)addr);
+}
+
+static int
+x86bios_init(void)
+{
+
+ mtx_init(&x86bios_lock, "x86bios lock", NULL, MTX_DEF);
+ bzero(&x86bios_vmc, sizeof(x86bios_vmc));
+
+ return (0);
+}
+
+static int
+x86bios_uninit(void)
+{
+
+ mtx_destroy(&x86bios_lock);
+
+ return (0);
+}
+
+#else
+
+#include <machine/iodev.h>
+
+#define X86BIOS_PAGE_SIZE 0x00001000 /* 4K */
+
+#define X86BIOS_IVT_SIZE 0x00000500 /* 1K + 256 (BDA) */
+
+#define X86BIOS_IVT_BASE 0x00000000
+#define X86BIOS_RAM_BASE 0x00001000
+#define X86BIOS_ROM_BASE 0x000a0000
+
+#define X86BIOS_ROM_SIZE (X86BIOS_MEM_SIZE - x86bios_rom_phys)
+#define X86BIOS_SEG_SIZE X86BIOS_PAGE_SIZE
+
+#define X86BIOS_PAGES (X86BIOS_MEM_SIZE / X86BIOS_PAGE_SIZE)
+
+#define X86BIOS_R_SS _pad2
+#define X86BIOS_R_SP _pad3.I16_reg.x_reg
+
+static struct x86emu x86bios_emu;
+
+static void *x86bios_ivt;
+static void *x86bios_rom;
+static void *x86bios_seg;
+
+static vm_offset_t *x86bios_map;
+
+static vm_paddr_t x86bios_rom_phys;
+static vm_paddr_t x86bios_seg_phys;
+
+static int x86bios_fault;
+static uint32_t x86bios_fault_addr;
+static uint16_t x86bios_fault_cs;
+static uint16_t x86bios_fault_ip;
+
+static void
+x86bios_set_fault(struct x86emu *emu, uint32_t addr)
+{
+
+ x86bios_fault = 1;
+ x86bios_fault_addr = addr;
+ x86bios_fault_cs = emu->x86.R_CS;
+ x86bios_fault_ip = emu->x86.R_IP;
+ x86emu_halt_sys(emu);
+}
+
+static void *
+x86bios_get_pages(uint32_t offset, size_t size)
+{
+ vm_offset_t addr;
+
+ if (offset + size > X86BIOS_MEM_SIZE + X86BIOS_IVT_SIZE)
+ return (NULL);
+
+ if (offset >= X86BIOS_MEM_SIZE)
+ offset -= X86BIOS_MEM_SIZE;
+ addr = x86bios_map[offset / X86BIOS_PAGE_SIZE];
+ if (addr != 0)
+ addr += offset % X86BIOS_PAGE_SIZE;
+
+ return ((void *)addr);
+}
+
+static void
+x86bios_set_pages(vm_offset_t va, vm_paddr_t pa, size_t size)
+{
+ int i, j;
+
+ for (i = pa / X86BIOS_PAGE_SIZE, j = 0;
+ j < howmany(size, X86BIOS_PAGE_SIZE); i++, j++)
+ x86bios_map[i] = va + j * X86BIOS_PAGE_SIZE;
+}
+
+static uint8_t
+x86bios_emu_rdb(struct x86emu *emu, uint32_t addr)
+{
+ uint8_t *va;
+
+ va = x86bios_get_pages(addr, sizeof(*va));
+ if (va == NULL)
+ x86bios_set_fault(emu, addr);
+
+ return (*va);
+}
+
+static uint16_t
+x86bios_emu_rdw(struct x86emu *emu, uint32_t addr)
+{
+ uint16_t *va;
+
+ va = x86bios_get_pages(addr, sizeof(*va));
+ if (va == NULL)
+ x86bios_set_fault(emu, addr);
+
+#ifndef __NO_STRICT_ALIGNMENT
+ if ((addr & 1) != 0)
+ return (le16dec(va));
+ else
+#endif
+ return (le16toh(*va));
+}
+
+static uint32_t
+x86bios_emu_rdl(struct x86emu *emu, uint32_t addr)
+{
+ uint32_t *va;
+
+ va = x86bios_get_pages(addr, sizeof(*va));
+ if (va == NULL)
+ x86bios_set_fault(emu, addr);
+
+#ifndef __NO_STRICT_ALIGNMENT
+ if ((addr & 3) != 0)
+ return (le32dec(va));
+ else
+#endif
+ return (le32toh(*va));
+}
+
+static void
+x86bios_emu_wrb(struct x86emu *emu, uint32_t addr, uint8_t val)
+{
+ uint8_t *va;
+
+ va = x86bios_get_pages(addr, sizeof(*va));
+ if (va == NULL)
+ x86bios_set_fault(emu, addr);
+
+ *va = val;
+}
+
+static void
+x86bios_emu_wrw(struct x86emu *emu, uint32_t addr, uint16_t val)
+{
+ uint16_t *va;
+
+ va = x86bios_get_pages(addr, sizeof(*va));
+ if (va == NULL)
+ x86bios_set_fault(emu, addr);
+
+#ifndef __NO_STRICT_ALIGNMENT
+ if ((addr & 1) != 0)
+ le16enc(va, val);
+ else
+#endif
+ *va = htole16(val);
+}
+
+static void
+x86bios_emu_wrl(struct x86emu *emu, uint32_t addr, uint32_t val)
+{
+ uint32_t *va;
+
+ va = x86bios_get_pages(addr, sizeof(*va));
+ if (va == NULL)
+ x86bios_set_fault(emu, addr);
+
+#ifndef __NO_STRICT_ALIGNMENT
+ if ((addr & 3) != 0)
+ le32enc(va, val);
+ else
+#endif
+ *va = htole32(val);
+}
+
+static uint8_t
+x86bios_emu_inb(struct x86emu *emu, uint16_t port)
+{
+
+#ifndef X86BIOS_NATIVE_ARCH
+ if (port == 0xb2) /* APM scratch register */
+ return (0);
+ if (port >= 0x80 && port < 0x88) /* POST status register */
+ return (0);
+#endif
+
+ return (iodev_read_1(port));
+}
+
+static uint16_t
+x86bios_emu_inw(struct x86emu *emu, uint16_t port)
+{
+ uint16_t val;
+
+#ifndef X86BIOS_NATIVE_ARCH
+ if (port >= 0x80 && port < 0x88) /* POST status register */
+ return (0);
+
+ if ((port & 1) != 0) {
+ val = iodev_read_1(port);
+ val |= iodev_read_1(port + 1) << 8;
+ } else
+#endif
+ val = iodev_read_2(port);
+
+ return (val);
+}
+
+static uint32_t
+x86bios_emu_inl(struct x86emu *emu, uint16_t port)
+{
+ uint32_t val;
+
+#ifndef X86BIOS_NATIVE_ARCH
+ if (port >= 0x80 && port < 0x88) /* POST status register */
+ return (0);
+
+ if ((port & 1) != 0) {
+ val = iodev_read_1(port);
+ val |= iodev_read_2(port + 1) << 8;
+ val |= iodev_read_1(port + 3) << 24;
+ } else if ((port & 2) != 0) {
+ val = iodev_read_2(port);
+ val |= iodev_read_2(port + 2) << 16;
+ } else
+#endif
+ val = iodev_read_4(port);
+
+ return (val);
+}
+
+static void
+x86bios_emu_outb(struct x86emu *emu, uint16_t port, uint8_t val)
+{
+
+#ifndef X86BIOS_NATIVE_ARCH
+ if (port == 0xb2) /* APM scratch register */
+ return;
+ if (port >= 0x80 && port < 0x88) /* POST status register */
+ return;
+#endif
+
+ iodev_write_1(port, val);
+}
+
+static void
+x86bios_emu_outw(struct x86emu *emu, uint16_t port, uint16_t val)
+{
+
+#ifndef X86BIOS_NATIVE_ARCH
+ if (port >= 0x80 && port < 0x88) /* POST status register */
+ return;
+
+ if ((port & 1) != 0) {
+ iodev_write_1(port, val);
+ iodev_write_1(port + 1, val >> 8);
+ } else
+#endif
+ iodev_write_2(port, val);
+}
+
+static void
+x86bios_emu_outl(struct x86emu *emu, uint16_t port, uint32_t val)
+{
+
+#ifndef X86BIOS_NATIVE_ARCH
+ if (port >= 0x80 && port < 0x88) /* POST status register */
+ return;
+
+ if ((port & 1) != 0) {
+ iodev_write_1(port, val);
+ iodev_write_2(port + 1, val >> 8);
+ iodev_write_1(port + 3, val >> 24);
+ } else if ((port & 2) != 0) {
+ iodev_write_2(port, val);
+ iodev_write_2(port + 2, val >> 16);
+ } else
+#endif
+ iodev_write_4(port, val);
+}
+
+void *
+x86bios_alloc(uint32_t *offset, size_t size, int flags)
+{
+ void *vaddr;
+
+ if (offset == NULL || size == 0)
+ return (NULL);
+ vaddr = contigmalloc(size, M_DEVBUF, flags, X86BIOS_RAM_BASE,
+ x86bios_rom_phys, X86BIOS_PAGE_SIZE, 0);
+ if (vaddr != NULL) {
+ *offset = vtophys(vaddr);
+ mtx_lock(&x86bios_lock);
+ x86bios_set_pages((vm_offset_t)vaddr, *offset, size);
+ mtx_unlock(&x86bios_lock);
+ }
+
+ return (vaddr);
+}
+
+void
+x86bios_free(void *addr, size_t size)
+{
+ vm_paddr_t paddr;
+
+ if (addr == NULL || size == 0)
+ return;
+ paddr = vtophys(addr);
+ if (paddr < X86BIOS_RAM_BASE || paddr >= x86bios_rom_phys ||
+ paddr % X86BIOS_PAGE_SIZE != 0)
+ return;
+ mtx_lock(&x86bios_lock);
+ bzero(x86bios_map + paddr / X86BIOS_PAGE_SIZE,
+ sizeof(*x86bios_map) * howmany(size, X86BIOS_PAGE_SIZE));
+ mtx_unlock(&x86bios_lock);
+ contigfree(addr, size, M_DEVBUF);
+}
+
+void
+x86bios_init_regs(struct x86regs *regs)
+{
+
+ bzero(regs, sizeof(*regs));
+ regs->X86BIOS_R_SS = X86BIOS_PHYSTOSEG(x86bios_seg_phys);
+ regs->X86BIOS_R_SP = X86BIOS_PAGE_SIZE - 2;
+}
+
+void
+x86bios_call(struct x86regs *regs, uint16_t seg, uint16_t off)
+{
+
+ if (x86bios_trace_call)
+ X86BIOS_TRACE(Calling 0x%06x, (seg << 4) + off, regs);
+
+ mtx_lock(&x86bios_lock);
+ memcpy(&x86bios_emu.x86, regs, sizeof(*regs));
+ x86bios_fault = 0;
+ spinlock_enter();
+ x86emu_exec_call(&x86bios_emu, seg, off);
+ spinlock_exit();
+ memcpy(regs, &x86bios_emu.x86, sizeof(*regs));
+ mtx_unlock(&x86bios_lock);
+
+ if (x86bios_trace_call) {
+ X86BIOS_TRACE(Exiting 0x%06x, (seg << 4) + off, regs);
+ if (x86bios_fault)
+ printf("Page fault at 0x%06x from 0x%04x:0x%04x.\n",
+ x86bios_fault_addr, x86bios_fault_cs,
+ x86bios_fault_ip);
+ }
+}
+
+uint32_t
+x86bios_get_intr(int intno)
+{
+
+ return (le32toh(*((uint32_t *)x86bios_ivt + intno)));
+}
+
+void
+x86bios_set_intr(int intno, uint32_t saddr)
+{
+
+ *((uint32_t *)x86bios_ivt + intno) = htole32(saddr);
+}
+
+void
+x86bios_intr(struct x86regs *regs, int intno)
+{
+
+ if (intno < 0 || intno > 255)
+ return;
+
+ if (x86bios_trace_int)
+ X86BIOS_TRACE(Calling INT 0x%02x, intno, regs);
+
+ mtx_lock(&x86bios_lock);
+ memcpy(&x86bios_emu.x86, regs, sizeof(*regs));
+ x86bios_fault = 0;
+ spinlock_enter();
+ x86emu_exec_intr(&x86bios_emu, intno);
+ spinlock_exit();
+ memcpy(regs, &x86bios_emu.x86, sizeof(*regs));
+ mtx_unlock(&x86bios_lock);
+
+ if (x86bios_trace_int) {
+ X86BIOS_TRACE(Exiting INT 0x%02x, intno, regs);
+ if (x86bios_fault)
+ printf("Page fault at 0x%06x from 0x%04x:0x%04x.\n",
+ x86bios_fault_addr, x86bios_fault_cs,
+ x86bios_fault_ip);
+ }
+}
+
+void *
+x86bios_offset(uint32_t offset)
+{
+
+ return (x86bios_get_pages(offset, 1));
+}
+
+static __inline void
+x86bios_unmap_mem(void)
+{
+
+ free(x86bios_map, M_DEVBUF);
+ if (x86bios_ivt != NULL)
+#ifdef X86BIOS_NATIVE_ARCH
+ pmap_unmapbios((vm_offset_t)x86bios_ivt, X86BIOS_IVT_SIZE);
+#else
+ free(x86bios_ivt, M_DEVBUF);
+#endif
+ if (x86bios_rom != NULL)
+ pmap_unmapdev((vm_offset_t)x86bios_rom, X86BIOS_ROM_SIZE);
+ if (x86bios_seg != NULL)
+ contigfree(x86bios_seg, X86BIOS_SEG_SIZE, M_DEVBUF);
+}
+
+static __inline int
+x86bios_map_mem(void)
+{
+
+ x86bios_map = malloc(sizeof(*x86bios_map) * X86BIOS_PAGES, M_DEVBUF,
+ M_WAITOK | M_ZERO);
+
+#ifdef X86BIOS_NATIVE_ARCH
+ x86bios_ivt = pmap_mapbios(X86BIOS_IVT_BASE, X86BIOS_IVT_SIZE);
+
+ /* Probe EBDA via BDA. */
+ x86bios_rom_phys = *(uint16_t *)((caddr_t)x86bios_ivt + 0x40e);
+ x86bios_rom_phys = x86bios_rom_phys << 4;
+ if (x86bios_rom_phys != 0 && x86bios_rom_phys < X86BIOS_ROM_BASE &&
+ X86BIOS_ROM_BASE - x86bios_rom_phys <= 128 * 1024)
+ x86bios_rom_phys =
+ rounddown(x86bios_rom_phys, X86BIOS_PAGE_SIZE);
+ else
+#else
+ x86bios_ivt = malloc(X86BIOS_IVT_SIZE, M_DEVBUF, M_ZERO | M_WAITOK);
+#endif
+
+ x86bios_rom_phys = X86BIOS_ROM_BASE;
+ x86bios_rom = pmap_mapdev(x86bios_rom_phys, X86BIOS_ROM_SIZE);
+ if (x86bios_rom == NULL)
+ goto fail;
+#ifdef X86BIOS_NATIVE_ARCH
+ /* Change attribute for EBDA. */
+ if (x86bios_rom_phys < X86BIOS_ROM_BASE &&
+ pmap_change_attr((vm_offset_t)x86bios_rom,
+ X86BIOS_ROM_BASE - x86bios_rom_phys, PAT_WRITE_BACK) != 0)
+ goto fail;
+#endif
+
+ x86bios_seg = contigmalloc(X86BIOS_SEG_SIZE, M_DEVBUF, M_WAITOK,
+ X86BIOS_RAM_BASE, x86bios_rom_phys, X86BIOS_PAGE_SIZE, 0);
+ x86bios_seg_phys = vtophys(x86bios_seg);
+
+ x86bios_set_pages((vm_offset_t)x86bios_ivt, X86BIOS_IVT_BASE,
+ X86BIOS_IVT_SIZE);
+ x86bios_set_pages((vm_offset_t)x86bios_rom, x86bios_rom_phys,
+ X86BIOS_ROM_SIZE);
+ x86bios_set_pages((vm_offset_t)x86bios_seg, x86bios_seg_phys,
+ X86BIOS_SEG_SIZE);
+
+ if (bootverbose) {
+ printf("x86bios: IVT 0x%06jx-0x%06jx at %p\n",
+ (vm_paddr_t)X86BIOS_IVT_BASE,
+ (vm_paddr_t)X86BIOS_IVT_SIZE + X86BIOS_IVT_BASE - 1,
+ x86bios_ivt);
+ printf("x86bios: SSEG 0x%06jx-0x%06jx at %p\n",
+ x86bios_seg_phys,
+ (vm_paddr_t)X86BIOS_SEG_SIZE + x86bios_seg_phys - 1,
+ x86bios_seg);
+ if (x86bios_rom_phys < X86BIOS_ROM_BASE)
+ printf("x86bios: EBDA 0x%06jx-0x%06jx at %p\n",
+ x86bios_rom_phys, (vm_paddr_t)X86BIOS_ROM_BASE - 1,
+ x86bios_rom);
+ printf("x86bios: ROM 0x%06jx-0x%06jx at %p\n",
+ (vm_paddr_t)X86BIOS_ROM_BASE,
+ (vm_paddr_t)X86BIOS_MEM_SIZE - X86BIOS_SEG_SIZE - 1,
+ (caddr_t)x86bios_rom + X86BIOS_ROM_BASE - x86bios_rom_phys);
+ }
+
+ return (0);
+
+fail:
+ x86bios_unmap_mem();
+
+ return (1);
+}
+
+static int
+x86bios_init(void)
+{
+
+ mtx_init(&x86bios_lock, "x86bios lock", NULL, MTX_DEF);
+
+ if (x86bios_map_mem() != 0)
+ return (ENOMEM);
+
+ bzero(&x86bios_emu, sizeof(x86bios_emu));
+
+ x86bios_emu.emu_rdb = x86bios_emu_rdb;
+ x86bios_emu.emu_rdw = x86bios_emu_rdw;
+ x86bios_emu.emu_rdl = x86bios_emu_rdl;
+ x86bios_emu.emu_wrb = x86bios_emu_wrb;
+ x86bios_emu.emu_wrw = x86bios_emu_wrw;
+ x86bios_emu.emu_wrl = x86bios_emu_wrl;
+
+ x86bios_emu.emu_inb = x86bios_emu_inb;
+ x86bios_emu.emu_inw = x86bios_emu_inw;
+ x86bios_emu.emu_inl = x86bios_emu_inl;
+ x86bios_emu.emu_outb = x86bios_emu_outb;
+ x86bios_emu.emu_outw = x86bios_emu_outw;
+ x86bios_emu.emu_outl = x86bios_emu_outl;
+
+ return (0);
+}
+
+static int
+x86bios_uninit(void)
+{
+
+ x86bios_unmap_mem();
+ mtx_destroy(&x86bios_lock);
+
+ return (0);
+}
+
+#endif
+
+void *
+x86bios_get_orm(uint32_t offset)
+{
+ uint8_t *p;
+
+ /* Does the shadow ROM contain BIOS POST code for x86? */
+ p = x86bios_offset(offset);
+ if (p == NULL || p[0] != 0x55 || p[1] != 0xaa ||
+ (p[3] != 0xe9 && p[3] != 0xeb))
+ return (NULL);
+
+ return (p);
+}
+
+int
+x86bios_match_device(uint32_t offset, device_t dev)
+{
+ uint8_t *p;
+ uint16_t device, vendor;
+ uint8_t class, progif, subclass;
+
+ /* Does the shadow ROM contain BIOS POST code for x86? */
+ p = x86bios_get_orm(offset);
+ if (p == NULL)
+ return (0);
+
+ /* Does it contain PCI data structure? */
+ p += le16toh(*(uint16_t *)(p + 0x18));
+ if (bcmp(p, "PCIR", 4) != 0 ||
+ le16toh(*(uint16_t *)(p + 0x0a)) < 0x18 || *(p + 0x14) != 0)
+ return (0);
+
+ /* Does it match the vendor, device, and classcode? */
+ vendor = le16toh(*(uint16_t *)(p + 0x04));
+ device = le16toh(*(uint16_t *)(p + 0x06));
+ progif = *(p + 0x0d);
+ subclass = *(p + 0x0e);
+ class = *(p + 0x0f);
+ if (vendor != pci_get_vendor(dev) || device != pci_get_device(dev) ||
+ class != pci_get_class(dev) || subclass != pci_get_subclass(dev) ||
+ progif != pci_get_progif(dev))
+ return (0);
+
+ return (1);
+}
+
+static int
+x86bios_modevent(module_t mod __unused, int type, void *data __unused)
+{
+
+ switch (type) {
+ case MOD_LOAD:
+ return (x86bios_init());
+ case MOD_UNLOAD:
+ return (x86bios_uninit());
+ default:
+ return (ENOTSUP);
+ }
+}
+
+static moduledata_t x86bios_mod = {
+ "x86bios",
+ x86bios_modevent,
+ NULL,
+};
+
+DECLARE_MODULE(x86bios, x86bios_mod, SI_SUB_CPU, SI_ORDER_ANY);
+MODULE_VERSION(x86bios, 1);
diff --git a/sys/compat/x86bios/x86bios.h b/sys/compat/x86bios/x86bios.h
new file mode 100644
index 0000000..491367d
--- /dev/null
+++ b/sys/compat/x86bios/x86bios.h
@@ -0,0 +1,157 @@
+/*-
+ * Copyright (c) 2009 Alex Keda <admin@lissyara.su>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/*
+ * x86 registers were borrowed from x86emu.h x86emu_regs.h
+ * for compatability.
+ */
+
+#ifndef _X86BIOS_H_
+#define _X86BIOS_H_
+
+#include <sys/endian.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+
+#ifdef __BIG_ENDIAN__
+
+struct x86_register32 {
+ uint32_t e_reg;
+};
+
+struct x86_register16 {
+ uint16_t filler0;
+ uint16_t x_reg;
+};
+
+struct x86_register8 {
+ uint8_t filler0;
+ uint8_t filler1;
+ uint8_t h_reg;
+ uint8_t l_reg;
+};
+
+#else /* !__BIG_ENDIAN__ */
+
+struct x86_register32 {
+ uint32_t e_reg;
+};
+
+struct x86_register16 {
+ uint16_t x_reg;
+};
+
+struct x86_register8 {
+ uint8_t l_reg;
+ uint8_t h_reg;
+};
+
+#endif /* __BIG_ENDIAN__ */
+
+union x86_register {
+ struct x86_register32 I32_reg;
+ struct x86_register16 I16_reg;
+ struct x86_register8 I8_reg;
+};
+
+struct x86regs {
+ uint16_t _pad0; /* CS */
+ uint16_t _pad1; /* DS */
+ uint16_t register_es;
+ uint16_t register_fs;
+ uint16_t register_gs;
+ uint16_t _pad2; /* SS */
+ uint32_t register_flags;
+ union x86_register register_a;
+ union x86_register register_b;
+ union x86_register register_c;
+ union x86_register register_d;
+
+ union x86_register _pad3; /* SP */
+ union x86_register register_bp;
+ union x86_register register_si;
+ union x86_register register_di;
+};
+
+typedef struct x86regs x86regs_t;
+
+/* 8 bit registers */
+#define R_AH register_a.I8_reg.h_reg
+#define R_AL register_a.I8_reg.l_reg
+#define R_BH register_b.I8_reg.h_reg
+#define R_BL register_b.I8_reg.l_reg
+#define R_CH register_c.I8_reg.h_reg
+#define R_CL register_c.I8_reg.l_reg
+#define R_DH register_d.I8_reg.h_reg
+#define R_DL register_d.I8_reg.l_reg
+
+/* 16 bit registers */
+#define R_AX register_a.I16_reg.x_reg
+#define R_BX register_b.I16_reg.x_reg
+#define R_CX register_c.I16_reg.x_reg
+#define R_DX register_d.I16_reg.x_reg
+
+/* 32 bit extended registers */
+#define R_EAX register_a.I32_reg.e_reg
+#define R_EBX register_b.I32_reg.e_reg
+#define R_ECX register_c.I32_reg.e_reg
+#define R_EDX register_d.I32_reg.e_reg
+
+/* special registers */
+#define R_BP register_bp.I16_reg.x_reg
+#define R_SI register_si.I16_reg.x_reg
+#define R_DI register_di.I16_reg.x_reg
+#define R_FLG register_flags
+
+/* special registers */
+#define R_EBP register_bp.I32_reg.e_reg
+#define R_ESI register_si.I32_reg.e_reg
+#define R_EDI register_di.I32_reg.e_reg
+#define R_EFLG register_flags
+
+/* segment registers */
+#define R_ES register_es
+#define R_FS register_fs
+#define R_GS register_gs
+
+#define X86BIOS_PHYSTOSEG(x) (((x) >> 4) & 0xff00)
+#define X86BIOS_PHYSTOOFF(x) ((x) & 0x0fff)
+
+__BEGIN_DECLS
+void *x86bios_alloc(uint32_t *offset, size_t size, int flags);
+void x86bios_call(struct x86regs *regs, uint16_t seg, uint16_t off);
+void x86bios_free(void *addr, size_t size);
+uint32_t x86bios_get_intr(int intno);
+void *x86bios_get_orm(uint32_t offset);
+void x86bios_init_regs(struct x86regs *regs);
+void x86bios_intr(struct x86regs *regs, int intno);
+int x86bios_match_device(uint32_t offset, device_t dev);
+void *x86bios_offset(uint32_t offset);
+void x86bios_set_intr(int intno, uint32_t saddr);
+__END_DECLS
+
+#endif /* !_X86BIOS_H_ */
OpenPOWER on IntegriCloud