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