Index: uspace/drv/time/cmos-rtc/cmos-rtc.c
===================================================================
--- uspace/drv/time/cmos-rtc/cmos-rtc.c	(revision eb083ad01c5554fd8151cee797b4fd5685499343)
+++ uspace/drv/time/cmos-rtc/cmos-rtc.c	(revision 8fde07823f267a4e88ec5ceba8a327aab4b511c4)
@@ -38,5 +38,8 @@
 #include <errno.h>
 #include <ddi.h>
+#include <as.h>
+#include <sysinfo.h>
 #include <libarch/ddi.h>
+#include <libarch/barrier.h>
 #include <stdio.h>
 #include <ddf/driver.h>
@@ -46,4 +49,5 @@
 #include <device/hw_res.h>
 #include <devman.h>
+#include <macros.h>
 #include <ipc/clock_ctl.h>
 
@@ -74,4 +78,10 @@
 } rtc_t;
 
+/** Pointer to the kernel shared variables with time */
+struct {
+	volatile sysarg_t seconds1;
+	volatile sysarg_t useconds;
+	volatile sysarg_t seconds2;
+} *kuptime = NULL;
 
 static int  rtc_time_get(ddf_fun_t *fun, struct tm *t);
@@ -91,6 +101,8 @@
 static int rtc_dev_remove(ddf_dev_t *dev);
 static void rtc_register_write(rtc_t *rtc, int reg, int data);
+static time_t uptime_get(void);
 
 static ddf_dev_ops_t rtc_dev_ops;
+static time_t boottime = 0;
 
 /** The RTC device driver's standard operations */
@@ -369,4 +381,6 @@
 {
 	bool bcd_mode;
+	time_t norm_time;
+	time_t uptime;
 	int  reg_b;
 	int  reg_a;
@@ -375,6 +389,15 @@
 
 	/* Try to normalize the content of the tm structure */
-	if (mktime(t) < 0)
+	if ((norm_time = mktime(t)) < 0)
 		return EINVAL;
+
+	uptime = uptime_get();
+	if (norm_time <= uptime) {
+		/* This is not acceptable */
+		return EINVAL;
+	}
+
+	/* boottime must be recomputed */
+	boottime = 0;
 
 	fibril_mutex_lock(&rtc->mutex);
@@ -555,4 +578,5 @@
 	rtc_t *rtc = RTC_FROM_FNODE(fun);
 	bool batt_ok;
+	sysarg_t r = EOK;
 
 	switch (method) {
@@ -561,4 +585,21 @@
 		    RTC_D_BATTERY_OK;
 		async_answer_1(callid, EOK, batt_ok);
+		break;
+	case CLOCK_GET_BOOTTIME:
+		if (boottime == 0) {
+			struct tm cur_tm;
+			time_t uptime;
+
+			uptime = uptime_get();
+			r = rtc_time_get(fun, &cur_tm);
+			if (r == EOK) {
+				time_t current_time = mktime(&cur_tm);
+				if (current_time < uptime)
+					r = EINVAL;
+				else
+					boottime = current_time - uptime;
+			}
+		}
+		async_answer_1(callid, r, boottime);
 		break;
 	default:
@@ -635,4 +676,49 @@
 }
 
+/** Get the current uptime
+ *
+ * The time variables are memory mapped (read-only) from kernel which
+ * updates them periodically.
+ *
+ * As it is impossible to read 2 values atomically, we use a trick:
+ * First we read the seconds, then we read the microseconds, then we
+ * read the seconds again. If a second elapsed in the meantime, set
+ * the microseconds to zero.
+ *
+ * This assures that the values returned by two subsequent calls
+ * to gettimeofday() are monotonous.
+ *
+ */
+static time_t
+uptime_get(void)
+{
+	if (kuptime == NULL) {
+		uintptr_t faddr;
+		int rc = sysinfo_get_value("clock.faddr", &faddr);
+		if (rc != EOK) {
+			errno = rc;
+			return -1;
+		}
+		
+		void *addr;
+		rc = physmem_map((void *) faddr, 1,
+		    AS_AREA_READ | AS_AREA_CACHEABLE, &addr);
+		if (rc != EOK) {
+			as_area_destroy(addr);
+			errno = rc;
+			return -1;
+		}
+		
+		kuptime = addr;
+	}
+
+	sysarg_t s2 = kuptime->seconds2;
+	
+	read_barrier();
+	sysarg_t s1 = kuptime->seconds1;
+	
+	return max(s1, s2);
+}
+
 int
 main(int argc, char **argv)
Index: uspace/lib/c/include/ipc/clock_ctl.h
===================================================================
--- uspace/lib/c/include/ipc/clock_ctl.h	(revision eb083ad01c5554fd8151cee797b4fd5685499343)
+++ uspace/lib/c/include/ipc/clock_ctl.h	(revision 8fde07823f267a4e88ec5ceba8a327aab4b511c4)
@@ -34,4 +34,5 @@
 typedef enum {
 	CLOCK_GET_BATTERY_STATUS = DEV_FIRST_CUSTOM_METHOD,
+	CLOCK_GET_BOOTTIME,
 } clock_ctl_t;
 
