[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC PATCH util-linux] Support hwclock read and set operations for Hurd
From: |
Zhaoming Luo |
Subject: |
[RFC PATCH util-linux] Support hwclock read and set operations for Hurd |
Date: |
Mon, 2 Dec 2024 10:06:48 +0800 |
From: Zhaoming Luo <zhaoming1357@qq.com>
* configure.ac: add HURD conditional for meson build
* sys-utils/Makemodule.am: compile hurd-specific rtc device operations
* sys-utils/hurd-hwclock-rtc.c: new file, hurd-specific rtc device
* operations
* sys-utils/hwclock.c: add --rtc option and probe_for_rtc_clock for hwclock in
Hurd
* sys-utils/hwclock.h: add variable for storing rtc device name in Hurd
---
configure.ac | 6 +-
sys-utils/Makemodule.am | 4 +
sys-utils/hurd-hwclock-rtc.c | 193 +++++++++++++++++++++++++++++++++++
sys-utils/hwclock.c | 8 +-
sys-utils/hwclock.h | 3 +
5 files changed, 209 insertions(+), 5 deletions(-)
create mode 100644 sys-utils/hurd-hwclock-rtc.c
diff --git a/configure.ac b/configure.ac
index 698da36..8de6af6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -263,16 +263,20 @@ AC_PATH_PROG([XSLTPROC], [xsltproc])
linux_os=no
bsd_os=no
+gnu_os=no
AS_CASE([${host_os}],
[*linux*],
[linux_os=yes],
[*darwin*],
[darwin_os=yes],
[*bsd*],
- [bsd_os=yes])
+ [bsd_os=yes],
+ [gnu*],
+ [gnu_os=yes])
AM_CONDITIONAL([LINUX], [test "x$linux_os" = xyes])
AM_CONDITIONAL([DARWIN], [test "x$darwin_os" = xyes])
AM_CONDITIONAL([BSD], [test "x$bsd_os" = xyes])
+AM_CONDITIONAL([HURD], [test "x$gnu_os" = xyes])
AS_IF([test "x$darwin_os" = xyes], [
AC_DEFINE([_DARWIN_C_SOURCE], [1], [Enable MAP_ANON in sys/mman.h on Mac OS
X])
diff --git a/sys-utils/Makemodule.am b/sys-utils/Makemodule.am
index 209b656..7582106 100644
--- a/sys-utils/Makemodule.am
+++ b/sys-utils/Makemodule.am
@@ -570,6 +570,10 @@ hwclock_SOURCES += \
lib/monotonic.c
hwclock_LDADD += $(REALTIME_LIBS)
endif
+if HURD
+hwclock_SOURCES += \
+ sys-utils/hurd-hwclock-rtc.c
+endif
if HAVE_AUDIT
hwclock_LDADD += -laudit
endif
diff --git a/sys-utils/hurd-hwclock-rtc.c b/sys-utils/hurd-hwclock-rtc.c
new file mode 100644
index 0000000..4c388fe
--- /dev/null
+++ b/sys-utils/hurd-hwclock-rtc.c
@@ -0,0 +1,193 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * hurd-hwclock-rtc.c - Use /dev/rtc for clock access in GNU Hurd
+ */
+#include <sys/ioctl.h>
+#include <hurd/rtc.h>
+
+#include "hwclock.h"
+
+/* default or user defined dev (by hwclock --rtc=<path>) */
+static const char *rtc_dev_name;
+static int rtc_dev_fd = -1;
+
+static void close_rtc(void)
+{
+ if (rtc_dev_fd != -1)
+ close(rtc_dev_fd);
+ rtc_dev_fd = -1;
+}
+
+static int open_rtc(const struct hwclock_control *ctl)
+{
+ static const char * const fls[] = {
+#ifdef __ia64__
+ "/dev/efirtc",
+ "/dev/misc/efirtc",
+#endif
+ "/dev/rtc0",
+ "/dev/rtc",
+ "/dev/misc/rtc"
+ };
+ size_t i;
+
+ if (rtc_dev_fd != -1)
+ return rtc_dev_fd;
+
+ /* --rtc option has been given */
+ if (ctl->rtc_dev_name) {
+ rtc_dev_name = ctl->rtc_dev_name;
+ rtc_dev_fd = open(rtc_dev_name, O_RDONLY | O_WRONLY);
+ } else {
+ for (i = 0; i < ARRAY_SIZE(fls); i++) {
+ if (ctl->verbose)
+ printf(_("Trying to open: %s\n"), fls[i]);
+ rtc_dev_fd = open(fls[i], O_RDONLY | O_WRONLY);
+
+ if (rtc_dev_fd < 0) {
+ if (errno == ENOENT || errno == ENODEV)
+ continue;
+ if (ctl->verbose)
+ warn(_("cannot open %s"), fls[i]);
+ }
+ rtc_dev_name = fls[i];
+ break;
+ }
+ if (rtc_dev_fd < 0)
+ rtc_dev_name = *fls; /* default for error messages */
+ }
+ if (rtc_dev_fd != -1)
+ atexit(close_rtc);
+ return rtc_dev_fd;
+}
+
+/*
+ * Not yet implemented
+ */
+static int synchronize_to_clock_tick_rtc([[maybe_unused]] const struct
hwclock_control *ctl)
+{
+ return 0;
+}
+
+static int open_rtc_or_exit(const struct hwclock_control *ctl)
+{
+ int rtc_fd = open_rtc(ctl);
+
+ if (rtc_fd < 0) {
+ warn(_("cannot open rtc device"));
+ hwclock_exit(ctl, EXIT_FAILURE);
+ }
+ return rtc_fd;
+}
+
+static int do_rtc_read_ioctl(int rtc_fd, struct tm *tm)
+{
+ int rc = -1;
+ struct rtc_time rtc_tm = { 0 };
+
+ rc = ioctl(rtc_fd, RTC_RD_TIME, &rtc_tm);
+
+ if (rc == -1) {
+ warn(_("ioctl(RTC_RD_NAME) to %s to read the time failed"),
+ rtc_dev_name);
+ return -1;
+ }
+
+ /* kernel uses private struct tm definition to be self contained */
+ tm->tm_sec = rtc_tm.tm_sec;
+ tm->tm_min = rtc_tm.tm_min;
+ tm->tm_hour = rtc_tm.tm_hour;
+ tm->tm_mday = rtc_tm.tm_mday;
+ tm->tm_mon = rtc_tm.tm_mon;
+ tm->tm_year = rtc_tm.tm_year;
+ tm->tm_wday = rtc_tm.tm_wday;
+ tm->tm_yday = rtc_tm.tm_yday;
+ tm->tm_isdst = -1; /* don't know whether it's dst */
+ return 0;
+}
+
+static int read_hardware_clock_rtc(const struct hwclock_control *ctl,
+ struct tm *tm)
+{
+ int rtc_fd, rc;
+
+ rtc_fd = open_rtc_or_exit(ctl);
+
+ /* Read the RTC time/date, return answer via tm */
+ rc = do_rtc_read_ioctl(rtc_fd, tm);
+
+ return rc;
+}
+
+/*
+ * Set the Hardware Clock to the broken down time <new_broken_time>. Use
+ * ioctls to "rtc" device /dev/rtc.
+ */
+static int set_hardware_clock_rtc(const struct hwclock_control *ctl,
+ const struct tm *new_broken_time)
+{
+ int rc = -1;
+ int rtc_fd;
+ struct rtc_time rtc_tm = { 0 };
+
+ rtc_fd = open_rtc_or_exit(ctl);
+
+ /* kernel uses private struct tm definition to be self contained */
+ rtc_tm.tm_sec = new_broken_time->tm_sec;
+ rtc_tm.tm_min = new_broken_time->tm_min;
+ rtc_tm.tm_hour = new_broken_time->tm_hour;
+ rtc_tm.tm_mday = new_broken_time->tm_mday;
+ rtc_tm.tm_mon = new_broken_time->tm_mon;
+ rtc_tm.tm_year = new_broken_time->tm_year;
+ rtc_tm.tm_wday = new_broken_time->tm_wday;
+ rtc_tm.tm_yday = new_broken_time->tm_yday;
+ rtc_tm.tm_isdst = new_broken_time->tm_isdst;
+
+ rc = ioctl(rtc_fd, RTC_SET_TIME, &rtc_tm);
+
+ if (rc == -1) {
+ warn(_("ioctl(RTC_SET_TIME) to %s to set the time failed"),
+ rtc_dev_name);
+ hwclock_exit(ctl, EXIT_FAILURE);
+ }
+
+ if (ctl->verbose)
+ printf(_("ioctl(RTC_SET_TIME) was successful.\n"));
+
+ return 0;
+}
+
+static int get_permissions_rtc(void)
+{
+ return 0;
+}
+
+static const char *get_device_path(void)
+{
+ return rtc_dev_name;
+}
+
+static const struct clock_ops rtc_interface = {
+ N_("Using the rtc interface to the clock."),
+ get_permissions_rtc,
+ read_hardware_clock_rtc,
+ set_hardware_clock_rtc,
+ synchronize_to_clock_tick_rtc,
+ get_device_path,
+};
+
+/* return &rtc if /dev/rtc can be opened, NULL otherwise */
+const struct clock_ops *probe_for_rtc_clock(const struct hwclock_control *ctl)
+{
+ const int rtc_fd = open_rtc(ctl);
+
+ if (rtc_fd < 0)
+ return NULL;
+ return &rtc_interface;
+}
diff --git a/sys-utils/hwclock.c b/sys-utils/hwclock.c
index 2b33dfb..f29539f 100644
--- a/sys-utils/hwclock.c
+++ b/sys-utils/hwclock.c
@@ -989,7 +989,7 @@ static void determine_clock_access_method(const struct
hwclock_control *ctl)
if (ctl->directisa)
ur = probe_for_cmos_clock();
#endif
-#ifdef __linux__
+#if defined(__linux__) || defined(__gnu_hurd__)
if (!ur)
ur = probe_for_rtc_clock(ctl);
#endif
@@ -1249,7 +1249,7 @@ usage(void)
fputs(USAGE_OPTIONS, stdout);
puts(_(" -u, --utc the RTC timescale is UTC"));
puts(_(" -l, --localtime the RTC timescale is Local"));
-#ifdef __linux__
+#if defined(__linux__) || defined(__gnu_hurd__)
printf(_(
" -f, --rtc <file> use an alternate file to
%1$s\n"), _PATH_RTC_DEV);
#endif
@@ -1356,7 +1356,7 @@ int main(int argc, char **argv)
{ "test", no_argument, NULL, OPT_TEST },
{ "date", required_argument, NULL, OPT_DATE },
{ "delay", required_argument, NULL, OPT_DELAY },
-#ifdef __linux__
+#if defined(__linux__) || defined(__gnu_hurd__)
{ "rtc", required_argument, NULL, 'f' },
#endif
{ "adjfile", required_argument, NULL, OPT_ADJFILE },
@@ -1521,7 +1521,7 @@ int main(int argc, char **argv)
case OPT_UPDATE:
ctl.update = 1; /* --update-drift */
break;
-#ifdef __linux__
+#if defined(__linux__) || defined(__gnu_hurd__)
case 'f':
ctl.rtc_dev_name = optarg; /* --rtc */
break;
diff --git a/sys-utils/hwclock.h b/sys-utils/hwclock.h
index 2522d6c..485e904 100644
--- a/sys-utils/hwclock.h
+++ b/sys-utils/hwclock.h
@@ -39,6 +39,9 @@ struct hwclock_control {
#ifdef __linux__
char *rtc_dev_name;
uint32_t param_idx; /* --param-index <n> */
+#endif
+#ifdef __gnu_hurd__
+ char *rtc_dev_name;
#endif
char *param_get_option;
char *param_set_option;
--
2.45.2
- [RFC PATCH util-linux] Support hwclock read and set operations for Hurd,
Zhaoming Luo <=
- Re: [RFC PATCH util-linux] Support hwclock read and set operations for Hurd, Samuel Thibault, 2024/12/01
- Re: [RFC PATCH util-linux] Support hwclock read and set operations for Hurd, Zhaoming Luo, 2024/12/02
- Re: [RFC PATCH util-linux] Support hwclock read and set operations for Hurd, Samuel Thibault, 2024/12/02
- Re: [RFC PATCH util-linux] Support hwclock read and set operations for Hurd, Zhaoming Luo, 2024/12/02
- Re: [RFC PATCH util-linux] Support hwclock read and set operations for Hurd, Samuel Thibault, 2024/12/03
- Re: [RFC PATCH util-linux] Support hwclock read and set operations for Hurd, Zhaoming Luo, 2024/12/03
- Re: [RFC PATCH util-linux] Support hwclock read and set operations for Hurd, Samuel Thibault, 2024/12/04