(root)/
strace-6.5/
src/
kd_ioctl.c
       1  /*
       2   * Support for decoding of VT ioctl commands.
       3   *
       4   * Copyright (c) 2019-2021 Eugene Syromyatnikov <evgsyr@gmail.com>
       5   * Copyright (c) 2019-2022 The strace developers.
       6   * All rights reserved.
       7   *
       8   * SPDX-License-Identifier: LGPL-2.1-or-later
       9   */
      10  
      11  #include "defs.h"
      12  
      13  #include <linux/kd.h>
      14  #include <linux/keyboard.h>
      15  
      16  #include "print_fields.h"
      17  #include "print_utils.h"
      18  
      19  #include "xlat/kd_default_led_flags.h"
      20  #include "xlat/kd_kbd_modes.h"
      21  #include "xlat/kd_kbd_types.h"
      22  #include "xlat/kd_keymap_flags.h"
      23  #include "xlat/kd_key_tables.h"
      24  #include "xlat/kd_key_types.h"
      25  #include "xlat/kd_key_fn_keys.h"
      26  #include "xlat/kd_key_fn_key_vals.h"
      27  #include "xlat/kd_key_spec_keys.h"
      28  #include "xlat/kd_key_pad_keys.h"
      29  #include "xlat/kd_key_dead_keys.h"
      30  #include "xlat/kd_key_cur_keys.h"
      31  #include "xlat/kd_key_shift_keys.h"
      32  #include "xlat/kd_key_ascii_keys.h"
      33  #include "xlat/kd_key_lock_keys.h"
      34  #include "xlat/kd_key_slock_keys.h"
      35  #include "xlat/kd_key_brl_keys.h"
      36  #include "xlat/kd_led_flags.h"
      37  #include "xlat/kd_meta_vals.h"
      38  #include "xlat/kd_modes.h"
      39  
      40  #define XLAT_MACROS_ONLY
      41  # include "xlat/kd_ioctl_cmds.h"
      42  #undef XLAT_MACROS_ONLY
      43  
      44  #ifdef HAVE_STRUCT_KBDIACRUC
      45  typedef struct kbdiacruc struct_kbdiacruc;
      46  #else
      47  typedef struct {
      48  	unsigned int diacr;
      49  	unsigned int base;
      50  	unsigned int result;
      51  } struct_kbdiacruc;
      52  #endif
      53  
      54  #ifdef HAVE_STRUCT_KBDIACRSUC
      55  typedef struct kbdiacrsuc struct_kbdiacrsuc;
      56  #else
      57  typedef struct {
      58  	unsigned int kb_cnt;
      59  	struct_kbdiacruc kbdiacruc[256];
      60  } struct_kbdiacrsuc;
      61  #endif
      62  
      63  enum {
      64  	KERNEL_PIT_TICK_RATE = 1193182,
      65  	KERNEL_E_TABSZ = 256,
      66  	KERNEL_MAX_DIACR = 256,
      67  };
      68  
      69  static int
      70  kiocsound(struct tcb *const tcp, const kernel_ulong_t arg)
      71  {
      72  	unsigned int freq = arg ? KERNEL_PIT_TICK_RATE / arg : 0;
      73  
      74  	tprint_arg_next();
      75  	PRINT_VAL_U(arg);
      76  	if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_RAW) {
      77  		if (freq)
      78  			tprintf_comment("%u Hz", freq);
      79  		else
      80  			tprints_comment("off");
      81  	}
      82  
      83  	return RVAL_IOCTL_DECODED;
      84  }
      85  
      86  static int
      87  kd_mk_tone(struct tcb *const tcp, const unsigned int arg)
      88  {
      89  	unsigned int ticks = arg >> 16;
      90  	unsigned int count = arg & 0xFFFF;
      91  	unsigned int freq = ticks && count ? KERNEL_PIT_TICK_RATE / count : 0;
      92  
      93  	tprint_arg_next();
      94  	tprint_flags_begin();
      95  	if (ticks) {
      96  		tprint_shift_begin();
      97  		PRINT_VAL_U(ticks);
      98  		tprint_shift();
      99  		PRINT_VAL_U(16);
     100  		tprint_shift_end();
     101  		tprint_flags_or();
     102  	}
     103  	PRINT_VAL_U(count);
     104  	tprint_flags_end();
     105  
     106  	if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_RAW) {
     107  		if (freq)
     108  			tprintf_comment("%u Hz, %u ms", freq, ticks);
     109  		else
     110  			tprints_comment("off");
     111  	}
     112  
     113  	return RVAL_IOCTL_DECODED;
     114  }
     115  
     116  static void
     117  print_leds(struct tcb *const tcp, const kernel_ulong_t arg,
     118  	   const bool get, const bool dflt)
     119  {
     120  	unsigned char val;
     121  
     122  	if (get) {
     123  		if (umove_or_printaddr(tcp, arg, &val))
     124  			return;
     125  	} else {
     126  		val = arg;
     127  	}
     128  
     129  	if (get)
     130  		tprint_indirect_begin();
     131  	printflags(dflt ? kd_default_led_flags : kd_led_flags, val,
     132  		   "LED_???");
     133  	if (get)
     134  		tprint_indirect_end();
     135  }
     136  
     137  static int
     138  kd_leds(struct tcb *const tcp, const unsigned int code,
     139  	const kernel_ulong_t arg)
     140  {
     141  	bool get = false;
     142  	bool dflt = false;
     143  
     144  	switch (code) {
     145  	case KDGETLED:
     146  	case KDGKBLED:
     147  		get = true;
     148  	}
     149  
     150  	switch (code) {
     151  	case KDGKBLED:
     152  	case KDSKBLED:
     153  		dflt = true;
     154  	}
     155  
     156  	if (entering(tcp)) {
     157  		tprint_arg_next();
     158  
     159  		if (get)
     160  			return 0;
     161  	}
     162  
     163  	print_leds(tcp, arg, get, dflt);
     164  
     165  	return RVAL_IOCTL_DECODED;
     166  }
     167  
     168  static int
     169  kd_get_kb_type(struct tcb *const tcp, const kernel_ulong_t arg)
     170  {
     171  	unsigned char val;
     172  
     173  	if (entering(tcp)) {
     174  		tprint_arg_next();
     175  		return 0;
     176  	}
     177  
     178  	if (umove_or_printaddr(tcp, arg, &val))
     179  		return RVAL_IOCTL_DECODED;
     180  
     181  	tprint_indirect_begin();
     182  	printxval(kd_kbd_types, val, "KB_???");
     183  	tprint_indirect_end();
     184  
     185  	return RVAL_IOCTL_DECODED;
     186  }
     187  
     188  static int
     189  kd_io(struct tcb *const tcp, kernel_ulong_t arg)
     190  {
     191  	enum { GPFIRST = 0x3b4, GPLAST = 0x3df };
     192  
     193  	tprint_arg_next();
     194  	PRINT_VAL_X(arg);
     195  
     196  	if (arg >= GPFIRST && arg <= GPLAST
     197  	    && xlat_verbose(xlat_verbosity) != XLAT_STYLE_RAW)
     198  		tprintf_comment("GPFIRST + %" PRI_klu, arg - GPFIRST);
     199  
     200  	return RVAL_IOCTL_DECODED;
     201  }
     202  
     203  static int
     204  kd_set_mode(struct tcb *const tcp, const kernel_ulong_t arg)
     205  {
     206  	tprint_arg_next();
     207  	printxval(kd_modes, arg, "KD_???");
     208  
     209  	return RVAL_IOCTL_DECODED;
     210  }
     211  
     212  static int
     213  kd_get_mode(struct tcb *const tcp, const kernel_ulong_t arg)
     214  {
     215  	unsigned int val;
     216  
     217  	if (entering(tcp)) {
     218  		tprint_arg_next();
     219  		return 0;
     220  	}
     221  
     222  	if (umove_or_printaddr(tcp, arg, &val))
     223  		return RVAL_IOCTL_DECODED;
     224  
     225  	tprint_indirect_begin();
     226  	printxval(kd_modes, val, "KD_???");
     227  	tprint_indirect_end();
     228  
     229  	return RVAL_IOCTL_DECODED;
     230  }
     231  
     232  static int
     233  kd_screen_map(struct tcb *const tcp, const kernel_ulong_t arg, const bool get)
     234  {
     235  	if (entering(tcp)) {
     236  		tprint_arg_next();
     237  
     238  		if (get)
     239  			return 0;
     240  	}
     241  
     242  	if (entering(tcp) || !syserror(tcp))
     243  		printstr_ex(tcp, arg, KERNEL_E_TABSZ, QUOTE_FORCE_HEX);
     244  	else
     245  		printaddr(arg);
     246  
     247  	return RVAL_IOCTL_DECODED;
     248  }
     249  
     250  static bool
     251  print_scrmap_array_member(struct tcb *tcp, void *elem_buf,
     252  			  size_t elem_size, void *data)
     253  {
     254  	unsigned short val = *(unsigned short *) elem_buf;
     255  
     256  	if ((xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV) ||
     257  	    ((val & ~UNI_DIRECT_MASK) != UNI_DIRECT_BASE))
     258  		PRINT_VAL_X(val);
     259  
     260  	if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW)
     261  		return true;
     262  
     263  	if ((val & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
     264  		(xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE
     265  			? tprintf_comment : tprintf_string)("UNI_DIRECT_BASE+%#hx",
     266  							    val & UNI_DIRECT_MASK);
     267  
     268  	return true;
     269  }
     270  
     271  static int
     272  kd_uni_screen_map(struct tcb *const tcp, const kernel_ulong_t arg,
     273  		  const bool get)
     274  {
     275  	unsigned short elem;
     276  
     277  	if (entering(tcp)) {
     278  		tprint_arg_next();
     279  
     280  		if (get)
     281  			return 0;
     282  	}
     283  
     284  	print_array(tcp, arg, KERNEL_E_TABSZ, &elem, sizeof(elem),
     285  		    tfetch_mem, print_scrmap_array_member, 0);
     286  
     287  	return RVAL_IOCTL_DECODED;
     288  }
     289  
     290  static int
     291  kd_set_kbd_mode(struct tcb *const tcp, const unsigned int arg)
     292  {
     293  	tprint_arg_next();
     294  	printxval_d(kd_kbd_modes, arg, "K_???");
     295  
     296  	return RVAL_IOCTL_DECODED;
     297  }
     298  
     299  static int
     300  kd_get_kbd_mode(struct tcb *const tcp, const kernel_ulong_t arg)
     301  {
     302  	unsigned int val;
     303  
     304  	if (entering(tcp)) {
     305  		tprint_arg_next();
     306  		return 0;
     307  	}
     308  
     309  	if (umove_or_printaddr(tcp, arg, &val))
     310  		return RVAL_IOCTL_DECODED;
     311  
     312  	tprint_indirect_begin();
     313  	printxval_d(kd_kbd_modes, val, "K_???");
     314  	tprint_indirect_end();
     315  
     316  	return RVAL_IOCTL_DECODED;
     317  }
     318  
     319  static int
     320  kd_kbd_entry(struct tcb *const tcp, const kernel_ulong_t arg, const bool get)
     321  {
     322  	static const struct xlat *xlat_tables[] = {
     323  		/* KT_LATIN */
     324  		[KT_FN]    = kd_key_fn_keys,
     325  		[KT_SPEC]  = kd_key_spec_keys,
     326  		[KT_PAD]   = kd_key_pad_keys,
     327  		[KT_DEAD]  = kd_key_dead_keys,
     328  		/* KT_CONS */
     329  		[KT_CUR]   = kd_key_cur_keys,
     330  		[KT_SHIFT] = kd_key_shift_keys,
     331  		/* KT_META */
     332  		[KT_ASCII] = kd_key_ascii_keys,
     333  		[KT_LOCK]  = kd_key_lock_keys,
     334  		/* KT_LETTER */
     335  		[KT_SLOCK] = kd_key_slock_keys,
     336  		/* KT_DEAD2 */
     337  		[KT_BRL]   = kd_key_brl_keys,
     338  	};
     339  
     340  	struct kbentry val;
     341  	unsigned char ktyp;
     342  	unsigned char kval;
     343  	const char *str = NULL;
     344  
     345  	if (entering(tcp)) {
     346  		tprint_arg_next();
     347  
     348  		if (umoven(tcp, arg, offsetofend(struct kbentry, kb_index),
     349  			   &val)) {
     350  			printaddr(arg);
     351  			return RVAL_IOCTL_DECODED;
     352  		}
     353  
     354  		tprint_struct_begin();
     355  
     356  		const char *keymap_str = xlookup(kd_key_tables, val.kb_table);
     357  
     358  		if (keymap_str) {
     359  			tprints_field_name("kb_table");
     360  			print_xlat_ex(val.kb_table, keymap_str,
     361  				      XLAT_STYLE_DEFAULT);
     362  		} else {
     363  			PRINT_FIELD_FLAGS(val, kb_table, kd_keymap_flags,
     364  					  "K_???");
     365  		}
     366  
     367  		tprint_struct_next();
     368  		PRINT_FIELD_U(val, kb_index);
     369  
     370  		if (get)
     371  			return 0;
     372  	} else if (syserror(tcp)) {
     373  		goto out;
     374  	}
     375  
     376  	tprint_struct_next();
     377  	if (umove(tcp, arg + offsetof(struct kbentry, kb_value),
     378  			 &val.kb_value)) {
     379  		tprints_field_name("kb_value");
     380  		tprint_unavailable();
     381  		goto out;
     382  	}
     383  
     384  	PRINT_FIELD_X(val, kb_value);
     385  
     386  	if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW)
     387  		goto out;
     388  
     389  	ktyp = KTYP(val.kb_value);
     390  	kval = KVAL(val.kb_value);
     391  
     392  	if (ktyp < ARRAY_SIZE(xlat_tables) && xlat_tables[ktyp])
     393  		str = xlookup(xlat_tables[ktyp], val.kb_value);
     394  
     395  	if (str) {
     396  		tprints_comment(str);
     397  	} else {
     398  		tprint_comment_begin();
     399  		tprints_arg_begin("K");
     400  		printxvals_ex(ktyp, NULL, XLAT_STYLE_ABBREV,
     401  			      kd_key_types, NULL);
     402  		tprint_arg_next();
     403  
     404  		switch (ktyp) {
     405  		case KT_LATIN:
     406  		case KT_META:
     407  		case KT_LETTER:
     408  		case KT_DEAD2:
     409  			print_char(kval, SCF_QUOTES | SCF_ESC_WS);
     410  			break;
     411  		default:
     412  			PRINT_VAL_X(kval);
     413  		}
     414  
     415  		tprint_arg_end();
     416  		tprint_comment_end();
     417  	}
     418  
     419  out:
     420  	tprint_struct_end();
     421  
     422  	return RVAL_IOCTL_DECODED;
     423  }
     424  
     425  static int
     426  kd_kbd_str_entry(struct tcb *const tcp, const kernel_ulong_t arg,
     427  		 const bool get)
     428  {
     429  	struct kbsentry val;
     430  
     431  	if (entering(tcp)) {
     432  		tprint_arg_next();
     433  
     434  		if (umove_or_printaddr(tcp, arg, &(val.kb_func)))
     435  			return RVAL_IOCTL_DECODED;
     436  
     437  		tprint_struct_begin();
     438  		PRINT_FIELD_XVAL(val, kb_func, kd_key_fn_key_vals,
     439  				 "KVAL(K_???"")");
     440  
     441  		if (get)
     442  			return 0;
     443  	} else if (syserror(tcp)) {
     444  		goto out;
     445  	}
     446  
     447  	tprint_struct_next();
     448  	tprints_field_name("kb_string");
     449  
     450  	int ret = umovestr(tcp, arg + offsetof(struct kbsentry, kb_string),
     451  			   sizeof(val.kb_string), (char *) val.kb_string);
     452  
     453  	if (ret < 0) {
     454  		tprint_unavailable();
     455  		goto out;
     456  	}
     457  
     458  	if (print_quoted_string((char *) val.kb_string,
     459  				MIN(max_strlen,
     460  				   (unsigned int) ret ?: sizeof(val.kb_string)),
     461  				QUOTE_OMIT_TRAILING_0))
     462  		tprint_more_data_follows();
     463  
     464  out:
     465  	tprint_struct_end();
     466  
     467  	return RVAL_IOCTL_DECODED;
     468  }
     469  
     470  static bool
     471  print_kbdiacr_array_member(struct tcb *tcp, void *elem_buf,
     472  			   size_t elem_size, void *data)
     473  {
     474  	struct kbdiacr *val = elem_buf;
     475  
     476  	tprint_struct_begin();
     477  	PRINT_FIELD_CHAR(*val, diacr, SCF_QUOTES | SCF_ESC_WS);
     478  	tprint_struct_next();
     479  	PRINT_FIELD_CHAR(*val, base, SCF_QUOTES | SCF_ESC_WS);
     480  	tprint_struct_next();
     481  	PRINT_FIELD_CHAR(*val, result, SCF_QUOTES | SCF_ESC_WS);
     482  	tprint_struct_end();
     483  
     484  	return true;
     485  }
     486  
     487  static int
     488  kd_diacr(struct tcb *const tcp, const kernel_ulong_t arg, const bool get)
     489  {
     490  	unsigned int kb_cnt; /* struct kbdiacrs.kb_cnt */
     491  	struct kbdiacr elem;
     492  
     493  	if (entering(tcp)) {
     494  		tprint_arg_next();
     495  
     496  		if (get)
     497  			return 0;
     498  	}
     499  
     500  	if (umove_or_printaddr(tcp, arg, &kb_cnt))
     501  		return RVAL_IOCTL_DECODED;
     502  
     503  	tprint_struct_begin();
     504  	tprints_field_name("kb_cnt");
     505  	PRINT_VAL_U(kb_cnt);
     506  	tprint_struct_next();
     507  	tprints_field_name("kbdiacr");
     508  	print_array_ex(tcp, arg + offsetof(struct kbdiacrs, kbdiacr),
     509  		       MIN(kb_cnt, KERNEL_MAX_DIACR), &elem, sizeof(elem),
     510  		       tfetch_mem, print_kbdiacr_array_member, 0,
     511  		       kb_cnt > KERNEL_MAX_DIACR ? PAF_ARRAY_TRUNCATED : 0,
     512  		       NULL, NULL);
     513  	tprint_struct_end();
     514  
     515  	return RVAL_IOCTL_DECODED;
     516  }
     517  
     518  static bool
     519  print_kbdiacruc_array_member(struct tcb *tcp, void *elem_buf,
     520  			     size_t elem_size, void *data)
     521  {
     522  	struct_kbdiacruc *val = elem_buf;
     523  
     524  	tprint_struct_begin();
     525  	PRINT_FIELD_X(*val, diacr);
     526  	tprint_struct_next();
     527  	PRINT_FIELD_X(*val, base);
     528  	tprint_struct_next();
     529  	PRINT_FIELD_X(*val, result);
     530  	tprint_struct_end();
     531  
     532  	return true;
     533  }
     534  
     535  static int
     536  kd_diacr_uc(struct tcb *const tcp, const kernel_ulong_t arg, const bool get)
     537  {
     538  	unsigned int kb_cnt; /* struct kbdiacrs.kb_cnt */
     539  	struct_kbdiacruc elem;
     540  
     541  	if (entering(tcp)) {
     542  		tprint_arg_next();
     543  
     544  		if (get)
     545  			return 0;
     546  	}
     547  
     548  	if (umove_or_printaddr(tcp, arg, &kb_cnt))
     549  		return RVAL_IOCTL_DECODED;
     550  
     551  	tprint_struct_begin();
     552  	tprints_field_name("kb_cnt");
     553  	PRINT_VAL_U(kb_cnt);
     554  	tprint_struct_next();
     555  	tprints_field_name("kbdiacruc");
     556  	print_array_ex(tcp, arg + offsetof(struct_kbdiacrsuc, kbdiacruc),
     557  		       MIN(kb_cnt, KERNEL_MAX_DIACR), &elem, sizeof(elem),
     558  		       tfetch_mem, print_kbdiacruc_array_member, 0,
     559  		       kb_cnt > KERNEL_MAX_DIACR ? PAF_ARRAY_TRUNCATED : 0,
     560  		       NULL, NULL);
     561  	tprint_struct_end();
     562  
     563  	return RVAL_IOCTL_DECODED;
     564  }
     565  
     566  static int
     567  kd_keycode(struct tcb *const tcp, const kernel_ulong_t arg, const bool get)
     568  {
     569  	struct kbkeycode val;
     570  
     571  	if (entering(tcp)) {
     572  		tprint_arg_next();
     573  
     574  		if (umove_or_printaddr(tcp, arg, &val))
     575  			return RVAL_IOCTL_DECODED;
     576  
     577  		tprint_struct_begin();
     578  		PRINT_FIELD_X(val, scancode);
     579  		tprint_struct_next();
     580  		PRINT_FIELD_X(val, keycode);
     581  
     582  		if (get)
     583  			return 0;
     584  
     585  		goto end;
     586  	}
     587  
     588  	/* exiting */
     589  	if (syserror(tcp) ||
     590  	    umove(tcp, arg + offsetof(struct kbkeycode, keycode), &val.keycode))
     591  	{
     592  		tprint_struct_end();
     593  		return RVAL_IOCTL_DECODED;
     594  	}
     595  
     596  	tprint_value_changed();
     597  	PRINT_VAL_X(val.keycode);
     598  
     599  end:
     600  	tprint_struct_end();
     601  
     602  	return RVAL_IOCTL_DECODED;
     603  }
     604  
     605  static int
     606  kd_sigaccept(struct tcb *const tcp, const kernel_ulong_t arg)
     607  {
     608  	tprint_arg_next();
     609  
     610  	if (arg < INT_MAX)
     611  		printsignal(arg);
     612  	else
     613  		PRINT_VAL_U(arg);
     614  
     615  	return RVAL_IOCTL_DECODED;
     616  }
     617  
     618  static void
     619  print_kbd_repeat(struct kbd_repeat *val)
     620  {
     621  	tprint_struct_begin();
     622  	PRINT_FIELD_D(*val, delay);
     623  	tprint_struct_next();
     624  	PRINT_FIELD_D(*val, period);
     625  	tprint_struct_end();
     626  }
     627  
     628  static int
     629  kd_kbdrep(struct tcb *const tcp, const kernel_ulong_t arg)
     630  {
     631  	struct kbd_repeat val;
     632  
     633  	if (entering(tcp)) {
     634  		tprint_arg_next();
     635  
     636  		if (umove_or_printaddr(tcp, arg, &val))
     637  			return RVAL_IOCTL_DECODED;
     638  
     639  		print_kbd_repeat(&val);
     640  
     641  		return 0;
     642  	}
     643  
     644  	/* exiting */
     645  	if (syserror(tcp) || umove(tcp, arg, &val))
     646  		return RVAL_IOCTL_DECODED;
     647  
     648  	tprint_value_changed();
     649  
     650  	print_kbd_repeat(&val);
     651  
     652  	return RVAL_IOCTL_DECODED;
     653  }
     654  
     655  static int
     656  kd_font(struct tcb *const tcp, const kernel_ulong_t arg, const bool get)
     657  {
     658  	if (entering(tcp)) {
     659  		tprint_arg_next();
     660  
     661  		if (get)
     662  			return 0;
     663  	}
     664  
     665  	/*
     666  	 * [GP]IO_FONT are equivalent to KDFONTOP with width == 8,
     667  	 * height == 32, and charcount == 256, so the total size
     668  	 * is (width + 7) / 8 * height * charcount == 8192.
     669  	 */
     670  	if (exiting(tcp) && syserror(tcp))
     671  		printaddr(arg);
     672  	else
     673  		printstr_ex(tcp, arg, 8192, QUOTE_FORCE_HEX);
     674  
     675  	return RVAL_IOCTL_DECODED;
     676  }
     677  
     678  static int
     679  kd_kbmeta(struct tcb *const tcp, const kernel_ulong_t arg, const bool get)
     680  {
     681  	unsigned int val;
     682  
     683  	if (entering(tcp)) {
     684  		tprint_arg_next();
     685  
     686  		if (get)
     687  			return 0;
     688  	}
     689  
     690  	if (get) {
     691  		if (umove_or_printaddr(tcp, arg, &val))
     692  			return RVAL_IOCTL_DECODED;
     693  	} else {
     694  		val = arg;
     695  	}
     696  
     697  	if (get)
     698  		tprint_indirect_begin();
     699  	printxval(kd_meta_vals, val, "K_???");
     700  	if (get)
     701  		tprint_indirect_end();
     702  
     703  	return RVAL_IOCTL_DECODED;
     704  }
     705  
     706  static int
     707  kd_unimapclr(struct tcb *const tcp, const kernel_ulong_t arg)
     708  {
     709  	struct unimapinit umi;
     710  
     711  	tprint_arg_next();
     712  
     713  	if (umove_or_printaddr(tcp, arg, &umi))
     714  		return RVAL_IOCTL_DECODED;
     715  
     716  	tprint_struct_begin();
     717  	PRINT_FIELD_U(umi, advised_hashsize);
     718  	tprint_struct_next();
     719  	PRINT_FIELD_U(umi, advised_hashstep);
     720  	tprint_struct_next();
     721  	PRINT_FIELD_U(umi, advised_hashlevel);
     722  	tprint_struct_end();
     723  
     724  	return RVAL_IOCTL_DECODED;
     725  }
     726  
     727  static int
     728  kd_cmap(struct tcb *const tcp, const kernel_ulong_t arg, const bool get)
     729  {
     730  	if (entering(tcp)) {
     731  		tprint_arg_next();
     732  
     733  		if (get)
     734  			return 0;
     735  	} else {
     736  		if (syserror(tcp)) {
     737  			printaddr(arg);
     738  
     739  			return RVAL_IOCTL_DECODED;
     740  		}
     741  	}
     742  
     743  	printstr_ex(tcp, arg, 3 * 16, QUOTE_FORCE_HEX);
     744  
     745  	return RVAL_IOCTL_DECODED;
     746  }
     747  
     748  int
     749  kd_ioctl(struct tcb *const tcp, const unsigned int code,
     750  	 kernel_ulong_t arg)
     751  {
     752  	arg = truncate_kulong_to_current_wordsize(arg);
     753  
     754  	switch (code) {
     755  	case KIOCSOUND:
     756  		return kiocsound(tcp, arg);
     757  
     758  	case KDMKTONE:
     759  		return kd_mk_tone(tcp, arg);
     760  
     761  	case KDGETLED:
     762  	case KDSETLED:
     763  	case KDGKBLED:
     764  	case KDSKBLED:
     765  		return kd_leds(tcp, code, arg);
     766  
     767  	case KDGKBTYPE:
     768  		return kd_get_kb_type(tcp, arg);
     769  
     770  	case KDADDIO:
     771  	case KDDELIO:
     772  		return kd_io(tcp, arg);
     773  
     774  	case KDSETMODE:
     775  		return kd_set_mode(tcp, arg);
     776  	case KDGETMODE:
     777  		return kd_get_mode(tcp, arg);
     778  
     779  	case GIO_SCRNMAP:
     780  	case PIO_SCRNMAP:
     781  		return kd_screen_map(tcp, arg, code == GIO_SCRNMAP);
     782  
     783  	case GIO_UNISCRNMAP:
     784  	case PIO_UNISCRNMAP:
     785  		return kd_uni_screen_map(tcp, arg, code == GIO_UNISCRNMAP);
     786  
     787  	case KDGKBMODE:
     788  		return kd_get_kbd_mode(tcp, arg);
     789  	case KDSKBMODE:
     790  		return kd_set_kbd_mode(tcp, arg);
     791  
     792  	case KDGKBENT:
     793  	case KDSKBENT:
     794  		return kd_kbd_entry(tcp, arg, code == KDGKBENT);
     795  
     796  	case KDGKBSENT:
     797  	case KDSKBSENT:
     798  		return kd_kbd_str_entry(tcp, arg, code == KDGKBSENT);
     799  
     800  	case KDGKBDIACR:
     801  	case KDSKBDIACR:
     802  		return kd_diacr(tcp, arg, code == KDGKBDIACR);
     803  
     804  	case KDGKBDIACRUC:
     805  	case KDSKBDIACRUC:
     806  		return kd_diacr_uc(tcp, arg, code == KDGKBDIACRUC);
     807  
     808  	case KDGETKEYCODE:
     809  	case KDSETKEYCODE:
     810  		return kd_keycode(tcp, arg, code == KDGETKEYCODE);
     811  
     812  	case KDSIGACCEPT:
     813  		return kd_sigaccept(tcp, arg);
     814  
     815  	case KDKBDREP:
     816  		return kd_kbdrep(tcp, arg);
     817  
     818  	case GIO_FONT:
     819  	case PIO_FONT:
     820  		return kd_font(tcp, arg, code == GIO_FONT);
     821  
     822  	case KDGKBMETA:
     823  	case KDSKBMETA:
     824  		return kd_kbmeta(tcp, arg, code == KDGKBMETA);
     825  
     826  	case PIO_UNIMAPCLR:
     827  		return kd_unimapclr(tcp, arg);
     828  
     829  	case GIO_CMAP:
     830  	case PIO_CMAP:
     831  		return kd_cmap(tcp, arg, code == GIO_CMAP);
     832  
     833  	/* no arguments */
     834  	case KDENABIO:
     835  	case KDDISABIO:
     836  	case KDMAPDISP:
     837  	case KDUNMAPDISP:
     838  	case PIO_FONTRESET:
     839  		return RVAL_IOCTL_DECODED;
     840  	}
     841  
     842  	/* GIO_UNIMAP, PIO_UNIMAP, GIO_FONTX, PIO_FONTX, KDFONTOP */
     843  	return kd_mpers_ioctl(tcp, code, arg);
     844  }