return 0;
}
#endif /* __alpha__ */
+
+static int resolve_rtc_param_alias(const char *alias, uint64_t *value)
+{
+ const struct hwclock_param *param = &hwclock_params[0];
+
+ while (param->name) {
+ if (!strcmp(alias, param->name)) {
+ *value = param->id;
+ return 0;
+ }
+ param++;
+ }
+
+ return 1;
+}
+
+/*
+ * Get the Hardware Clock parameter setting from the kernel.
+ */
+int get_param_rtc(const struct hwclock_control *ctl, struct rtc_param *param)
+{
+ int rtc_fd;
+
+ /* handle name */
+ if (resolve_rtc_param_alias(ctl->param_get_option, ¶m->param)) {
+ char *end = NULL;
+ int base;
+
+ base = strncmp(ctl->param_get_option, "0x", 2) ? 10 : 16;
+ errno = 0;
+ param->param = strtoull(ctl->param_get_option, &end, base);
+ if (errno || !end || *end) {
+ warnx(_("could not convert parameter name to number"));
+ return 1;
+ }
+ }
+
+ /* get parameter */
+ rtc_fd = open_rtc(ctl);
+ if (rtc_fd < 0) {
+ warn(_("cannot open %s"), rtc_dev_name);
+ return 1;
+ }
+
+ if (ioctl(rtc_fd, RTC_PARAM_GET, param) == -1) {
+ warn(_("ioctl(%d, RTC_PARAM_GET, param) to %s failed"),
+ rtc_fd, rtc_dev_name);
+ return 1;
+ }
+
+ if (ctl->verbose)
+ printf(_("ioctl(%d, RTC_PARAM_GET, param) to %s succeeded.\n"),
+ rtc_fd, rtc_dev_name);
+
+ return 0;
+}
}
#endif /* __linux__ __alpha__ */
+static int
+manipulate_rtc_param(const struct hwclock_control *ctl)
+{
+ if (ctl->param_get_option) {
+ struct rtc_param param = {};
+
+ if (get_param_rtc(ctl, ¶m)) {
+ warnx(_("unable to read the RTC parameter 0x%llx."), param.param);
+ return 1;
+ }
+
+ printf(_("The RTC parameter 0x%llx is set to 0x%llx.\n"),
+ param.param, param.uvalue);
+ }
+
+ return 1;
+}
+
static void out_version(void)
{
printf(UTIL_LINUX_VERSION);
static void __attribute__((__noreturn__))
usage(void)
{
+ const struct hwclock_param *param = &hwclock_params[0];
+
fputs(USAGE_HEADER, stdout);
printf(_(" %s [function] [option...]\n"), program_invocation_short_name);
puts(_(" --getepoch display the RTC epoch"));
puts(_(" --setepoch set the RTC epoch according to --epoch"));
#endif
+ puts(_(" --param-get <param> display the RTC parameter"));
puts(_(" --predict predict the drifted RTC time according to --date"));
fputs(USAGE_OPTIONS, stdout);
puts(_(" -u, --utc the RTC timescale is UTC"));
puts(_(" <param> is either a numeric RTC parameter value or one of these aliases:"));
while (param->name) {
- printf(_(" %1$s: %2$s (0x%3$x)\n"), param->name, param->help, param->id);
+ printf(_(" - %1$s: %2$s (0x%3$x)\n"), param->name, param->help, param->id);
param++;
}
- puts(_(" See Kernel's include/uapi/linux/rtc.h for paramters and values."));
+ puts(_(" See Kernel's include/uapi/linux/rtc.h for parameters."));
fputs(USAGE_ARG_SEPARATOR, stdout);
- puts(_(" <param> and <value> accept hexadecimal values if prefixed with 0x, otherwise decimal."));
+ puts(_(" <param> accepts hexadecimal values if prefixed with 0x, otherwise decimal."));
printf(USAGE_MAN_TAIL("hwclock(8)"));
exit(EXIT_SUCCESS);
OPT_GET,
OPT_GETEPOCH,
OPT_NOADJFILE,
+ OPT_PARAM_GET,
OPT_PREDICT,
OPT_SET,
OPT_SETEPOCH,
{ "setepoch", no_argument, NULL, OPT_SETEPOCH },
{ "epoch", required_argument, NULL, OPT_EPOCH },
#endif
+ { "param-get", required_argument, NULL, OPT_PARAM_GET },
{ "noadjfile", no_argument, NULL, OPT_NOADJFILE },
{ "directisa", no_argument, NULL, OPT_DIRECTISA },
{ "test", no_argument, NULL, OPT_TEST },
ctl.epoch_option = optarg; /* --epoch */
break;
#endif
+ case OPT_PARAM_GET:
+ ctl.param_get_option = optarg;
+ ctl.show = 0;
+ break;
case OPT_NOADJFILE:
ctl.noadjfile = 1;
break;
}
}
+ if (ctl.param_get_option) {
+ if (manipulate_rtc_param(&ctl))
+ hwclock_exit(&ctl, EXIT_FAILURE);
+
+ hwclock_exit(&ctl, EXIT_SUCCESS);
+ }
+
#if defined(__linux__) && defined(__alpha__)
if (ctl.getepoch || ctl.setepoch) {
manipulate_epoch(&ctl);
#include "c.h"
#include "debug.h"
+#include "nls.h"
#define HWCLOCK_DEBUG_INIT (1 << 0)
#define HWCLOCK_DEBUG_RANDOM_SLEEP (1 << 1)
#ifdef __linux__
char *rtc_dev_name;
#endif
+ char *param_get_option;
unsigned int
hwaudit_on:1,
adjust:1,
extern int set_epoch_rtc(const struct hwclock_control *ctl);
#endif
+struct rtc_param {
+ uint64_t param;
+ union {
+ uint64_t uvalue;
+ int64_t svalue;
+ uint64_t ptr;
+ };
+ uint32_t index;
+ uint32_t __pad;
+};
+
+#define RTC_PARAM_GET _IOW('p', 0x13, struct rtc_param)
+
+#define RTC_PARAM_FEATURES 0
+#define RTC_PARAM_CORRECTION 1
+#define RTC_PARAM_BACKUP_SWITCH_MODE 2
+
+struct hwclock_param {
+ int id;
+ const char *name;
+ const char *help;
+};
+
+static struct hwclock_param hwclock_params[] = {
+ { RTC_PARAM_FEATURES, "features", N_("supported features") },
+ { RTC_PARAM_CORRECTION, "correction", N_("time correction") },
+ { RTC_PARAM_BACKUP_SWITCH_MODE, "bsm", N_("backup switch mode") },
+ { }
+};
+
+extern int get_param_rtc(const struct hwclock_control *ctl, struct rtc_param *param);
+
extern void __attribute__((__noreturn__))
hwclock_exit(const struct hwclock_control *ctl, int status);