[PATCH 2/2] hwclock, rtcwake: handle EINVAL from RTC_RD_TIME as "time not set"
Thomas Perrot via busybox <[email protected]> Tue, 26 May 2026 11:21:48 +0200
| Newsgroups | gmane.linux.busybox |
|---|---|
| Message-ID | <[email protected]> |
Some RTC drivers (e.g. rtc-nxp-bbnsm) return EINVAL from RTC_RD_TIME when the hardware counter is not yet enabled, which is the case on a freshly manufactured board that has never had its time set. Previously this caused hwclock and rtcwake to exit with the cryptic message: hwclock: RTC_RD_TIME: Invalid argument Now that rtc_read_tm() returns -errno instead of dying, update both callers to map EINVAL to an informative "RTC time is not set" error message. Other ioctl failures are still reported via perror as before. A local rtc_read_tm_or_die() helper in hwclock.c avoids duplicating the error-handling logic across the two call sites in read_rtc(). Signed-off-by: Thomas Perrot <[email protected]> Reviewed-by: Alexandre Belloni <[email protected]> --- util-linux/hwclock.c | 15 +++++++++++++-- util-linux/rtcwake.c | 8 +++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c index c3fd0eb57568..da7b4e330418 100644 --- a/util-linux/hwclock.c +++ b/util-linux/hwclock.c @@ -66,6 +66,17 @@ #if !SHOW_HWCLOCK_DIFF # define read_rtc(pp_rtcname, sys_tv, utc) read_rtc(pp_rtcname, utc) #endif +static void rtc_read_tm_or_die(struct tm *ptm, int fd) +{ + int err = rtc_read_tm(ptm, fd); + if (err) { + if (err == -EINVAL) + bb_simple_error_msg_and_die("RTC time is not set"); + errno = -err; + bb_simple_perror_msg_and_die("ioctl(RTC_RD_TIME)"); + } +} + static time_t read_rtc(const char **pp_rtcname, struct timeval *sys_tv, int utc) { struct tm tm_time; @@ -73,13 +84,13 @@ static time_t read_rtc(const char **pp_rtcname, struct timeval *sys_tv, int utc) fd = rtc_xopen(pp_rtcname, O_RDONLY); - rtc_read_tm(&tm_time, fd); + rtc_read_tm_or_die(&tm_time, fd); #if SHOW_HWCLOCK_DIFF { int before = tm_time.tm_sec; while (1) { - rtc_read_tm(&tm_time, fd); + rtc_read_tm_or_die(&tm_time, fd); xgettimeofday(sys_tv); if (before != (int)tm_time.tm_sec) break; diff --git a/util-linux/rtcwake.c b/util-linux/rtcwake.c index a8dfab064452..11ba92156f40 100644 --- a/util-linux/rtcwake.c +++ b/util-linux/rtcwake.c @@ -183,7 +183,13 @@ int rtcwake_main(int argc UNUSED_PARAM, char **argv) sys_time = time(NULL); { struct tm tm_time; - rtc_read_tm(&tm_time, fd); + int err = rtc_read_tm(&tm_time, fd); + if (err) { + if (err == -EINVAL) + bb_simple_error_msg_and_die("RTC time is not set"); + errno = -err; + bb_simple_perror_msg_and_die("ioctl(RTC_RD_TIME)"); + } rtc_time = rtc_tm2time(&tm_time, utc); } -- 2.54.0