(root)/
strace-6.5/
src/
rtc.c
       1  /*
       2   * Copyright (c) 2004 Ulrich Drepper <drepper@redhat.com>
       3   * Copyright (c) 2004-2016 Dmitry V. Levin <ldv@strace.io>
       4   * Copyright (c) 2015-2021 The strace developers.
       5   * All rights reserved.
       6   *
       7   * SPDX-License-Identifier: LGPL-2.1-or-later
       8   */
       9  
      10  #include "defs.h"
      11  
      12  #include DEF_MPERS_TYPE(struct_rtc_pll_info)
      13  
      14  #include <linux/ioctl.h>
      15  #include <linux/rtc.h>
      16  
      17  typedef struct rtc_pll_info struct_rtc_pll_info;
      18  
      19  #include MPERS_DEFS
      20  
      21  typedef struct {
      22  	uint64_t param;
      23  	union {
      24  		uint64_t uvalue;
      25  		int64_t  svalue;
      26  		uint64_t ptr;
      27  	};
      28  	uint32_t index;
      29  	uint32_t __pad;
      30  } struct_rtc_param;
      31  
      32  #define XLAT_MACROS_ONLY
      33  # include "xlat/rtc_ioctl_cmds.h"
      34  # include "xlat/rtc_feature_bits.h"
      35  #undef XLAT_MACROS_ONLY
      36  
      37  #include "xlat/rtc_vl_flags.h"
      38  #include "xlat/rtc_params.h"
      39  #include "xlat/rtc_features.h"
      40  #include "xlat/rtc_backup_switch_modes.h"
      41  
      42  static void
      43  print_rtc_time(struct tcb *tcp, const struct rtc_time *rt)
      44  {
      45  	tprint_struct_begin();
      46  	PRINT_FIELD_D(*rt, tm_sec);
      47  	tprint_struct_next();
      48  	PRINT_FIELD_D(*rt, tm_min);
      49  	tprint_struct_next();
      50  	PRINT_FIELD_D(*rt, tm_hour);
      51  	tprint_struct_next();
      52  	PRINT_FIELD_D(*rt, tm_mday);
      53  	tprint_struct_next();
      54  	PRINT_FIELD_D(*rt, tm_mon);
      55  	tprint_struct_next();
      56  	PRINT_FIELD_D(*rt, tm_year);
      57  	if (abbrev(tcp)) {
      58  		tprint_struct_next();
      59  		tprint_more_data_follows();
      60  	} else {
      61  		tprint_struct_next();
      62  		PRINT_FIELD_D(*rt, tm_wday);
      63  		tprint_struct_next();
      64  		PRINT_FIELD_D(*rt, tm_yday);
      65  		tprint_struct_next();
      66  		PRINT_FIELD_D(*rt, tm_isdst);
      67  	}
      68  	tprint_struct_end();
      69  }
      70  
      71  static void
      72  decode_rtc_time(struct tcb *const tcp, const kernel_ulong_t addr)
      73  {
      74  	struct rtc_time rt;
      75  
      76  	if (!umove_or_printaddr(tcp, addr, &rt))
      77  		print_rtc_time(tcp, &rt);
      78  }
      79  
      80  static void
      81  decode_rtc_wkalrm(struct tcb *const tcp, const kernel_ulong_t addr)
      82  {
      83  	struct rtc_wkalrm wk;
      84  
      85  	if (umove_or_printaddr(tcp, addr, &wk))
      86  		return;
      87  
      88  	tprint_struct_begin();
      89  	PRINT_FIELD_U(wk, enabled);
      90  	tprint_struct_next();
      91  	PRINT_FIELD_U(wk, pending);
      92  	tprint_struct_next();
      93  	PRINT_FIELD_OBJ_TCB_PTR(wk, time, tcp, print_rtc_time);
      94  	tprint_struct_end();
      95  }
      96  
      97  static void
      98  decode_rtc_pll_info(struct tcb *const tcp, const kernel_ulong_t addr)
      99  {
     100  	struct_rtc_pll_info pll;
     101  
     102  	if (umove_or_printaddr(tcp, addr, &pll))
     103  		return;
     104  
     105  	tprint_struct_begin();
     106  	PRINT_FIELD_D(pll, pll_ctrl);
     107  	tprint_struct_next();
     108  	PRINT_FIELD_D(pll, pll_value);
     109  	tprint_struct_next();
     110  	PRINT_FIELD_D(pll, pll_max);
     111  	tprint_struct_next();
     112  	PRINT_FIELD_D(pll, pll_min);
     113  	tprint_struct_next();
     114  	PRINT_FIELD_D(pll, pll_posmult);
     115  	tprint_struct_next();
     116  	PRINT_FIELD_D(pll, pll_negmult);
     117  	tprint_struct_next();
     118  	PRINT_FIELD_D(pll, pll_clock);
     119  	tprint_struct_end();
     120  }
     121  
     122  static void
     123  decode_rtc_vl(struct tcb *const tcp, const kernel_ulong_t addr)
     124  {
     125  	unsigned int val;
     126  
     127  	if (umove_or_printaddr(tcp, addr, &val))
     128  		return;
     129  
     130  	tprint_indirect_begin();
     131  	printflags(rtc_vl_flags, val, "RTC_VL_???");
     132  	tprint_indirect_end();
     133  }
     134  
     135  static long
     136  decode_rtc_param(struct tcb *const tcp, const kernel_ulong_t addr, const bool get)
     137  {
     138  	struct_rtc_param param;
     139  
     140  	if (umove_or_printaddr(tcp, addr, &param))
     141  		return RVAL_IOCTL_DECODED;
     142  
     143  	tprint_struct_begin();
     144  	if (entering(tcp))
     145  		PRINT_FIELD_XVAL(param, param, rtc_params, "RTC_PARAM_???");
     146  	if (entering(tcp) ^ get) {
     147  		if (entering(tcp))
     148  			tprint_struct_next();
     149  		switch (param.param) {
     150  		case RTC_PARAM_FEATURES:
     151  			PRINT_FIELD_FLAGS(param, uvalue, rtc_features,
     152  					  "1<<RTC_FEATURE_???");
     153  			break;
     154  		case RTC_PARAM_CORRECTION:
     155  			PRINT_FIELD_D(param, svalue);
     156  			break;
     157  		case RTC_PARAM_BACKUP_SWITCH_MODE:
     158  			PRINT_FIELD_XVAL(param, uvalue, rtc_backup_switch_modes,
     159  					 "RTC_BSM_???");
     160  			break;
     161  		default:
     162  			PRINT_FIELD_X(param, uvalue);
     163  		}
     164  	}
     165  	if (entering(tcp)) {
     166  		tprint_struct_next();
     167  		PRINT_FIELD_U(param, index);
     168  	}
     169  	if (param.__pad) {
     170  		tprint_struct_next();
     171  		PRINT_FIELD_X(param, __pad);
     172  	}
     173  	tprint_struct_end();
     174  
     175  	return entering(tcp) && get ? 0 : RVAL_IOCTL_DECODED;
     176  }
     177  
     178  MPERS_PRINTER_DECL(int, rtc_ioctl, struct tcb *const tcp,
     179  		   const unsigned int code, const kernel_ulong_t arg)
     180  {
     181  	switch (code) {
     182  	case RTC_ALM_READ:
     183  	case RTC_RD_TIME:
     184  		if (entering(tcp))
     185  			return 0;
     186  		ATTRIBUTE_FALLTHROUGH;
     187  	case RTC_ALM_SET:
     188  	case RTC_SET_TIME:
     189  		tprint_arg_next();
     190  		decode_rtc_time(tcp, arg);
     191  		break;
     192  	case RTC_IRQP_SET:
     193  	case RTC_EPOCH_SET:
     194  		tprint_arg_next();
     195  		PRINT_VAL_U(arg);
     196  		break;
     197  	case RTC_IRQP_READ:
     198  	case RTC_EPOCH_READ:
     199  		if (entering(tcp))
     200  			return 0;
     201  		tprint_arg_next();
     202  		printnum_ulong(tcp, arg);
     203  		break;
     204  	case RTC_WKALM_RD:
     205  		if (entering(tcp))
     206  			return 0;
     207  		ATTRIBUTE_FALLTHROUGH;
     208  	case RTC_WKALM_SET:
     209  		tprint_arg_next();
     210  		decode_rtc_wkalrm(tcp, arg);
     211  		break;
     212  	case RTC_PLL_GET:
     213  		if (entering(tcp))
     214  			return 0;
     215  		ATTRIBUTE_FALLTHROUGH;
     216  	case RTC_PLL_SET:
     217  		tprint_arg_next();
     218  		decode_rtc_pll_info(tcp, arg);
     219  		break;
     220  	case RTC_VL_READ:
     221  		if (entering(tcp))
     222  			return 0;
     223  		tprint_arg_next();
     224  		decode_rtc_vl(tcp, arg);
     225  		break;
     226  	case RTC_PARAM_GET:
     227  	case RTC_PARAM_SET:
     228  		if (entering(tcp))
     229  			tprint_arg_next();
     230  		else
     231  			tprint_value_changed();
     232  		return decode_rtc_param(tcp, arg, code == RTC_PARAM_GET);
     233  	case RTC_AIE_ON:
     234  	case RTC_AIE_OFF:
     235  	case RTC_UIE_ON:
     236  	case RTC_UIE_OFF:
     237  	case RTC_PIE_ON:
     238  	case RTC_PIE_OFF:
     239  	case RTC_WIE_ON:
     240  	case RTC_WIE_OFF:
     241  	case RTC_VL_CLR:
     242  		/* no args */
     243  		break;
     244  	default:
     245  		return RVAL_DECODED;
     246  	}
     247  
     248  	return RVAL_IOCTL_DECODED;
     249  }