]> git.ipfire.org Git - thirdparty/util-linux.git/blame - sys-utils/hwclock-rtc.c
build-sys: move hwclock to sys-utils/
[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>
63cccae4 9#include <sysexits.h>
7eda085c 10#include <sys/ioctl.h>
998f392a
SK
11#include <sys/select.h>
12#include <sys/time.h>
13#include <time.h>
14#include <unistd.h>
7eda085c 15
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 */
41/* The following is roughly equivalent */
42struct sparc_rtc_time
43{
ef71b8f1
SK
44 int sec; /* Seconds 0-59 */
45 int min; /* Minutes 0-59 */
46 int hour; /* Hour 0-23 */
47 int dow; /* Day of the week 1-7 */
48 int dom; /* Day of the month 1-31 */
49 int month; /* Month of year 1-12 */
50 int year; /* Year 0-99 */
7eda085c
KZ
51};
52
53#define RTCGET _IOR('p', 20, struct sparc_rtc_time)
54#define RTCSET _IOW('p', 21, struct sparc_rtc_time)
55
7eda085c
KZ
56/* non-sparc stuff */
57#if 0
ef71b8f1
SK
58# include <linux/version.h>
59/*
60 * Check if the /dev/rtc interface is available in this version of the
61 * system headers. 131072 is linux 2.0.0.
62 */
63# if LINUX_VERSION_CODE >= 131072
64# include <linux/mc146818rtc.h>
65# endif
7eda085c
KZ
66#endif
67
ef71b8f1
SK
68/*
69 * struct rtc_time is present since 1.3.99.
70 * Earlier (since 1.3.89), a struct tm was used.
71 */
7eda085c 72struct linux_rtc_time {
ef71b8f1
SK
73 int tm_sec;
74 int tm_min;
75 int tm_hour;
76 int tm_mday;
77 int tm_mon;
78 int tm_year;
79 int tm_wday;
80 int tm_yday;
81 int tm_isdst;
7eda085c
KZ
82};
83
84/* RTC_RD_TIME etc have this definition since 1.99.9 (pre2.0-9) */
85#ifndef RTC_RD_TIME
ef71b8f1
SK
86# define RTC_RD_TIME _IOR('p', 0x09, struct linux_rtc_time)
87# define RTC_SET_TIME _IOW('p', 0x0a, struct linux_rtc_time)
88# define RTC_UIE_ON _IO('p', 0x03) /* Update int. enable on */
89# define RTC_UIE_OFF _IO('p', 0x04) /* Update int. enable off */
7eda085c 90#endif
ef71b8f1 91
7eda085c
KZ
92/* RTC_EPOCH_READ and RTC_EPOCH_SET are present since 2.0.34 and 2.1.89 */
93#ifndef RTC_EPOCH_READ
ef71b8f1
SK
94# define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */
95# define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */
7eda085c
KZ
96#endif
97
ef71b8f1
SK
98/*
99 * /dev/rtc is conventionally chardev 10/135
88681c5f
KZ
100 * ia64 uses /dev/efirtc, chardev 10/136
101 * devfs (obsolete) used /dev/misc/... for miscdev
102 * new RTC framework + udev uses dynamic major and /dev/rtc0.../dev/rtcN
103 * ... so we need an overridable default
104 */
7eda085c 105
88681c5f
KZ
106/* default or user defined dev (by hwclock --rtc=<path>) */
107char *rtc_dev_name;
364cda48 108
27f9db17
KZ
109static int rtc_dev_fd = -1;
110
ef71b8f1
SK
111static void close_rtc(void)
112{
27f9db17
KZ
113 if (rtc_dev_fd != -1)
114 close(rtc_dev_fd);
115 rtc_dev_fd = -1;
116}
117
ef71b8f1
SK
118static int open_rtc(void)
119{
88681c5f
KZ
120 char *fls[] = {
121#ifdef __ia64__
122 "/dev/efirtc",
123 "/dev/misc/efirtc",
124#endif
125 "/dev/rtc",
126 "/dev/rtc0",
127 "/dev/misc/rtc",
128 NULL
129 };
5d1f6bae
MK
130 char **p;
131
27f9db17
KZ
132 if (rtc_dev_fd != -1)
133 return rtc_dev_fd;
134
5d1f6bae
MK
135 /* --rtc option has been given */
136 if (rtc_dev_name)
27f9db17
KZ
137 rtc_dev_fd = open(rtc_dev_name, O_RDONLY);
138 else {
ef71b8f1 139 for (p = fls; *p; ++p) {
27f9db17
KZ
140 rtc_dev_fd = open(*p, O_RDONLY);
141
ef71b8f1
SK
142 if (rtc_dev_fd < 0
143 && (errno == ENOENT || errno == ENODEV))
27f9db17
KZ
144 continue;
145 rtc_dev_name = *p;
146 break;
147 }
148 if (rtc_dev_fd < 0)
149 rtc_dev_name = *fls; /* default for error messages */
5d1f6bae 150 }
27f9db17
KZ
151
152 if (rtc_dev_fd != 1)
153 atexit(close_rtc);
154 return rtc_dev_fd;
63cccae4
KZ
155}
156
ef71b8f1
SK
157static int open_rtc_or_exit(void)
158{
63cccae4
KZ
159 int rtc_fd = open_rtc();
160
161 if (rtc_fd < 0) {
111c05d3 162 warn(_("open() of %s failed"), rtc_dev_name);
88058a71 163 hwclock_exit(EX_OSFILE);
364cda48
KZ
164 }
165 return rtc_fd;
166}
167
ef71b8f1
SK
168static int do_rtc_read_ioctl(int rtc_fd, struct tm *tm)
169{
364cda48
KZ
170 int rc = -1;
171 char *ioctlname;
7eda085c 172
7eda085c 173#ifdef __sparc__
364cda48
KZ
174 /* some but not all sparcs use a different ioctl and struct */
175 struct sparc_rtc_time stm;
176
177 ioctlname = "RTCGET";
178 rc = ioctl(rtc_fd, RTCGET, &stm);
179 if (rc == 0) {
180 tm->tm_sec = stm.sec;
181 tm->tm_min = stm.min;
182 tm->tm_hour = stm.hour;
183 tm->tm_mday = stm.dom;
184 tm->tm_mon = stm.month - 1;
185 tm->tm_year = stm.year - 1900;
186 tm->tm_wday = stm.dow - 1;
ef71b8f1 187 tm->tm_yday = -1; /* day in the year */
364cda48 188 }
7eda085c 189#endif
364cda48
KZ
190 if (rc == -1) { /* no sparc, or RTCGET failed */
191 ioctlname = "RTC_RD_TIME";
192 rc = ioctl(rtc_fd, RTC_RD_TIME, tm);
193 }
194 if (rc == -1) {
111c05d3
SK
195 warn(_("ioctl(%s) to %s to read the time failed"),
196 ioctlname, rtc_dev_name);
cdedde03 197 return -1;
364cda48
KZ
198 }
199
ef71b8f1 200 tm->tm_isdst = -1; /* don't know whether it's dst */
364cda48
KZ
201 return 0;
202}
7eda085c 203
ef71b8f1
SK
204/*
205 * Wait for the top of a clock tick by reading /dev/rtc in a busy loop until
206 * we see it.
207 */
208static int busywait_for_rtc_clock_tick(const int rtc_fd)
209{
210 struct tm start_time;
211 /* The time when we were called (and started waiting) */
212 struct tm nowtime;
213 int rc;
214 struct timeval begin, now;
215
216 if (debug)
217 printf(_("Waiting in loop for time from %s to change\n"),
218 rtc_dev_name);
219
220 rc = do_rtc_read_ioctl(rtc_fd, &start_time);
221 if (rc)
222 return 1;
223
224 /*
225 * Wait for change. Should be within a second, but in case
226 * something weird happens, we have a time limit (1.5s) on this loop
227 * to reduce the impact of this failure.
228 */
229 gettimeofday(&begin, NULL);
230 do {
231 rc = do_rtc_read_ioctl(rtc_fd, &nowtime);
232 if (rc || start_time.tm_sec != nowtime.tm_sec)
233 break;
234 gettimeofday(&now, NULL);
235 if (time_diff(now, begin) > 1.5) {
111c05d3 236 warnx(_("Timed out waiting for time change."));
ef71b8f1
SK
237 return 2;
238 }
239 } while (1);
240
241 if (rc)
242 return 3;
243 return 0;
7eda085c
KZ
244}
245
ef71b8f1
SK
246/*
247 * Same as synchronize_to_clock_tick(), but just for /dev/rtc.
248 */
249static int synchronize_to_clock_tick_rtc(void)
250{
251 int rtc_fd; /* File descriptor of /dev/rtc */
252 int ret;
253
254 rtc_fd = open_rtc();
255 if (rtc_fd == -1) {
111c05d3 256 warn(_("open() of %s failed"), rtc_dev_name);
ef71b8f1
SK
257 ret = 1;
258 } else {
259 int rc; /* Return code from ioctl */
260 /* Turn on update interrupts (one per second) */
442d61c6 261#if defined(__alpha__) || defined(__sparc__)
ef71b8f1
SK
262 /*
263 * Not all alpha kernels reject RTC_UIE_ON, but probably
264 * they should.
265 */
266 rc = -1;
267 errno = EINVAL;
7eda085c 268#else
ef71b8f1 269 rc = ioctl(rtc_fd, RTC_UIE_ON, 0);
7eda085c 270#endif
ef71b8f1
SK
271 if (rc == -1 && (errno == ENOTTY || errno == EINVAL)) {
272 /*
273 * This rtc device doesn't have interrupt functions.
274 * This is typical on an Alpha, where the Hardware
275 * Clock interrupts are used by the kernel for the
276 * system clock, so aren't at the user's disposal.
277 */
278 if (debug)
279 printf(_
280 ("%s does not have interrupt functions. "),
281 rtc_dev_name);
282 ret = busywait_for_rtc_clock_tick(rtc_fd);
283 } else if (rc == 0) {
d03dd608 284#ifdef Wait_until_update_interrupt
ef71b8f1
SK
285 unsigned long dummy;
286
287 /* this blocks until the next update interrupt */
288 rc = read(rtc_fd, &dummy, sizeof(dummy));
289 ret = 1;
290 if (rc == -1)
111c05d3
SK
291 warn(_
292 ("read() to %s to wait for clock tick failed"),
293 rtc_dev_name);
ef71b8f1
SK
294 else
295 ret = 0;
d03dd608 296#else
ef71b8f1
SK
297 /*
298 * Just reading rtc_fd fails on broken hardware: no
299 * update interrupt comes and a bootscript with a
300 * hwclock call hangs
301 */
302 fd_set rfds;
303 struct timeval tv;
304
305 /*
306 * Wait up to five seconds for the next update
307 * interrupt
308 */
309 FD_ZERO(&rfds);
310 FD_SET(rtc_fd, &rfds);
311 tv.tv_sec = 5;
312 tv.tv_usec = 0;
313 rc = select(rtc_fd + 1, &rfds, NULL, NULL, &tv);
314 ret = 1;
315 if (rc == -1)
111c05d3
SK
316 warn(_
317 ("select() to %s to wait for clock tick failed"),
318 rtc_dev_name);
ef71b8f1 319 else if (rc == 0)
111c05d3
SK
320 warn(_
321 ("select() to %s to wait for clock tick timed out"),
322 rtc_dev_name);
ef71b8f1
SK
323 else
324 ret = 0;
d03dd608
KZ
325#endif
326
ef71b8f1
SK
327 /* Turn off update interrupts */
328 rc = ioctl(rtc_fd, RTC_UIE_OFF, 0);
329 if (rc == -1)
111c05d3
SK
330 warn(_
331 ("ioctl() to %s to turn off update interrupts failed"),
332 rtc_dev_name);
ef71b8f1 333 } else {
111c05d3
SK
334 warn(_
335 ("ioctl() to %s to turn on update interrupts "
336 "failed unexpectedly"), rtc_dev_name);
ef71b8f1
SK
337 ret = 1;
338 }
339 }
340 return ret;
7eda085c
KZ
341}
342
ef71b8f1
SK
343static int read_hardware_clock_rtc(struct tm *tm)
344{
55a4a75c 345 int rtc_fd, rc;
7eda085c 346
63cccae4 347 rtc_fd = open_rtc_or_exit();
7eda085c 348
364cda48 349 /* Read the RTC time/date, return answer via tm */
55a4a75c 350 rc = do_rtc_read_ioctl(rtc_fd, tm);
7eda085c 351
55a4a75c 352 return rc;
7eda085c
KZ
353}
354
ef71b8f1
SK
355/*
356 * Set the Hardware Clock to the broken down time <new_broken_time>. Use
357 * ioctls to "rtc" device /dev/rtc.
358 */
359static int set_hardware_clock_rtc(const struct tm *new_broken_time)
360{
364cda48
KZ
361 int rc = -1;
362 int rtc_fd;
363 char *ioctlname;
364
63cccae4
KZ
365 rtc_fd = open_rtc_or_exit();
366
7eda085c 367#ifdef __sparc__
364cda48
KZ
368 {
369 struct sparc_rtc_time stm;
370
371 stm.sec = new_broken_time->tm_sec;
372 stm.min = new_broken_time->tm_min;
373 stm.hour = new_broken_time->tm_hour;
374 stm.dom = new_broken_time->tm_mday;
375 stm.month = new_broken_time->tm_mon + 1;
376 stm.year = new_broken_time->tm_year + 1900;
377 stm.dow = new_broken_time->tm_wday + 1;
378
379 ioctlname = "RTCSET";
380 rc = ioctl(rtc_fd, RTCSET, &stm);
381 }
7eda085c 382#endif
364cda48
KZ
383 if (rc == -1) { /* no sparc, or RTCSET failed */
384 ioctlname = "RTC_SET_TIME";
385 rc = ioctl(rtc_fd, RTC_SET_TIME, new_broken_time);
386 }
387
388 if (rc == -1) {
111c05d3
SK
389 warn(_("ioctl(%s) to %s to set the time failed."),
390 ioctlname, rtc_dev_name);
88058a71 391 hwclock_exit(EX_IOERR);
364cda48
KZ
392 }
393
394 if (debug)
395 printf(_("ioctl(%s) was successful.\n"), ioctlname);
396
364cda48 397 return 0;
7eda085c
KZ
398}
399
ef71b8f1
SK
400static int get_permissions_rtc(void)
401{
7eda085c
KZ
402 return 0;
403}
404
405static struct clock_ops rtc = {
88681c5f 406 "/dev interface to clock",
7eda085c
KZ
407 get_permissions_rtc,
408 read_hardware_clock_rtc,
409 set_hardware_clock_rtc,
410 synchronize_to_clock_tick_rtc,
411};
412
413/* return &rtc if /dev/rtc can be opened, NULL otherwise */
c9c1304d 414struct clock_ops *probe_for_rtc_clock(void)
ef71b8f1 415{
364cda48 416 int rtc_fd = open_rtc();
27f9db17 417 if (rtc_fd >= 0)
364cda48 418 return &rtc;
364cda48 419 if (debug)
111c05d3 420 warn(_("Open of %s failed"), rtc_dev_name);
364cda48 421 return NULL;
7eda085c
KZ
422}
423
ef71b8f1
SK
424/*
425 * Get the Hardware Clock epoch setting from the kernel.
426 */
427int get_epoch_rtc(unsigned long *epoch_p, int silent)
428{
429 int rtc_fd;
430
431 rtc_fd = open_rtc();
432 if (rtc_fd < 0) {
433 if (!silent) {
434 if (errno == ENOENT)
111c05d3
SK
435 warnx(_
436 ("To manipulate the epoch value in the kernel, we must "
437 "access the Linux 'rtc' device driver via the device special "
438 "file %s. This file does not exist on this system."),
439 rtc_dev_name);
ef71b8f1 440 else
111c05d3 441 warn(_("Unable to open %s"), rtc_dev_name);
ef71b8f1
SK
442 }
443 return 1;
444 }
445
446 if (ioctl(rtc_fd, RTC_EPOCH_READ, epoch_p) == -1) {
447 if (!silent)
111c05d3 448 warn(_("ioctl(RTC_EPOCH_READ) to %s failed"),
ef71b8f1
SK
449 rtc_dev_name);
450 return 1;
451 }
7eda085c 452
ef71b8f1
SK
453 if (debug)
454 printf(_("we have read epoch %ld from %s "
455 "with RTC_EPOCH_READ ioctl.\n"), *epoch_p,
456 rtc_dev_name);
7eda085c 457
ef71b8f1 458 return 0;
7eda085c
KZ
459}
460
ef71b8f1
SK
461/*
462 * Set the Hardware Clock epoch in the kernel.
463 */
464int set_epoch_rtc(unsigned long epoch)
465{
466 int rtc_fd;
467
468 if (epoch < 1900) {
469 /* kernel would not accept this epoch value
470 *
471 * Bad habit, deciding not to do what the user asks just
472 * because one believes that the kernel might not like it.
473 */
111c05d3
SK
474 warnx(_("The epoch value may not be less than 1900. "
475 "You requested %ld"), epoch);
ef71b8f1
SK
476 return 1;
477 }
478
479 rtc_fd = open_rtc();
480 if (rtc_fd < 0) {
481 if (errno == ENOENT)
111c05d3
SK
482 warnx(_
483 ("To manipulate the epoch value in the kernel, we must "
484 "access the Linux 'rtc' device driver via the device special "
485 "file %s. This file does not exist on this system."),
486 rtc_dev_name);
ef71b8f1 487 else
111c05d3 488 warn(_("Unable to open %s"), rtc_dev_name);
ef71b8f1
SK
489 return 1;
490 }
7eda085c 491
ef71b8f1
SK
492 if (debug)
493 printf(_("setting epoch to %ld "
494 "with RTC_EPOCH_SET ioctl to %s.\n"), epoch,
495 rtc_dev_name);
496
497 if (ioctl(rtc_fd, RTC_EPOCH_SET, epoch) == -1) {
498 if (errno == EINVAL)
111c05d3
SK
499 warnx(_("The kernel device driver for %s "
500 "does not have the RTC_EPOCH_SET ioctl."),
501 rtc_dev_name);
ef71b8f1 502 else
111c05d3 503 warn(_("ioctl(RTC_EPOCH_SET) to %s failed"),
ef71b8f1
SK
504 rtc_dev_name);
505 return 1;
506 }
7eda085c 507
ef71b8f1 508 return 0;
7eda085c 509}