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