diff --git a/bsd-user/bsd-ioctl.c b/bsd-user/bsd-ioctl.c new file mode 100644 index 0000000000..94110d4ad5 --- /dev/null +++ b/bsd-user/bsd-ioctl.c @@ -0,0 +1,219 @@ +/* + * BSD ioctl(2) emulation + * + * Copyright (c) 2013-2015 Stacey D. Son + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#include "qemu/osdep.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "qemu.h" + +#include "syscall_defs.h" +#include "bsd-ioctl.h" +#include "os-ioctl-cryptodev.h" +#include "os-ioctl-filio.h" +#include "os-ioctl-in6_var.h" +#include "os-ioctl-sockio.h" +#include "os-ioctl-ttycom.h" +#include "os-ioctl-disk.h" + +static void target_to_host_termios(void *dst, const void *src) +{ + struct termios *host = dst; + const struct target_termios *target = src; + + host->c_iflag = target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl); + host->c_oflag = target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl); + host->c_cflag = target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl); + host->c_lflag = target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl); + + memset(host->c_cc, 0, sizeof(host->c_cc)); + host->c_cc[VEOF] = target->c_cc[TARGET_VEOF]; + host->c_cc[VEOL] = target->c_cc[TARGET_VEOL]; +#ifdef VEOL2 + host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2]; +#endif + host->c_cc[VERASE] = target->c_cc[TARGET_VERASE]; +#ifdef VWERASE + host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE]; +#endif + host->c_cc[VKILL] = target->c_cc[TARGET_VKILL]; +#ifdef VREPRINT + host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT]; +#endif +#ifdef VERASE2 + host->c_cc[VERASE2] = target->c_cc[TARGET_VERASE2]; +#endif + host->c_cc[VINTR] = target->c_cc[TARGET_VINTR]; + host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT]; + host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP]; +#ifdef VDSUSP + host->c_cc[VDSUSP] = target->c_cc[TARGET_VDSUSP]; +#endif + host->c_cc[VSTART] = target->c_cc[TARGET_VSTART]; + host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP]; +#ifdef VLNEXT + host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT]; +#endif +#ifdef VDISCARD + host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD]; +#endif + host->c_cc[VMIN] = target->c_cc[TARGET_VMIN]; + host->c_cc[VTIME] = target->c_cc[TARGET_VTIME]; +#ifdef VSTATUS + host->c_cc[VSTATUS] = target->c_cc[TARGET_VSTATUS]; +#endif + + host->c_ispeed = tswap32(target->c_ispeed); + host->c_ospeed = tswap32(target->c_ospeed); +} + +static void host_to_target_termios(void *dst, const void *src) +{ + struct target_termios *target = dst; + const struct termios *host = src; + + target->c_iflag = tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl)); + target->c_oflag = tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl)); + target->c_cflag = tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl)); + target->c_lflag = tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl)); + + memset(target->c_cc, 0, sizeof(target->c_cc)); + target->c_cc[TARGET_VEOF] = host->c_cc[VEOF]; + target->c_cc[TARGET_VEOL] = host->c_cc[VEOL]; +#ifdef VEOL2 + target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2]; +#endif + target->c_cc[TARGET_VERASE] = host->c_cc[VERASE]; +#ifdef VWERASE + target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE]; +#endif + target->c_cc[TARGET_VKILL] = host->c_cc[VKILL]; +#ifdef VREPRINT + target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT]; +#endif +#ifdef VERASE2 + target->c_cc[TARGET_VERASE2] = host->c_cc[VERASE2]; +#endif + target->c_cc[TARGET_VINTR] = host->c_cc[VINTR]; + target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT]; + target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP]; +#ifdef VDSUSP + target->c_cc[TARGET_VDSUSP] = host->c_cc[VDSUSP]; +#endif + target->c_cc[TARGET_VSTART] = host->c_cc[VSTART]; + target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP]; +#ifdef VLNEXT + target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT]; +#endif +#ifdef VDISCARD + target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD]; +#endif + target->c_cc[TARGET_VMIN] = host->c_cc[VMIN]; + target->c_cc[TARGET_VTIME] = host->c_cc[VTIME]; +#ifdef VSTATUS + target->c_cc[TARGET_VSTATUS] = host->c_cc[VSTATUS]; +#endif + + target->c_ispeed = tswap32(host->c_ispeed); + target->c_ospeed = tswap32(host->c_ospeed); +} + +static const StructEntry struct_termios_def = { + .convert = { host_to_target_termios, target_to_host_termios }, + .size = { sizeof(struct target_termios), sizeof(struct termios) }, + .align = { __alignof__(struct target_termios), + __alignof__(struct termios) }, +}; + +/* ioctl structure type definitions */ +#define STRUCT(name, ...) STRUCT_ ## name, +#define STRUCT_SPECIAL(name) STRUCT_ ## name, +enum { +#include "os-ioctl-types.h" +STRUCT_MAX +}; +#undef STRUCT +#undef STRUCT_SPECIAL + +#define STRUCT(name, ...) \ + static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL }; +#define STRUCT_SPECIAL(name) +#include "os-ioctl-types.h" +#undef STRUCT +#undef STRUCT_SPECIAL + + +struct IOCTLEntry; + +typedef abi_long do_ioctl_fn(const struct IOCTLEntry *ie, uint8_t *buf_temp, + int fd, abi_long cmd, abi_long arg); + +struct IOCTLEntry { + unsigned int target_cmd; + unsigned int host_cmd; + const char *name; + int access; + do_ioctl_fn *do_ioctl; + const argtype arg_type[5]; +}; +typedef struct IOCTLEntry IOCTLEntry; + +#define MAX_STRUCT_SIZE 4096 + +static abi_long do_ioctl_unsupported(__unused const IOCTLEntry *ie, + __unused uint8_t *buf_temp, + __unused int fd, __unused abi_long cmd, + __unused abi_long arg); + +static abi_long do_ioctl_in6_ifreq_sockaddr_int(const IOCTLEntry *ie, + uint8_t *buf_temp, int fd, abi_long cmd, abi_long arg); + +static IOCTLEntry ioctl_entries[] = { +#define IOC_ 0x0000 +#define IOC_R 0x0001 +#define IOC_W 0x0002 +#define IOC_RW (IOC_R | IOC_W) +#define IOCTL(cmd, access, ...) \ + { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } }, +#define IOCTL_SPECIAL(cmd, access, dofn, ...) \ + { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } }, +#define IOCTL_SPECIAL_UNIMPL(cmd, access, dofn, ...) \ + { TARGET_ ## cmd, 0, #cmd, access, dofn, { __VA_ARGS__ } }, +#include "os-ioctl-cmds.h" + { 0, 0 }, +};