]> git.ipfire.org Git - thirdparty/util-linux.git/blame - sys-utils/hwclock-rtc.c
hwclock: add --param-get option
[thirdparty/util-linux.git] / sys-utils / hwclock-rtc.c
CommitLineData
ef71b8f1 1/*
68a2ade7
KZ
2 * SPDX-License-Identifier: GPL-2.0-or-later
3 *
ef71b8f1
SK
4 * rtc.c - Use /dev/rtc for clock access
5 */
998f392a 6#include <asm/ioctl.h>
5213517f 7#include <errno.h>
998f392a
SK
8#include <fcntl.h>
9#include <stdio.h>
10#include <stdlib.h>
7eda085c 11#include <sys/ioctl.h>
998f392a
SK
12#include <sys/select.h>
13#include <sys/time.h>
14#include <time.h>
15#include <unistd.h>
7eda085c 16
f78a9021 17#include "monotonic.h"
7eda085c
KZ
18#include "nls.h"
19
c7f75390
KZ
20#include "hwclock.h"
21
7eda085c
KZ
22/*
23 * Get defines for rtc stuff.
24 *
ef71b8f1
SK
25 * Getting the rtc defines is nontrivial. The obvious way is by including
26 * <linux/mc146818rtc.h> but that again includes <asm/io.h> which again
27 * includes ... and on sparc and alpha this gives compilation errors for
28 * many kernel versions. So, we give the defines ourselves here. Moreover,
29 * some Sparc person decided to be incompatible, and used a struct rtc_time
30 * different from that used in mc146818rtc.h.
7eda085c
KZ
31 */
32
ef71b8f1
SK
33/*
34 * On Sparcs, there is a <asm/rtc.h> that defines different ioctls (that are
35 * required on my machine). However, this include file does not exist on
36 * other architectures.
37 */
7eda085c
KZ
38/* One might do:
39#ifdef __sparc__
ef71b8f1 40# include <asm/rtc.h>
7eda085c
KZ
41#endif
42 */
bd078689 43#ifdef __sparc__
7eda085c
KZ
44/* The following is roughly equivalent */
45struct sparc_rtc_time
46{
ef71b8f1
SK
47 int sec; /* Seconds 0-59 */
48 int min; /* Minutes 0-59 */
49 int hour; /* Hour 0-23 */
50 int dow; /* Day of the week 1-7 */
51 int dom; /* Day of the month 1-31 */
52 int month; /* Month of year 1-12 */
53 int year; /* Year 0-99 */
7eda085c 54};
7eda085c
KZ
55#define RTCGET _IOR('p', 20, struct sparc_rtc_time)
56#define RTCSET _IOW('p', 21, struct sparc_rtc_time)
bd078689 57#endif
7eda085c 58
ef71b8f1
SK
59/*
60 * struct rtc_time is present since 1.3.99.
61 * Earlier (since 1.3.89), a struct tm was used.
62 */
7eda085c 63struct linux_rtc_time {
ef71b8f1
SK
64 int tm_sec;
65 int tm_min;
66 int tm_hour;
67 int tm_mday;
68 int tm_mon;
69 int tm_year;
70 int tm_wday;
71 int tm_yday;
72 int tm_isdst;
7eda085c
KZ
73};
74
75/* RTC_RD_TIME etc have this definition since 1.99.9 (pre2.0-9) */
76#ifndef RTC_RD_TIME
ef71b8f1
SK
77# define RTC_RD_TIME _IOR('p', 0x09, struct linux_rtc_time)
78# define RTC_SET_TIME _IOW('p', 0x0a, struct linux_rtc_time)
79# define RTC_UIE_ON _IO('p', 0x03) /* Update int. enable on */
80# define RTC_UIE_OFF _IO('p', 0x04) /* Update int. enable off */
7eda085c 81#endif
ef71b8f1 82
7eda085c
KZ
83/* RTC_EPOCH_READ and RTC_EPOCH_SET are present since 2.0.34 and 2.1.89 */
84#ifndef RTC_EPOCH_READ
ef71b8f1
SK
85# define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */
86# define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */
7eda085c
KZ
87#endif
88
ef71b8f1
SK
89/*
90 * /dev/rtc is conventionally chardev 10/135
88681c5f
KZ
91 * ia64 uses /dev/efirtc, chardev 10/136
92 * devfs (obsolete) used /dev/misc/... for miscdev
93 * new RTC framework + udev uses dynamic major and /dev/rtc0.../dev/rtcN
94 * ... so we need an overridable default
95 */
7eda085c 96
88681c5f 97/* default or user defined dev (by hwclock --rtc=<path>) */
067b6028 98static const char *rtc_dev_name;
27f9db17
KZ
99static int rtc_dev_fd = -1;
100
ef71b8f1
SK
101static void close_rtc(void)
102{
27f9db17
KZ
103 if (rtc_dev_fd != -1)
104 close(rtc_dev_fd);
105 rtc_dev_fd = -1;
106}
107
336f7c5f 108static int open_rtc(const struct hwclock_control *ctl)
ef71b8f1 109{
067b6028 110 static const char *fls[] = {
88681c5f
KZ
111#ifdef __ia64__
112 "/dev/efirtc",
113 "/dev/misc/efirtc",
114#endif
88681c5f 115 "/dev/rtc0",
1811900a 116 "/dev/rtc",
067b6028 117 "/dev/misc/rtc"
88681c5f 118 };
067b6028 119 size_t i;
5d1f6bae 120
27f9db17
KZ
121 if (rtc_dev_fd != -1)
122 return rtc_dev_fd;
123
5d1f6bae 124 /* --rtc option has been given */
336f7c5f
SK
125 if (ctl->rtc_dev_name) {
126 rtc_dev_name = ctl->rtc_dev_name;
27f9db17 127 rtc_dev_fd = open(rtc_dev_name, O_RDONLY);
336f7c5f 128 } else {
067b6028 129 for (i = 0; i < ARRAY_SIZE(fls); i++) {
de4568f7 130 if (ctl->verbose)
067b6028
SK
131 printf(_("Trying to open: %s\n"), fls[i]);
132 rtc_dev_fd = open(fls[i], O_RDONLY);
27f9db17 133
b3fc2a3c
KZ
134 if (rtc_dev_fd < 0) {
135 if (errno == ENOENT || errno == ENODEV)
136 continue;
137 if (ctl->verbose)
138 warn(_("cannot open %s"), fls[i]);
139 }
067b6028 140 rtc_dev_name = fls[i];
27f9db17
KZ
141 break;
142 }
143 if (rtc_dev_fd < 0)
144 rtc_dev_name = *fls; /* default for error messages */
5d1f6bae 145 }
926ffe74 146 if (rtc_dev_fd != -1)
27f9db17
KZ
147 atexit(close_rtc);
148 return rtc_dev_fd;
63cccae4
KZ
149}
150
336f7c5f 151static int open_rtc_or_exit(const struct hwclock_control *ctl)
ef71b8f1 152{
336f7c5f 153 int rtc_fd = open_rtc(ctl);
63cccae4
KZ
154
155 if (rtc_fd < 0) {
067b6028 156 warn(_("cannot open rtc device"));
c47a8f2a 157 hwclock_exit(ctl, EXIT_FAILURE);
364cda48
KZ
158 }
159 return rtc_fd;
160}
161
ef71b8f1
SK
162static int do_rtc_read_ioctl(int rtc_fd, struct tm *tm)
163{
364cda48
KZ
164 int rc = -1;
165 char *ioctlname;
7eda085c 166#ifdef __sparc__
364cda48
KZ
167 /* some but not all sparcs use a different ioctl and struct */
168 struct sparc_rtc_time stm;
fc35f2db
SK
169#endif
170
171 ioctlname = "RTC_RD_TIME";
172 rc = ioctl(rtc_fd, RTC_RD_TIME, tm);
364cda48 173
fc35f2db
SK
174#ifdef __sparc__
175 if (rc == -1) { /* sparc sbus */
176 ioctlname = "RTCGET";
177 rc = ioctl(rtc_fd, RTCGET, &stm);
178 if (rc == 0) {
179 tm->tm_sec = stm.sec;
180 tm->tm_min = stm.min;
181 tm->tm_hour = stm.hour;
182 tm->tm_mday = stm.dom;
183 tm->tm_mon = stm.month - 1;
184 tm->tm_year = stm.year - 1900;
185 tm->tm_wday = stm.dow - 1;
186 tm->tm_yday = -1; /* day in the year */
187 }
364cda48 188 }
7eda085c 189#endif
fc35f2db 190
364cda48 191 if (rc == -1) {
111c05d3
SK
192 warn(_("ioctl(%s) to %s to read the time failed"),
193 ioctlname, rtc_dev_name);
cdedde03 194 return -1;
364cda48
KZ
195 }
196
ef71b8f1 197 tm->tm_isdst = -1; /* don't know whether it's dst */
364cda48
KZ
198 return 0;
199}
7eda085c 200
ef71b8f1 201/*
0411a57e
WP
202 * Wait for the top of a clock tick by reading /dev/rtc in a busy loop
203 * until we see it. This function is used for rtc drivers without ioctl
204 * interrupts. This is typical on an Alpha, where the Hardware Clock
205 * interrupts are used by the kernel for the system clock, so aren't at
206 * the user's disposal.
ef71b8f1 207 */
336f7c5f
SK
208static int busywait_for_rtc_clock_tick(const struct hwclock_control *ctl,
209 const int rtc_fd)
ef71b8f1
SK
210{
211 struct tm start_time;
212 /* The time when we were called (and started waiting) */
213 struct tm nowtime;
214 int rc;
cf8c1917 215 struct timeval begin = { 0 }, now = { 0 };
ef71b8f1 216
de4568f7 217 if (ctl->verbose) {
0411a57e
WP
218 printf("ioctl(%d, RTC_UIE_ON, 0): %s\n",
219 rtc_fd, strerror(errno));
ef71b8f1
SK
220 printf(_("Waiting in loop for time from %s to change\n"),
221 rtc_dev_name);
0411a57e 222 }
ef71b8f1 223
4a6f658c
WP
224 if (do_rtc_read_ioctl(rtc_fd, &start_time))
225 return 1;
ef71b8f1
SK
226
227 /*
228 * Wait for change. Should be within a second, but in case
229 * something weird happens, we have a time limit (1.5s) on this loop
230 * to reduce the impact of this failure.
231 */
f78a9021 232 gettime_monotonic(&begin);
ef71b8f1
SK
233 do {
234 rc = do_rtc_read_ioctl(rtc_fd, &nowtime);
235 if (rc || start_time.tm_sec != nowtime.tm_sec)
236 break;
f78a9021 237 gettime_monotonic(&now);
ef71b8f1 238 if (time_diff(now, begin) > 1.5) {
111c05d3 239 warnx(_("Timed out waiting for time change."));
4a6f658c 240 return 1;
ef71b8f1
SK
241 }
242 } while (1);
243
244 if (rc)
4a6f658c
WP
245 return 1;
246 return 0;
7eda085c
KZ
247}
248
ef71b8f1
SK
249/*
250 * Same as synchronize_to_clock_tick(), but just for /dev/rtc.
251 */
336f7c5f 252static int synchronize_to_clock_tick_rtc(const struct hwclock_control *ctl)
ef71b8f1
SK
253{
254 int rtc_fd; /* File descriptor of /dev/rtc */
4bfd519e 255 int ret = 1;
ef71b8f1 256
336f7c5f 257 rtc_fd = open_rtc(ctl);
ef71b8f1 258 if (rtc_fd == -1) {
067b6028 259 warn(_("cannot open rtc device"));
4bfd519e 260 return ret;
042f62df
RP
261 }
262
263 /* Turn on update interrupts (one per second) */
264 int rc = ioctl(rtc_fd, RTC_UIE_ON, 0);
265
266 if (rc != -1) {
267 /*
268 * Just reading rtc_fd fails on broken hardware: no
269 * update interrupt comes and a bootscript with a
270 * hwclock call hangs
271 */
272 fd_set rfds;
273 struct timeval tv;
274
275 /*
276 * Wait up to ten seconds for the next update
277 * interrupt
278 */
279 FD_ZERO(&rfds);
280 FD_SET(rtc_fd, &rfds);
281 tv.tv_sec = 10;
282 tv.tv_usec = 0;
283 rc = select(rtc_fd + 1, &rfds, NULL, NULL, &tv);
284 if (0 < rc)
285 ret = 0;
286 else if (rc == 0) {
287 warnx(_("select() to %s to wait for clock tick timed out"),
288 rtc_dev_name);
289 } else
290 warn(_("select() to %s to wait for clock tick failed"),
291 rtc_dev_name);
292 /* Turn off update interrupts */
293 rc = ioctl(rtc_fd, RTC_UIE_OFF, 0);
294 if (rc == -1)
295 warn(_("ioctl() to %s to turn off update interrupts failed"),
296 rtc_dev_name);
c8650db3
ŁS
297 } else if (errno == ENOTTY || errno == EINVAL) {
298 /* rtc ioctl interrupts are unimplemented */
299 ret = busywait_for_rtc_clock_tick(ctl, rtc_fd);
300 } else
301 warn(_("ioctl(%d, RTC_UIE_ON, 0) to %s failed"),
302 rtc_fd, rtc_dev_name);
ef71b8f1 303 return ret;
7eda085c
KZ
304}
305
336f7c5f
SK
306static int read_hardware_clock_rtc(const struct hwclock_control *ctl,
307 struct tm *tm)
ef71b8f1 308{
55a4a75c 309 int rtc_fd, rc;
7eda085c 310
336f7c5f 311 rtc_fd = open_rtc_or_exit(ctl);
7eda085c 312
364cda48 313 /* Read the RTC time/date, return answer via tm */
55a4a75c 314 rc = do_rtc_read_ioctl(rtc_fd, tm);
7eda085c 315
55a4a75c 316 return rc;
7eda085c
KZ
317}
318
ef71b8f1
SK
319/*
320 * Set the Hardware Clock to the broken down time <new_broken_time>. Use
321 * ioctls to "rtc" device /dev/rtc.
322 */
336f7c5f
SK
323static int set_hardware_clock_rtc(const struct hwclock_control *ctl,
324 const struct tm *new_broken_time)
ef71b8f1 325{
364cda48
KZ
326 int rc = -1;
327 int rtc_fd;
328 char *ioctlname;
329
336f7c5f 330 rtc_fd = open_rtc_or_exit(ctl);
63cccae4 331
fc35f2db
SK
332 ioctlname = "RTC_SET_TIME";
333 rc = ioctl(rtc_fd, RTC_SET_TIME, new_broken_time);
334
7eda085c 335#ifdef __sparc__
fc35f2db 336 if (rc == -1) { /* sparc sbus */
364cda48
KZ
337 struct sparc_rtc_time stm;
338
339 stm.sec = new_broken_time->tm_sec;
340 stm.min = new_broken_time->tm_min;
341 stm.hour = new_broken_time->tm_hour;
342 stm.dom = new_broken_time->tm_mday;
343 stm.month = new_broken_time->tm_mon + 1;
344 stm.year = new_broken_time->tm_year + 1900;
345 stm.dow = new_broken_time->tm_wday + 1;
346
347 ioctlname = "RTCSET";
348 rc = ioctl(rtc_fd, RTCSET, &stm);
349 }
7eda085c 350#endif
364cda48
KZ
351
352 if (rc == -1) {
c9a86ff6 353 warn(_("ioctl(%s) to %s to set the time failed"),
111c05d3 354 ioctlname, rtc_dev_name);
c47a8f2a 355 hwclock_exit(ctl, EXIT_FAILURE);
364cda48
KZ
356 }
357
de4568f7 358 if (ctl->verbose)
364cda48
KZ
359 printf(_("ioctl(%s) was successful.\n"), ioctlname);
360
364cda48 361 return 0;
7eda085c
KZ
362}
363
ef71b8f1
SK
364static int get_permissions_rtc(void)
365{
7eda085c
KZ
366 return 0;
367}
368
df4f1a66
KZ
369static const char *get_device_path(void)
370{
371 return rtc_dev_name;
372}
373
bd078689 374static struct clock_ops rtc_interface = {
8f729d60 375 N_("Using the rtc interface to the clock."),
7eda085c
KZ
376 get_permissions_rtc,
377 read_hardware_clock_rtc,
378 set_hardware_clock_rtc,
379 synchronize_to_clock_tick_rtc,
df4f1a66 380 get_device_path,
7eda085c
KZ
381};
382
383/* return &rtc if /dev/rtc can be opened, NULL otherwise */
336f7c5f 384struct clock_ops *probe_for_rtc_clock(const struct hwclock_control *ctl)
ef71b8f1 385{
bd078689
SK
386 const int rtc_fd = open_rtc(ctl);
387
388 if (rtc_fd < 0)
389 return NULL;
390 return &rtc_interface;
7eda085c
KZ
391}
392
bd078689 393#ifdef __alpha__
ef71b8f1
SK
394/*
395 * Get the Hardware Clock epoch setting from the kernel.
396 */
af68bd01 397int get_epoch_rtc(const struct hwclock_control *ctl, unsigned long *epoch_p)
ef71b8f1
SK
398{
399 int rtc_fd;
400
336f7c5f 401 rtc_fd = open_rtc(ctl);
ef71b8f1 402 if (rtc_fd < 0) {
cbc36f79 403 warn(_("cannot open %s"), rtc_dev_name);
ef71b8f1
SK
404 return 1;
405 }
406
407 if (ioctl(rtc_fd, RTC_EPOCH_READ, epoch_p) == -1) {
f613c3c2
WP
408 warn(_("ioctl(%d, RTC_EPOCH_READ, epoch_p) to %s failed"),
409 rtc_fd, rtc_dev_name);
ef71b8f1
SK
410 return 1;
411 }
7eda085c 412
de4568f7 413 if (ctl->verbose)
f613c3c2
WP
414 printf(_("ioctl(%d, RTC_EPOCH_READ, epoch_p) to %s succeeded.\n"),
415 rtc_fd, rtc_dev_name);
7eda085c 416
ef71b8f1 417 return 0;
7eda085c
KZ
418}
419
ef71b8f1
SK
420/*
421 * Set the Hardware Clock epoch in the kernel.
422 */
336f7c5f 423int set_epoch_rtc(const struct hwclock_control *ctl)
ef71b8f1
SK
424{
425 int rtc_fd;
f7599b4f 426 unsigned long epoch;
ef71b8f1 427
9bf8088f 428 errno = 0;
f7599b4f
WP
429 epoch = strtoul(ctl->epoch_option, NULL, 10);
430
431 /* There were no RTC clocks before 1900. */
9bf8088f 432 if (errno || epoch < 1900 || epoch == ULONG_MAX) {
f7599b4f 433 warnx(_("invalid epoch '%s'."), ctl->epoch_option);
ef71b8f1
SK
434 return 1;
435 }
436
336f7c5f 437 rtc_fd = open_rtc(ctl);
ef71b8f1 438 if (rtc_fd < 0) {
cbc36f79 439 warn(_("cannot open %s"), rtc_dev_name);
ef71b8f1
SK
440 return 1;
441 }
7eda085c 442
f7599b4f 443 if (ioctl(rtc_fd, RTC_EPOCH_SET, epoch) == -1) {
f613c3c2
WP
444 warn(_("ioctl(%d, RTC_EPOCH_SET, %lu) to %s failed"),
445 rtc_fd, epoch, rtc_dev_name);
ef71b8f1
SK
446 return 1;
447 }
7eda085c 448
de4568f7 449 if (ctl->verbose)
f613c3c2
WP
450 printf(_("ioctl(%d, RTC_EPOCH_SET, %lu) to %s succeeded.\n"),
451 rtc_fd, epoch, rtc_dev_name);
452
ef71b8f1 453 return 0;
7eda085c 454}
bd078689 455#endif /* __alpha__ */
6097b12d
BK
456
457static int resolve_rtc_param_alias(const char *alias, uint64_t *value)
458{
459 const struct hwclock_param *param = &hwclock_params[0];
460
461 while (param->name) {
462 if (!strcmp(alias, param->name)) {
463 *value = param->id;
464 return 0;
465 }
466 param++;
467 }
468
469 return 1;
470}
471
472/*
473 * Get the Hardware Clock parameter setting from the kernel.
474 */
475int get_param_rtc(const struct hwclock_control *ctl, struct rtc_param *param)
476{
477 int rtc_fd;
478
479 /* handle name */
480 if (resolve_rtc_param_alias(ctl->param_get_option, &param->param)) {
481 char *end = NULL;
482 int base;
483
484 base = strncmp(ctl->param_get_option, "0x", 2) ? 10 : 16;
485 errno = 0;
486 param->param = strtoull(ctl->param_get_option, &end, base);
487 if (errno || !end || *end) {
488 warnx(_("could not convert parameter name to number"));
489 return 1;
490 }
491 }
492
493 /* get parameter */
494 rtc_fd = open_rtc(ctl);
495 if (rtc_fd < 0) {
496 warn(_("cannot open %s"), rtc_dev_name);
497 return 1;
498 }
499
500 if (ioctl(rtc_fd, RTC_PARAM_GET, param) == -1) {
501 warn(_("ioctl(%d, RTC_PARAM_GET, param) to %s failed"),
502 rtc_fd, rtc_dev_name);
503 return 1;
504 }
505
506 if (ctl->verbose)
507 printf(_("ioctl(%d, RTC_PARAM_GET, param) to %s succeeded.\n"),
508 rtc_fd, rtc_dev_name);
509
510 return 0;
511}