Here's a patch to VBoxService that makes it write to the RTC after it updates the system clock.
-- Sam Morris <https://robots.org.uk/> CAAA AA1A CA69 A83A 892B 1855 D20B 4202 5CDA 27B9
--- virtualbox-5.0.14-dfsg.orig/src/VBox/Additions/common/VBoxService/VBoxServiceTimeSync.cpp
+++ virtualbox-5.0.14-dfsg/src/VBox/Additions/common/VBoxService/VBoxServiceTimeSync.cpp
@@ -86,6 +86,15 @@
#ifdef RT_OS_WINDOWS
# include <Windows.h>
#else
+# ifdef RT_OS_LINUX
+# include <fcntl.h>
+# include <linux/rtc.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <sys/ioctl.h>
+# include <sys/stat.h>
+# include <sys/types.h>
+# endif /* RT_OS_LINUX */
# include <unistd.h>
# include <errno.h>
# include <time.h>
@@ -450,6 +459,89 @@ static void vgsvcTimeSyncCancelAdjust(vo
#endif /* !RT_OS_WINDOWS */
}
+/**
+ * Updates "hardware" RTC, so that time is correct during early boot.
+ *
+ */
+static void vgsvcTimeSyncSaveToRTC() {
+#ifdef RT_OS_LINUX
+ FILE *adjtime_f = NULL;
+ char *adjtime_line = NULL;
+ size_t adjtime_buffer_len = 0;
+ ssize_t adjtime_line_len;
+ struct tm * (*xtime) (const time_t *) = NULL;
+ time_t now;
+ struct tm *now_tm = NULL;
+ int rtc_fd = -1;
+
+ if (!(adjtime_f = fopen("/etc/adjtime", "re")))
+ {
+ VGSvcError("vgsvcTimeSyncSaveToRTC: open(/etc/adjtime) failed, error=%d\n", errno);
+ goto out;
+ }
+
+ getline(&adjtime_line, &adjtime_buffer_len, adjtime_f);
+ getline(&adjtime_line, &adjtime_buffer_len, adjtime_f);
+ if ((adjtime_line_len = getline(&adjtime_line, &adjtime_buffer_len, adjtime_f)) == -1) {
+ VGSvcError("vgsvcTimeSyncSaveToRTC: could not read /etc/adjtime, assuming UTC is in use, error=%d\n", errno);
+ xtime = &gmtime;
+ }
+ else
+ {
+ if (adjtime_line[adjtime_line_len-1] == '\n')
+ adjtime_line[adjtime_line_len-1] = '\0';
+
+ if (strcmp(adjtime_line, "LOCAL") == 0)
+ {
+ VGSvcVerbose(3, "RTC using local time\n");
+ xtime = &localtime;
+ }
+ else if (strcmp(adjtime_line, "UTC") == 0)
+ {
+ VGSvcVerbose(3, "RTC using UTC\n");
+ xtime = &gmtime;
+ }
+ else
+ {
+ VGSvcError("vgsvcTimeSyncSaveToRTC: unknown time standard '%s', not setting RTC\n", adjtime_line);
+ goto out;
+ }
+ }
+
+ if ((now = time(NULL)) == (time_t)-1)
+ {
+ VGSvcError("vgsvcTimeSyncSaveToRTC: time() failed, error=%d\n", errno);
+ goto out;
+ }
+ if (!(now_tm = (*xtime)(&now)))
+ {
+ VGSvcError("vgsvcTimeSyncSaveToRTC: {gm|local}time() failed\n");
+ goto out;
+ }
+
+ if ((rtc_fd = open("/dev/rtc", O_RDONLY|O_CLOEXEC)) == -1)
+ {
+ VGSvcError("vgsvcTimeSyncSaveToRTC: open(/dev/rtc) failed, error=%d\n", errno);
+ goto out;
+ }
+
+ if (ioctl(rtc_fd, RTC_SET_TIME, now_tm) == -1)
+ {
+ VGSvcError("vgsvcTimeSyncSaveToRTC: ioctl(RTC_SET_TIME) failed, errno=%d\n", errno);
+ goto out;
+ }
+
+ VGSvcVerbose(3, "RTC updated\n");
+
+out:
+ close(rtc_fd);
+ free(adjtime_line);
+ if (adjtime_f)
+ fclose(adjtime_f);
+ return;
+#endif /* !RT_OS_LINUX */
+}
+
/**
* Try adjust the time using adjtime or similar.
@@ -585,6 +677,7 @@ DECLCALLBACK(int) vgsvcTimeSyncWorker(bo
vgsvcTimeSyncCancelAdjust();
vgsvcTimeSyncSet(&Drift);
}
+ vgsvcTimeSyncSaveToRTC();
}
else
vgsvcTimeSyncCancelAdjust();
signature.asc
Description: This is a digitally signed message part

