diff options
46 files changed, 3653 insertions, 1 deletions
@@ -8,7 +8,7 @@ Noteworthy changes in release ?.?? (????-??-??) * Implemented decoding of process_mrelease syscall, introduced in Linux 5.15. * Implemented decoding of SECCOMP_GET_NOTIF_SIZES operation of seccomp syscall. - * Implemented decoding of SECCOMP_* ioctl commands. + * Implemented decoding of KD* and SECCOMP_* ioctl commands. * Enhanced decoding of io_uring_register and times syscalls. * Updated lists of BTRFS_*, DM_*, FAN_REPORT_*, IORING_* and MPOL_* constants. diff --git a/configure.ac b/configure.ac index e662c12f4..058825907 100644 --- a/configure.ac +++ b/configure.ac @@ -424,6 +424,7 @@ AC_CHECK_HEADERS(m4_normalize([ elf.h gcov.h iconv.h + linux/kd.h mqueue.h netinet/sctp.h netipx/ipx.h diff --git a/src/Makefile.am b/src/Makefile.am index e686c2f99..f11ef1254 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -160,6 +160,8 @@ libstrace_a_SOURCES = \ ipc_shm.c \ ipc_shmctl.c \ kcmp.c \ + kd_ioctl.c \ + kd_mpers_ioctl.c \ kernel_dirent.h \ kernel_fcntl.h \ kernel_rusage.h \ diff --git a/src/defs.h b/src/defs.h index b634e4e67..feb8b6c13 100644 --- a/src/defs.h +++ b/src/defs.h @@ -1338,6 +1338,7 @@ DECL_IOCTL(fs_f); DECL_IOCTL(fs_x); DECL_IOCTL(gpio); DECL_IOCTL(inotify); +DECL_IOCTL(kd); DECL_IOCTL(kvm); DECL_IOCTL(nbd); DECL_IOCTL(nsfs); diff --git a/src/ioctl.c b/src/ioctl.c index f32ae9761..1965af32c 100644 --- a/src/ioctl.c +++ b/src/ioctl.c @@ -366,6 +366,8 @@ ioctl_decode(struct tcb *tcp) return evdev_ioctl(tcp, code, arg); case 'I': return inotify_ioctl(tcp, code, arg); + case 'K': + return kd_ioctl(tcp, code, arg); case 'L': return loop_ioctl(tcp, code, arg); case 'M': diff --git a/src/kd_ioctl.c b/src/kd_ioctl.c new file mode 100644 index 000000000..3102cf5af --- /dev/null +++ b/src/kd_ioctl.c @@ -0,0 +1,817 @@ +/* + * Support for decoding of VT ioctl commands. + * + * Copyright (c) 2019-2021 Eugene Syromyatnikov <evgsyr@gmail.com> + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + +#include <linux/kd.h> +#include <linux/keyboard.h> + +#include "print_fields.h" +#include "print_utils.h" + +#include "xlat/kd_default_led_flags.h" +#include "xlat/kd_kbd_modes.h" +#include "xlat/kd_kbd_types.h" +#include "xlat/kd_keymap_flags.h" +#include "xlat/kd_key_tables.h" +#include "xlat/kd_key_types.h" +#include "xlat/kd_key_fn_keys.h" +#include "xlat/kd_key_fn_key_vals.h" +#include "xlat/kd_key_spec_keys.h" +#include "xlat/kd_key_pad_keys.h" +#include "xlat/kd_key_dead_keys.h" +#include "xlat/kd_key_cur_keys.h" +#include "xlat/kd_key_shift_keys.h" +#include "xlat/kd_key_ascii_keys.h" +#include "xlat/kd_key_lock_keys.h" +#include "xlat/kd_key_slock_keys.h" +#include "xlat/kd_key_brl_keys.h" +#include "xlat/kd_led_flags.h" +#include "xlat/kd_meta_vals.h" +#include "xlat/kd_modes.h" + +#define XLAT_MACROS_ONLY +# include "xlat/kd_ioctl_cmds.h" +#undef XLAT_MACROS_ONLY + +enum { + KERNEL_PIT_TICK_RATE = 1193182, + KERNEL_E_TABSZ = 256, + KERNEL_MAX_DIACR = 256, +}; + +static int +kiocsound(struct tcb *const tcp, const kernel_ulong_t arg) +{ + unsigned int freq = arg ? KERNEL_PIT_TICK_RATE / arg : 0; + + tprint_arg_next(); + PRINT_VAL_U(arg); + if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_RAW) { + if (freq) + tprintf_comment("%u Hz", freq); + else + tprints_comment("off"); + } + + return RVAL_IOCTL_DECODED; +} + +static int +kd_mk_tone(struct tcb *const tcp, const unsigned int arg) +{ + unsigned int ticks = arg >> 16; + unsigned int count = arg & 0xFFFF; + unsigned int freq = ticks && count ? KERNEL_PIT_TICK_RATE / count : 0; + + tprint_arg_next(); + if (ticks) + tprintf("%u<<16|%u", ticks, count); + else + PRINT_VAL_U(count); + + if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_RAW) { + if (freq) + tprintf_comment("%u Hz, %u ms", freq, ticks); + else + tprints_comment("off"); + } + + return RVAL_IOCTL_DECODED; +} + +static void +print_leds(struct tcb *const tcp, const kernel_ulong_t arg, + const bool get, const bool dflt) +{ + unsigned char val; + + if (get) { + if (umove_or_printaddr(tcp, arg, &val)) + return; + } else { + val = arg; + } + + if (get) + tprint_indirect_begin(); + printflags(dflt ? kd_default_led_flags : kd_led_flags, val, + "LED_???"); + if (get) + tprint_indirect_end(); +} + +static int +kd_leds(struct tcb *const tcp, const unsigned int code, + const kernel_ulong_t arg) +{ + bool get = false; + bool dflt = false; + + switch (code) { + case KDGETLED: + case KDGKBLED: + get = true; + } + + switch (code) { + case KDGKBLED: + case KDSKBLED: + dflt = true; + } + + if (entering(tcp)) { + tprint_arg_next(); + + if (get) + return 0; + } + + print_leds(tcp, arg, get, dflt); + + return RVAL_IOCTL_DECODED; +} + +static int +kd_get_kb_type(struct tcb *const tcp, const kernel_ulong_t arg) +{ + unsigned char val; + + if (entering(tcp)) { + tprint_arg_next(); + return 0; + } + + if (umove_or_printaddr(tcp, arg, &val)) + return RVAL_IOCTL_DECODED; + + tprint_indirect_begin(); + printxval(kd_kbd_types, val, "KB_???"); + tprint_indirect_end(); + + return RVAL_IOCTL_DECODED; +} + +static int +kd_io(struct tcb *const tcp, kernel_ulong_t arg) +{ + enum { GPFIRST = 0x3b4, GPLAST = 0x3df }; + + tprint_arg_next(); + PRINT_VAL_X(arg); + + if (arg >= GPFIRST && arg <= GPLAST + && xlat_verbose(xlat_verbosity) != XLAT_STYLE_RAW) + tprintf_comment("GPFIRST + %" PRI_klu, arg - GPFIRST); + + return RVAL_IOCTL_DECODED; +} + +static int +kd_set_mode(struct tcb *const tcp, const kernel_ulong_t arg) +{ + tprint_arg_next(); + printxval(kd_modes, arg, "KD_???"); + + return RVAL_IOCTL_DECODED; +} + +static int +kd_get_mode(struct tcb *const tcp, const kernel_ulong_t arg) +{ + unsigned int val; + + if (entering(tcp)) { + tprint_arg_next(); + return 0; + } + + if (umove_or_printaddr(tcp, arg, &val)) + return RVAL_IOCTL_DECODED; + + tprint_indirect_begin(); + printxval(kd_modes, val, "KD_???"); + tprint_indirect_end(); + + return RVAL_IOCTL_DECODED; +} + +static int +kd_screen_map(struct tcb *const tcp, const kernel_ulong_t arg, const bool get) +{ + if (entering(tcp)) { + tprint_arg_next(); + + if (get) + return 0; + } + + if (entering(tcp) || !syserror(tcp)) + printstr_ex(tcp, arg, KERNEL_E_TABSZ, QUOTE_FORCE_HEX); + else + printaddr(arg); + + return RVAL_IOCTL_DECODED; +} + +static bool +print_scrmap_array_member(struct tcb *tcp, void *elem_buf, + size_t elem_size, void *data) +{ + unsigned short val = *(unsigned short *) elem_buf; + + if ((xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV) || + ((val & ~UNI_DIRECT_MASK) != UNI_DIRECT_BASE)) + PRINT_VAL_X(val); + + if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW) + return true; + + if ((val & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE) + (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE + ? tprintf_comment : tprintf)("UNI_DIRECT_BASE+%#hx", + val & UNI_DIRECT_MASK); + + return true; +} + +static int +kd_uni_screen_map(struct tcb *const tcp, const kernel_ulong_t arg, + const bool get) +{ + unsigned short elem; + + if (entering(tcp)) { + tprint_arg_next(); + + if (get) + return 0; + } + + print_array(tcp, arg, KERNEL_E_TABSZ, &elem, sizeof(elem), + tfetch_mem, print_scrmap_array_member, 0); + + return RVAL_IOCTL_DECODED; +} + +static int +kd_set_kbd_mode(struct tcb *const tcp, const unsigned int arg) +{ + tprint_arg_next(); + printxval_d(kd_kbd_modes, arg, "K_???"); + + return RVAL_IOCTL_DECODED; +} + +static int +kd_get_kbd_mode(struct tcb *const tcp, const kernel_ulong_t arg) +{ + unsigned int val; + + if (entering(tcp)) { + tprint_arg_next(); + return 0; + } + + if (umove_or_printaddr(tcp, arg, &val)) + return RVAL_IOCTL_DECODED; + + tprint_indirect_begin(); + printxval_d(kd_kbd_modes, val, "K_???"); + tprint_indirect_end(); + + return RVAL_IOCTL_DECODED; +} + +static int +kd_kbd_entry(struct tcb *const tcp, const kernel_ulong_t arg, const bool get) +{ + static const struct xlat *xlat_tables[] = { + /* KT_LATIN */ + [KT_FN] = kd_key_fn_keys, + [KT_SPEC] = kd_key_spec_keys, + [KT_PAD] = kd_key_pad_keys, + [KT_DEAD] = kd_key_dead_keys, + /* KT_CONS */ + [KT_CUR] = kd_key_cur_keys, + [KT_SHIFT] = kd_key_shift_keys, + /* KT_META */ + [KT_ASCII] = kd_key_ascii_keys, + [KT_LOCK] = kd_key_lock_keys, + /* KT_LETTER */ + [KT_SLOCK] = kd_key_slock_keys, + /* KT_DEAD2 */ + [KT_BRL] = kd_key_brl_keys, + }; + + struct kbentry val; + unsigned char ktyp; + unsigned char kval; + const char *str = NULL; + + if (entering(tcp)) { + tprint_arg_next(); + + if (umoven(tcp, arg, offsetofend(struct kbentry, kb_index), + &val)) { + printaddr(arg); + return RVAL_IOCTL_DECODED; + } + + tprint_struct_begin(); + + const char *keymap_str = xlookup(kd_key_tables, val.kb_table); + + if (keymap_str) { + tprints_field_name("kb_table"); + print_xlat_ex(val.kb_table, keymap_str, + XLAT_STYLE_DEFAULT); + } else { + PRINT_FIELD_FLAGS(val, kb_table, kd_keymap_flags, + "K_???"); + } + + tprint_struct_next(); + PRINT_FIELD_U(val, kb_index); + + if (get) + return 0; + } else if (syserror(tcp)) { + goto out; + } + + tprint_struct_next(); + if (umove(tcp, arg + offsetof(struct kbentry, kb_value), + &val.kb_value)) { + tprints_field_name("kb_value"); + tprint_unavailable(); + goto out; + } + + PRINT_FIELD_X(val, kb_value); + + if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW) + goto out; + + ktyp = KTYP(val.kb_value); + kval = KVAL(val.kb_value); + + if (ktyp < ARRAY_SIZE(xlat_tables) && xlat_tables[ktyp]) + str = xlookup(xlat_tables[ktyp], val.kb_value); + + if (str) { + tprints_comment(str); + } else { + tprint_comment_begin(); + tprints_arg_begin("K"); + printxvals_ex(ktyp, NULL, XLAT_STYLE_ABBREV, + kd_key_types, NULL); + tprint_arg_next(); + + switch (ktyp) { + case KT_LATIN: + case KT_META: + case KT_LETTER: + case KT_DEAD2: + print_char(kval, SCF_QUOTES | SCF_ESC_WS); + break; + default: + PRINT_VAL_X(kval); + } + + tprint_arg_end(); + tprint_comment_end(); + } + +out: + tprint_struct_end(); + + return RVAL_IOCTL_DECODED; +} + +static int +kd_kbd_str_entry(struct tcb *const tcp, const kernel_ulong_t arg, + const bool get) +{ + struct kbsentry val; + + if (entering(tcp)) { + tprint_arg_next(); + + if (umove_or_printaddr(tcp, arg, &(val.kb_func))) + return RVAL_IOCTL_DECODED; + + tprint_struct_begin(); + PRINT_FIELD_XVAL(val, kb_func, kd_key_fn_key_vals, + "KVAL(K_???"")"); + + if (get) + return 0; + } else if (syserror(tcp)) { + goto out; + } + + tprint_struct_next(); + tprints_field_name("kb_string"); + + int ret = umovestr(tcp, arg + offsetof(struct kbsentry, kb_string), + sizeof(val.kb_string), (char *) val.kb_string); + + if (ret < 0) { + tprint_unavailable(); + goto out; + } + + if (print_quoted_string((char *) val.kb_string, + MIN(max_strlen, + (unsigned int) ret ?: sizeof(val.kb_string)), + QUOTE_OMIT_TRAILING_0)) + tprint_more_data_follows(); + +out: + tprint_struct_end(); + + return RVAL_IOCTL_DECODED; +} + +static bool +print_kbdiacr_array_member(struct tcb *tcp, void *elem_buf, + size_t elem_size, void *data) +{ + struct kbdiacr *val = elem_buf; + + tprint_struct_begin(); + PRINT_FIELD_CHAR(*val, diacr, SCF_QUOTES | SCF_ESC_WS); + tprint_struct_next(); + PRINT_FIELD_CHAR(*val, base, SCF_QUOTES | SCF_ESC_WS); + tprint_struct_next(); + PRINT_FIELD_CHAR(*val, result, SCF_QUOTES | SCF_ESC_WS); + tprint_struct_end(); + + return true; +} + +static int +kd_diacr(struct tcb *const tcp, const kernel_ulong_t arg, const bool get) +{ + unsigned int kb_cnt; /* struct kbdiacrs.kb_cnt */ + struct kbdiacr elem; + + if (entering(tcp)) { + tprint_arg_next(); + + if (get) + return 0; + } + + if (umove_or_printaddr(tcp, arg, &kb_cnt)) + return RVAL_IOCTL_DECODED; + + tprint_struct_begin(); + tprints_field_name("kb_cnt"); + PRINT_VAL_U(kb_cnt); + tprint_struct_next(); + tprints_field_name("kbdiacr"); + print_array_ex(tcp, arg + offsetof(struct kbdiacrs, kbdiacr), + MIN(kb_cnt, KERNEL_MAX_DIACR), &elem, sizeof(elem), + tfetch_mem, print_kbdiacr_array_member, 0, + kb_cnt > KERNEL_MAX_DIACR ? PAF_ARRAY_TRUNCATED : 0, + NULL, NULL); + tprint_struct_end(); + + return RVAL_IOCTL_DECODED; +} + +static bool +print_kbdiacruc_array_member(struct tcb *tcp, void *elem_buf, + size_t elem_size, void *data) +{ + struct kbdiacruc *val = elem_buf; + + tprint_struct_begin(); + PRINT_FIELD_X(*val, diacr); + tprint_struct_next(); + PRINT_FIELD_X(*val, base); + tprint_struct_next(); + PRINT_FIELD_X(*val, result); + tprint_struct_end(); + + return true; +} + +static int +kd_diacr_uc(struct tcb *const tcp, const kernel_ulong_t arg, const bool get) +{ + unsigned int kb_cnt; /* struct kbdiacrs.kb_cnt */ + struct kbdiacruc elem; + + if (entering(tcp)) { + tprint_arg_next(); + + if (get) + return 0; + } + + if (umove_or_printaddr(tcp, arg, &kb_cnt)) + return RVAL_IOCTL_DECODED; + + tprint_struct_begin(); + tprints_field_name("kb_cnt"); + PRINT_VAL_U(kb_cnt); + tprint_struct_next(); + tprints_field_name("kbdiacruc"); + print_array_ex(tcp, arg + offsetof(struct kbdiacrsuc, kbdiacruc), + MIN(kb_cnt, KERNEL_MAX_DIACR), &elem, sizeof(elem), + tfetch_mem, print_kbdiacruc_array_member, 0, + kb_cnt > KERNEL_MAX_DIACR ? PAF_ARRAY_TRUNCATED : 0, + NULL, NULL); + tprint_struct_end(); + + return RVAL_IOCTL_DECODED; +} + +static int +kd_keycode(struct tcb *const tcp, const kernel_ulong_t arg, const bool get) +{ + struct kbkeycode val; + + if (entering(tcp)) { + tprint_arg_next(); + + if (umove_or_printaddr(tcp, arg, &val)) + return RVAL_IOCTL_DECODED; + + tprint_struct_begin(); + PRINT_FIELD_X(val, scancode); + tprint_struct_next(); + PRINT_FIELD_X(val, keycode); + + if (get) + return 0; + + goto end; + } + + /* exiting */ + if (syserror(tcp) || + umove(tcp, arg + offsetof(struct kbkeycode, keycode), &val.keycode)) + { + tprint_struct_end(); + return RVAL_IOCTL_DECODED; + } + + tprint_value_changed(); + PRINT_VAL_X(val.keycode); + +end: + tprint_struct_end(); + + return RVAL_IOCTL_DECODED; +} + +static int +kd_sigaccept(struct tcb *const tcp, const kernel_ulong_t arg) +{ + tprint_arg_next(); + + if (arg < INT_MAX) + printsignal(arg); + else + PRINT_VAL_U(arg); + + return RVAL_IOCTL_DECODED; +} + +static void +print_kbd_repeat(struct kbd_repeat *val) +{ + tprint_struct_begin(); + PRINT_FIELD_D(*val, delay); + tprint_struct_next(); + PRINT_FIELD_D(*val, period); + tprint_struct_end(); +} + +static int +kd_kbdrep(struct tcb *const tcp, const kernel_ulong_t arg) +{ + struct kbd_repeat val; + + if (entering(tcp)) { + tprint_arg_next(); + + if (umove_or_printaddr(tcp, arg, &val)) + return RVAL_IOCTL_DECODED; + + print_kbd_repeat(&val); + + return 0; + } + + /* exiting */ + if (syserror(tcp) || umove(tcp, arg, &val)) + return RVAL_IOCTL_DECODED; + + tprint_value_changed(); + + print_kbd_repeat(&val); + + return RVAL_IOCTL_DECODED; +} + +static int +kd_font(struct tcb *const tcp, const kernel_ulong_t arg, const bool get) +{ + if (entering(tcp)) { + tprint_arg_next(); + + if (get) + return 0; + } + + /* + * [GP]IO_FONT are equivalent to KDFONTOP with width == 8, + * height == 32, and charcount == 256, so the total size + * is (width + 7) / 8 * height * charcount == 8192. + */ + if (exiting(tcp) && syserror(tcp)) + printaddr(arg); + else + printstr_ex(tcp, arg, 8192, QUOTE_FORCE_HEX); + + return RVAL_IOCTL_DECODED; +} + +static int +kd_kbmeta(struct tcb *const tcp, const kernel_ulong_t arg, const bool get) +{ + unsigned int val; + + if (entering(tcp)) { + tprint_arg_next(); + + if (get) + return 0; + } + + if (get) { + if (umove_or_printaddr(tcp, arg, &val)) + return RVAL_IOCTL_DECODED; + } else { + val = arg; + } + + if (get) + tprint_indirect_begin(); + printxval(kd_meta_vals, val, "K_???"); + if (get) + tprint_indirect_end(); + + return RVAL_IOCTL_DECODED; +} + +static int +kd_unimapclr(struct tcb *const tcp, const kernel_ulong_t arg) +{ + struct unimapinit umi; + + tprint_arg_next(); + + if (umove_or_printaddr(tcp, arg, &umi)) + return RVAL_IOCTL_DECODED; + + tprint_struct_begin(); + PRINT_FIELD_U(umi, advised_hashsize); + tprint_struct_next(); + PRINT_FIELD_U(umi, advised_hashstep); + tprint_struct_next(); + PRINT_FIELD_U(umi, advised_hashlevel); + tprint_struct_end(); + + return RVAL_IOCTL_DECODED; +} + +static int +kd_cmap(struct tcb *const tcp, const kernel_ulong_t arg, const bool get) +{ + if (entering(tcp)) { + tprint_arg_next(); + + if (get) + return 0; + } else { + if (syserror(tcp)) { + printaddr(arg); + + return RVAL_IOCTL_DECODED; + } + } + + printstr_ex(tcp, arg, 3 * 16, QUOTE_FORCE_HEX); + + return RVAL_IOCTL_DECODED; +} + +int +kd_ioctl(struct tcb *const tcp, const unsigned int code, + kernel_ulong_t arg) +{ + arg = truncate_kulong_to_current_wordsize(arg); + + switch (code) { + case KIOCSOUND: + return kiocsound(tcp, arg); + + case KDMKTONE: + return kd_mk_tone(tcp, arg); + + case KDGETLED: + case KDSETLED: + case KDGKBLED: + case KDSKBLED: + return kd_leds(tcp, code, arg); + + case KDGKBTYPE: + return kd_get_kb_type(tcp, arg); + + case KDADDIO: + case KDDELIO: + return kd_io(tcp, arg); + + case KDSETMODE: + return kd_set_mode(tcp, arg); + case KDGETMODE: + return kd_get_mode(tcp, arg); + + case GIO_SCRNMAP: + case PIO_SCRNMAP: + return kd_screen_map(tcp, arg, code == GIO_SCRNMAP); + + case GIO_UNISCRNMAP: + case PIO_UNISCRNMAP: + return kd_uni_screen_map(tcp, arg, code == GIO_UNISCRNMAP); + + case KDGKBMODE: + return kd_get_kbd_mode(tcp, arg); + case KDSKBMODE: + return kd_set_kbd_mode(tcp, arg); + + case KDGKBENT: + case KDSKBENT: + return kd_kbd_entry(tcp, arg, code == KDGKBENT); + + case KDGKBSENT: + case KDSKBSENT: + return kd_kbd_str_entry(tcp, arg, code == KDGKBSENT); + + case KDGKBDIACR: + case KDSKBDIACR: + return kd_diacr(tcp, arg, code == KDGKBDIACR); + + case KDGKBDIACRUC: + case KDSKBDIACRUC: + return kd_diacr_uc(tcp, arg, code == KDGKBDIACRUC); + + case KDGETKEYCODE: + case KDSETKEYCODE: + return kd_keycode(tcp, arg, code == KDGETKEYCODE); + + case KDSIGACCEPT: + return kd_sigaccept(tcp, arg); + + case KDKBDREP: + return kd_kbdrep(tcp, arg); + + case GIO_FONT: + case PIO_FONT: + return kd_font(tcp, arg, code == GIO_FONT); + + case KDGKBMETA: + case KDSKBMETA: + return kd_kbmeta(tcp, arg, code == KDGKBMETA); + + case PIO_UNIMAPCLR: + return kd_unimapclr(tcp, arg); + + case GIO_CMAP: + case PIO_CMAP: + return kd_cmap(tcp, arg, code == GIO_CMAP); + + /* no arguments */ + case KDENABIO: + case KDDISABIO: + case KDMAPDISP: + case KDUNMAPDISP: + case PIO_FONTRESET: + return RVAL_IOCTL_DECODED; + } + + /* GIO_UNIMAP, PIO_UNIMAP, GIO_FONTX, PIO_FONTX, KDFONTOP */ + return kd_mpers_ioctl(tcp, code, arg); +} diff --git a/src/kd_mpers_ioctl.c b/src/kd_mpers_ioctl.c new file mode 100644 index 000000000..b42269b6b --- /dev/null +++ b/src/kd_mpers_ioctl.c @@ -0,0 +1,269 @@ +/* + * Support for decoding of personality-dependent VT ioctl commands. + * + * Copyright (c) 2019-2021 Eugene Syromyatnikov <evgsyr@gmail.com> + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + +#include <linux/kd.h> + +#include DEF_MPERS_TYPE(struct_unimapdesc) +#include DEF_MPERS_TYPE(struct_consolefontdesc) +#include DEF_MPERS_TYPE(struct_console_font) +#include DEF_MPERS_TYPE(struct_console_font_op) + +typedef struct unimapdesc struct_unimapdesc; +typedef struct consolefontdesc struct_consolefontdesc; +typedef struct console_font struct_console_font; +typedef struct console_font_op struct_console_font_op; + +#include MPERS_DEFS + +#include "print_fields.h" + +#include "xlat/kd_font_flags.h" +#include "xlat/kd_font_ops.h" + +#define XLAT_MACROS_ONLY +# include "xlat/kd_ioctl_cmds.h" +#undef XLAT_MACROS_ONLY + + +static bool +print_unipair_array_member(struct tcb *tcp, void *elem_buf, + size_t elem_size, void *data) +{ + struct unipair *val = elem_buf; + + tprint_struct_begin(); + PRINT_FIELD_X(*val, unicode); + tprint_struct_next(); + PRINT_FIELD_X(*val, fontpos); + tprint_struct_end(); + + return true; +} + +static int +kd_unimap(struct tcb *const tcp, const kernel_ulong_t arg, const bool get) +{ + struct_unimapdesc val; + struct unipair elem; + uint16_t cnt; + + if (entering(tcp)) + tprint_arg_next(); + + if (umove_or_printaddr_ignore_syserror(tcp, arg, &val)) { + if (exiting(tcp)) + tprint_struct_end(); + + return RVAL_IOCTL_DECODED; + } + + if (entering(tcp)) { + set_tcb_priv_ulong(tcp, val.entry_ct); + tprint_struct_begin(); + PRINT_FIELD_U(val, entry_ct); + + if (get) + return 0; + } else { + tprint_value_changed(); + PRINT_VAL_U(val.entry_ct); + } + + if (exiting(tcp) && syserror(tcp) && tcp->u_error != ENOMEM) { + tprint_struct_next(); + PRINT_FIELD_PTR(val, entries); + tprint_struct_end(); + return RVAL_IOCTL_DECODED; + } + + cnt = entering(tcp) ? val.entry_ct : get_tcb_priv_ulong(tcp); + + tprint_struct_next(); + tprints_field_name("entries"); + print_array(tcp, (mpers_ptr_t) val.entries, cnt, &elem, sizeof(elem), + tfetch_mem, print_unipair_array_member, 0); + + tprint_struct_end(); + + return get && entering(tcp) ? 0 : RVAL_IOCTL_DECODED; +} + +static void +print_consolefontdesc(struct tcb *const tcp, const struct_consolefontdesc *cfd, + const bool get) +{ + tprint_struct_begin(); + PRINT_FIELD_U(*cfd, charcount); + tprint_struct_next(); + PRINT_FIELD_U(*cfd, charheight); + tprint_struct_next(); + if (get) { + PRINT_FIELD_PTR(*cfd, chardata); + } else { + tprints_field_name("chardata"); + printstr_ex(tcp, (mpers_ptr_t) cfd->chardata, + MIN(cfd->charcount, 512) * 32, QUOTE_FORCE_HEX); + } + + tprint_struct_end(); +} + +static int +kd_fontx(struct tcb *const tcp, const kernel_ulong_t arg, const bool get) +{ + struct_consolefontdesc val; + + if (entering(tcp)) { + tprint_arg_next(); + + if (umove_or_printaddr(tcp, arg, &val)) + return RVAL_IOCTL_DECODED; + } else { + if (syserror(tcp) || umove(tcp, arg, &val)) + return RVAL_IOCTL_DECODED; + + tprint_value_changed(); + } + + print_consolefontdesc(tcp, &val, get && entering(tcp)); + + return get && entering(tcp) ? 0 : RVAL_IOCTL_DECODED; +} + +static void +print_console_font_op(struct tcb *const tcp, const struct_console_font_op *cfo) +{ + enum { KERNEL_MAX_FONT_NAME = 32 }; + + tprint_struct_begin(); + + if (entering(tcp)) { + PRINT_FIELD_XVAL(*cfo, op, kd_font_ops, "KD_FONT_OP_???"); + + switch (cfo->op) { + case KD_FONT_OP_SET_DEFAULT: + case KD_FONT_OP_COPY: + break; + default: + tprint_struct_next(); + PRINT_FIELD_FLAGS(*cfo, flags, kd_font_flags, + "KD_FONT_FLAG_???"); + } + + tprint_struct_next(); + } + + switch (cfo->op) { + case KD_FONT_OP_COPY: + PRINT_FIELD_U(*cfo, height); + break; + default: + PRINT_FIELD_U(*cfo, width); + tprint_struct_next(); + PRINT_FIELD_U(*cfo, height); + } + + switch (cfo->op) { + case KD_FONT_OP_SET_DEFAULT: + case KD_FONT_OP_COPY: + break; + default: + tprint_struct_next(); + PRINT_FIELD_U(*cfo, charcount); + } + + switch (cfo->op) { + case KD_FONT_OP_GET: + if (entering(tcp)) { + tprint_struct_next(); + PRINT_FIELD_PTR(*cfo, data); + break; + } + ATTRIBUTE_FALLTHROUGH; + + case KD_FONT_OP_SET: + tprint_struct_next(); + tprints_field_name("data"); + printstr_ex(tcp, (mpers_ptr_t) cfo->data, + ROUNDUP_DIV(MIN(cfo->width, 32), 8) * 32 * + MIN(cfo->charcount, 512), + QUOTE_FORCE_HEX); + break; + + case KD_FONT_OP_SET_DEFAULT: + if (entering(tcp)) { + tprint_struct_next(); + tprints_field_name("data"); + printstr_ex(tcp, (mpers_ptr_t) cfo->data, + KERNEL_MAX_FONT_NAME, + QUOTE_0_TERMINATED + | QUOTE_EXPECT_TRAILING_0); + } + break; + + case KD_FONT_OP_COPY: + break; + + default: + tprint_struct_next(); + PRINT_FIELD_PTR(*cfo, data); + } + + tprint_struct_end(); +} + +static int +kd_font_op(struct tcb *const tcp, const kernel_ulong_t arg) +{ + struct_console_font_op val; + + if (entering(tcp)) { + tprint_arg_next(); + + if (umove_or_printaddr(tcp, arg, &val)) + return RVAL_IOCTL_DECODED; + } else { + if (syserror(tcp) || umove(tcp, arg, &val)) + return RVAL_IOCTL_DECODED; + + tprint_value_changed(); + } + + print_console_font_op(tcp, &val); + + switch (val.op) { + case KD_FONT_OP_SET: + case KD_FONT_OP_COPY: + return RVAL_IOCTL_DECODED; + } + + return entering(tcp) ? 0 : RVAL_IOCTL_DECODED; +} + +MPERS_PRINTER_DECL(int, kd_mpers_ioctl, struct tcb *const tcp, + const unsigned int code, const kernel_ulong_t arg) +{ + switch (code) + { + case GIO_UNIMAP: + case PIO_UNIMAP: + return kd_unimap(tcp, arg, code == GIO_UNIMAP); + + case GIO_FONTX: + case PIO_FONTX: + return kd_fontx(tcp, arg, code == GIO_FONTX); + + case KDFONTOP: + return kd_font_op(tcp, arg); + } + + return RVAL_DECODED; +} diff --git a/src/xlat/kd_default_led_flags.in b/src/xlat/kd_default_led_flags.in new file mode 100644 index 000000000..b0ab5a3ad --- /dev/null +++ b/src/xlat/kd_default_led_flags.in @@ -0,0 +1,7 @@ +#unconditional +LED_SCR +LED_NUM +LED_CAP +LED_SCR<<4 +LED_NUM<<4 +LED_CAP<<4 diff --git a/src/xlat/kd_font_flags.in b/src/xlat/kd_font_flags.in new file mode 100644 index 000000000..665d59a22 --- /dev/null +++ b/src/xlat/kd_font_flags.in @@ -0,0 +1,2 @@ +KD_FONT_FLAG_DONT_RECALC 0x1 +KD_FONT_FLAG_OLD 0x80000000 diff --git a/src/xlat/kd_font_ops.in b/src/xlat/kd_font_ops.in new file mode 100644 index 000000000..29d336882 --- /dev/null +++ b/src/xlat/kd_font_ops.in @@ -0,0 +1,5 @@ +#value_indexed +KD_FONT_OP_SET 0 +KD_FONT_OP_GET 1 +KD_FONT_OP_SET_DEFAULT 2 +KD_FONT_OP_COPY 3 diff --git a/src/xlat/kd_ioctl_cmds.in b/src/xlat/kd_ioctl_cmds.in new file mode 100644 index 000000000..3f2ad3e09 --- /dev/null +++ b/src/xlat/kd_ioctl_cmds.in @@ -0,0 +1,48 @@ +#sorted +/* include/uapi/linux/kd.h */ +KIOCSOUND 0x4B2F +KDMKTONE 0x4B30 +KDGETLED 0x4B31 +KDSETLED 0x4B32 +KDGKBTYPE 0x4B33 +KDADDIO 0x4B34 +KDDELIO 0x4B35 +KDENABIO 0x4B36 +KDDISABIO 0x4B37 +KDSETMODE 0x4B3A +KDGETMODE 0x4B3B +KDMAPDISP 0x4B3C +KDUNMAPDISP 0x4B3D +GIO_SCRNMAP 0x4B40 +PIO_SCRNMAP 0x4B41 +KDGKBMODE 0x4B44 +KDSKBMODE 0x4B45 +KDGKBENT 0x4B46 +KDSKBENT 0x4B47 +KDGKBSENT 0x4B48 +KDSKBSENT 0x4B49 +KDGKBDIACR 0x4B4A +KDSKBDIACR 0x4B4B +KDGETKEYCODE 0x4B4C +KDSETKEYCODE 0x4B4D +KDSIGACCEPT 0x4B4E +KDKBDREP 0x4B52 +GIO_FONT 0x4B60 +PIO_FONT 0x4B61 +KDGKBMETA 0x4B62 +KDSKBMETA 0x4B63 +KDGKBLED 0x4B64 +KDSKBLED 0x4B65 +GIO_UNIMAP 0x4B66 +PIO_UNIMAP 0x4B67 +PIO_UNIMAPCLR 0x4B68 +GIO_UNISCRNMAP 0x4B69 +PIO_UNISCRNMAP 0x4B6A +GIO_FONTX 0x4B6B +PIO_FONTX 0x4B6C +PIO_FONTRESET 0x4B6D +GIO_CMAP 0x4B70 +PIO_CMAP 0x4B71 +KDFONTOP 0x4B72 +KDGKBDIACRUC 0x4BFA +KDSKBDIACRUC 0x4BFB diff --git a/src/xlat/kd_kbd_modes.in b/src/xlat/kd_kbd_modes.in new file mode 100644 index 000000000..a38cc0e3c --- /dev/null +++ b/src/xlat/kd_kbd_modes.in @@ -0,0 +1,6 @@ +#value_indexed +K_RAW 0 +K_XLATE 1 +K_MEDIUMRAW 2 +K_UNICODE 3 +K_OFF 4 diff --git a/src/xlat/kd_kbd_types.in b/src/xlat/kd_kbd_types.in new file mode 100644 index 000000000..23516e233 --- /dev/null +++ b/src/xlat/kd_kbd_types.in @@ -0,0 +1,3 @@ +KB_84 0x1 +KB_101 0x2 +KB_OTHER 0x3 diff --git a/src/xlat/kd_key_ascii_keys.in b/src/xlat/kd_key_ascii_keys.in new file mode 100644 index 000000000..8f15c54e7 --- /dev/null +++ b/src/xlat/kd_key_ascii_keys.in @@ -0,0 +1,27 @@ +#sorted +K_ASC0 K(KT_ASCII,0) +K_ASC1 K(KT_ASCII,1) +K_ASC2 K(KT_ASCII,2) +K_ASC3 K(KT_ASCII,3) +K_ASC4 K(KT_ASCII,4) +K_ASC5 K(KT_ASCII,5) +K_ASC6 K(KT_ASCII,6) +K_ASC7 K(KT_ASCII,7) +K_ASC8 K(KT_ASCII,8) +K_ASC9 K(KT_ASCII,9) +K_HEX0 K(KT_ASCII,10) +K_HEX1 K(KT_ASCII,11) +K_HEX2 K(KT_ASCII,12) +K_HEX3 K(KT_ASCII,13) +K_HEX4 K(KT_ASCII,14) +K_HEX5 K(KT_ASCII,15) +K_HEX6 K(KT_ASCII,16) +K_HEX7 K(KT_ASCII,17) +K_HEX8 K(KT_ASCII,18) +K_HEX9 K(KT_ASCII,19) +K_HEXa K(KT_ASCII,20) +K_HEXb K(KT_ASCII,21) +K_HEXc K(KT_ASCII,22) +K_HEXd K(KT_ASCII,23) +K_HEXe K(KT_ASCII,24) +K_HEXf K(KT_ASCII,25) diff --git a/src/xlat/kd_key_brl_keys.in b/src/xlat/kd_key_brl_keys.in new file mode 100644 index 000000000..1ea09bfaf --- /dev/null +++ b/src/xlat/kd_key_brl_keys.in @@ -0,0 +1,12 @@ +#sorted +K_BRL_BLANK K(KT_BRL, 0) +K_BRL_DOT1 K(KT_BRL, 1) +K_BRL_DOT2 K(KT_BRL, 2) +K_BRL_DOT3 K(KT_BRL, 3) +K_BRL_DOT4 K(KT_BRL, 4) +K_BRL_DOT5 K(KT_BRL, 5) +K_BRL_DOT6 K(KT_BRL, 6) +K_BRL_DOT7 K(KT_BRL, 7) +K_BRL_DOT8 K(KT_BRL, 8) +K_BRL_DOT9 K(KT_BRL, 9) +K_BRL_DOT10 K(KT_BRL, 10) diff --git a/src/xlat/kd_key_cur_keys.in b/src/xlat/kd_key_cur_keys.in new file mode 100644 index 000000000..51d1458fc --- /dev/null +++ b/src/xlat/kd_key_cur_keys.in @@ -0,0 +1,5 @@ +#sorted +K_DOWN K(KT_CUR,0) +K_LEFT K(KT_CUR,1) +K_RIGHT K(KT_CUR,2) +K_UP K(KT_CUR,3) diff --git a/src/xlat/kd_key_dead_keys.in b/src/xlat/kd_key_dead_keys.in new file mode 100644 index 000000000..9d08fb22b --- /dev/null +++ b/src/xlat/kd_key_dead_keys.in @@ -0,0 +1,28 @@ +#sorted +K_DGRAVE K(KT_DEAD,0) +K_DACUTE K(KT_DEAD,1) +K_DCIRCM K(KT_DEAD,2) +K_DTILDE K(KT_DEAD,3) +K_DDIERE K(KT_DEAD,4) +K_DCEDIL K(KT_DEAD,5) +K_DMACRON K(KT_DEAD,6) +K_DBREVE K(KT_DEAD,7) +K_DABDOT K(KT_DEAD,8) +K_DABRING K(KT_DEAD,9) +K_DDBACUTE K(KT_DEAD,10) +K_DCARON K(KT_DEAD,11) +K_DOGONEK K(KT_DEAD,12) +K_DIOTA K(KT_DEAD,13) +K_DVOICED K(KT_DEAD,14) +K_DSEMVOICED K(KT_DEAD,15) +K_DBEDOT K(KT_DEAD,16) +K_DHOOK K(KT_DEAD,17) +K_DHORN K(KT_DEAD,18) +K_DSTROKE K(KT_DEAD,19) +K_DABCOMMA K(KT_DEAD,20) +K_DABREVCOMMA K(KT_DEAD,21) +K_DDBGRAVE K(KT_DEAD,22) +K_DINVBREVE K(KT_DEAD,23) +K_DBECOMMA K(KT_DEAD,24) +K_DCURRENCY K(KT_DEAD,25) +K_DGREEK K(KT_DEAD,26) diff --git a/src/xlat/kd_key_fn_key_vals.in b/src/xlat/kd_key_fn_key_vals.in new file mode 100644 index 000000000..a79ea1b07 --- /dev/null +++ b/src/xlat/kd_key_fn_key_vals.in @@ -0,0 +1,258 @@ +#value_indexed +#unconditional +KVAL(K_F1) +KVAL(K_F2) +KVAL(K_F3) +KVAL(K_F4) +KVAL(K_F5) +KVAL(K_F6) +KVAL(K_F7) +KVAL(K_F8) +KVAL(K_F9) +KVAL(K_F10) +KVAL(K_F11) +KVAL(K_F12) +KVAL(K_F13) +KVAL(K_F14) +KVAL(K_F15) +KVAL(K_F16) +KVAL(K_F17) +KVAL(K_F18) +KVAL(K_F19) +KVAL(K_F20) +KVAL(K_FIND) +KVAL(K_INSERT) +KVAL(K_REMOVE) +KVAL(K_SELECT) +KVAL(K_PGUP) +KVAL(K_PGDN) +KVAL(K_MACRO) +KVAL(K_HELP) +KVAL(K_DO) +KVAL(K_PAUSE) +KVAL(K_F21) +KVAL(K_F22) +KVAL(K_F23) +KVAL(K_F24) +KVAL(K_F25) +KVAL(K_F26) +KVAL(K_F27) +KVAL(K_F28) +KVAL(K_F29) +KVAL(K_F30) +KVAL(K_F31) +KVAL(K_F32) +KVAL(K_F33) +KVAL(K_F34) +KVAL(K_F35) +KVAL(K_F36) +KVAL(K_F37) +KVAL(K_F38) +KVAL(K_F39) +KVAL(K_F40) +KVAL(K_F41) +KVAL(K_F42) +KVAL(K_F43) +KVAL(K_F44) +KVAL(K_F45) +KVAL(K_F46) +KVAL(K_F47) +KVAL(K_F48) +KVAL(K_F49) +KVAL(K_F50) +KVAL(K_F51) +KVAL(K_F52) +KVAL(K_F53) +KVAL(K_F54) +KVAL(K_F55) +KVAL(K_F56) +KVAL(K_F57) +KVAL(K_F58) +KVAL(K_F59) +KVAL(K_F60) +KVAL(K_F61) +KVAL(K_F62) +KVAL(K_F63) +KVAL(K_F64) +KVAL(K_F65) +KVAL(K_F66) +KVAL(K_F67) +KVAL(K_F68) +KVAL(K_F69) +KVAL(K_F70) +KVAL(K_F71) +KVAL(K_F72) +KVAL(K_F73) +KVAL(K_F74) +KVAL(K_F75) +KVAL(K_F76) +KVAL(K_F77) +KVAL(K_F78) +KVAL(K_F79) +KVAL(K_F80) +KVAL(K_F81) +KVAL(K_F82) +KVAL(K_F83) +KVAL(K_F84) +KVAL(K_F85) +KVAL(K_F86) +KVAL(K_F87) +KVAL(K_F88) +KVAL(K_F89) +KVAL(K_F90) +KVAL(K_F91) +KVAL(K_F92) +KVAL(K_F93) +KVAL(K_F94) +KVAL(K_F95) +KVAL(K_F96) +KVAL(K_F97) +KVAL(K_F98) +KVAL(K_F99) +KVAL(K_F100) +KVAL(K_F101) +KVAL(K_F102) +KVAL(K_F103) +KVAL(K_F104) +KVAL(K_F105) +KVAL(K_F106) +KVAL(K_F107) +KVAL(K_F108) +KVAL(K_F109) +KVAL(K_F110) +KVAL(K_F111) +KVAL(K_F112) +KVAL(K_F113) +KVAL(K_F114) +KVAL(K_F115) +KVAL(K_F116) +KVAL(K_F117) +KVAL(K_F118) +KVAL(K_F119) +KVAL(K_F120) +KVAL(K_F121) +KVAL(K_F122) +KVAL(K_F123) +KVAL(K_F124) +KVAL(K_F125) +KVAL(K_F126) +KVAL(K_F127) +KVAL(K_F128) +KVAL(K_F129) +KVAL(K_F130) +KVAL(K_F131) +KVAL(K_F132) +KVAL(K_F133) +KVAL(K_F134) +KVAL(K_F135) +KVAL(K_F136) +KVAL(K_F137) +KVAL(K_F138) +KVAL(K_F139) +KVAL(K_F140) +KVAL(K_F141) +KVAL(K_F142) +KVAL(K_F143) +KVAL(K_F144) +KVAL(K_F145) +KVAL(K_F146) +KVAL(K_F147) +KVAL(K_F148) +KVAL(K_F149) +KVAL(K_F150) +KVAL(K_F151) +KVAL(K_F152) +KVAL(K_F153) +KVAL(K_F154) +KVAL(K_F155) +KVAL(K_F156) +KVAL(K_F157) +KVAL(K_F158) +KVAL(K_F159) +KVAL(K_F160) +KVAL(K_F161) +KVAL(K_F162) +KVAL(K_F163) +KVAL(K_F164) +KVAL(K_F165) +KVAL(K_F166) +KVAL(K_F167) +KVAL(K_F168) +KVAL(K_F169) +KVAL(K_F170) +KVAL(K_F171) +KVAL(K_F172) +KVAL(K_F173) +KVAL(K_F174) +KVAL(K_F175) +KVAL(K_F176) +KVAL(K_F177) +KVAL(K_F178) +KVAL(K_F179) +KVAL(K_F180) +KVAL(K_F181) +KVAL(K_F182) +KVAL(K_F183) +KVAL(K_F184) +KVAL(K_F185) +KVAL(K_F186) +KVAL(K_F187) +KVAL(K_F188) +KVAL(K_F189) +KVAL(K_F190) +KVAL(K_F191) +KVAL(K_F192) +KVAL(K_F193) +KVAL(K_F194) +KVAL(K_F195) +KVAL(K_F196) +KVAL(K_F197) +KVAL(K_F198) +KVAL(K_F199) +KVAL(K_F200) +KVAL(K_F201) +KVAL(K_F202) +KVAL(K_F203) +KVAL(K_F204) +KVAL(K_F205) +KVAL(K_F206) +KVAL(K_F207) +KVAL(K_F208) +KVAL(K_F209) +KVAL(K_F210) +KVAL(K_F211) +KVAL(K_F212) +KVAL(K_F213) +KVAL(K_F214) +KVAL(K_F215) +KVAL(K_F216) +KVAL(K_F217) +KVAL(K_F218) +KVAL(K_F219) +KVAL(K_F220) +KVAL(K_F221) +KVAL(K_F222) +KVAL(K_F223) +KVAL(K_F224) +KVAL(K_F225) +KVAL(K_F226) +KVAL(K_F227) +KVAL(K_F228) +KVAL(K_F229) +KVAL(K_F230) +KVAL(K_F231) +KVAL(K_F232) +KVAL(K_F233) +KVAL(K_F234) +KVAL(K_F235) +KVAL(K_F236) +KVAL(K_F237) +KVAL(K_F238) +KVAL(K_F239) +KVAL(K_F240) +KVAL(K_F241) +KVAL(K_F242) +KVAL(K_F243) +KVAL(K_F244) +KVAL(K_F245) +KVAL(K_UNDO) diff --git a/src/xlat/kd_key_fn_keys.in b/src/xlat/kd_key_fn_keys.in new file mode 100644 index 000000000..65a29f2f5 --- /dev/null +++ b/src/xlat/kd_key_fn_keys.in @@ -0,0 +1,257 @@ +#sorted +K_F1 K(KT_FN,0) +K_F2 K(KT_FN,1) +K_F3 K(KT_FN,2) +K_F4 K(KT_FN,3) +K_F5 K(KT_FN,4) +K_F6 K(KT_FN,5) +K_F7 K(KT_FN,6) +K_F8 K(KT_FN,7) +K_F9 K(KT_FN,8) +K_F10 K(KT_FN,9) +K_F11 K(KT_FN,10) +K_F12 K(KT_FN,11) +K_F13 K(KT_FN,12) +K_F14 K(KT_FN,13) +K_F15 K(KT_FN,14) +K_F16 K(KT_FN,15) +K_F17 K(KT_FN,16) +K_F18 K(KT_FN,17) +K_F19 K(KT_FN,18) +K_F20 K(KT_FN,19) +K_FIND K(KT_FN,20) +K_INSERT K(KT_FN,21) +K_REMOVE K(KT_FN,22) +K_SELECT K(KT_FN,23) +K_PGUP K(KT_FN,24) +K_PGDN K(KT_FN,25) +K_MACRO K(KT_FN,26) +K_HELP K(KT_FN,27) +K_DO K(KT_FN,28) +K_PAUSE K(KT_FN,29) +K_F21 K(KT_FN,30) +K_F22 K(KT_FN,31) +K_F23 K(KT_FN,32) +K_F24 K(KT_FN,33) +K_F25 K(KT_FN,34) +K_F26 K(KT_FN,35) +K_F27 K(KT_FN,36) +K_F28 K(KT_FN,37) +K_F29 K(KT_FN,38) +K_F30 K(KT_FN,39) +K_F31 K(KT_FN,40) +K_F32 K(KT_FN,41) +K_F33 K(KT_FN,42) +K_F34 K(KT_FN,43) +K_F35 K(KT_FN,44) +K_F36 K(KT_FN,45) +K_F37 K(KT_FN,46) +K_F38 K(KT_FN,47) +K_F39 K(KT_FN,48) +K_F40 K(KT_FN,49) +K_F41 K(KT_FN,50) +K_F42 K(KT_FN,51) +K_F43 K(KT_FN,52) +K_F44 K(KT_FN,53) +K_F45 K(KT_FN,54) +K_F46 K(KT_FN,55) +K_F47 K(KT_FN,56) +K_F48 K(KT_FN,57) +K_F49 K(KT_FN,58) +K_F50 K(KT_FN,59) +K_F51 K(KT_FN,60) +K_F52 K(KT_FN,61) +K_F53 K(KT_FN,62) +K_F54 K(KT_FN,63) +K_F55 K(KT_FN,64) +K_F56 K(KT_FN,65) +K_F57 K(KT_FN,66) +K_F58 K(KT_FN,67) +K_F59 K(KT_FN,68) +K_F60 K(KT_FN,69) +K_F61 K(KT_FN,70) +K_F62 K(KT_FN,71) +K_F63 K(KT_FN,72) +K_F64 K(KT_FN,73) +K_F65 K(KT_FN,74) +K_F66 K(KT_FN,75) +K_F67 K(KT_FN,76) +K_F68 K(KT_FN,77) +K_F69 K(KT_FN,78) +K_F70 K(KT_FN,79) +K_F71 K(KT_FN,80) +K_F72 K(KT_FN,81) +K_F73 K(KT_FN,82) +K_F74 K(KT_FN,83) +K_F75 K(KT_FN,84) +K_F76 K(KT_FN,85) +K_F77 K(KT_FN,86) +K_F78 K(KT_FN,87) +K_F79 K(KT_FN,88) +K_F80 K(KT_FN,89) +K_F81 K(KT_FN,90) +K_F82 K(KT_FN,91) +K_F83 K(KT_FN,92) +K_F84 K(KT_FN,93) +K_F85 K(KT_FN,94) +K_F86 K(KT_FN,95) +K_F87 K(KT_FN,96) +K_F88 K(KT_FN,97) +K_F89 K(KT_FN,98) +K_F90 K(KT_FN,99) +K_F91 K(KT_FN,100) +K_F92 K(KT_FN,101) +K_F93 K(KT_FN,102) +K_F94 K(KT_FN,103) +K_F95 K(KT_FN,104) +K_F96 K(KT_FN,105) +K_F97 K(KT_FN,106) +K_F98 K(KT_FN,107) +K_F99 K(KT_FN,108) +K_F100 K(KT_FN,109) +K_F101 K(KT_FN,110) +K_F102 K(KT_FN,111) +K_F103 K(KT_FN,112) +K_F104 K(KT_FN,113) +K_F105 K(KT_FN,114) +K_F106 K(KT_FN,115) +K_F107 K(KT_FN,116) +K_F108 K(KT_FN,117) +K_F109 K(KT_FN,118) +K_F110 K(KT_FN,119) +K_F111 K(KT_FN,120) +K_F112 K(KT_FN,121) +K_F113 K(KT_FN,122) +K_F114 K(KT_FN,123) +K_F115 K(KT_FN,124) +K_F116 K(KT_FN,125) +K_F117 K(KT_FN,126) +K_F118 K(KT_FN,127) +K_F119 K(KT_FN,128) +K_F120 K(KT_FN,129) +K_F121 K(KT_FN,130) +K_F122 K(KT_FN,131) +K_F123 K(KT_FN,132) +K_F124 K(KT_FN,133) +K_F125 K(KT_FN,134) +K_F126 K(KT_FN,135) +K_F127 K(KT_FN,136) +K_F128 K(KT_FN,137) +K_F129 K(KT_FN,138) +K_F130 K(KT_FN,139) +K_F131 K(KT_FN,140) +K_F132 K(KT_FN,141) +K_F133 K(KT_FN,142) +K_F134 K(KT_FN,143) +K_F135 K(KT_FN,144) +K_F136 K(KT_FN,145) +K_F137 K(KT_FN,146) +K_F138 K(KT_FN,147) +K_F139 K(KT_FN,148) +K_F140 K(KT_FN,149) +K_F141 K(KT_FN,150) +K_F142 K(KT_FN,151) +K_F143 K(KT_FN,152) +K_F144 K(KT_FN,153) +K_F145 K(KT_FN,154) +K_F146 K(KT_FN,155) +K_F147 K(KT_FN,156) +K_F148 K(KT_FN,157) +K_F149 K(KT_FN,158) +K_F150 K(KT_FN,159) +K_F151 K(KT_FN,160) +K_F152 K(KT_FN,161) +K_F153 K(KT_FN,162) +K_F154 K(KT_FN,163) +K_F155 K(KT_FN,164) +K_F156 K(KT_FN,165) +K_F157 K(KT_FN,166) +K_F158 K(KT_FN,167) +K_F159 K(KT_FN,168) +K_F160 K(KT_FN,169) +K_F161 K(KT_FN,170) +K_F162 K(KT_FN,171) +K_F163 K(KT_FN,172) +K_F164 K(KT_FN,173) +K_F165 K(KT_FN,174) +K_F166 K(KT_FN,175) +K_F167 K(KT_FN,176) +K_F168 K(KT_FN,177) +K_F169 K(KT_FN,178) +K_F170 K(KT_FN,179) +K_F171 K(KT_FN,180) +K_F172 K(KT_FN,181) +K_F173 K(KT_FN,182) +K_F174 K(KT_FN,183) +K_F175 K(KT_FN,184) +K_F176 K(KT_FN,185) +K_F177 K(KT_FN,186) +K_F178 K(KT_FN,187) +K_F179 K(KT_FN,188) +K_F180 K(KT_FN,189) +K_F181 K(KT_FN,190) +K_F182 K(KT_FN,191) +K_F183 K(KT_FN,192) +K_F184 K(KT_FN,193) +K_F185 K(KT_FN,194) +K_F186 K(KT_FN,195) +K_F187 K(KT_FN,196) +K_F188 K(KT_FN,197) +K_F189 K(KT_FN,198) +K_F190 K(KT_FN,199) +K_F191 K(KT_FN,200) +K_F192 K(KT_FN,201) +K_F193 K(KT_FN,202) +K_F194 K(KT_FN,203) +K_F195 K(KT_FN,204) +K_F196 K(KT_FN,205) +K_F197 K(KT_FN,206) +K_F198 K(KT_FN,207) +K_F199 K(KT_FN,208) +K_F200 K(KT_FN,209) +K_F201 K(KT_FN,210) +K_F202 K(KT_FN,211) +K_F203 K(KT_FN,212) +K_F204 K(KT_FN,213) +K_F205 K(KT_FN,214) +K_F206 K(KT_FN,215) +K_F207 K(KT_FN,216) +K_F208 K(KT_FN,217) +K_F209 K(KT_FN,218) +K_F210 K(KT_FN,219) +K_F211 K(KT_FN,220) +K_F212 K(KT_FN,221) +K_F213 K(KT_FN,222) +K_F214 K(KT_FN,223) +K_F215 K(KT_FN,224) +K_F216 K(KT_FN,225) +K_F217 K(KT_FN,226) +K_F218 K(KT_FN,227) +K_F219 K(KT_FN,228) +K_F220 K(KT_FN,229) +K_F221 K(KT_FN,230) +K_F222 K(KT_FN,231) +K_F223 K(KT_FN,232) +K_F224 K(KT_FN,233) +K_F225 K(KT_FN,234) +K_F226 K(KT_FN,235) +K_F227 K(KT_FN,236) +K_F228 K(KT_FN,237) +K_F229 K(KT_FN,238) +K_F230 K(KT_FN,239) +K_F231 K(KT_FN,240) +K_F232 K(KT_FN,241) +K_F233 K(KT_FN,242) +K_F234 K(KT_FN,243) +K_F235 K(KT_FN,244) +K_F236 K(KT_FN,245) +K_F237 K(KT_FN,246) +K_F238 K(KT_FN,247) +K_F239 K(KT_FN,248) +K_F240 K(KT_FN,249) +K_F241 K(KT_FN,250) +K_F242 K(KT_FN,251) +K_F243 K(KT_FN,252) +K_F244 K(KT_FN,253) +K_F245 K(KT_FN,254) +K_UNDO K(KT_FN,255) diff --git a/src/xlat/kd_key_lock_keys.in b/src/xlat/kd_key_lock_keys.in new file mode 100644 index 000000000..b2ec999fc --- /dev/null +++ b/src/xlat/kd_key_lock_keys.in @@ -0,0 +1,10 @@ +#sorted +K_SHIFTLOCK K(KT_LOCK,KG_SHIFT) +K_ALTGRLOCK K(KT_LOCK,KG_ALTGR) +K_CTRLLOCK K(KT_LOCK,KG_CTRL) +K_ALTLOCK K(KT_LOCK,KG_ALT) +K_SHIFTLLOCK K(KT_LOCK,KG_SHIFTL) +K_SHIFTRLOCK K(KT_LOCK,KG_SHIFTR) +K_CTRLLLOCK K(KT_LOCK,KG_CTRLL) +K_CTRLRLOCK K(KT_LOCK,KG_CTRLR) +K_CAPSSHIFTLOCK K(KT_LOCK,KG_CAPSSHIFT) diff --git a/src/xlat/kd_key_pad_keys.in b/src/xlat/kd_key_pad_keys.in new file mode 100644 index 000000000..a988997a0 --- /dev/null +++ b/src/xlat/kd_key_pad_keys.in @@ -0,0 +1,21 @@ +#sorted +K_P0 K(KT_PAD,0) +K_P1 K(KT_PAD,1) +K_P2 K(KT_PAD,2) +K_P3 K(KT_PAD,3) +K_P4 K(KT_PAD,4) +K_P5 K(KT_PAD,5) +K_P6 K(KT_PAD,6) +K_P7 K(KT_PAD,7) +K_P8 K(KT_PAD,8) +K_P9 K(KT_PAD,9) +K_PPLUS K(KT_PAD,10) +K_PMINUS K(KT_PAD,11) +K_PSTAR K(KT_PAD,12) +K_PSLASH K(KT_PAD,13) +K_PENTER K(KT_PAD,14) +K_PCOMMA K(KT_PAD,15) +K_PDOT K(KT_PAD,16) +K_PPLUSMINUS K(KT_PAD,17) +K_PPARENL K(KT_PAD,18) +K_PPARENR K(KT_PAD,19) diff --git a/src/xlat/kd_key_shift_keys.in b/src/xlat/kd_key_shift_keys.in new file mode 100644 index 000000000..219907444 --- /dev/null +++ b/src/xlat/kd_key_shift_keys.in @@ -0,0 +1,10 @@ +#sorted +K_SHIFT K(KT_SHIFT,KG_SHIFT) +K_ALTGR K(KT_SHIFT,KG_ALTGR) +K_CTRL K(KT_SHIFT,KG_CTRL) +K_ALT K(KT_SHIFT,KG_ALT) +K_SHIFTL K(KT_SHIFT,KG_SHIFTL) +K_SHIFTR K(KT_SHIFT,KG_SHIFTR) +K_CTRLL K(KT_SHIFT,KG_CTRLL) +K_CTRLR K(KT_SHIFT,KG_CTRLR) +K_CAPSSHIFT K(KT_SHIFT,KG_CAPSSHIFT) diff --git a/src/xlat/kd_key_slock_keys.in b/src/xlat/kd_key_slock_keys.in new file mode 100644 index 000000000..605f36299 --- /dev/null +++ b/src/xlat/kd_key_slock_keys.in @@ -0,0 +1,10 @@ +#sorted +K_SHIFT_SLOCK K(KT_SLOCK,KG_SHIFT) +K_ALTGR_SLOCK K(KT_SLOCK,KG_ALTGR) +K_CTRL_SLOCK K(KT_SLOCK,KG_CTRL) +K_ALT_SLOCK K(KT_SLOCK,KG_ALT) +K_SHIFTL_SLOCK K(KT_SLOCK,KG_SHIFTL) +K_SHIFTR_SLOCK K(KT_SLOCK,KG_SHIFTR) +K_CTRLL_SLOCK K(KT_SLOCK,KG_CTRLL) +K_CTRLR_SLOCK K(KT_SLOCK,KG_CTRLR) +K_CAPSSHIFT_SLOCK K(KT_SLOCK,KG_CAPSSHIFT) diff --git a/src/xlat/kd_key_spec_keys.in b/src/xlat/kd_key_spec_keys.in new file mode 100644 index 000000000..d3a17de47 --- /dev/null +++ b/src/xlat/kd_key_spec_keys.in @@ -0,0 +1,23 @@ +#sorted +K_HOLE K(KT_SPEC,0) +K_ENTER K(KT_SPEC,1) +K_SH_REGS K(KT_SPEC,2) +K_SH_MEM K(KT_SPEC,3) +K_SH_STAT K(KT_SPEC,4) +K_BREAK K(KT_SPEC,5) +K_CONS K(KT_SPEC,6) +K_CAPS K(KT_SPEC,7) +K_NUM K(KT_SPEC,8) +K_HOLD K(KT_SPEC,9) +K_SCROLLFORW K(KT_SPEC,10) +K_SCROLLBACK K(KT_SPEC,11) +K_BOOT K(KT_SPEC,12) +K_CAPSON K(KT_SPEC,13) +K_COMPOSE K(KT_SPEC,14) +K_SAK K(KT_SPEC,15) +K_DECRCONSOLE K(KT_SPEC,16) +K_INCRCONSOLE K(KT_SPEC,17) +K_SPAWNCONSOLE K(KT_SPEC,18) +K_BARENUMLOCK K(KT_SPEC,19) +K_ALLOCATED K(KT_SPEC,126) +K_NOSUCHMAP K(KT_SPEC,127) diff --git a/src/xlat/kd_key_tables.in b/src/xlat/kd_key_tables.in new file mode 100644 index 000000000..ac22dd7e5 --- /dev/null +++ b/src/xlat/kd_key_tables.in @@ -0,0 +1,5 @@ +#value_indexed +K_NORMTAB 0 +K_SHIFTTAB 1 +K_ALTTAB 2 +K_ALTSHIFTTAB 3 diff --git a/src/xlat/kd_key_types.in b/src/xlat/kd_key_types.in new file mode 100644 index 000000000..feac2c50f --- /dev/null +++ b/src/xlat/kd_key_types.in @@ -0,0 +1,16 @@ +#value_indexed +KT_LATIN 0 +KT_FN 1 +KT_SPEC 2 +KT_PAD 3 +KT_DEAD 4 +KT_CONS 5 +KT_CUR 6 +KT_SHIFT 7 +KT_META 8 +KT_ASCII 9 +KT_LOCK 10 +KT_LETTER 11 +KT_SLOCK 12 +KT_DEAD2 13 +KT_BRL 14 diff --git a/src/xlat/kd_keymap_flags.in b/src/xlat/kd_keymap_flags.in new file mode 100644 index 000000000..5e5ad336f --- /dev/null +++ b/src/xlat/kd_keymap_flags.in @@ -0,0 +1,8 @@ +1<<KG_SHIFT 1<<0 +1<<KG_ALTGR 1<<1 +1<<KG_CTRL 1<<2 +1<<KG_ALT 1<<3 +1<<KG_SHIFTL 1<<4 +1<<KG_SHIFTR 1<<5 +1<<KG_CTRLL 1<<6 +1<<KG_CTRLR 1<<7 diff --git a/src/xlat/kd_led_flags.in b/src/xlat/kd_led_flags.in new file mode 100644 index 000000000..afefb621a --- /dev/null +++ b/src/xlat/kd_led_flags.in @@ -0,0 +1,3 @@ +LED_SCR 0x1 +LED_NUM 0x2 +LED_CAP 0x4 diff --git a/src/xlat/kd_meta_vals.in b/src/xlat/kd_meta_vals.in new file mode 100644 index 000000000..b0b43b167 --- /dev/null +++ b/src/xlat/kd_meta_vals.in @@ -0,0 +1,2 @@ +K_METABIT 0x3 +K_ESCPREFIX 0x4 diff --git a/src/xlat/kd_modes.in b/src/xlat/kd_modes.in new file mode 100644 index 000000000..99ffdb867 --- /dev/null +++ b/src/xlat/kd_modes.in @@ -0,0 +1,5 @@ +#value_indexed +KD_TEXT 0x0 +KD_GRAPHICS 0x1 +KD_TEXT0 0x2 +KD_TEXT1 0x3 diff --git a/tests/.gitignore b/tests/.gitignore index d76512dc8..7d32596fa 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -302,6 +302,18 @@ ioctl_hdio-v-Xabbrev ioctl_hdio-v-Xraw ioctl_hdio-v-Xverbose ioctl_inotify +ioctl_kd +ioctl_kd-Xabbrev +ioctl_kd-Xraw +ioctl_kd-Xverbose +ioctl_kd-success +ioctl_kd-success-Xabbrev +ioctl_kd-success-Xraw +ioctl_kd-success-Xverbose +ioctl_kd-success-s1024 +ioctl_kd-success-s1024-Xabbrev +ioctl_kd-success-s1024-Xraw +ioctl_kd-success-s1024-Xverbose ioctl_kvm_run ioctl_kvm_run-v ioctl_kvm_run_auxstr_vcpu diff --git a/tests/Makefile.am b/tests/Makefile.am index fe33e180a..cd71b4638 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -192,6 +192,14 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ ioctl_hdio-success-v-Xabbrev \ ioctl_hdio-success-v-Xraw \ ioctl_hdio-success-v-Xverbose \ + ioctl_kd-success \ + ioctl_kd-success-Xabbrev \ + ioctl_kd-success-Xraw \ + ioctl_kd-success-Xverbose \ + ioctl_kd-success-s1024 \ + ioctl_kd-success-s1024-Xabbrev \ + ioctl_kd-success-s1024-Xraw \ + ioctl_kd-success-s1024-Xverbose \ ioctl_loop-nv \ ioctl_loop-v \ ioctl_mtd-success \ diff --git a/tests/gen_tests.in b/tests/gen_tests.in index 30a520e68..a88af6970 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -296,6 +296,18 @@ ioctl_hdio-v-Xabbrev +ioctl.test -a27 -v -Xabbrev ioctl_hdio-v-Xraw +ioctl.test -a20 -v -Xraw ioctl_hdio-v-Xverbose +ioctl.test -a39 -v -Xverbose ioctl_inotify +ioctl.test +ioctl_kd +ioctl.test -a20 +ioctl_kd-Xabbrev +ioctl.test -a20 -Xabbrev +ioctl_kd-Xraw +ioctl.test -a18 -Xraw +ioctl_kd-Xverbose +ioctl.test -a20 -Xverbose +ioctl_kd-success +ioctl-success.sh -a20 +ioctl_kd-success-Xabbrev +ioctl-success.sh -a20 -Xabbrev +ioctl_kd-success-Xraw +ioctl-success.sh -a18 -Xraw +ioctl_kd-success-Xverbose +ioctl-success.sh -a20 -Xverbose +ioctl_kd-success-s1024 +ioctl-success.sh -a20 -s1024 +ioctl_kd-success-s1024-Xabbrev +ioctl-success.sh -a20 -s1024 -Xabbrev +ioctl_kd-success-s1024-Xraw +ioctl-success.sh -a18 -s1024 -Xraw +ioctl_kd-success-s1024-Xverbose +ioctl-success.sh -a20 -s1024 -Xverbose ioctl_kvm_run +ioctl.test -a36 -y ioctl_kvm_run-v +ioctl.test -v -a36 -y ioctl_kvm_run_auxstr_vcpu +ioctl.test -a36 -y -e kvm=vcpu diff --git a/tests/ioctl_kd-Xabbrev.c b/tests/ioctl_kd-Xabbrev.c new file mode 100644 index 000000000..cab5d2820 --- /dev/null +++ b/tests/ioctl_kd-Xabbrev.c @@ -0,0 +1 @@ +#include "ioctl_kd.c" diff --git a/tests/ioctl_kd-Xraw.c b/tests/ioctl_kd-Xraw.c new file mode 100644 index 000000000..d97346cf4 --- /dev/null +++ b/tests/ioctl_kd-Xraw.c @@ -0,0 +1,2 @@ +#define XLAT_RAW 1 +#include "ioctl_kd.c" diff --git a/tests/ioctl_kd-Xverbose.c b/tests/ioctl_kd-Xverbose.c new file mode 100644 index 000000000..db171cc7e --- /dev/null +++ b/tests/ioctl_kd-Xverbose.c @@ -0,0 +1,2 @@ +#define XLAT_VERBOSE 1 +#include "ioctl_kd.c" diff --git a/tests/ioctl_kd-success-Xabbrev.c b/tests/ioctl_kd-success-Xabbrev.c new file mode 100644 index 000000000..a1fe5d90b --- /dev/null +++ b/tests/ioctl_kd-success-Xabbrev.c @@ -0,0 +1 @@ +#include "ioctl_kd-success.c" diff --git a/tests/ioctl_kd-success-Xraw.c b/tests/ioctl_kd-success-Xraw.c new file mode 100644 index 000000000..de7f49365 --- /dev/null +++ b/tests/ioctl_kd-success-Xraw.c @@ -0,0 +1,2 @@ +#define XLAT_RAW 1 +#include "ioctl_kd-success.c" diff --git a/tests/ioctl_kd-success-Xverbose.c b/tests/ioctl_kd-success-Xverbose.c new file mode 100644 index 000000000..e22aeecca --- /dev/null +++ b/tests/ioctl_kd-success-Xverbose.c @@ -0,0 +1,2 @@ +#define XLAT_VERBOSE 1 +#include "ioctl_kd-success.c" diff --git a/tests/ioctl_kd-success-s1024-Xabbrev.c b/tests/ioctl_kd-success-s1024-Xabbrev.c new file mode 100644 index 000000000..a0c9c5cb0 --- /dev/null +++ b/tests/ioctl_kd-success-s1024-Xabbrev.c @@ -0,0 +1,2 @@ +#define DEFAULT_STRLEN 1024 +#include "ioctl_kd-success-Xabbrev.c" diff --git a/tests/ioctl_kd-success-s1024-Xraw.c b/tests/ioctl_kd-success-s1024-Xraw.c new file mode 100644 index 000000000..e86c67713 --- /dev/null +++ b/tests/ioctl_kd-success-s1024-Xraw.c @@ -0,0 +1,2 @@ +#define DEFAULT_STRLEN 1024 +#include "ioctl_kd-success-Xraw.c" diff --git a/tests/ioctl_kd-success-s1024-Xverbose.c b/tests/ioctl_kd-success-s1024-Xverbose.c new file mode 100644 index 000000000..4c4e3051a --- /dev/null +++ b/tests/ioctl_kd-success-s1024-Xverbose.c @@ -0,0 +1,2 @@ +#define DEFAULT_STRLEN 1024 +#include "ioctl_kd-success-Xverbose.c" diff --git a/tests/ioctl_kd-success-s1024.c b/tests/ioctl_kd-success-s1024.c new file mode 100644 index 000000000..b952eebcf --- /dev/null +++ b/tests/ioctl_kd-success-s1024.c @@ -0,0 +1,2 @@ +#define DEFAULT_STRLEN 1024 +#include "ioctl_kd-success.c" diff --git a/tests/ioctl_kd-success.c b/tests/ioctl_kd-success.c new file mode 100644 index 000000000..21dea646b --- /dev/null +++ b/tests/ioctl_kd-success.c @@ -0,0 +1,2 @@ +#define RETVAL_INJECTED 1 +#include "ioctl_kd.c" diff --git a/tests/ioctl_kd.c b/tests/ioctl_kd.c new file mode 100644 index 000000000..eb4e50a52 --- /dev/null +++ b/tests/ioctl_kd.c @@ -0,0 +1,1733 @@ +/* + * This file is part of ioctl_kd strace test. + * + * Copyright (c) 2019-2021 Eugene Syromyatnikov <evgsyr@gmail.com> + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" + +#include <errno.h> +#include <inttypes.h> +#include <limits.h> +#include <signal.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "scno.h" + +#include <linux/ioctl.h> +#include <linux/kd.h> +#include <linux/keyboard.h> + +#ifndef RETVAL_INJECTED +# define RETVAL_INJECTED 0 +#endif + +#if RETVAL_INJECTED +# define RETVAL "42 (INJECTED)\n" +#else +# define RETVAL "-1 EBADF (%m)\n" +#endif + +#define ARG_XLAT_KNOWN(val_, str_) val_, XLAT_KNOWN(val_, str_) +#define ARG_XLAT_UNKNOWN(val_, str_) val_, XLAT_UNKNOWN(val_, str_) + +struct arg_val { + kernel_ulong_t val; + const char *str; +}; + +static long +sys_ioctl(kernel_long_t fd, kernel_ulong_t cmd, kernel_ulong_t arg) +{ + return syscall(__NR_ioctl, fd, cmd, arg); +} + +static void +check_null_invalid(unsigned int c, const char *s) +{ + static char *p; + + if (!p) + p = tail_alloc(1); + + sys_ioctl(-1, c, 0); + printf("ioctl(-1, " XLAT_FMT ", NULL) = " RETVAL, XLAT_SEL(c, s)); + + if (F8ILL_KULONG_SUPPORTED) { + sys_ioctl(-1, c, F8ILL_KULONG_MASK); + printf("ioctl(-1, " XLAT_FMT ", NULL) = " RETVAL, + XLAT_SEL(c, s)); + } + + sys_ioctl(-1, c, (uintptr_t) p + 1); + printf("ioctl(-1, " XLAT_FMT ", %p) = " RETVAL, XLAT_SEL(c, s), p + 1); +} + +/* GIO_SCRNMAP, PIO_SCRNMAP */ +static void +check_scrnmap(unsigned int c, const char *s) +{ + char *scrnmap = tail_alloc(E_TABSZ); + + int saved_errno; + long rc; + + fill_memory_ex(scrnmap, E_TABSZ, 0, 0xff); + + check_null_invalid(c, s); + + sys_ioctl(-1, c, (uintptr_t) scrnmap + E_TABSZ - 31); + printf("ioctl(-1, " XLAT_FMT ", %p) = " RETVAL, + XLAT_SEL(c, s), scrnmap + E_TABSZ - 31); + + sys_ioctl(-1, c, (uintptr_t) scrnmap + E_TABSZ - 32); + printf("ioctl(-1, " XLAT_FMT ", %p) = " RETVAL, + XLAT_SEL(c, s), scrnmap + E_TABSZ - 32); + + rc = sys_ioctl(-1, c, (uintptr_t) scrnmap + E_TABSZ - 33); + saved_errno = errno; + printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(c, s)); + if ((rc >= 0 || c == PIO_SCRNMAP) && (DEFAULT_STRLEN <= 32)) { + print_quoted_hex(scrnmap + E_TABSZ - 33, 32); + printf("..."); + } else { + printf("%p", scrnmap + E_TABSZ - 33); + } + errno = saved_errno; + printf(") = " RETVAL); + + rc = sys_ioctl(-1, c, (uintptr_t) scrnmap); + saved_errno = errno; + printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(c, s)); + if (rc >= 0 || c == PIO_SCRNMAP) { + print_quoted_hex(scrnmap, MIN(E_TABSZ, DEFAULT_STRLEN)); + if (DEFAULT_STRLEN < E_TABSZ) + printf("..."); + } else { + printf("%p", scrnmap); + } + errno = saved_errno; + printf(") = " RETVAL); +} + +/* KDGKBENT, KDSKBENT */ +static void +check_kbdent(unsigned int c, const char *s) +{ + static const struct arg_val kbtbl_vecs[] = { + { ARG_XLAT_KNOWN(0, "K_NORMTAB") }, + { ARG_XLAT_KNOWN(0x1, "K_SHIFTTAB") }, + { ARG_XLAT_KNOWN(0x3, "K_ALTSHIFTTAB") }, + { ARG_XLAT_KNOWN(0x4, "1<<KG_CTRL") }, + { ARG_XLAT_KNOWN(0xff, + "1<<KG_SHIFT|1<<KG_ALTGR|1<<KG_CTRL" + "|1<<KG_ALT|1<<KG_SHIFTL|1<<KG_SHIFTR" + "|1<<KG_CTRLL|1<<KG_CTRLR") }, + }; + + static const struct arg_val kbval_vecs[] = { + { ARG_STR(0) NRAW(" /* K(KT_LATIN, '\\x00') */") }, + { ARG_STR(0x10) NRAW(" /* K(KT_LATIN, '\\x10') */") }, + { ARG_STR(0x20) NRAW(" /* K(KT_LATIN, ' ') */") }, + { ARG_STR(0x7e) NRAW(" /* K(KT_LATIN, '~') */") }, + { ARG_STR(0x7f) NRAW(" /* K(KT_LATIN, '\\x7f') */") }, + + { ARG_STR(0x100) NRAW(" /* K_F1 */") }, + { ARG_STR(0x11d) NRAW(" /* K_PAUSE */") }, + { ARG_STR(0x1ff) NRAW(" /* K_UNDO */") }, + + { ARG_STR(0x200) NRAW(" /* K_HOLE */") }, + { ARG_STR(0x213) NRAW(" /* K_BARENUMLOCK */") }, + { ARG_STR(0x214) NRAW(" /* K(KT_SPEC, 0x14) */") }, + { ARG_STR(0x27d) NRAW(" /* K(KT_SPEC, 0x7d) */") }, + { ARG_STR(0x27e) NRAW(" /* K_ALLOCATED */") }, + { ARG_STR(0x27f) NRAW(" /* K_NOSUCHMAP */") }, + { ARG_STR(0x280) NRAW(" /* K(KT_SPEC, 0x80) */") }, + { ARG_STR(0x2ff) NRAW(" /* K(KT_SPEC, 0xff) */") }, + + { ARG_STR(0x300) NRAW(" /* K_P0 */") }, + { ARG_STR(0x313) NRAW(" /* K_PPARENR */") }, + { ARG_STR(0x314) NRAW(" /* K(KT_PAD, 0x14) */") }, + { ARG_STR(0x37f) NRAW(" /* K(KT_PAD, 0x7f) */") }, + { ARG_STR(0x3ff) NRAW(" /* K(KT_PAD, 0xff) */") }, + + { ARG_STR(0x400) NRAW(" /* K_DGRAVE */") }, + { ARG_STR(0x41a) NRAW(" /* K_DGREEK */") }, + { ARG_STR(0x41b) NRAW(" /* K(KT_DEAD, 0x1b) */") }, + { ARG_STR(0x47f) NRAW(" /* K(KT_DEAD, 0x7f) */") }, + { ARG_STR(0x4ff) NRAW(" /* K(KT_DEAD, 0xff) */") }, + + { ARG_STR(0x500) NRAW(" /* K(KT_CONS, 0) */") }, + { ARG_STR(0x540) NRAW(" /* K(KT_CONS, 0x40) */") }, + { ARG_STR(0x5ff) NRAW(" /* K(KT_CONS, 0xff) */") }, + + { ARG_STR(0x600) NRAW(" /* K_DOWN */") }, + { ARG_STR(0x603) NRAW(" /* K_UP */") }, + { ARG_STR(0x604) NRAW(" /* K(KT_CUR, 0x4) */") }, + { ARG_STR(0x680) NRAW(" /* K(KT_CUR, 0x80) */") }, + { ARG_STR(0x6ff) NRAW(" /* K(KT_CUR, 0xff) */") }, + + { ARG_STR(0x700) NRAW(" /* K_SHIFT */") }, + { ARG_STR(0x708) NRAW(" /* K_CAPSSHIFT */") }, + { ARG_STR(0x709) NRAW(" /* K(KT_SHIFT, 0x9) */") }, + { ARG_STR(0x7ff) NRAW(" /* K(KT_SHIFT, 0xff) */") }, + + { ARG_STR(0x800) NRAW(" /* K(KT_META, '\\x00') */") }, + { ARG_STR(0x841) NRAW(" /* K(KT_META, 'A') */") }, + { ARG_STR(0x8ff) NRAW(" /* K(KT_META, '\\xff') */") }, + + { ARG_STR(0x900) NRAW(" /* K_ASC0 */") }, + { ARG_STR(0x909) NRAW(" /* K_ASC9 */") }, + { ARG_STR(0x90a) NRAW(" /* K_HEX0 */") }, + { ARG_STR(0x919) NRAW(" /* K_HEXf */") }, + { ARG_STR(0x91a) NRAW(" /* K(KT_ASCII, 0x1a) */") }, + { ARG_STR(0x9ff) NRAW(" /* K(KT_ASCII, 0xff) */") }, + + { ARG_STR(0xa00) NRAW(" /* K_SHIFTLOCK */") }, + { ARG_STR(0xa08) NRAW(" /* K_CAPSSHIFTLOCK */") }, + { ARG_STR(0xa09) NRAW(" /* K(KT_LOCK, 0x9) */") }, + { ARG_STR(0xaff) NRAW(" /* K(KT_LOCK, 0xff) */") }, + + { ARG_STR(0xb00) NRAW(" /* K(KT_LETTER, '\\x00') */") }, + { ARG_STR(0xb40) NRAW(" /* K(KT_LETTER, '@') */") }, + { ARG_STR(0xb7f) NRAW(" /* K(KT_LETTER, '\\x7f') */") }, + { ARG_STR(0xbff) NRAW(" /* K(KT_LETTER, '\\xff') */") }, + + { ARG_STR(0xc00) NRAW(" /* K_SHIFT_SLOCK */") }, + { ARG_STR(0xc08) NRAW(" /* K_CAPSSHIFT_SLOCK */") }, + { ARG_STR(0xc09) NRAW(" /* K(KT_SLOCK, 0x9) */") }, + { ARG_STR(0xcff) NRAW(" /* K(KT_SLOCK, 0xff) */") }, + + { ARG_STR(0xd00) NRAW(" /* K(KT_DEAD2, '\\x00') */") }, + { ARG_STR(0xd13) NRAW(" /* K(KT_DEAD2, '\\x13') */") }, + { ARG_STR(0xd5c) NRAW(" /* K(KT_DEAD2, '\\\\') */") }, + { ARG_STR(0xdff) NRAW(" /* K(KT_DEAD2, '\\xff') */") }, + + { ARG_STR(0xe00) NRAW(" /* K_BRL_BLANK */") }, + { ARG_STR(0xe0a) NRAW(" /* K_BRL_DOT10 */") }, + { ARG_STR(0xe0b) NRAW(" /* K(KT_BRL, 0xb) */") }, + { ARG_STR(0xeff) NRAW(" /* K(KT_BRL, 0xff) */") }, + + { ARG_STR(0xf00) NRAW(" /* K(0xf, 0) */") }, + { ARG_STR(0xfed) NRAW(" /* K(0xf, 0xed) */") }, + { ARG_STR(0xf00d) NRAW(" /* K(0xf0, 0xd) */") }, + }; + + struct kbentry *kbe = tail_alloc(sizeof(*kbe)); + + int saved_errno; + long rc; + + check_null_invalid(c, s); + + kbe->kb_value = 0xa8a8; + sys_ioctl(-1, c, (uintptr_t) kbe + 2); + printf("ioctl(-1, " XLAT_FMT ", {kb_table=%s, kb_index=168%s}" + ") = " RETVAL, + XLAT_SEL(c, s), XLAT_STR(1<<KG_ALT|1<<KG_SHIFTR|1<<KG_CTRLR), + RETVAL_INJECTED || c == KDSKBENT ? ", kb_value=???" : "" + ); + + for (size_t i = 0; + i < MAX(ARRAY_SIZE(kbtbl_vecs), ARRAY_SIZE(kbval_vecs)); i++) { + kbe->kb_table = kbtbl_vecs[i % ARRAY_SIZE(kbtbl_vecs)].val; + kbe->kb_index = i * 3141; + kbe->kb_value = kbval_vecs[i % ARRAY_SIZE(kbval_vecs)].val; + + rc = sys_ioctl(-1, c, (uintptr_t) kbe); + saved_errno = errno; + printf("ioctl(-1, " XLAT_FMT ", {kb_table=%s, kb_index=%u", + XLAT_SEL(c, s), + kbtbl_vecs[i % ARRAY_SIZE(kbtbl_vecs)].str, + kbe->kb_index); + if (rc >= 0 || c == KDSKBENT) { + printf(", kb_value=%s", + kbval_vecs[i % ARRAY_SIZE(kbval_vecs)].str); + } + errno = saved_errno; + printf("}) = " RETVAL); + } +} + +/* KDGKBSENT, KDSKBSENT */ +static void +check_kbdsent(unsigned int c, const char *s) +{ + static struct arg_val kbse_offsets[] = { + { sizeof(struct kbsentry) - 1, "KVAL(K_F2)" }, + { sizeof(struct kbsentry) - 2, "KVAL(K_F1)" }, + { sizeof(struct kbsentry) - 34, "KVAL(K_F214)" }, + { sizeof(struct kbsentry) - 35, "KVAL(K_F213)" }, + { 1, "KVAL(K_F1)" }, + { 0, "KVAL(K_F245)" }, + }; + + static const struct arg_val kbfn_vecs[] = { + { ARG_XLAT_KNOWN(0, "KVAL(K_F1)") }, + { ARG_XLAT_KNOWN(0x10, "KVAL(K_F17)") }, + { ARG_XLAT_KNOWN(0x7f, "KVAL(K_F118)") }, + { ARG_XLAT_KNOWN(0xff, "KVAL(K_UNDO)") }, + }; + + struct kbsentry *kbse = tail_alloc(sizeof(*kbse)); + + int saved_errno; + + fill_memory_ex(kbse->kb_string, sizeof(kbse->kb_string), 0, 0xff); + kbse->kb_func = 0xfe; + + check_null_invalid(c, s); + + for (size_t i = 0; i < ARRAY_SIZE(kbse_offsets); i++) { + sys_ioctl(-1, c, + (uintptr_t) kbse + kbse_offsets[i].val); + saved_errno = errno; + printf("ioctl(-1, " XLAT_FMT ", {kb_func=%s", + XLAT_SEL(c, s), + sprintxlat(kbse_offsets[i].str, + (kbse_offsets[i].val + 254) % 0xff, NULL)); + + if (RETVAL_INJECTED || c == KDSKBSENT) { + printf(", kb_string="); + if (kbse_offsets[i].val < 255 * 2) { + print_quoted_stringn( + (char *) kbse->kb_string + + kbse_offsets[i].val, + MIN(DEFAULT_STRLEN, + sizeof(kbse->kb_string))); + } else { + printf("???"); + } + } + + errno = saved_errno; + printf("}) = " RETVAL); + } + + fill_memory_ex(kbse->kb_string, sizeof(kbse->kb_string), 0x80, 0x7f); + kbse->kb_func = KVAL(K_PGDN); + + sys_ioctl(-1, c, (uintptr_t) kbse); + saved_errno = errno; + printf("ioctl(-1, " XLAT_FMT ", {kb_func=" + XLAT_KNOWN(0x19, "KVAL(K_PGDN)"), + XLAT_SEL(c, s)); + + if (RETVAL_INJECTED || c == KDSKBSENT) { + printf(", kb_string="); + print_quoted_stringn((char *) kbse->kb_string, + MIN(DEFAULT_STRLEN, + sizeof(kbse->kb_string))); + } + + errno = saved_errno; + printf("}) = " RETVAL); + + for (size_t i = 0; i < ARRAY_SIZE(kbfn_vecs); i++) { + kbse->kb_func = kbfn_vecs[i].val; + fill_memory_ex(kbse->kb_string, sizeof(kbse->kb_string), + i * 357 + 42, i * 257 + 13); + + sys_ioctl(-1, c, (uintptr_t) kbse); + saved_errno = errno; + printf("ioctl(-1, " XLAT_FMT ", {kb_func=%s", + XLAT_SEL(c, s), + kbfn_vecs[i].str); + + if (RETVAL_INJECTED || c == KDSKBSENT) { + printf(", kb_string="); + print_quoted_stringn((char *) kbse->kb_string, + MIN(DEFAULT_STRLEN, + sizeof(kbse->kb_string))); + } + + errno = saved_errno; + printf("}) = " RETVAL); + } +} + +/* KDGKBDIACR, KDSKBDIACR */ +static void +check_diacr(unsigned int c, const char *s) +{ + static struct arg_val diac_vecs[] = { + { 0, "\\x00" }, + { '\n', "\\n" }, + { ' ', " " }, + { 'a', "a" }, + { '~', "~" }, + { '\'', "\\'" }, + { '\\', "\\\\" }, + { '"', "\"" }, + { '`', "`" }, + { 0x7f, "\\x7f" }, + { 0xff, "\\xff" }, + }; + + struct kbdiacrs *diacrs0 = tail_alloc(sizeof(diacrs0->kb_cnt)); + struct kbdiacrs *diacrs1 = tail_alloc(sizeof(diacrs1->kb_cnt) + + 4 * sizeof(struct kbdiacr)); + struct kbdiacrs *diacrs2 = tail_alloc(sizeof(*diacrs2)); + + int saved_errno; + + check_null_invalid(c, s); + + for (size_t i = 0; i < 2; i++) { + diacrs0->kb_cnt = i; + sys_ioctl(-1, c, (uintptr_t) diacrs0); + saved_errno = errno; + printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(c, s)); + if (RETVAL_INJECTED || c == KDSKBDIACR) { + printf("{kb_cnt=%zu, kbdiacr=", i); + if (i) + printf("%p}", diacrs0->kbdiacr); + else + printf("[]}"); + } else { + printf("%p", diacrs0); + } + errno = saved_errno; + printf(") = " RETVAL); + } + + fill_memory_ex(diacrs1->kbdiacr, 4 * sizeof(struct kbdiacr), 40, 44); + for (size_t i = 0; i < 7; i++) { + diacrs1->kb_cnt = i; + sys_ioctl(-1, c, (uintptr_t) diacrs1); + saved_errno = errno; + printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(c, s)); + if (RETVAL_INJECTED || c == KDSKBDIACR) { + printf("{kb_cnt=%zu, kbdiacr=[", i); + for (size_t j = 0; j < MIN(i, 4); j++) + printf("%s{diacr='%c', base='%c', result='%c'}", + j ? ", " : "", (int) (40 + j * 3), + (int) (41 + j * 3), (int) (42 + j * 3)); + + if (i > 4) + printf(", ... /* %p */", diacrs1->kbdiacr + 4); + printf("]}"); + } else { + printf("%p", diacrs1); + } + errno = saved_errno; + printf(") = " RETVAL); + } + + fill_memory_ex(diacrs2->kbdiacr, sizeof(diacrs2->kbdiacr), 40, 52); + + for (size_t i = ARRAY_SIZE(diacrs2->kbdiacr) - 1; + i < ARRAY_SIZE(diacrs2->kbdiacr) + 3; i++) { + diacrs2->kb_cnt = i; + sys_ioctl(-1, c, (uintptr_t) diacrs2); + printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(c, s)); + saved_errno = errno; + if (RETVAL_INJECTED || c == KDSKBDIACR) { + printf("{kb_cnt=%zu, kbdiacr=[", i); + for (size_t j = 0; + j < MIN(i, MIN(DEFAULT_STRLEN, + ARRAY_SIZE(diacrs2->kbdiacr))); j++) + printf("%s{diacr='%c', base='%c', result='%c'}", + j ? ", " : "", + (int) (40 + (j * 3 + 0) % 52), + (int) (40 + (j * 3 + 1) % 52), + (int) (40 + (j * 3 + 2) % 52)); + + if (i > MIN(DEFAULT_STRLEN, + ARRAY_SIZE(diacrs2->kbdiacr))) + printf(", ..."); + printf("]}"); + } else { + printf("%p", diacrs2); + } + errno = saved_errno; + printf(") = " RETVAL); + } + + for (size_t i = 0; i< ARRAY_SIZE(diac_vecs); i++) { + diacrs2->kbdiacr[i].diacr = diac_vecs[i].val; + diacrs2->kbdiacr[i].base = diac_vecs[i].val; + diacrs2->kbdiacr[i].result = diac_vecs[i].val; + } + diacrs2->kb_cnt = ARRAY_SIZE(diac_vecs); + + sys_ioctl(-1, c, (uintptr_t) diacrs2); + printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(c, s)); + saved_errno = errno; + if (RETVAL_INJECTED || c == KDSKBDIACR) { + printf("{kb_cnt=%zu, kbdiacr=[", ARRAY_SIZE(diac_vecs)); + for (size_t i = 0; i < ARRAY_SIZE(diac_vecs); i++) + printf("%1$s{diacr='%2$s', base='%2$s', result='%2$s'}", + i ? ", " : "", diac_vecs[i].str); + printf("]}"); + } else { + printf("%p", diacrs2); + } + errno = saved_errno; + printf(") = " RETVAL); +} + +/* KDGETKEYCODE, KDSETKEYCODE */ +static void +check_xetkeycode(unsigned int c, const char *s) +{ + static const struct kbkeycode args[] = { + { 0, 0 }, + { 0, 0xdeadface }, + { 0xfacefeed, 0 }, + { 0xdecaffed, 0xdadfaced }, + }; + struct kbkeycode *tail_arg = tail_alloc(sizeof(args[0])); + + check_null_invalid(c, s); + + sys_ioctl(-1, c, (uintptr_t) tail_arg + 4); + printf("ioctl(-1, " XLAT_FMT ", %p) = " RETVAL, + XLAT_SEL(c, s), (char *) tail_arg + 4); + + for (size_t i = 0; i < ARRAY_SIZE(args); i++) { + memcpy(tail_arg, args + i, sizeof(args[i])); + + sys_ioctl(-1, c, (uintptr_t) tail_arg); + printf("ioctl(-1, " XLAT_FMT ", {scancode=%#x, keycode=%#x", + XLAT_SEL(c, s), args[i].scancode, args[i].keycode); + if ((c == KDGETKEYCODE) && RETVAL_INJECTED) + printf(" => %#x", args[i].keycode); + printf("}) = " RETVAL); + } +} + +/* KDKBDREP */ +static void +check_kbdrep(unsigned int c, const char *s) +{ + static const struct kbd_repeat args[] = { + { -1, -1 }, + { -1234567890, 0 }, + { 0, -2134567890 }, + { 314159265, 271828182 }, + }; + struct kbd_repeat *tail_arg = tail_alloc(sizeof(args[0])); + + check_null_invalid(c, s); + + sys_ioctl(-1, c, (uintptr_t) tail_arg + 4); + printf("ioctl(-1, " XLAT_FMT ", %p) = " RETVAL, + XLAT_SEL(c, s), (char *) tail_arg + 4); + + for (size_t i = 0; i < ARRAY_SIZE(args); i++) { + memcpy(tail_arg, args + i, sizeof(args[i])); + + sys_ioctl(-1, c, (uintptr_t) tail_arg); + printf("ioctl(-1, " XLAT_FMT, XLAT_SEL(c, s)); + for (size_t j = 0; j < 1 + RETVAL_INJECTED; j++) { + printf("%s {delay=%d, period=%d}", + j ? " =>" : ",", args[i].delay, args[i].period); + } + printf(") = " RETVAL); + } +} + +/* GIO_FONT, PIO_FONT */ +static void +check_font(unsigned int c, const char *s) +{ + char *data = tail_alloc(8192); + char *data_end = data + 8192; + + fill_memory(data, 8192); + + check_null_invalid(c, s); + + sys_ioctl(-1, c, (uintptr_t) data_end - 31); + printf("ioctl(-1, " XLAT_FMT ", %p) = " RETVAL, + XLAT_SEL(c, s), data_end - 31); + + sys_ioctl(-1, c, (uintptr_t) data_end - 32); + printf("ioctl(-1, " XLAT_FMT ", %p) = " RETVAL, + XLAT_SEL(c, s), data_end - 32); + + bool ok = (DEFAULT_STRLEN == 32) + && ((c != GIO_FONT) || RETVAL_INJECTED); + sys_ioctl(-1, c, (uintptr_t) data_end - 33); + printf("ioctl(-1, " XLAT_FMT ", %s", XLAT_SEL(c, s), ok ? "\"" : ""); + if (ok) { + for (size_t i = 8192 - 33; i < 8192 - 1; i++) + printf("\\x%hhx", (unsigned char) ( 0x80 + i % 0x80)); + } else { + printf("%p", data_end - 33); + } + printf("%s) = " RETVAL, ok ? "\"..." : ""); + + ok = (c != GIO_FONT) || RETVAL_INJECTED; + sys_ioctl(-1, c, (uintptr_t) data_end - 1025); + printf("ioctl(-1, " XLAT_FMT ", %s", XLAT_SEL(c, s), ok ? "\"" : ""); + if (ok) { + for (size_t i = 8192 - 1025; i < 8192 - 1025 + DEFAULT_STRLEN; + i++) + printf("\\x%hhx", (unsigned char) (0x80 + i % 0x80)); + } else { + printf("%p", data_end - 1025); + } + printf("%s) = " RETVAL, ok ? "\"..." : ""); + + sys_ioctl(-1, c, (uintptr_t) data); + printf("ioctl(-1, " XLAT_FMT ", %s", XLAT_SEL(c, s), ok ? "\"" : ""); + if (ok) { + for (size_t i = 0; i < DEFAULT_STRLEN; i++) + printf("\\x%hhx", (unsigned char) (0x80 + i % 0x80)); + } else { + printf("%p", data); + } + printf("%s) = " RETVAL, ok ? "\"..." : ""); +} + +/* GIO_UNIMAP, PIO_UNIMAP */ +static void +check_unimap(unsigned int c, const char *s) +{ + struct unimapdesc *umd = tail_alloc(sizeof(*umd)); + struct unipair *ups = tail_alloc(33 * sizeof(*ups)); + + fill_memory16(ups, 33 * sizeof(*ups)); + ups[0].unicode = 0; + ups[0].fontpos = 0; + + check_null_invalid(c, s); + + umd->entry_ct = 0xdead; + umd->entries = NULL; + sys_ioctl(-1, c, (uintptr_t) umd); + printf("ioctl(-1, " XLAT_FMT ", {entry_ct=57005%s, entries=NULL}) = " + RETVAL, XLAT_SEL(c, s), c == GIO_UNIMAP ? " => 57005" : ""); + + umd->entry_ct = 0; + umd->entries = ups + 33; + sys_ioctl(-1, c, (uintptr_t) umd); + printf("ioctl(-1, " XLAT_FMT ", {entry_ct=0%s, entries=", + XLAT_SEL(c, s), c == GIO_UNIMAP ? " => 0" : ""); + if (c == GIO_UNIMAP && !RETVAL_INJECTED) + printf("%p", ups + 33); + else + printf("[]"); + printf("}) = " RETVAL); + + umd->entry_ct = 1; + sys_ioctl(-1, c, (uintptr_t) umd); + printf("ioctl(-1, " XLAT_FMT ", {entry_ct=1%s, entries=%p}) = " RETVAL, + XLAT_SEL(c, s), c == GIO_UNIMAP ? " => 1" : "", ups + 33); + + for (unsigned int i = 0; i < 6; i++) { + umd->entry_ct = 31 + (i + 1) / 2; + umd->entries = ups + 2 - i / 2; + sys_ioctl(-1, c, (uintptr_t) umd); + printf("ioctl(-1, " XLAT_FMT ", {entry_ct=%u", + XLAT_SEL(c, s), 31 + (i + 1) / 2); + + if (c == GIO_UNIMAP) { + printf(" => %u", 31 + (i + 1) / 2); +#if !RETVAL_INJECTED + printf(", entries=%p}) = " RETVAL, ups + 2 - i / 2); + continue; +#endif + } + + printf(", entries=[%s", i > 3 ? "{unicode=0, fontpos=0}" : ""); + + for (unsigned int j = 0; j < 31 +#if DEFAULT_STRLEN > 32 + + MIN(i / 2, 1) +#else + + ((i / 2) == 1) +#endif + ; j++) { + printf("%s{unicode=%#x, fontpos=%#x}", + j == 0 && i < 4 ? "" : ", ", + 0x80c4 + 2 * (j - MIN(i / 2, 1)), + 0x80c5 + 2 * (j - MIN(i / 2, 1))); + } + if (i == 1 || i == 3 || ((DEFAULT_STRLEN > 32) && (i == 5))) + printf(", ... /* %p */", ups + 33); +#if DEFAULT_STRLEN == 32 + if (i > 3) + printf(", ..."); +#endif + printf("]}) = " RETVAL); + } +} + +/* GIO_UNISCRNMAP, PIO_UNISCRNMAP */ +static void +check_uniscrnmap(unsigned int c, const char *s) +{ + uint16_t *map = tail_alloc(256 * sizeof(*map)); + for (unsigned int i = 0; i < 256; i++) + map[i] = 0xeff1 + 32 * (i % 112) - i / 8; + + check_null_invalid(c, s); + + for (unsigned int i = 0; i < 3; i++) { + sys_ioctl(-1, c, (uintptr_t) (map + 224 - 112 * i)); + printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(c, s)); + + if (c == GIO_UNISCRNMAP && !RETVAL_INJECTED) { + printf("%p) = " RETVAL, map + 224 - 112 * i); + continue; + } + + for (size_t j = 0; + j < MIN(32 + 112 * i, DEFAULT_STRLEN); j++) { + uint16_t v = 0xefd5 + 32 * (j % 112) - j / 8 + i * 14; + if ((j % 112) < (2 - (i + 1 - j / 112) / 2) + || (j % 112) > (17 - (i + 1 - j / 112) / 2)) { + printf("%s%#hx", j ? ", " : "[", v); + } else { + printf(", " + XLAT_KNOWN_FMT("%#hx", + "UNI_DIRECT_BASE+%#hx"), + XLAT_SEL(v, (uint16_t) (v - 0xf000))); + } + } + + if (DEFAULT_STRLEN == 32 || i < 2) { + printf(", ..."); + if (DEFAULT_STRLEN >= 32 + 112 * i) + printf(" /* %p */", map + 256); + } + + printf("]) = " RETVAL); + } +} + +/* GIO_FONTX, PIO_FONTX */ +static void +check_fontx(unsigned int c, const char *s) +{ + static const short cnts[] = { 1, 32, 256 }; + struct consolefontdesc *cfd = tail_alloc(sizeof(*cfd)); + char *data = tail_alloc(2048); + char *data_end = data + 2048; + + fill_memory_ex(data, 2048, 0xf0, 255); + + check_null_invalid(c, s); + + cfd->charcount = 0; + cfd->charheight = 0xdead; + cfd->chardata = NULL; + sys_ioctl(-1, c, (uintptr_t) cfd); + printf("ioctl(-1, " XLAT_FMT + ", {charcount=0, charheight=57005, chardata=NULL}%s) = " RETVAL, + XLAT_SEL(c, s), RETVAL_INJECTED && (c == GIO_FONTX) + ? " => {charcount=0, charheight=57005, chardata=NULL}" : ""); + + cfd->chardata = data_end; + sys_ioctl(-1, c, (uintptr_t) cfd); + printf("ioctl(-1, " XLAT_FMT + ", {charcount=0, charheight=57005, chardata=%p}", + XLAT_SEL(c, s), data_end); +#if RETVAL_INJECTED + if (c == GIO_FONTX) + printf(" => {charcount=0, charheight=57005, chardata=\"\"}"); +#endif + printf(") = " RETVAL); + + cfd->chardata = data; + sys_ioctl(-1, c, (uintptr_t) cfd); + printf("ioctl(-1, " XLAT_FMT + ", {charcount=0, charheight=57005, chardata=%p}", + XLAT_SEL(c, s), data); +#if RETVAL_INJECTED + if (c == GIO_FONTX) + printf(" => {charcount=0, charheight=57005, chardata=\"\"}"); +#endif + printf(") = " RETVAL); + + for (size_t i = 0; i < ARRAY_SIZE(cnts); i++) { + char *p = data_end - MIN(2048, cnts[i] * 32); + cfd->charcount = cnts[i]; + + cfd->chardata = p + 1; + sys_ioctl(-1, c, (uintptr_t) cfd); + printf("ioctl(-1, " XLAT_FMT + ", {charcount=%u, charheight=57005, chardata=", + XLAT_SEL(c, s), cnts[i]); + if (c == PIO_FONTX && cnts[i] * 32 > DEFAULT_STRLEN) { + print_quoted_hex(p + 1, DEFAULT_STRLEN); + printf("...}"); + } else { + printf("%p}", p + 1); + } +#if RETVAL_INJECTED + if (c == GIO_FONTX) { + printf(" => {charcount=%u, charheight=57005, chardata=", + cnts[i]); + if (cnts[i] * 32 > DEFAULT_STRLEN) { + print_quoted_hex(p + 1, DEFAULT_STRLEN); + printf("...}"); + } else { + printf("%p}", p + 1); + } + } +#endif + printf(") = " RETVAL); + + cfd->chardata = p; + sys_ioctl(-1, c, (uintptr_t) cfd); + printf("ioctl(-1, " XLAT_FMT + ", {charcount=%u, charheight=57005, chardata=", + XLAT_SEL(c, s), cnts[i]); + if (c == PIO_FONTX) { + print_quoted_hex(p, MIN(DEFAULT_STRLEN, cnts[i] * 32)); + if (cnts[i] * 32 > DEFAULT_STRLEN) + printf("..."); + } else { + printf("%p", p); + } + printf("}"); +#if RETVAL_INJECTED + if (c == GIO_FONTX) { + printf(" => {charcount=%u, charheight=57005, chardata=", + cnts[i]); + print_quoted_hex(p, MIN(DEFAULT_STRLEN, cnts[i] * 32)); + if (cnts[i] * 32 > DEFAULT_STRLEN) + printf("..."); + printf("}"); + } +#endif + printf(") = " RETVAL); + } +} + +/* GIO_CMAP, PIO_CMAP */ +static void +check_cmap(unsigned int c, const char *s) +{ + char *cmap = tail_alloc(48); + + fill_memory(cmap, 48); + + check_null_invalid(c, s); + + sys_ioctl(-1, c, (uintptr_t) (cmap + 1)); + printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(c, s)); + if ((c == PIO_CMAP || RETVAL_INJECTED) && (DEFAULT_STRLEN == 32)) { + printf("\""); + for (unsigned int i = 0; i < MIN(DEFAULT_STRLEN, 48); i++) + printf("\\x%x", 0x81 + i); + printf("\"..."); + } else { + printf("%p", cmap + 1); + } + printf(") = " RETVAL); + + sys_ioctl(-1, c, (uintptr_t) cmap); + printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(c, s)); + if (c == PIO_CMAP || RETVAL_INJECTED) { + printf("\""); + for (unsigned int i = 0; i < MIN(DEFAULT_STRLEN, 48); i++) + printf("\\x%x", 0x80 + i); +#if DEFAULT_STRLEN == 32 + printf("\"..."); +#else + printf("\""); +#endif + } else { + printf("%p", cmap); + } + printf(") = " RETVAL); +} + +/* KDGKBDIACRUC, KDSKBDIACRUC */ +static void +check_diacruc(unsigned int c, const char *s) +{ + struct kbdiacrsuc *diacrs0 = tail_alloc(sizeof(diacrs0->kb_cnt)); + struct kbdiacrsuc *diacrs1 = tail_alloc(sizeof(diacrs1->kb_cnt) + + 4 * sizeof(struct kbdiacruc)); + struct kbdiacrsuc *diacrs2 = tail_alloc(sizeof(*diacrs2)); + + int saved_errno; + + check_null_invalid(c, s); + + for (size_t i = 0; i < 2; i++) { + diacrs0->kb_cnt = i; + sys_ioctl(-1, c, (uintptr_t) diacrs0); + saved_errno = errno; + printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(c, s)); + if (RETVAL_INJECTED || c == KDSKBDIACRUC) { + printf("{kb_cnt=%zu, kbdiacruc=", i); + if (i) + printf("%p}", diacrs0->kbdiacruc); + else + printf("[]}"); + } else { + printf("%p", diacrs0); + } + errno = saved_errno; + printf(") = " RETVAL); + } + + fill_memory32(diacrs1->kbdiacruc, 4 * sizeof(struct kbdiacruc)); + for (size_t i = 0; i < 7; i++) { + diacrs1->kb_cnt = i; + sys_ioctl(-1, c, (uintptr_t) diacrs1); + saved_errno = errno; + printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(c, s)); + if (RETVAL_INJECTED || c == KDSKBDIACRUC) { + printf("{kb_cnt=%zu, kbdiacruc=[", i); + for (size_t j = 0; j < MIN(i, 4); j++) + printf("%s{diacr=%#x, base=%#x, result=%#x}", + j ? ", " : "", + (unsigned int) (0x80a0c0e0 + j * 3), + (unsigned int) (0x80a0c0e1 + j * 3), + (unsigned int) (0x80a0c0e2 + j * 3)); + + if (i > 4) { + printf(", ... /* %p */", + diacrs1->kbdiacruc + 4); + } + printf("]}"); + } else { + printf("%p", diacrs1); + } + errno = saved_errno; + printf(") = " RETVAL); + } + + fill_memory32(diacrs2->kbdiacruc, sizeof(diacrs2->kbdiacruc)); + + for (size_t i = ARRAY_SIZE(diacrs2->kbdiacruc) - 1; + i < ARRAY_SIZE(diacrs2->kbdiacruc) + 3; i++) { + diacrs2->kb_cnt = i; + sys_ioctl(-1, c, (uintptr_t) diacrs2); + printf("ioctl(-1, " XLAT_FMT ", ", XLAT_SEL(c, s)); + saved_errno = errno; + if (RETVAL_INJECTED || c == KDSKBDIACRUC) { + printf("{kb_cnt=%zu, kbdiacruc=[", i); + for (size_t j = 0; + j < MIN(i, MIN(ARRAY_SIZE(diacrs2->kbdiacruc), + DEFAULT_STRLEN)); j++) + printf("%s{diacr=%#x, base=%#x, result=%#x}", + j ? ", " : "", + (unsigned int) (0x80a0c0e0 + j * 3), + (unsigned int) (0x80a0c0e1 + j * 3), + (unsigned int) (0x80a0c0e2 + j * 3)); + + if (i > MIN(DEFAULT_STRLEN, + ARRAY_SIZE(diacrs2->kbdiacruc))) + printf(", ..."); + printf("]}"); + } else { + printf("%p", diacrs2); + } + errno = saved_errno; + printf(") = " RETVAL); + } +} + +int +main(int argc, char *argv[]) +{ + static const kernel_ulong_t magic = + (kernel_ulong_t) 0xdeadbeefbadc0dedULL; + + static const uint32_t unknown_ioctls[] = { + 0xfffffff1, 0xc0007fff, 0xfffb800c, 0xfff8c000, + 0xffffffff, 0xffffffff, 0xffffffff, 0xf3ffffff, + }; + + enum { MAP_ELEM_BIT = sizeof(unknown_ioctls[0]) * CHAR_BIT }; + + long rc; + +#if RETVAL_INJECTED + unsigned long num_skip; + bool locked = false; + + if (argc < 2) + error_msg_and_fail("Usage: %s NUM_SKIP", argv[0]); + + num_skip = strtoul(argv[1], NULL, 0); + + for (unsigned int i = 0; i < num_skip; i++) { + long rc = sys_ioctl(-1, KDGETLED, 0); + printf("ioctl(-1, " XLAT_FMT ", NULL) = %s%s\n", + XLAT_ARGS(KDGETLED), sprintrc(rc), + rc == 42 ? " (INJECTED)" : ""); + + if (rc != 42) + continue; + + locked = true; + break; + } + + if (!locked) + error_msg_and_fail("Have not locked on ioctl(-1" + ", KDGETLED, NULL) returning 42"); +#endif + + for (size_t i = 0; i < ARRAY_SIZE(unknown_ioctls); i++) { + for (size_t j = 0; j < MAP_ELEM_BIT; j++) { + if (!((unknown_ioctls[i] >> j) & 1)) + continue; + + const unsigned int id = i * MAP_ELEM_BIT + j; + + sys_ioctl(-1, 'K' << 8 | id, magic); + printf("ioctl(-1, " + NABBR("%#x") VERB(" /* ") + NRAW("_IOC(%s, 0x4b, %#x, 0)") VERB(" */") + ", %#lx) = " RETVAL, +#if XLAT_RAW || XLAT_VERBOSE + 'K' << 8 | id, +#endif +#if !XLAT_RAW + _IOC_NONE ? "0" : "_IOC_NONE", id, +#endif + (unsigned long) magic); + } + } + + + /* KIOCSOUND */ + sys_ioctl(-1, KIOCSOUND, 0); + printf("ioctl(-1, " XLAT_FMT ", 0" NRAW(" /* off */") ") = " RETVAL, + XLAT_ARGS(KIOCSOUND)); + + sys_ioctl(-1, KIOCSOUND, 1); + printf("ioctl(-1, " XLAT_FMT ", 1" NRAW(" /* 1193182 Hz */") + ") = " RETVAL, XLAT_ARGS(KIOCSOUND)); + + sys_ioctl(-1, KIOCSOUND, 440); + printf("ioctl(-1, " XLAT_FMT ", 440" NRAW(" /* 2711 Hz */") + ") = " RETVAL, XLAT_ARGS(KIOCSOUND)); + + sys_ioctl(-1, KIOCSOUND, 1193182); + printf("ioctl(-1, " XLAT_FMT ", 1193182" NRAW(" /* 1 Hz */") + ") = " RETVAL, XLAT_ARGS(KIOCSOUND)); + + sys_ioctl(-1, KIOCSOUND, 1193183); + printf("ioctl(-1, " XLAT_FMT ", 1193183" NRAW(" /* off */") + ") = " RETVAL, XLAT_ARGS(KIOCSOUND)); + + sys_ioctl(-1, KIOCSOUND, + (kernel_ulong_t) (0xbadc0ded00000000ULL | 2710)); + printf("ioctl(-1, " XLAT_FMT +#if SIZEOF_LONG == 4 + ", 2710" NRAW(" /* 440 Hz */") +#else + ", 13464652297489353366" NRAW(" /* off */") +#endif + ") = " RETVAL, XLAT_ARGS(KIOCSOUND)); + + sys_ioctl(-1, KIOCSOUND, (kernel_ulong_t) 0xbadc0deddeadfaceULL); + printf("ioctl(-1, " XLAT_FMT +#if SIZEOF_LONG == 8 + ", 13464652301225294542" +#else + ", 3735943886" +#endif + NRAW(" /* off */") ") = " RETVAL, XLAT_ARGS(KIOCSOUND)); + + /* KDMKTONE */ + sys_ioctl(-1, KDMKTONE, 0); + printf("ioctl(-1, " XLAT_FMT ", 0" NRAW(" /* off */") ") = " RETVAL, + XLAT_ARGS(KDMKTONE)); + + sys_ioctl(-1, KDMKTONE, 440); + printf("ioctl(-1, " XLAT_FMT ", 440" NRAW(" /* off */") ") = " RETVAL, + XLAT_ARGS(KDMKTONE)); + + sys_ioctl(-1, KDMKTONE, 0xffff); + printf("ioctl(-1, " XLAT_FMT ", 65535" NRAW(" /* off */") ") = " RETVAL, + XLAT_ARGS(KDMKTONE)); + + sys_ioctl(-1, KDMKTONE, 0x10000); + printf("ioctl(-1, " XLAT_FMT ", 1<<16|0" NRAW(" /* off */") + ") = " RETVAL, XLAT_ARGS(KDMKTONE)); + + sys_ioctl(-1, KDMKTONE, + (kernel_ulong_t) (0xbadc0ded00000000ULL | 0x10001)); + printf("ioctl(-1, " XLAT_FMT ", 1<<16|1" NRAW(" /* 1193182 Hz, 1 ms */") + ") = " RETVAL, XLAT_ARGS(KDMKTONE)); + + sys_ioctl(-1, KDMKTONE, 0x1ffff); + printf("ioctl(-1, " XLAT_FMT ", 1<<16|65535" NRAW(" /* 18 Hz, 1 ms */") + ") = " RETVAL, XLAT_ARGS(KDMKTONE)); + + sys_ioctl(-1, KDMKTONE, (kernel_ulong_t) 0xbadc0deddeadfaceULL); + printf("ioctl(-1, " XLAT_FMT ", 57005<<16|64206" + NRAW(" /* 18 Hz, 57005 ms */") ") = " RETVAL, + XLAT_ARGS(KDMKTONE)); + + + /* KDGETLED */ + static const struct arg_val led_vecs[] = { + { ARG_STR(0) }, + { ARG_XLAT_KNOWN(0x1, "LED_SCR") }, + { ARG_XLAT_KNOWN(0x7, "LED_SCR|LED_NUM|LED_CAP") }, + { ARG_XLAT_KNOWN(0xfe, "LED_NUM|LED_CAP|0xf8") }, + { (kernel_ulong_t) 0xbadc0dedfeedfaf0ULL, + XLAT_UNKNOWN(0xf0, "LED_???") }, + }; + + unsigned char *leds = tail_alloc(sizeof(*leds)); + + check_null_invalid(ARG_STR(KDGETLED)); + + for (size_t i = 0; i < ARRAY_SIZE(led_vecs); i++) { + *leds = led_vecs[i].val; + rc = sys_ioctl(-1, KDGETLED, (uintptr_t) leds); + if (rc >= 0) { + printf("ioctl(-1, " XLAT_FMT ", [%s]) = " RETVAL, + XLAT_ARGS(KDGETLED), led_vecs[i].str); + } else { + printf("ioctl(-1, " XLAT_FMT ", %p) = " RETVAL, + XLAT_ARGS(KDGETLED), leds); + } + } + + + /* KDSETLED */ + for (size_t i = 0; i < ARRAY_SIZE(led_vecs); i++) { + sys_ioctl(-1, KDSETLED, led_vecs[i].val); + printf("ioctl(-1, " XLAT_FMT ", %s) = " RETVAL, + XLAT_ARGS(KDSETLED), led_vecs[i].str); + } + + sys_ioctl(-1, KDSETLED, (kernel_ulong_t) 0xdeadc0defeedfaceULL); + printf("ioctl(-1, " XLAT_FMT ", %s) = " RETVAL, + XLAT_ARGS(KDSETLED), XLAT_STR(LED_NUM|LED_CAP|0xc8)); + + + /* KDGKBTYPE */ + static const struct arg_val kbt_vecs[] = { + { ARG_XLAT_UNKNOWN(0, "KB_???") }, + { ARG_XLAT_KNOWN(0x1, "KB_84") }, + { ARG_XLAT_KNOWN(0x2, "KB_101") }, + { ARG_XLAT_KNOWN(0x3, "KB_OTHER") }, + { ARG_XLAT_UNKNOWN(0x4, "KB_???") }, + { (kernel_ulong_t) 0xbadc0dedcacafefeULL, + XLAT_UNKNOWN(0xfe, "KB_???") }, + }; + + unsigned char *kbt = tail_alloc(sizeof(*kbt)); + + check_null_invalid(ARG_STR(KDGKBTYPE)); + + for (size_t i = 0; i < ARRAY_SIZE(kbt_vecs); i++) { + *kbt = kbt_vecs[i].val; + rc = sys_ioctl(-1, KDGKBTYPE, (uintptr_t) kbt); + if (rc >= 0) { + printf("ioctl(-1, " XLAT_FMT ", [%s]) = " RETVAL, + XLAT_ARGS(KDGKBTYPE), kbt_vecs[i].str); + } else { + printf("ioctl(-1, " XLAT_FMT ", %p) = " RETVAL, + XLAT_ARGS(KDGKBTYPE), kbt); + } + } + + + /* KDADDIO */ + static const struct arg_val iop_vecs[] = { + { ARG_STR(0) }, + { ARG_STR(0x3b3) }, + { ARG_STR(0x3b4) NRAW(" /* GPFIRST + 0 */") }, + { ARG_STR(0x3c0) NRAW(" /* GPFIRST + 12 */") }, + { ARG_STR(0x3df) NRAW(" /* GPFIRST + 43 */") }, + { ARG_STR(0x3e0) }, + { ARG_STR(0xdeadc0de) }, + { (kernel_ulong_t) 0xbadc0dedfacefeedULL, +#if SIZEOF_LONG > 4 + "0xbadc0dedfacefeed" +#else + "0xfacefeed" +#endif + }, + }; + + for (size_t i = 0; i < ARRAY_SIZE(iop_vecs); i++) { + sys_ioctl(-1, KDADDIO, iop_vecs[i].val); + printf("ioctl(-1, " XLAT_FMT ", %s) = " RETVAL, + XLAT_ARGS(KDADDIO), iop_vecs[i].str); + } + + + /* KDDELIO */ + for (size_t i = 0; i < ARRAY_SIZE(iop_vecs); i++) { + sys_ioctl(-1, KDDELIO, iop_vecs[i].val); + printf("ioctl(-1, " XLAT_FMT ", %s) = " RETVAL, + XLAT_ARGS(KDDELIO), iop_vecs[i].str); + } + + + /* KDENABIO */ + sys_ioctl(-1, KDENABIO, (kernel_ulong_t) 0xbadc0deddeadface); + printf("ioctl(-1, " XLAT_FMT ") = " RETVAL, XLAT_ARGS(KDENABIO)); + + + /* KDDISABIO */ + sys_ioctl(-1, KDDISABIO, (kernel_ulong_t) 0xbadc0deddeadface); + printf("ioctl(-1, " XLAT_FMT ") = " RETVAL, XLAT_ARGS(KDDISABIO)); + + + /* KDSETMODE */ + static const struct arg_val mode_vecs[] = { + { ARG_XLAT_KNOWN(0, "KD_TEXT") }, + { ARG_XLAT_KNOWN(0x1, "KD_GRAPHICS") }, + { ARG_XLAT_KNOWN(0x3, "KD_TEXT1") }, + { ARG_XLAT_UNKNOWN(0x4, "KD_???") }, + { (kernel_ulong_t) 0xbadc0dedcacafefeULL, + "0xcacafefe" NRAW(" /* KD_??? */") }, + }; + + for (size_t i = 0; i < ARRAY_SIZE(mode_vecs); i++) { + sys_ioctl(-1, KDSETMODE, mode_vecs[i].val); + printf("ioctl(-1, " XLAT_FMT ", %s) = " RETVAL, + XLAT_ARGS(KDSETMODE), mode_vecs[i].str); + } + + + /* KDGETMODE */ + unsigned int *mode = tail_alloc(sizeof(*mode)); + + check_null_invalid(ARG_STR(KDGETMODE)); + + for (size_t i = 0; i < ARRAY_SIZE(mode_vecs); i++) { + *mode = mode_vecs[i].val; + rc = sys_ioctl(-1, KDGETMODE, (uintptr_t) mode); + if (rc >= 0) { + printf("ioctl(-1, " XLAT_FMT ", [%s]) = " RETVAL, + XLAT_ARGS(KDGETMODE), mode_vecs[i].str); + } else { + printf("ioctl(-1, " XLAT_FMT ", %p) = " RETVAL, + XLAT_ARGS(KDGETMODE), mode); + } + } + + + /* KDMAPDISP */ + sys_ioctl(-1, KDMAPDISP, (kernel_ulong_t) 0xbadc0deddeadface); + printf("ioctl(-1, " XLAT_FMT ") = " RETVAL, XLAT_ARGS(KDMAPDISP)); + + + /* KDUNMAPDISP */ + sys_ioctl(-1, KDUNMAPDISP, (kernel_ulong_t) 0xbadc0deddeadface); + printf("ioctl(-1, " XLAT_FMT ") = " RETVAL, XLAT_ARGS(KDUNMAPDISP)); + + + /* GIO_SCRNMAP */ + check_scrnmap(ARG_STR(GIO_SCRNMAP)); + + + /* PIO_SCRNMAP */ + check_scrnmap(ARG_STR(PIO_SCRNMAP)); + + + /* KDGKBMODE */ + static const struct arg_val kbmode_vecs[] = { + { ARG_XLAT_UNKNOWN(-1, "K_???") }, + { ARG_XLAT_KNOWN(0, "K_RAW") }, + { ARG_XLAT_KNOWN(1, "K_XLATE") }, + { ARG_XLAT_KNOWN(4, "K_OFF") }, + { ARG_XLAT_UNKNOWN(5, "K_???") }, + { (kernel_ulong_t) 0xbadc0dedfeeddeadULL, + XLAT_UNKNOWN(-17965395, "K_???") }, + }; + + check_null_invalid(ARG_STR(KDGKBMODE)); + + for (size_t i = 0; i < ARRAY_SIZE(kbmode_vecs); i++) { + *mode = kbmode_vecs[i].val; + rc = sys_ioctl(-1, KDGKBMODE, (uintptr_t) mode); + if (rc >= 0) { + printf("ioctl(-1, " XLAT_FMT ", [%s]) = " RETVAL, + XLAT_ARGS(KDGKBMODE), kbmode_vecs[i].str); + } else { + printf("ioctl(-1, " XLAT_FMT ", %p) = " RETVAL, + XLAT_ARGS(KDGKBMODE), mode); + } + } + + + /* KDSKBMODE */ + for (size_t i = 0; i < ARRAY_SIZE(kbmode_vecs); i++) { + sys_ioctl(-1, KDSKBMODE, kbmode_vecs[i].val); + printf("ioctl(-1, " XLAT_FMT ", %s) = " RETVAL, + XLAT_ARGS(KDSKBMODE), kbmode_vecs[i].str); + } + + + /* KDGKBENT */ + check_kbdent(ARG_STR(KDGKBENT)); + + + /* KDSKBENT */ + check_kbdent(ARG_STR(KDSKBENT)); + + + /* KDGKBSENT */ + check_kbdsent(ARG_STR(KDGKBSENT)); + + + /* KDSKBSENT */ + check_kbdsent(ARG_STR(KDSKBSENT)); + + + /* KDGKBDIACR */ + check_diacr(ARG_STR(KDGKBDIACR)); + + + /* KDSKBDIACR */ + check_diacr(ARG_STR(KDSKBDIACR)); + + + /* KDGETKEYCODE */ + check_xetkeycode(ARG_STR(KDGETKEYCODE)); + + + /* KDSETKEYCODE */ + check_xetkeycode(ARG_STR(KDSETKEYCODE)); + + + /* KDSIGACCEPT */ + static const struct { + kernel_ulong_t val; + const char *str; + } sigaccept_vecs[] = { + { (kernel_ulong_t) -1ULL, + SIZEOF_LONG == 8 ? "18446744073709551615" : "4294967295" }, + { 0, "0" }, + { ARG_XLAT_KNOWN(SIGHUP, "SIGHUP") }, + { ARG_XLAT_KNOWN(SIGUSR1, "SIGUSR1") }, + { ARG_XLAT_KNOWN(32, "SIGRTMIN") }, + { ARG_XLAT_KNOWN(33, "SIGRT_1") }, + { ARG_STR(128) }, + }; + + for (size_t i = 0; i < ARRAY_SIZE(sigaccept_vecs); i++) { + sys_ioctl(-1, KDSIGACCEPT, sigaccept_vecs[i].val); + printf("ioctl(-1, " XLAT_FMT ", %s) = " RETVAL, + XLAT_ARGS(KDSIGACCEPT), sigaccept_vecs[i].str); + } + + + /* KDKBDREP */ + check_kbdrep(ARG_STR(KDKBDREP)); + + + /* GIO_FONT */ + check_font(ARG_STR(GIO_FONT)); + + + /* PIO_FONT */ + check_font(ARG_STR(PIO_FONT)); + + + /* KDGKBMETA */ + static const struct { + kernel_ulong_t arg; + const char *str; + } meta_vecs[] = { + { ARG_XLAT_UNKNOWN(0, "K_???") }, + { ARG_XLAT_UNKNOWN(0x1, "K_???") }, + { ARG_XLAT_UNKNOWN(0x2, "K_???") }, + { ARG_XLAT_KNOWN(0x3, "K_METABIT") }, + { ARG_XLAT_KNOWN(0x4, "K_ESCPREFIX") }, + { ARG_XLAT_UNKNOWN(0x5, "K_???") }, + { (kernel_ulong_t) 0xdeadfacebeeffeedULL, + "0xbeeffeed" NRAW(" /* K_??? */") }, + }; + int *meta = tail_alloc(sizeof(*meta)); + + check_null_invalid(ARG_STR(KDGKBMETA)); + + for (size_t i = 0; i < ARRAY_SIZE(meta_vecs); i++) { + *meta = meta_vecs[i].arg; + sys_ioctl(-1, KDGKBMETA, (uintptr_t) meta); + printf("ioctl(-1, " XLAT_FMT ", ", XLAT_ARGS(KDGKBMETA)); +#if RETVAL_INJECTED + printf("[%s]", meta_vecs[i].str); +#else + printf("%p", meta); +#endif + printf(") = " RETVAL); + } + + + /* KDSKBMETA */ + for (size_t i = 0; i < ARRAY_SIZE(meta_vecs); i++) { + sys_ioctl(-1, KDSKBMETA, meta_vecs[i].arg); + printf("ioctl(-1, " XLAT_FMT ", %s) = " RETVAL, + XLAT_ARGS(KDSKBMETA), meta_vecs[i].str); + } + + + /* KDGKBLED */ + static const struct arg_val kbled_vecs[] = { + { ARG_STR(0) }, + { ARG_XLAT_KNOWN(0x1, "LED_SCR") }, + { ARG_XLAT_KNOWN(0x7, "LED_SCR|LED_NUM|LED_CAP") }, + { ARG_XLAT_KNOWN(0x10, "LED_SCR<<4") }, + { ARG_XLAT_KNOWN(0x70, "LED_SCR<<4|LED_NUM<<4|LED_CAP<<4") }, + { ARG_XLAT_KNOWN(0xfe, "LED_NUM|LED_CAP|LED_SCR<<4|LED_NUM<<4" + "|LED_CAP<<4|0x88") }, + { (kernel_ulong_t) 0xbadc0dedfeedfa88ULL, + XLAT_UNKNOWN(0x88, "LED_???") }, + }; + + unsigned char *kbleds = tail_alloc(sizeof(*kbleds)); + + check_null_invalid(ARG_STR(KDGKBLED)); + + for (size_t i = 0; i < ARRAY_SIZE(kbled_vecs); i++) { + *kbleds = kbled_vecs[i].val; + rc = sys_ioctl(-1, KDGKBLED, (uintptr_t) kbleds); + if (rc >= 0) { + printf("ioctl(-1, " XLAT_FMT ", [%s]) = " RETVAL, + XLAT_ARGS(KDGKBLED), kbled_vecs[i].str); + } else { + printf("ioctl(-1, " XLAT_FMT ", %p) = " RETVAL, + XLAT_ARGS(KDGKBLED), kbleds); + } + } + + + /* KDSKBLED */ + for (size_t i = 0; i < ARRAY_SIZE(kbled_vecs); i++) { + sys_ioctl(-1, KDSKBLED, kbled_vecs[i].val); + printf("ioctl(-1, " XLAT_FMT ", %s) = " RETVAL, + XLAT_ARGS(KDSKBLED), kbled_vecs[i].str); + } + + + /* GIO_UNIMAP */ + check_unimap(ARG_STR(GIO_UNIMAP)); + + + /* PIO_UNIMAP */ + check_unimap(ARG_STR(PIO_UNIMAP)); + + + /* PIO_UNIMAPCLR */ + struct unimapinit *umi = tail_alloc(sizeof(*umi)); + + check_null_invalid(ARG_STR(PIO_UNIMAPCLR)); + + sys_ioctl(-1, PIO_UNIMAPCLR, (uintptr_t) umi + 2); + printf("ioctl(-1, " XLAT_FMT ", %p) = " RETVAL, + XLAT_ARGS(PIO_UNIMAPCLR), (char *) umi + 2); + + memset(umi, 0, sizeof(*umi)); + sys_ioctl(-1, PIO_UNIMAPCLR, (uintptr_t) umi); + printf("ioctl(-1, " XLAT_FMT ", {advised_hashsize=0" + ", advised_hashstep=0, advised_hashlevel=0}) = " RETVAL, + XLAT_ARGS(PIO_UNIMAPCLR)); + + fill_memory16(umi, sizeof(*umi)); + sys_ioctl(-1, PIO_UNIMAPCLR, (uintptr_t) umi); + printf("ioctl(-1, " XLAT_FMT ", {advised_hashsize=32960" + ", advised_hashstep=32961, advised_hashlevel=32962}) = " RETVAL, + XLAT_ARGS(PIO_UNIMAPCLR)); + + + /* GIO_UNISCRNMAP */ + check_uniscrnmap(ARG_STR(GIO_UNISCRNMAP)); + + + /* PIO_UNISCRNMAP */ + check_uniscrnmap(ARG_STR(PIO_UNISCRNMAP)); + + + /* GIO_FONTX */ + check_fontx(ARG_STR(GIO_FONTX)); + + + /* PIO_FONTX */ + check_fontx(ARG_STR(GIO_FONTX)); + + + /* PIO_FONTRESET */ + sys_ioctl(-1, PIO_FONTRESET, (kernel_ulong_t) 0xbadc0deddeadface); + printf("ioctl(-1, " XLAT_FMT ") = " RETVAL, XLAT_ARGS(PIO_FONTRESET)); + + + /* GIO_CMAP */ + check_cmap(ARG_STR(GIO_CMAP)); + + + /* PIO_CMAP */ + check_cmap(ARG_STR(PIO_CMAP)); + + + /* KDFONTOP */ + struct console_font_op *cfo = tail_alloc(sizeof(*cfo)); + unsigned char *cfo_data = tail_alloc(2048); + unsigned char *cfo_data_end = cfo_data + 2048; + + fill_memory(cfo_data, 2048); + + check_null_invalid(ARG_STR(KDFONTOP)); + + cfo->op = 4; + cfo->flags = 0xdeadbeef; + cfo->width = 0xbadc0ded; + cfo->height = 0xfacecafe; + cfo->charcount = 0xdadfaded; + cfo->data = NULL; + sys_ioctl(-1, KDFONTOP, (uintptr_t) cfo); + printf("ioctl(-1, " XLAT_FMT ", {op=0x4" NRAW(" /* KD_FONT_OP_??? */") + ", flags=" XLAT_KNOWN(0xdeadbeef, "KD_FONT_FLAG_DONT_RECALC" + "|KD_FONT_FLAG_OLD|0x5eadbeee") + ", width=3134983661, height=4207856382, charcount=3672092141" + ", data=NULL}" +#if RETVAL_INJECTED + " => {width=3134983661, height=4207856382, charcount=3672092141" + ", data=NULL}" +#endif + ") = " RETVAL, XLAT_ARGS(KDFONTOP)); + + cfo->op = 0xbeefface; + cfo->flags = 0x5a1ecafe;; + cfo->data = (unsigned char *) cfo; + sys_ioctl(-1, KDFONTOP, (uintptr_t) cfo); + printf("ioctl(-1, " XLAT_FMT ", {op=0xbeefface" + NRAW(" /* KD_FONT_OP_??? */") + ", flags=0x5a1ecafe" NRAW(" /* KD_FONT_FLAG_??? */") + ", width=3134983661, height=4207856382, charcount=3672092141" + ", data=%p}" +#if RETVAL_INJECTED + " => {width=3134983661, height=4207856382, charcount=3672092141" + ", data=%p}" +#endif + ") = " RETVAL, XLAT_ARGS(KDFONTOP), cfo +#if RETVAL_INJECTED + , cfo +#endif + ); + + static const struct strval32 kdfont_ops[] = { + { ARG_XLAT_KNOWN(0, "KD_FONT_OP_SET") }, + { ARG_XLAT_KNOWN(0x1, "KD_FONT_OP_GET") }, + }; + + for (size_t i = 0; i < ARRAY_SIZE(kdfont_ops); i++) { + cfo->op = kdfont_ops[i].val; + cfo->flags = 1; + cfo->width = 0; + cfo->height = 0; + cfo->charcount = 0; + cfo->data = NULL; + sys_ioctl(-1, KDFONTOP, (uintptr_t) cfo); + printf("ioctl(-1, " XLAT_FMT ", {op=%s, flags=" + XLAT_FMT ", width=0, height=0, charcount=0, data=NULL}", + XLAT_ARGS(KDFONTOP), kdfont_ops[i].str, + XLAT_ARGS(KD_FONT_FLAG_DONT_RECALC)); + if (kdfont_ops[i].val == KD_FONT_OP_GET && RETVAL_INJECTED) { + printf(" => {width=0, height=0, charcount=0" + ", data=NULL}"); + } + printf(") = " RETVAL); + + cfo->data = cfo_data_end; + for (size_t j = 0; j < 2; j++) { + cfo->charcount = j; + sys_ioctl(-1, KDFONTOP, (uintptr_t) cfo); + printf("ioctl(-1, " XLAT_FMT ", {op=%s, flags=" + XLAT_FMT ", width=0, height=0, charcount=%zu" + ", data=", + XLAT_ARGS(KDFONTOP), kdfont_ops[i].str, + XLAT_ARGS(KD_FONT_FLAG_DONT_RECALC), j); + if (kdfont_ops[i].val == KD_FONT_OP_SET) + printf("\"\""); + else + printf("%p", cfo_data_end); +#if RETVAL_INJECTED + if (kdfont_ops[i].val == KD_FONT_OP_GET) { + printf("} => {width=0, height=0, charcount=%zu" + ", data=\"\"", j); + } +#endif + printf("}) = " RETVAL); + + } + + cfo->flags = 0; + cfo->width = 1; + cfo->data = cfo_data_end - 31; + sys_ioctl(-1, KDFONTOP, (uintptr_t) cfo); + printf("ioctl(-1, " XLAT_FMT ", {op=%s, flags=0, width=1" + ", height=0, charcount=1, data=%p}", + XLAT_ARGS(KDFONTOP), kdfont_ops[i].str, + cfo_data_end - 31); + if (kdfont_ops[i].val == KD_FONT_OP_GET && RETVAL_INJECTED) { + printf(" => {width=1, height=0, charcount=1, data=%p}", + cfo_data_end - 31); + } + printf(") = " RETVAL); + + cfo->data = cfo_data_end - 32; + sys_ioctl(-1, KDFONTOP, (uintptr_t) cfo); + printf("ioctl(-1, " XLAT_FMT ", {op=%s, flags=0, width=1" + ", height=0, charcount=1, data=", + XLAT_ARGS(KDFONTOP), kdfont_ops[i].str); + if (kdfont_ops[i].val == KD_FONT_OP_SET) + print_quoted_hex(cfo_data_end - 32, 32); + else + printf("%p", cfo_data_end - 32); + if (kdfont_ops[i].val == KD_FONT_OP_GET && RETVAL_INJECTED) { + printf("} => {width=1, height=0, charcount=1, data="); + print_quoted_hex(cfo_data_end - 32, 32); + + } + printf("}) = " RETVAL); + + cfo->charcount = 32; + cfo->data = cfo_data_end - 1023; + sys_ioctl(-1, KDFONTOP, (uintptr_t) cfo); + printf("ioctl(-1, " XLAT_FMT ", {op=%s, flags=0, width=1" + ", height=0, charcount=32, data=", + XLAT_ARGS(KDFONTOP), kdfont_ops[i].str); + if (kdfont_ops[i].val == KD_FONT_OP_SET && DEFAULT_STRLEN == 32) + { + print_quoted_hex(cfo_data_end - 1023, 32); + printf("..."); + } else { + printf("%p", cfo_data_end - 1023); + } + if (kdfont_ops[i].val == KD_FONT_OP_GET && RETVAL_INJECTED) { + printf("} => {width=1, height=0, charcount=32, data="); +#if DEFAULT_STRLEN == 32 + print_quoted_hex(cfo_data_end - 1023, 32); + printf("..."); +#else + printf("%p", cfo_data_end - 1023); +#endif + + } + printf("}) = " RETVAL); + + cfo->data = cfo_data_end - 1024; + sys_ioctl(-1, KDFONTOP, (uintptr_t) cfo); + printf("ioctl(-1, " XLAT_FMT ", {op=%s, flags=0, width=1" + ", height=0, charcount=32, data=", + XLAT_ARGS(KDFONTOP), kdfont_ops[i].str); + if (kdfont_ops[i].val == KD_FONT_OP_SET) { + print_quoted_hex(cfo_data_end - 1024, DEFAULT_STRLEN); +#if DEFAULT_STRLEN == 32 + printf("..."); +#endif + } else { + printf("%p", cfo_data_end - 1024); + } + if (kdfont_ops[i].val == KD_FONT_OP_GET && RETVAL_INJECTED) { + printf("} => {width=1, height=0, charcount=32, data="); + print_quoted_hex(cfo_data_end - 1024, DEFAULT_STRLEN); +#if DEFAULT_STRLEN == 32 + printf("..."); +#endif + } + printf("}) = " RETVAL); + + cfo->charcount = 256; + cfo->data = cfo_data_end - 1025; + sys_ioctl(-1, KDFONTOP, (uintptr_t) cfo); + printf("ioctl(-1, " XLAT_FMT ", {op=%s, flags=0, width=1" + ", height=0, charcount=256, data=", + XLAT_ARGS(KDFONTOP), kdfont_ops[i].str); + if (kdfont_ops[i].val == KD_FONT_OP_SET) { + print_quoted_hex(cfo_data_end - 1025, DEFAULT_STRLEN); + printf("..."); + } else { + printf("%p", cfo_data_end - 1025); + } + if (kdfont_ops[i].val == KD_FONT_OP_GET && RETVAL_INJECTED) { + printf("} => {width=1, height=0, charcount=256, data="); + print_quoted_hex(cfo_data_end - 1025, DEFAULT_STRLEN); + printf("..."); + + } + printf("}) = " RETVAL); + } + + cfo->op = 2; + cfo->data = NULL; + sys_ioctl(-1, KDFONTOP, (uintptr_t) cfo); + printf("ioctl(-1, " XLAT_FMT ", {op=" XLAT_FMT ", width=1, height=0" + ", data=NULL}" +#if RETVAL_INJECTED + " => {width=1, height=0}" +#endif + ") = " RETVAL, + XLAT_ARGS(KDFONTOP), XLAT_ARGS(KD_FONT_OP_SET_DEFAULT)); + + cfo->data = cfo_data_end - 1; + cfo->data[0] = '\0'; + sys_ioctl(-1, KDFONTOP, (uintptr_t) cfo); + printf("ioctl(-1, " XLAT_FMT ", {op=" XLAT_FMT ", width=1, height=0" + ", data=\"\"}" +#if RETVAL_INJECTED + " => {width=1, height=0}" +#endif + ") = " RETVAL, + XLAT_ARGS(KDFONTOP), XLAT_ARGS(KD_FONT_OP_SET_DEFAULT)); + + cfo->data[0] = 'x'; + sys_ioctl(-1, KDFONTOP, (uintptr_t) cfo); + printf("ioctl(-1, " XLAT_FMT ", {op=" XLAT_FMT ", width=1, height=0" + ", data=%p}" +#if RETVAL_INJECTED + " => {width=1, height=0}" +#endif + ") = " RETVAL, + XLAT_ARGS(KDFONTOP), XLAT_ARGS(KD_FONT_OP_SET_DEFAULT), + cfo_data_end - 1); + + cfo->width = 0xcafebeef; + cfo->height = 0xbea7bee5; + cfo->data = cfo_data_end - 32; + strcpy((char *) cfo->data, + "\1\2\3\r\n\t\v\f\\\"OH\377HAI\7\10\02101234567890x"); + for (size_t j = 0; j < 2; j++) { + sys_ioctl(-1, KDFONTOP, (uintptr_t) cfo); + printf("ioctl(-1, " XLAT_FMT ", {op=" XLAT_FMT + ", width=3405692655, height=3198664421, data=\"\\1\\2\\3" + "\\r\\n\\t\\v\\f\\\\\\\"OH\\377HAI\\7\\10\\0210123456789" + "0x\"%s}" +#if RETVAL_INJECTED + " => {width=3405692655, height=3198664421}" +#endif + ") = " RETVAL, + XLAT_ARGS(KDFONTOP), XLAT_ARGS(KD_FONT_OP_SET_DEFAULT), + j ? "..." : ""); + + cfo->data[31] = 'y'; + } + + cfo->op = 3; + cfo->height = 0; + sys_ioctl(-1, KDFONTOP, (uintptr_t) cfo); + printf("ioctl(-1, " XLAT_FMT ", {op=" XLAT_FMT ", height=0}) = " RETVAL, + XLAT_ARGS(KDFONTOP), XLAT_ARGS(KD_FONT_OP_COPY)); + + + /* KDGKBDIACRUC */ + check_diacruc(ARG_STR(KDGKBDIACRUC)); + + + /* KDSKBDIACRUC */ + check_diacruc(ARG_STR(KDSKBDIACRUC)); + + + puts("+++ exited with 0 +++"); + return 0; +} diff --git a/tests/pure_executables.list b/tests/pure_executables.list index 6f47fd26b..2223337d4 100755 --- a/tests/pure_executables.list +++ b/tests/pure_executables.list @@ -205,6 +205,10 @@ ioctl_hdio-v-Xabbrev ioctl_hdio-v-Xraw ioctl_hdio-v-Xverbose ioctl_inotify +ioctl_kd +ioctl_kd-Xabbrev +ioctl_kd-Xraw +ioctl_kd-Xverbose ioctl_kvm_run ioctl_kvm_run-v ioctl_kvm_run_auxstr_vcpu |