All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2 0/6] efi_loader: complete implementation of GetTime()
@ 2018-07-07 21:39 Heinrich Schuchardt
  2018-07-07 21:39 ` [U-Boot] [PATCH v2 1/6] drivers: rtc: resolve year 2038 problem in rtc_to_tm Heinrich Schuchardt
                   ` (5 more replies)
  0 siblings, 6 replies; 10+ messages in thread
From: Heinrich Schuchardt @ 2018-07-07 21:39 UTC (permalink / raw)
  To: u-boot

The year 2038 problem in rtc_to_tm() is reusing code from Linux.

The EFI runtime service GetTime() is used to read the time form the real
time clock.

The RTC drivers are made usable even if U-Boot is built without
CONFIG_CMD_DATE.

The implementation of the GetTime() runtime service is corrected.

v2:
	do not support non-driver-model drivers

Heinrich Schuchardt (6):
  drivers: rtc: resolve year 2038 problem in rtc_to_tm
  rtc: remove CONFIG_CMD_DATE dependency
  efi_loader: remove unused efi_get_time_init()
  efi_loader: complete implementation of GetTime()
  efi_selftest: support printing leading zeroes
  efi_selftest: unit test for GetTime()

 cmd/bootefi.c                           |  3 -
 drivers/rtc/Makefile                    |  1 +
 drivers/rtc/at91sam9_rtt.c              |  4 --
 drivers/rtc/date.c                      | 43 ---------------
 drivers/rtc/davinci.c                   |  2 -
 drivers/rtc/ds1302.c                    |  4 --
 drivers/rtc/ds1306.c                    |  4 --
 drivers/rtc/ds1307.c                    |  4 --
 drivers/rtc/ds1337.c                    |  4 --
 drivers/rtc/ds1374.c                    |  3 -
 drivers/rtc/ds164x.c                    |  4 --
 drivers/rtc/ds174x.c                    |  4 --
 drivers/rtc/ds3231.c                    |  4 --
 drivers/rtc/i2c_rtc_emul.c              |  4 +-
 drivers/rtc/imxdi.c                     |  4 --
 drivers/rtc/m41t11.c                    |  3 -
 drivers/rtc/m41t60.c                    |  3 -
 drivers/rtc/m41t62.c                    |  4 --
 drivers/rtc/m48t35ax.c                  |  4 --
 drivers/rtc/max6900.c                   |  4 --
 drivers/rtc/mc146818.c                  |  3 -
 drivers/rtc/mcfrtc.c                    |  4 --
 drivers/rtc/mk48t59.c                   |  4 --
 drivers/rtc/pcf8563.c                   |  4 --
 drivers/rtc/rs5c372.c                   |  3 -
 drivers/rtc/rtc-lib.c                   | 73 +++++++++++++++++++++++++
 drivers/rtc/rx8025.c                    |  4 --
 drivers/rtc/s3c24x0_rtc.c               |  4 --
 drivers/rtc/x1205.c                     |  4 --
 include/efi_loader.h                    |  1 -
 include/rtc.h                           | 16 +++++-
 lib/efi_loader/efi_runtime.c            | 58 ++++++++++++++------
 lib/efi_selftest/Makefile               |  1 +
 lib/efi_selftest/efi_selftest_console.c | 33 +++++++----
 lib/efi_selftest/efi_selftest_rtc.c     | 67 +++++++++++++++++++++++
 35 files changed, 221 insertions(+), 168 deletions(-)
 create mode 100644 drivers/rtc/rtc-lib.c
 create mode 100644 lib/efi_selftest/efi_selftest_rtc.c

-- 
2.18.0

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH v2 1/6] drivers: rtc: resolve year 2038 problem in rtc_to_tm
  2018-07-07 21:39 [U-Boot] [PATCH v2 0/6] efi_loader: complete implementation of GetTime() Heinrich Schuchardt
@ 2018-07-07 21:39 ` Heinrich Schuchardt
  2018-07-08 21:32   ` Alexander Graf
  2018-07-20 12:37   ` [U-Boot] [U-Boot, v2, " Tom Rini
  2018-07-07 21:39 ` [U-Boot] [PATCH v2 2/6] rtc: remove CONFIG_CMD_DATE dependency Heinrich Schuchardt
                   ` (4 subsequent siblings)
  5 siblings, 2 replies; 10+ messages in thread
From: Heinrich Schuchardt @ 2018-07-07 21:39 UTC (permalink / raw)
  To: u-boot

Our implementation of rtc_to_tm() cannot handle dates of more than
0x7fffffff seconds after 1970-01-01.

Adopt the Linux kernel implementation.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
v2
	adopt the Linux kernel implementation
---
 drivers/rtc/Makefile       |  1 +
 drivers/rtc/date.c         | 43 ----------------------
 drivers/rtc/i2c_rtc_emul.c |  4 ++-
 drivers/rtc/rtc-lib.c      | 73 ++++++++++++++++++++++++++++++++++++++
 include/rtc.h              | 16 +++++++--
 5 files changed, 90 insertions(+), 47 deletions(-)
 create mode 100644 drivers/rtc/rtc-lib.c

diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 09f2b08244..513e3ffc07 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_DM_RTC) += rtc-uclass.o
 
 obj-$(CONFIG_RTC_AT91SAM9_RTT) += at91sam9_rtt.o
 obj-y += date.o
+obj-y += rtc-lib.o
 obj-$(CONFIG_RTC_DAVINCI) += davinci.o
 obj-$(CONFIG_RTC_DS1302) += ds1302.o
 obj-$(CONFIG_RTC_DS1306) += ds1306.o
diff --git a/drivers/rtc/date.c b/drivers/rtc/date.c
index 1256ffe374..f2568cf886 100644
--- a/drivers/rtc/date.c
+++ b/drivers/rtc/date.c
@@ -19,10 +19,6 @@
 #define	days_in_year(a)		(leapyear(a) ? 366 : 365)
 #define	days_in_month(a)	(month_days[(a) - 1])
 
-static int month_days[12] = {
-	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-};
-
 static int month_offset[] = {
 	0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
 };
@@ -65,45 +61,6 @@ int rtc_calc_weekday(struct rtc_time *tm)
 	return 0;
 }
 
-int rtc_to_tm(int tim, struct rtc_time *tm)
-{
-	register int i;
-	register long hms, day;
-
-	day = tim / SECDAY;
-	hms = tim % SECDAY;
-
-	/* Hours, minutes, seconds are easy */
-	tm->tm_hour = hms / 3600;
-	tm->tm_min = (hms % 3600) / 60;
-	tm->tm_sec = (hms % 3600) % 60;
-
-	/* Number of years in days */
-	for (i = STARTOFTIME; day >= days_in_year(i); i++)
-		day -= days_in_year(i);
-	tm->tm_year = i;
-
-	/* Number of months in days left */
-	if (leapyear(tm->tm_year))
-		days_in_month(FEBRUARY) = 29;
-	for (i = 1; day >= days_in_month(i); i++)
-		day -= days_in_month(i);
-	days_in_month(FEBRUARY) = 28;
-	tm->tm_mon = i;
-
-	/* Days are what is left over (+1) from all that */
-	tm->tm_mday = day + 1;
-
-	/* Zero unused fields */
-	tm->tm_yday = 0;
-	tm->tm_isdst = 0;
-
-	/*
-	 * Determine the day of week
-	 */
-	return rtc_calc_weekday(tm);
-}
-
 /*
  * Converts Gregorian date to seconds since 1970-01-01 00:00:00.
  * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
diff --git a/drivers/rtc/i2c_rtc_emul.c b/drivers/rtc/i2c_rtc_emul.c
index bad61c377f..d4b33e59d6 100644
--- a/drivers/rtc/i2c_rtc_emul.c
+++ b/drivers/rtc/i2c_rtc_emul.c
@@ -96,7 +96,9 @@ static int sandbox_i2c_rtc_get(struct udevice *dev, struct rtc_time *time)
 		now = plat->base_time;
 	}
 
-	return rtc_to_tm(now + plat->offset, time);
+	rtc_to_tm(now + plat->offset, time);
+
+	return 0;
 }
 
 static int sandbox_i2c_rtc_set(struct udevice *dev, const struct rtc_time *time)
diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c
new file mode 100644
index 0000000000..b8a7a8b2d3
--- /dev/null
+++ b/drivers/rtc/rtc-lib.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * rtc and date/time utility functions
+ *
+ * Copyright (C) 2005-06 Tower Technologies
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ *
+ * U-Boot rtc_time differs from Linux rtc_time:
+ * - The year field takes the actual value, not year - 1900.
+ * - January is month 1.
+ */
+
+#include <common.h>
+#include <rtc.h>
+#include <linux/math64.h>
+
+static const unsigned char rtc_days_in_month[] = {
+	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
+
+/*
+ * The number of days in the month.
+ */
+static int rtc_month_days(unsigned int month, unsigned int year)
+{
+	return rtc_days_in_month[month] + (is_leap_year(year) && month == 1);
+}
+
+/*
+ * rtc_to_tm - Converts u64 to rtc_time.
+ * Convert seconds since 01-01-1970 00:00:00 to Gregorian date.
+ */
+void rtc_to_tm(u64 time, struct rtc_time *tm)
+{
+	unsigned int month, year, secs, days;
+
+	days = div_u64_rem(time, 86400, &secs);
+
+	/* day of the week, 1970-01-01 was a Thursday */
+	tm->tm_wday = (days + 4) % 7;
+
+	year = 1970 + days / 365;
+	days -= (year - 1970) * 365
+		+ LEAPS_THRU_END_OF(year - 1)
+		- LEAPS_THRU_END_OF(1970 - 1);
+	while (days < 0) {
+		year -= 1;
+		days += 365 + is_leap_year(year);
+	}
+	tm->tm_year = year; /* Not year - 1900 */
+	tm->tm_yday = days + 1;
+
+	for (month = 0; month < 11; month++) {
+		int newdays;
+
+		newdays = days - rtc_month_days(month, year);
+		if (newdays < 0)
+			break;
+		days = newdays;
+	}
+	tm->tm_mon = month + 1; /* January = 1 */
+	tm->tm_mday = days + 1;
+
+	tm->tm_hour = secs / 3600;
+	secs -= tm->tm_hour * 3600;
+	tm->tm_min = secs / 60;
+	tm->tm_sec = secs - tm->tm_min * 60;
+
+	/* Zero unused fields */
+	tm->tm_isdst = 0;
+}
diff --git a/include/rtc.h b/include/rtc.h
index 746624d799..0d964d56d5 100644
--- a/include/rtc.h
+++ b/include/rtc.h
@@ -208,7 +208,18 @@ void rtc_write32(int reg, u32 value);
  * rtc_init() - Set up the real time clock ready for use
  */
 void rtc_init(void);
-#endif
+#endif /* CONFIG_DM_RTC */
+
+/**
+ * is_leap_year - Check if year is a leap year
+ *
+ * @year	Year
+ * @return	1 if leap year
+ */
+static inline bool is_leap_year(unsigned int year)
+{
+	return (!(year % 4) && (year % 100)) || !(year % 400);
+}
 
 /**
  * rtc_calc_weekday() - Work out the weekday from a time
@@ -231,9 +242,8 @@ int rtc_calc_weekday(struct rtc_time *time);
  *
  * @time_t:	Number of seconds since 1970-01-01 00:00:00
  * @time:	Place to put the broken-out time
- * @return 0 if OK, -EINVAL if the weekday could not be determined
  */
-int rtc_to_tm(int time_t, struct rtc_time *time);
+void rtc_to_tm(u64 time_t, struct rtc_time *time);
 
 /**
  * rtc_mktime() - Convert a broken-out time into a time_t value
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH v2 2/6] rtc: remove CONFIG_CMD_DATE dependency
  2018-07-07 21:39 [U-Boot] [PATCH v2 0/6] efi_loader: complete implementation of GetTime() Heinrich Schuchardt
  2018-07-07 21:39 ` [U-Boot] [PATCH v2 1/6] drivers: rtc: resolve year 2038 problem in rtc_to_tm Heinrich Schuchardt
@ 2018-07-07 21:39 ` Heinrich Schuchardt
  2018-07-07 21:39 ` [U-Boot] [PATCH v2 3/6] efi_loader: remove unused efi_get_time_init() Heinrich Schuchardt
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Heinrich Schuchardt @ 2018-07-07 21:39 UTC (permalink / raw)
  To: u-boot

The EFI subsystem accesses the real time clock and is enabled by default.
So we should drop any CONFIG_CMD_DATE dependency from the real time clock
drivers.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
v2
	new patch
---
 drivers/rtc/at91sam9_rtt.c | 4 ----
 drivers/rtc/davinci.c      | 2 --
 drivers/rtc/ds1302.c       | 4 ----
 drivers/rtc/ds1306.c       | 4 ----
 drivers/rtc/ds1307.c       | 4 ----
 drivers/rtc/ds1337.c       | 4 ----
 drivers/rtc/ds1374.c       | 3 ---
 drivers/rtc/ds164x.c       | 4 ----
 drivers/rtc/ds174x.c       | 4 ----
 drivers/rtc/ds3231.c       | 4 ----
 drivers/rtc/imxdi.c        | 4 ----
 drivers/rtc/m41t11.c       | 3 ---
 drivers/rtc/m41t60.c       | 3 ---
 drivers/rtc/m41t62.c       | 4 ----
 drivers/rtc/m48t35ax.c     | 4 ----
 drivers/rtc/max6900.c      | 4 ----
 drivers/rtc/mc146818.c     | 3 ---
 drivers/rtc/mcfrtc.c       | 4 ----
 drivers/rtc/mk48t59.c      | 4 ----
 drivers/rtc/pcf8563.c      | 4 ----
 drivers/rtc/rs5c372.c      | 3 ---
 drivers/rtc/rx8025.c       | 4 ----
 drivers/rtc/s3c24x0_rtc.c  | 4 ----
 drivers/rtc/x1205.c        | 4 ----
 24 files changed, 89 deletions(-)

diff --git a/drivers/rtc/at91sam9_rtt.c b/drivers/rtc/at91sam9_rtt.c
index da5bb3e2f7..6f92660ef1 100644
--- a/drivers/rtc/at91sam9_rtt.c
+++ b/drivers/rtc/at91sam9_rtt.c
@@ -27,8 +27,6 @@
 #include <asm/arch/at91_rtt.h>
 #include <asm/arch/at91_gpbr.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 int rtc_get (struct rtc_time *tmp)
 {
 	at91_rtt_t *rtt = (at91_rtt_t *) ATMEL_BASE_RTT;
@@ -78,5 +76,3 @@ void rtc_reset (void)
 	while (readl(&rtt->vr) != 0)
 		;
 }
-
-#endif
diff --git a/drivers/rtc/davinci.c b/drivers/rtc/davinci.c
index f03dc56069..b6930bd839 100644
--- a/drivers/rtc/davinci.c
+++ b/drivers/rtc/davinci.c
@@ -9,7 +9,6 @@
 #include <asm/io.h>
 #include <asm/davinci_rtc.h>
 
-#if defined(CONFIG_CMD_DATE)
 int rtc_get(struct rtc_time *tmp)
 {
 	struct davinci_rtc *rtc = (struct davinci_rtc *)DAVINCI_RTC_BASE;
@@ -79,4 +78,3 @@ void rtc_reset(void)
 	/* run RTC counter */
 	writel(0x01, &rtc->ctrl);
 }
-#endif
diff --git a/drivers/rtc/ds1302.c b/drivers/rtc/ds1302.c
index 87ddd01916..b94163f748 100644
--- a/drivers/rtc/ds1302.c
+++ b/drivers/rtc/ds1302.c
@@ -9,8 +9,6 @@
 #include <command.h>
 #include <rtc.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 /* GPP Pins */
 #define DATA		0x200
 #define SCLK		0x400
@@ -328,5 +326,3 @@ int rtc_set(struct rtc_time *tmp)
 
 	return 0;
 }
-
-#endif
diff --git a/drivers/rtc/ds1306.c b/drivers/rtc/ds1306.c
index bd1e0845aa..02d617e09c 100644
--- a/drivers/rtc/ds1306.c
+++ b/drivers/rtc/ds1306.c
@@ -19,8 +19,6 @@
 #include <rtc.h>
 #include <spi.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 #define	RTC_SECONDS		0x00
 #define	RTC_MINUTES		0x01
 #define	RTC_HOURS		0x02
@@ -437,5 +435,3 @@ static void rtc_write (unsigned char reg, unsigned char val)
 }
 
 #endif /* end of code exclusion (see #ifdef CONFIG_SXNI855T above) */
-
-#endif
diff --git a/drivers/rtc/ds1307.c b/drivers/rtc/ds1307.c
index cdb088c9b1..48220b45db 100644
--- a/drivers/rtc/ds1307.c
+++ b/drivers/rtc/ds1307.c
@@ -51,8 +51,6 @@ enum ds_type {
 
 #ifndef CONFIG_DM_RTC
 
-#if defined(CONFIG_CMD_DATE)
-
 /*---------------------------------------------------------------------*/
 #undef DEBUG_RTC
 
@@ -204,8 +202,6 @@ static void rtc_write (uchar reg, uchar val)
 	i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
 }
 
-#endif /* CONFIG_CMD_DATE*/
-
 #endif /* !CONFIG_DM_RTC */
 
 #ifdef CONFIG_DM_RTC
diff --git a/drivers/rtc/ds1337.c b/drivers/rtc/ds1337.c
index 9a0a214386..9b31048e97 100644
--- a/drivers/rtc/ds1337.c
+++ b/drivers/rtc/ds1337.c
@@ -15,8 +15,6 @@
 #include <rtc.h>
 #include <i2c.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 /*
  * RTC register addresses
  */
@@ -190,5 +188,3 @@ static void rtc_write (uchar reg, uchar val)
 {
 	i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
 }
-
-#endif
diff --git a/drivers/rtc/ds1374.c b/drivers/rtc/ds1374.c
index bc27f61c72..5a2060fe75 100644
--- a/drivers/rtc/ds1374.c
+++ b/drivers/rtc/ds1374.c
@@ -18,8 +18,6 @@
 #include <rtc.h>
 #include <i2c.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 /*---------------------------------------------------------------------*/
 #undef DEBUG_RTC
 #define DEBUG_RTC
@@ -214,4 +212,3 @@ static void rtc_write_raw (uchar reg, uchar val)
 {
 		i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
 }
-#endif
diff --git a/drivers/rtc/ds164x.c b/drivers/rtc/ds164x.c
index 7ee6214b2b..f8707892e7 100644
--- a/drivers/rtc/ds164x.c
+++ b/drivers/rtc/ds164x.c
@@ -20,8 +20,6 @@
 #include <rtc.h>
 
 
-#if defined(CONFIG_CMD_DATE)
-
 static uchar    rtc_read(unsigned int addr );
 static void     rtc_write(unsigned int addr, uchar val);
 
@@ -171,5 +169,3 @@ static void rtc_write( unsigned int addr, uchar val )
 #endif
 	*(volatile unsigned char*)(addr) = val;
 }
-
-#endif
diff --git a/drivers/rtc/ds174x.c b/drivers/rtc/ds174x.c
index b6daf59e80..94f943d97a 100644
--- a/drivers/rtc/ds174x.c
+++ b/drivers/rtc/ds174x.c
@@ -16,8 +16,6 @@
 #include <command.h>
 #include <rtc.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 static uchar rtc_read( unsigned int addr );
 static void  rtc_write( unsigned int addr, uchar val);
 
@@ -172,5 +170,3 @@ static void rtc_write( unsigned int addr, uchar val )
 #endif
 	out8( addr, val );
 }
-
-#endif
diff --git a/drivers/rtc/ds3231.c b/drivers/rtc/ds3231.c
index 0e66f6ea0f..9352ff87a2 100644
--- a/drivers/rtc/ds3231.c
+++ b/drivers/rtc/ds3231.c
@@ -16,8 +16,6 @@
 #include <rtc.h>
 #include <i2c.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 /*
  * RTC register addresses
  */
@@ -166,5 +164,3 @@ static void rtc_write (uchar reg, uchar val)
 {
 	i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
 }
-
-#endif
diff --git a/drivers/rtc/imxdi.c b/drivers/rtc/imxdi.c
index 3c4797f4c5..39920f1a7a 100644
--- a/drivers/rtc/imxdi.c
+++ b/drivers/rtc/imxdi.c
@@ -17,8 +17,6 @@
 #include <linux/compat.h>
 #include <rtc.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 #include <asm/io.h>
 #include <asm/arch/imx-regs.h>
 
@@ -222,5 +220,3 @@ void rtc_reset(void)
 {
 	di_init();
 }
-
-#endif
diff --git a/drivers/rtc/m41t11.c b/drivers/rtc/m41t11.c
index e997152098..960348bb3e 100644
--- a/drivers/rtc/m41t11.c
+++ b/drivers/rtc/m41t11.c
@@ -29,8 +29,6 @@
 #endif
 */
 
-#if defined(CONFIG_SYS_I2C_RTC_ADDR) && defined(CONFIG_CMD_DATE)
-
 /* ------------------------------------------------------------------------- */
 /*
   these are simple defines for the chip local to here so they aren't too
@@ -167,4 +165,3 @@ void rtc_reset (void)
 	val = val & 0x3F;/*turn off freq test keep calibration*/
 	i2c_write(CONFIG_SYS_I2C_RTC_ADDR, RTC_CONTROL_ADDR, 1, &val, 1);
 }
-#endif
diff --git a/drivers/rtc/m41t60.c b/drivers/rtc/m41t60.c
index 7846193e26..c84c8e11b3 100644
--- a/drivers/rtc/m41t60.c
+++ b/drivers/rtc/m41t60.c
@@ -20,8 +20,6 @@
 #include <rtc.h>
 #include <i2c.h>
 
-#if defined(CONFIG_SYS_I2C_RTC_ADDR) && defined(CONFIG_CMD_DATE)
-
 /*
  * Convert between century and "century bits" (CB1 and CB0).  These routines
  * assume years are in the range 1900 - 2299.
@@ -237,4 +235,3 @@ void rtc_reset(void)
 	}
 	rtc_dump("end reset");
 }
-#endif /* CONFIG_RTC_M41T60 && CONFIG_SYS_I2C_RTC_ADDR && CONFIG_CMD_DATE */
diff --git a/drivers/rtc/m41t62.c b/drivers/rtc/m41t62.c
index d53ef7d862..137438389d 100644
--- a/drivers/rtc/m41t62.c
+++ b/drivers/rtc/m41t62.c
@@ -18,8 +18,6 @@
 #include <rtc.h>
 #include <i2c.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 #define M41T62_REG_SSEC	0
 #define M41T62_REG_SEC	1
 #define M41T62_REG_MIN	2
@@ -130,5 +128,3 @@ void rtc_reset(void)
 	val &= ~M41T80_ALHOUR_HT;
 	i2c_write(CONFIG_SYS_I2C_RTC_ADDR, M41T62_REG_ALARM_HOUR, 1, &val, 1);
 }
-
-#endif
diff --git a/drivers/rtc/m48t35ax.c b/drivers/rtc/m48t35ax.c
index 0b035ced26..1cc24cccae 100644
--- a/drivers/rtc/m48t35ax.c
+++ b/drivers/rtc/m48t35ax.c
@@ -16,8 +16,6 @@
 #include <rtc.h>
 #include <config.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 static uchar rtc_read  (uchar reg);
 static void  rtc_write (uchar reg, uchar val);
 
@@ -135,5 +133,3 @@ static void rtc_write (uchar reg, uchar val)
 	*(unsigned char *)
 		((CONFIG_SYS_NVRAM_BASE_ADDR + CONFIG_SYS_NVRAM_SIZE - 8) + reg) = val;
 }
-
-#endif
diff --git a/drivers/rtc/max6900.c b/drivers/rtc/max6900.c
index f5c651bad0..b35186579a 100644
--- a/drivers/rtc/max6900.c
+++ b/drivers/rtc/max6900.c
@@ -15,8 +15,6 @@
 #include <rtc.h>
 #include <i2c.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 #ifndef	CONFIG_SYS_I2C_RTC_ADDR
 #define	CONFIG_SYS_I2C_RTC_ADDR	0x50
 #endif
@@ -104,5 +102,3 @@ int rtc_set (struct rtc_time *tmp)
 void rtc_reset (void)
 {
 }
-
-#endif
diff --git a/drivers/rtc/mc146818.c b/drivers/rtc/mc146818.c
index 500eef2ee0..444d4baf0b 100644
--- a/drivers/rtc/mc146818.c
+++ b/drivers/rtc/mc146818.c
@@ -19,8 +19,6 @@
 #define out8(p, v) outb(v, p)
 #endif
 
-#if defined(CONFIG_CMD_DATE)
-
 /* Set this to 1 to clear the CMOS RAM */
 #define CLEAR_CMOS		0
 
@@ -191,7 +189,6 @@ static void mc146818_init(void)
 	/* Clear any pending interrupts */
 	mc146818_read8(RTC_CONFIG_C);
 }
-#endif /* CONFIG_CMD_DATE */
 
 #ifdef CONFIG_DM_RTC
 
diff --git a/drivers/rtc/mcfrtc.c b/drivers/rtc/mcfrtc.c
index 0ac8e4dbc5..e10638ec7d 100644
--- a/drivers/rtc/mcfrtc.c
+++ b/drivers/rtc/mcfrtc.c
@@ -6,8 +6,6 @@
 
 #include <common.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 #include <command.h>
 #include <rtc.h>
 #include <asm/immap.h>
@@ -104,5 +102,3 @@ void rtc_reset(void)
 
 	rtc->cr |= RTC_CR_SWR;
 }
-
-#endif				/* CONFIG_MCFRTC && CONFIG_CMD_DATE */
diff --git a/drivers/rtc/mk48t59.c b/drivers/rtc/mk48t59.c
index d29d5ce600..8c90a70407 100644
--- a/drivers/rtc/mk48t59.c
+++ b/drivers/rtc/mk48t59.c
@@ -70,8 +70,6 @@ void nvram_write(short dest, const void *src, size_t count)
 		rtc_write(d++, *s++);
 }
 
-#if defined(CONFIG_CMD_DATE)
-
 /* ------------------------------------------------------------------------- */
 
 int rtc_get (struct rtc_time *tmp)
@@ -175,5 +173,3 @@ void rtc_set_watchdog(short multi, short res)
 	wd_value = RTC_WDS | ((multi & 0x1F) << 2) | (res & 0x3);
 	rtc_write(RTC_WATCHDOG, wd_value);
 }
-
-#endif
diff --git a/drivers/rtc/pcf8563.c b/drivers/rtc/pcf8563.c
index e2fa6b6aab..a839d6cc98 100644
--- a/drivers/rtc/pcf8563.c
+++ b/drivers/rtc/pcf8563.c
@@ -15,8 +15,6 @@
 #include <rtc.h>
 #include <i2c.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 static uchar rtc_read  (uchar reg);
 static void  rtc_write (uchar reg, uchar val);
 
@@ -117,5 +115,3 @@ static void rtc_write (uchar reg, uchar val)
 {
 	i2c_reg_write (CONFIG_SYS_I2C_RTC_ADDR, reg, val);
 }
-
-#endif
diff --git a/drivers/rtc/rs5c372.c b/drivers/rtc/rs5c372.c
index c815c915d5..97ec001aef 100644
--- a/drivers/rtc/rs5c372.c
+++ b/drivers/rtc/rs5c372.c
@@ -24,7 +24,6 @@
 #include <rtc.h>
 #include <i2c.h>
 
-#if defined(CONFIG_CMD_DATE)
 /*
  * Reads are always done starting with register 15, which requires some
  * jumping-through-hoops to access the data correctly.
@@ -255,5 +254,3 @@ rtc_reset (void)
 	if (!setup_done)
 		rs5c372_enable();
 }
-
-#endif
diff --git a/drivers/rtc/rx8025.c b/drivers/rtc/rx8025.c
index 1c2b92fe00..7bd9f8b42a 100644
--- a/drivers/rtc/rx8025.c
+++ b/drivers/rtc/rx8025.c
@@ -13,8 +13,6 @@
 #include <rtc.h>
 #include <i2c.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 /*---------------------------------------------------------------------*/
 #undef DEBUG_RTC
 
@@ -190,5 +188,3 @@ static void rtc_write (uchar reg, uchar val)
 		printf("Error writing to RTC\n");
 
 }
-
-#endif /* CONFIG_RTC_RX8025 && CONFIG_CMD_DATE */
diff --git a/drivers/rtc/s3c24x0_rtc.c b/drivers/rtc/s3c24x0_rtc.c
index 1253085f53..96ea3cf878 100644
--- a/drivers/rtc/s3c24x0_rtc.c
+++ b/drivers/rtc/s3c24x0_rtc.c
@@ -11,8 +11,6 @@
 #include <common.h>
 #include <command.h>
 
-#if (defined(CONFIG_CMD_DATE))
-
 #include <asm/arch/s3c24x0_cpu.h>
 
 #include <rtc.h>
@@ -149,5 +147,3 @@ void rtc_reset(void)
 	writeb((readb(&rtc->rtccon) & ~0x06) | 0x08, &rtc->rtccon);
 	writeb(readb(&rtc->rtccon) & ~(0x08 | 0x01), &rtc->rtccon);
 }
-
-#endif
diff --git a/drivers/rtc/x1205.c b/drivers/rtc/x1205.c
index e9d8390f39..ed6aaa5237 100644
--- a/drivers/rtc/x1205.c
+++ b/drivers/rtc/x1205.c
@@ -22,8 +22,6 @@
 #include <rtc.h>
 #include <i2c.h>
 
-#if defined(CONFIG_CMD_DATE)
-
 #define CCR_SEC			0
 #define CCR_MIN			1
 #define CCR_HOUR		2
@@ -160,5 +158,3 @@ void rtc_reset(void)
 	 * Nothing to do
 	 */
 }
-
-#endif
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH v2 3/6] efi_loader: remove unused efi_get_time_init()
  2018-07-07 21:39 [U-Boot] [PATCH v2 0/6] efi_loader: complete implementation of GetTime() Heinrich Schuchardt
  2018-07-07 21:39 ` [U-Boot] [PATCH v2 1/6] drivers: rtc: resolve year 2038 problem in rtc_to_tm Heinrich Schuchardt
  2018-07-07 21:39 ` [U-Boot] [PATCH v2 2/6] rtc: remove CONFIG_CMD_DATE dependency Heinrich Schuchardt
@ 2018-07-07 21:39 ` Heinrich Schuchardt
  2018-07-07 21:39 ` [U-Boot] [PATCH v2 4/6] efi_loader: complete implementation of GetTime() Heinrich Schuchardt
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Heinrich Schuchardt @ 2018-07-07 21:39 UTC (permalink / raw)
  To: u-boot

Remove unused function efi_get_time_init().

Initialization of the RTC has to be done in board bring up not in the EFI
subsystem.

There is no RTC device in the UEFI spec. The RTC is only accessed through
the runtime services.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
v2
	update commit message
---
 cmd/bootefi.c                | 3 ---
 include/efi_loader.h         | 1 -
 lib/efi_loader/efi_runtime.c | 5 -----
 3 files changed, 9 deletions(-)

diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index e57e70fc61..b60c151fb4 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -90,9 +90,6 @@ efi_status_t efi_init_obj_list(void)
 	ret = efi_reset_system_init();
 	if (ret != EFI_SUCCESS)
 		goto out;
-	ret = efi_get_time_init();
-	if (ret != EFI_SUCCESS)
-		goto out;
 
 out:
 	efi_obj_list_initialized = ret;
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 8363a4c5f4..f162adfff7 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -437,7 +437,6 @@ efi_status_t efi_reset_system_init(void);
 efi_status_t __efi_runtime EFIAPI efi_get_time(
 			struct efi_time *time,
 			struct efi_time_cap *capabilities);
-efi_status_t efi_get_time_init(void);
 
 #ifdef CONFIG_CMD_BOOTEFI_SELFTEST
 /*
diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c
index 92175aebdb..f44e0555b7 100644
--- a/lib/efi_loader/efi_runtime.c
+++ b/lib/efi_loader/efi_runtime.c
@@ -186,11 +186,6 @@ efi_status_t __weak __efi_runtime EFIAPI efi_get_time(
 	return EFI_DEVICE_ERROR;
 }
 
-efi_status_t __weak efi_get_time_init(void)
-{
-	return EFI_SUCCESS;
-}
-
 struct efi_runtime_detach_list_struct {
 	void *ptr;
 	void *patchto;
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH v2 4/6] efi_loader: complete implementation of GetTime()
  2018-07-07 21:39 [U-Boot] [PATCH v2 0/6] efi_loader: complete implementation of GetTime() Heinrich Schuchardt
                   ` (2 preceding siblings ...)
  2018-07-07 21:39 ` [U-Boot] [PATCH v2 3/6] efi_loader: remove unused efi_get_time_init() Heinrich Schuchardt
@ 2018-07-07 21:39 ` Heinrich Schuchardt
  2018-07-07 21:39 ` [U-Boot] [PATCH v2 5/6] efi_selftest: support printing leading zeroes Heinrich Schuchardt
  2018-07-07 21:39 ` [U-Boot] [PATCH v2 6/6] efi_selftest: unit test for GetTime() Heinrich Schuchardt
  5 siblings, 0 replies; 10+ messages in thread
From: Heinrich Schuchardt @ 2018-07-07 21:39 UTC (permalink / raw)
  To: u-boot

Implement the missing parts of the GetTime() runtime service.

Fill seconds.
Fill daylight saving time flag correctly.
Provide dummy values for capabilities.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
v2
	do not add support for non driver model drivers
---
 lib/efi_loader/efi_runtime.c | 53 ++++++++++++++++++++++++++++--------
 1 file changed, 41 insertions(+), 12 deletions(-)

diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c
index f44e0555b7..351db8d8ed 100644
--- a/lib/efi_loader/efi_runtime.c
+++ b/lib/efi_loader/efi_runtime.c
@@ -129,24 +129,41 @@ static void EFIAPI efi_reset_system_boottime(
 	while (1) { }
 }
 
+/**
+ * efi_get_time_boottime - get current time
+ *
+ * This function implements the GetTime runtime service.
+ * See the Unified Extensible Firmware Interface (UEFI) specification
+ * for details.
+ *
+ * @time:		pointer to structure to receive current time
+ * @capabilities:	pointer to structure to receive RTC properties
+ * Return Value:	status code
+ */
 static efi_status_t EFIAPI efi_get_time_boottime(
 			struct efi_time *time,
 			struct efi_time_cap *capabilities)
 {
-#if defined(CONFIG_CMD_DATE) && defined(CONFIG_DM_RTC)
-	struct rtc_time tm;
+#ifdef CONFIG_DM_RTC
+	efi_status_t ret = EFI_SUCCESS;
 	int r;
+	struct rtc_time tm;
 	struct udevice *dev;
 
 	EFI_ENTRY("%p %p", time, capabilities);
 
-	r = uclass_get_device(UCLASS_RTC, 0, &dev);
-	if (r)
-		return EFI_EXIT(EFI_DEVICE_ERROR);
+	if (!time) {
+		ret = EFI_INVALID_PARAMETER;
+		goto out;
+	}
 
-	r = dm_rtc_get(dev, &tm);
-	if (r)
-		return EFI_EXIT(EFI_DEVICE_ERROR);
+	r = uclass_get_device(UCLASS_RTC, 0, &dev);
+	if (!r)
+		r = dm_rtc_get(dev, &tm);
+	if (r) {
+		ret = EFI_DEVICE_ERROR;
+		goto out;
+	}
 
 	memset(time, 0, sizeof(*time));
 	time->year = tm.tm_year;
@@ -154,11 +171,23 @@ static efi_status_t EFIAPI efi_get_time_boottime(
 	time->day = tm.tm_mday;
 	time->hour = tm.tm_hour;
 	time->minute = tm.tm_min;
-	time->daylight = tm.tm_isdst;
-
-	return EFI_EXIT(EFI_SUCCESS);
+	time->second = tm.tm_sec;
+	time->daylight = EFI_TIME_ADJUST_DAYLIGHT;
+	if (tm.tm_isdst > 0)
+		time->daylight |= EFI_TIME_IN_DAYLIGHT;
+	time->timezone = EFI_UNSPECIFIED_TIMEZONE;
+
+	if (capabilities) {
+		/* Set reasonable dummy values */
+		capabilities->resolution = 1;		/* 1 Hz */
+		capabilities->accuracy = 100000000;	/* 100 ppm */
+		capabilities->sets_to_zero = false;
+	}
+out:
+	return EFI_EXIT(ret);
 #else
-	return EFI_DEVICE_ERROR;
+	EFI_ENTRY("%p %p", time, capabilities);
+	return EFI_EXIT(EFI_DEVICE_ERROR);
 #endif
 }
 
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH v2 5/6] efi_selftest: support printing leading zeroes
  2018-07-07 21:39 [U-Boot] [PATCH v2 0/6] efi_loader: complete implementation of GetTime() Heinrich Schuchardt
                   ` (3 preceding siblings ...)
  2018-07-07 21:39 ` [U-Boot] [PATCH v2 4/6] efi_loader: complete implementation of GetTime() Heinrich Schuchardt
@ 2018-07-07 21:39 ` Heinrich Schuchardt
  2018-07-07 21:39 ` [U-Boot] [PATCH v2 6/6] efi_selftest: unit test for GetTime() Heinrich Schuchardt
  5 siblings, 0 replies; 10+ messages in thread
From: Heinrich Schuchardt @ 2018-07-07 21:39 UTC (permalink / raw)
  To: u-boot

Allow specifying the precision when printing integers, e.g.

efi_st_printf("%.4u-%.2u-%.2u\n", year, month, day);

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
v2
	no change
---
 lib/efi_selftest/efi_selftest_console.c | 33 ++++++++++++++++---------
 1 file changed, 22 insertions(+), 11 deletions(-)

diff --git a/lib/efi_selftest/efi_selftest_console.c b/lib/efi_selftest/efi_selftest_console.c
index c3655a1fcc..eb139c127c 100644
--- a/lib/efi_selftest/efi_selftest_console.c
+++ b/lib/efi_selftest/efi_selftest_console.c
@@ -70,11 +70,12 @@ static void pointer(void *pointer, u16 **buf)
 /*
  * Print an unsigned 32bit value as decimal number to an u16 string
  *
- * @value: value to be printed
- * @buf: pointer to buffer address
- * on return position of terminating zero word
+ * @value:	value to be printed
+ * @prec:	minimum number of digits to display
+ * @buf:	pointer to buffer address
+ *		on return position of terminating zero word
  */
-static void uint2dec(u32 value, u16 **buf)
+static void uint2dec(u32 value, int prec, u16 **buf)
 {
 	u16 *pos = *buf;
 	int i;
@@ -93,7 +94,7 @@ static void uint2dec(u32 value, u16 **buf)
 	for (i = 0; i < 10; ++i) {
 		/* Write current digit */
 		c = f >> 60;
-		if (c || pos != *buf)
+		if (c || pos != *buf || 10 - i <= prec)
 			*pos++ = c + '0';
 		/* Eliminate current digit */
 		f &= 0xfffffffffffffff;
@@ -109,11 +110,12 @@ static void uint2dec(u32 value, u16 **buf)
 /*
  * Print a signed 32bit value as decimal number to an u16 string
  *
- * @value: value to be printed
- * @buf: pointer to buffer address
+ * @value:	value to be printed
+ * @prec:	minimum number of digits to display
+ * @buf:	pointer to buffer address
  * on return position of terminating zero word
  */
-static void int2dec(s32 value, u16 **buf)
+static void int2dec(s32 value, int prec, u16 **buf)
 {
 	u32 u;
 	u16 *pos = *buf;
@@ -124,7 +126,7 @@ static void int2dec(s32 value, u16 **buf)
 	} else {
 		u = value;
 	}
-	uint2dec(u, &pos);
+	uint2dec(u, prec, &pos);
 	*buf = pos;
 }
 
@@ -143,6 +145,7 @@ void efi_st_printc(int color, const char *fmt, ...)
 	u16 *pos = buf;
 	const char *s;
 	u16 *u;
+	int prec;
 
 	va_start(args, fmt);
 
@@ -172,12 +175,20 @@ void efi_st_printc(int color, const char *fmt, ...)
 			break;
 		case '%':
 			++c;
+			/* Parse precision */
+			if (*c == '.') {
+				++c;
+				prec = *c - '0';
+				++c;
+			} else {
+				prec = 0;
+			}
 			switch (*c) {
 			case '\0':
 				--c;
 				break;
 			case 'd':
-				int2dec(va_arg(args, s32), &pos);
+				int2dec(va_arg(args, s32), prec, &pos);
 				break;
 			case 'p':
 				++c;
@@ -209,7 +220,7 @@ void efi_st_printc(int color, const char *fmt, ...)
 					*pos++ = *s;
 				break;
 			case 'u':
-				uint2dec(va_arg(args, u32), &pos);
+				uint2dec(va_arg(args, u32), prec, &pos);
 				break;
 			default:
 				break;
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH v2 6/6] efi_selftest: unit test for GetTime()
  2018-07-07 21:39 [U-Boot] [PATCH v2 0/6] efi_loader: complete implementation of GetTime() Heinrich Schuchardt
                   ` (4 preceding siblings ...)
  2018-07-07 21:39 ` [U-Boot] [PATCH v2 5/6] efi_selftest: support printing leading zeroes Heinrich Schuchardt
@ 2018-07-07 21:39 ` Heinrich Schuchardt
  5 siblings, 0 replies; 10+ messages in thread
From: Heinrich Schuchardt @ 2018-07-07 21:39 UTC (permalink / raw)
  To: u-boot

Provide a unit test for the GetTime() runtime service.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
v2
	no change
---
 lib/efi_selftest/Makefile           |  1 +
 lib/efi_selftest/efi_selftest_rtc.c | 67 +++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+)
 create mode 100644 lib/efi_selftest/efi_selftest_rtc.c

diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
index 1f3084cfb8..590f90b16d 100644
--- a/lib/efi_selftest/Makefile
+++ b/lib/efi_selftest/Makefile
@@ -25,6 +25,7 @@ efi_selftest_exitbootservices.o \
 efi_selftest_fdt.o \
 efi_selftest_gop.o \
 efi_selftest_manageprotocols.o \
+efi_selftest_rtc.o \
 efi_selftest_snp.o \
 efi_selftest_textinput.o \
 efi_selftest_textoutput.o \
diff --git a/lib/efi_selftest/efi_selftest_rtc.c b/lib/efi_selftest/efi_selftest_rtc.c
new file mode 100644
index 0000000000..8d440dc0b3
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_rtc.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_rtc
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * Test the real time clock runtime services.
+ */
+
+#include <efi_selftest.h>
+
+#define EFI_ST_NO_RTC "Could not read real time clock\n"
+
+static struct efi_runtime_services *runtime;
+
+/*
+ * Setup unit test.
+ *
+ * @handle:	handle of the loaded image
+ * @systable:	system table
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+		 const struct efi_system_table *systable)
+{
+	runtime = systable->runtime;
+	return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ * Display current time.
+ *
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+	efi_status_t ret;
+	struct efi_time tm;
+
+	/* Display current time */
+	ret = runtime->get_time(&tm, NULL);
+	if (ret != EFI_SUCCESS) {
+#ifdef CONFIG_CMD_DATE
+		efi_st_error(EFI_ST_NO_RTC);
+		return EFI_ST_FAILURE;
+#else
+		efi_st_todo(EFI_ST_NO_RTC);
+		return EFI_ST_SUCCESS;
+#endif
+	} else {
+		efi_st_printf("Time according to real time clock: "
+			      "%.4u-%.2u-%.2u %.2u:%.2u:%.2u\n",
+			      tm.year, tm.month, tm.day,
+			      tm.hour, tm.minute, tm.second);
+	}
+
+	return EFI_ST_SUCCESS;
+}
+
+EFI_UNIT_TEST(rtc) = {
+	.name = "real time clock",
+	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+	.setup = setup,
+	.execute = execute,
+};
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH v2 1/6] drivers: rtc: resolve year 2038 problem in rtc_to_tm
  2018-07-07 21:39 ` [U-Boot] [PATCH v2 1/6] drivers: rtc: resolve year 2038 problem in rtc_to_tm Heinrich Schuchardt
@ 2018-07-08 21:32   ` Alexander Graf
  2018-07-09  8:13     ` Arnd Bergmann
  2018-07-20 12:37   ` [U-Boot] [U-Boot, v2, " Tom Rini
  1 sibling, 1 reply; 10+ messages in thread
From: Alexander Graf @ 2018-07-08 21:32 UTC (permalink / raw)
  To: u-boot



On 07.07.18 23:39, Heinrich Schuchardt wrote:
> Our implementation of rtc_to_tm() cannot handle dates of more than
> 0x7fffffff seconds after 1970-01-01.
> 
> Adopt the Linux kernel implementation.
> 
> Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>

This patch is slightly out of scope for efi-next and the other patches
are independent of it FWIW, so I'll leave it to others to review.

I'll CC Arnd though, as I'm quite sure he has a good grip on anything
2038 :)


Alex

> ---
> v2
> 	adopt the Linux kernel implementation
> ---
>  drivers/rtc/Makefile       |  1 +
>  drivers/rtc/date.c         | 43 ----------------------
>  drivers/rtc/i2c_rtc_emul.c |  4 ++-
>  drivers/rtc/rtc-lib.c      | 73 ++++++++++++++++++++++++++++++++++++++
>  include/rtc.h              | 16 +++++++--
>  5 files changed, 90 insertions(+), 47 deletions(-)
>  create mode 100644 drivers/rtc/rtc-lib.c
> 
> diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
> index 09f2b08244..513e3ffc07 100644
> --- a/drivers/rtc/Makefile
> +++ b/drivers/rtc/Makefile
> @@ -8,6 +8,7 @@ obj-$(CONFIG_DM_RTC) += rtc-uclass.o
>  
>  obj-$(CONFIG_RTC_AT91SAM9_RTT) += at91sam9_rtt.o
>  obj-y += date.o
> +obj-y += rtc-lib.o
>  obj-$(CONFIG_RTC_DAVINCI) += davinci.o
>  obj-$(CONFIG_RTC_DS1302) += ds1302.o
>  obj-$(CONFIG_RTC_DS1306) += ds1306.o
> diff --git a/drivers/rtc/date.c b/drivers/rtc/date.c
> index 1256ffe374..f2568cf886 100644
> --- a/drivers/rtc/date.c
> +++ b/drivers/rtc/date.c
> @@ -19,10 +19,6 @@
>  #define	days_in_year(a)		(leapyear(a) ? 366 : 365)
>  #define	days_in_month(a)	(month_days[(a) - 1])
>  
> -static int month_days[12] = {
> -	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
> -};
> -
>  static int month_offset[] = {
>  	0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
>  };
> @@ -65,45 +61,6 @@ int rtc_calc_weekday(struct rtc_time *tm)
>  	return 0;
>  }
>  
> -int rtc_to_tm(int tim, struct rtc_time *tm)
> -{
> -	register int i;
> -	register long hms, day;
> -
> -	day = tim / SECDAY;
> -	hms = tim % SECDAY;
> -
> -	/* Hours, minutes, seconds are easy */
> -	tm->tm_hour = hms / 3600;
> -	tm->tm_min = (hms % 3600) / 60;
> -	tm->tm_sec = (hms % 3600) % 60;
> -
> -	/* Number of years in days */
> -	for (i = STARTOFTIME; day >= days_in_year(i); i++)
> -		day -= days_in_year(i);
> -	tm->tm_year = i;
> -
> -	/* Number of months in days left */
> -	if (leapyear(tm->tm_year))
> -		days_in_month(FEBRUARY) = 29;
> -	for (i = 1; day >= days_in_month(i); i++)
> -		day -= days_in_month(i);
> -	days_in_month(FEBRUARY) = 28;
> -	tm->tm_mon = i;
> -
> -	/* Days are what is left over (+1) from all that */
> -	tm->tm_mday = day + 1;
> -
> -	/* Zero unused fields */
> -	tm->tm_yday = 0;
> -	tm->tm_isdst = 0;
> -
> -	/*
> -	 * Determine the day of week
> -	 */
> -	return rtc_calc_weekday(tm);
> -}
> -
>  /*
>   * Converts Gregorian date to seconds since 1970-01-01 00:00:00.
>   * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
> diff --git a/drivers/rtc/i2c_rtc_emul.c b/drivers/rtc/i2c_rtc_emul.c
> index bad61c377f..d4b33e59d6 100644
> --- a/drivers/rtc/i2c_rtc_emul.c
> +++ b/drivers/rtc/i2c_rtc_emul.c
> @@ -96,7 +96,9 @@ static int sandbox_i2c_rtc_get(struct udevice *dev, struct rtc_time *time)
>  		now = plat->base_time;
>  	}
>  
> -	return rtc_to_tm(now + plat->offset, time);
> +	rtc_to_tm(now + plat->offset, time);
> +
> +	return 0;
>  }
>  
>  static int sandbox_i2c_rtc_set(struct udevice *dev, const struct rtc_time *time)
> diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c
> new file mode 100644
> index 0000000000..b8a7a8b2d3
> --- /dev/null
> +++ b/drivers/rtc/rtc-lib.c
> @@ -0,0 +1,73 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * rtc and date/time utility functions
> + *
> + * Copyright (C) 2005-06 Tower Technologies
> + * Author: Alessandro Zummo <a.zummo@towertech.it>
> + *
> + * U-Boot rtc_time differs from Linux rtc_time:
> + * - The year field takes the actual value, not year - 1900.
> + * - January is month 1.
> + */
> +
> +#include <common.h>
> +#include <rtc.h>
> +#include <linux/math64.h>
> +
> +static const unsigned char rtc_days_in_month[] = {
> +	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
> +};
> +
> +#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
> +
> +/*
> + * The number of days in the month.
> + */
> +static int rtc_month_days(unsigned int month, unsigned int year)
> +{
> +	return rtc_days_in_month[month] + (is_leap_year(year) && month == 1);
> +}
> +
> +/*
> + * rtc_to_tm - Converts u64 to rtc_time.
> + * Convert seconds since 01-01-1970 00:00:00 to Gregorian date.
> + */
> +void rtc_to_tm(u64 time, struct rtc_time *tm)
> +{
> +	unsigned int month, year, secs, days;
> +
> +	days = div_u64_rem(time, 86400, &secs);
> +
> +	/* day of the week, 1970-01-01 was a Thursday */
> +	tm->tm_wday = (days + 4) % 7;
> +
> +	year = 1970 + days / 365;
> +	days -= (year - 1970) * 365
> +		+ LEAPS_THRU_END_OF(year - 1)
> +		- LEAPS_THRU_END_OF(1970 - 1);
> +	while (days < 0) {
> +		year -= 1;
> +		days += 365 + is_leap_year(year);
> +	}
> +	tm->tm_year = year; /* Not year - 1900 */
> +	tm->tm_yday = days + 1;
> +
> +	for (month = 0; month < 11; month++) {
> +		int newdays;
> +
> +		newdays = days - rtc_month_days(month, year);
> +		if (newdays < 0)
> +			break;
> +		days = newdays;
> +	}
> +	tm->tm_mon = month + 1; /* January = 1 */
> +	tm->tm_mday = days + 1;
> +
> +	tm->tm_hour = secs / 3600;
> +	secs -= tm->tm_hour * 3600;
> +	tm->tm_min = secs / 60;
> +	tm->tm_sec = secs - tm->tm_min * 60;
> +
> +	/* Zero unused fields */
> +	tm->tm_isdst = 0;
> +}
> diff --git a/include/rtc.h b/include/rtc.h
> index 746624d799..0d964d56d5 100644
> --- a/include/rtc.h
> +++ b/include/rtc.h
> @@ -208,7 +208,18 @@ void rtc_write32(int reg, u32 value);
>   * rtc_init() - Set up the real time clock ready for use
>   */
>  void rtc_init(void);
> -#endif
> +#endif /* CONFIG_DM_RTC */
> +
> +/**
> + * is_leap_year - Check if year is a leap year
> + *
> + * @year	Year
> + * @return	1 if leap year
> + */
> +static inline bool is_leap_year(unsigned int year)
> +{
> +	return (!(year % 4) && (year % 100)) || !(year % 400);
> +}
>  
>  /**
>   * rtc_calc_weekday() - Work out the weekday from a time
> @@ -231,9 +242,8 @@ int rtc_calc_weekday(struct rtc_time *time);
>   *
>   * @time_t:	Number of seconds since 1970-01-01 00:00:00
>   * @time:	Place to put the broken-out time
> - * @return 0 if OK, -EINVAL if the weekday could not be determined
>   */
> -int rtc_to_tm(int time_t, struct rtc_time *time);
> +void rtc_to_tm(u64 time_t, struct rtc_time *time);
>  
>  /**
>   * rtc_mktime() - Convert a broken-out time into a time_t value
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH v2 1/6] drivers: rtc: resolve year 2038 problem in rtc_to_tm
  2018-07-08 21:32   ` Alexander Graf
@ 2018-07-09  8:13     ` Arnd Bergmann
  0 siblings, 0 replies; 10+ messages in thread
From: Arnd Bergmann @ 2018-07-09  8:13 UTC (permalink / raw)
  To: u-boot

On Sun, Jul 8, 2018 at 11:32 PM, Alexander Graf <agraf@suse.de> wrote:
>
>
> On 07.07.18 23:39, Heinrich Schuchardt wrote:
>> Our implementation of rtc_to_tm() cannot handle dates of more than
>> 0x7fffffff seconds after 1970-01-01.
>>
>> Adopt the Linux kernel implementation.
>>
>> Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
>
> This patch is slightly out of scope for efi-next and the other patches
> are independent of it FWIW, so I'll leave it to others to review.
>
> I'll CC Arnd though, as I'm quite sure he has a good grip on anything
> 2038 :)

Ok, I'll point out some common issues with RTC devices:

>> diff --git a/drivers/rtc/i2c_rtc_emul.c b/drivers/rtc/i2c_rtc_emul.c
>> index bad61c377f..d4b33e59d6 100644
>> --- a/drivers/rtc/i2c_rtc_emul.c
>> +++ b/drivers/rtc/i2c_rtc_emul.c
>> @@ -96,7 +96,9 @@ static int sandbox_i2c_rtc_get(struct udevice *dev, struct rtc_time *time)
>>               now = plat->base_time;
>>       }
>>
>> -     return rtc_to_tm(now + plat->offset, time);
>> +     rtc_to_tm(now + plat->offset, time);
>> +
>> +     return 0;
>>  }

Looking at the sources here:
https://github.com/u-boot/u-boot/blob/master/drivers/rtc/i2c_rtc_emul.c

I found that 'now' is sometimes an 'int' and sometimes a 'long', but
both of them
are typically signed 32-bit numbers that still overflow. To actually make this
patch have any effect, u-boot would consistently need to use 64-bit signed
numbers in all the common code as well as in drivers for devices that support
times after 2038.

In particular the rtc_mktime() should use the same types as rtc_to_tm(), since
it does the reverse operation.

>> diff --git a/include/rtc.h b/include/rtc.h
>> index 746624d799..0d964d56d5 100644
>> --- a/include/rtc.h
>> +++ b/include/rtc.h
>> @@ -208,7 +208,18 @@ void rtc_write32(int reg, u32 value);
>>   * rtc_init() - Set up the real time clock ready for use
>>   */
>>  void rtc_init(void);
>> -#endif
>> +#endif /* CONFIG_DM_RTC */
>> +
>> +/**
>> + * is_leap_year - Check if year is a leap year
>> + *
>> + * @year     Year
>> + * @return   1 if leap year
>> + */
>> +static inline bool is_leap_year(unsigned int year)
>> +{
>> +     return (!(year % 4) && (year % 100)) || !(year % 400);
>> +}

Note that many hardware RTC implementations get the the
leap year computation wrong: Since 2000 was a leap year but
2100 is not, a typical shortcut was to assume that every fourth
year is a leap year. In RTC devices that have a two-digit
BCD number for storing the year, this means we can use the 00-99
range either to encode years 2000 through 2099, or (using the
typical wrapping) assuming that all numbers larger 69 are 1970 through
1999, while numbers from 00 to 69 are 2000 through 2099.

The i2c test driver has an unsigned 8-bit number for the year, starting
at 1900, so it could support years up to 2155, which is also a common
value in hardware RTCs, but I would assume that many of those also
have a problem on March 1, 2100, working on the assumption that there
is a Feb 29 that year, which requires adding another day to the
calculation after that day.

      Arnd

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [U-Boot] [U-Boot, v2, 1/6] drivers: rtc: resolve year 2038 problem in rtc_to_tm
  2018-07-07 21:39 ` [U-Boot] [PATCH v2 1/6] drivers: rtc: resolve year 2038 problem in rtc_to_tm Heinrich Schuchardt
  2018-07-08 21:32   ` Alexander Graf
@ 2018-07-20 12:37   ` Tom Rini
  1 sibling, 0 replies; 10+ messages in thread
From: Tom Rini @ 2018-07-20 12:37 UTC (permalink / raw)
  To: u-boot

On Sat, Jul 07, 2018 at 11:39:11PM +0200, Heinrich Schuchardt wrote:

> Our implementation of rtc_to_tm() cannot handle dates of more than
> 0x7fffffff seconds after 1970-01-01.
> 
> Adopt the Linux kernel implementation.
> 
> Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20180720/697d91f2/attachment.sig>

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2018-07-20 12:37 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-07 21:39 [U-Boot] [PATCH v2 0/6] efi_loader: complete implementation of GetTime() Heinrich Schuchardt
2018-07-07 21:39 ` [U-Boot] [PATCH v2 1/6] drivers: rtc: resolve year 2038 problem in rtc_to_tm Heinrich Schuchardt
2018-07-08 21:32   ` Alexander Graf
2018-07-09  8:13     ` Arnd Bergmann
2018-07-20 12:37   ` [U-Boot] [U-Boot, v2, " Tom Rini
2018-07-07 21:39 ` [U-Boot] [PATCH v2 2/6] rtc: remove CONFIG_CMD_DATE dependency Heinrich Schuchardt
2018-07-07 21:39 ` [U-Boot] [PATCH v2 3/6] efi_loader: remove unused efi_get_time_init() Heinrich Schuchardt
2018-07-07 21:39 ` [U-Boot] [PATCH v2 4/6] efi_loader: complete implementation of GetTime() Heinrich Schuchardt
2018-07-07 21:39 ` [U-Boot] [PATCH v2 5/6] efi_selftest: support printing leading zeroes Heinrich Schuchardt
2018-07-07 21:39 ` [U-Boot] [PATCH v2 6/6] efi_selftest: unit test for GetTime() Heinrich Schuchardt

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.