[PATCH] uefirttime: add fwts tests for the UEFI get/set time runtime services

Ivan Hu ivan.hu at canonical.com
Tue Oct 16 08:37:51 UTC 2012


Add the set and get time tests of the UEFI runtime service interfaces
which test via efi_runtime driver.

Signed-off-by: Ivan Hu <ivan.hu at canonical.com>
---
 src/Makefile.am                  |    5 +-
 src/lib/include/fwts_uefi.h      |    7 +
 src/uefi/uefirttime/uefirttime.c |  267 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 277 insertions(+), 2 deletions(-)
 create mode 100644 src/uefi/uefirttime/uefirttime.c

diff --git a/src/Makefile.am b/src/Makefile.am
index 6054eb3..b7adc20 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -6,7 +6,7 @@
 # but libfwts.so depends on libraries produced by acpica/source/compiler.
 SUBDIRS = acpica/source/compiler lib acpica
  
-AM_CPPFLAGS = -I$(top_srcdir)/src/lib/include -I$(top_srcdir)/src/acpica/source/include -Wall -Werror
+AM_CPPFLAGS = -I$(top_srcdir)/src/lib/include -I$(top_srcdir)/src/acpica/source/include -I$(top_srcdir)/efi_runtime -Wall -Werror
 
 bin_PROGRAMS = fwts
 fwts_SOURCES = main.c \
@@ -66,7 +66,8 @@ fwts_SOURCES = main.c \
 	kernel/version/version.c \
 	kernel/oops/oops.c \
 	uefi/csm/csm.c \
-	uefi/uefidump/uefidump.c
+	uefi/uefidump/uefidump.c \
+	uefi/uefirttime/uefirttime.c
 
 fwts_LDFLAGS = -ljson -lm
 
diff --git a/src/lib/include/fwts_uefi.h b/src/lib/include/fwts_uefi.h
index f45027d..73cd773 100644
--- a/src/lib/include/fwts_uefi.h
+++ b/src/lib/include/fwts_uefi.h
@@ -41,6 +41,13 @@ enum {
 	FWTS_UEFI_VAR_RUNTIME_ACCESS =		0x00000004
 };
 
+enum {
+	FWTS_UEFI_TIME_ADJUST_DAYLIGHT =	0x01,
+	FWTS_UEFI_TIME_IN_DAYLIGHT = 		0x02
+};
+
+#define FWTS_UEFI_UNSPECIFIED_TIMEZONE 0x07FF
+
 #if 0
 typedef struct {
 	char *description;
diff --git a/src/uefi/uefirttime/uefirttime.c b/src/uefi/uefirttime/uefirttime.c
new file mode 100644
index 0000000..bba15d2
--- /dev/null
+++ b/src/uefi/uefirttime/uefirttime.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2010-2012 Canonical
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stddef.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include "fwts.h"
+#include "fwts_uefi.h"
+#include "efi_runtime.h"
+
+#define is_leap(year) \
+		((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
+
+static int fd;
+static uint32_t dayofmonth[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+static bool dayvalid(EFI_TIME *Time)
+{
+	if (Time->Day < 1)
+		return false;
+
+	if (Time->Day > dayofmonth[Time->Month - 1])
+		return false;
+
+	/* check month 2 */
+	if (Time->Month == 2 && (!is_leap(Time->Year) && Time->Day > 28))
+		return false;
+
+	return true;
+}
+
+static bool checktimefields(EFI_TIME *Time)
+{
+	if (Time->Year < 1998 || Time->Year > 2099)
+		return false;
+
+	if (Time->Month < 1 || Time->Month > 12)
+		return false;
+
+	if (!dayvalid(Time))
+		return false;
+
+	if (Time->Hour > 23)
+		return false;
+
+	if (Time->Minute > 59)
+		return false;
+
+	if (Time->Second > 59)
+		return false;
+
+	if (Time->Nanosecond > 999999999)
+		return false;
+
+	if (!(Time->TimeZone == FWTS_UEFI_UNSPECIFIED_TIMEZONE ||
+		(Time->TimeZone >= -1440 && Time->TimeZone <= 1440)))
+		return false;
+
+	if (Time->Daylight & (~(FWTS_UEFI_TIME_ADJUST_DAYLIGHT |
+						FWTS_UEFI_TIME_IN_DAYLIGHT)))
+		return false;
+
+	return true;
+}
+
+static int uefirttime_init(fwts_framework *fw)
+{
+	if (fwts_firmware_detect() != FWTS_FIRMWARE_UEFI) {
+		fwts_log_info(fw, "Cannot detect any UEFI firmware. Aborted.");
+		return FWTS_ABORTED;
+	}
+
+	fd = open("/dev/efi_runtime", O_RDONLY);
+	if (fd == -1) {
+		fwts_log_info(fw, "Cannot open efi_runtime driver. Aborted.");
+		return FWTS_ABORTED;
+	}
+
+	return FWTS_OK;
+}
+
+static int uefirttime_test1(fwts_framework *fw)
+{
+	long ioret;
+	struct efi_gettime gettime;
+	EFI_TIME efi_time;
+
+	EFI_TIME_CAPABILITIES efi_time_cap;
+	uint64_t status;
+
+	gettime.Capabilities = &efi_time_cap;
+	gettime.Time = &efi_time;
+	gettime.status = &status;
+
+	ioret = ioctl(fd, EFI_RUNTIME_GET_TIME, &gettime);
+
+	if (ioret == -1) {
+		fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeGetTime",
+			"Failed to get time with UEFI runtime service.");
+		return FWTS_ERROR;
+	}
+
+	if (!checktimefields(gettime.Time)) {
+		fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeGetTime",
+			"Time field invalid with gettime runtime service.");
+		return FWTS_ERROR;
+	}
+
+	fwts_passed(fw, "Test passed.");
+
+	return FWTS_OK;
+}
+
+static int uefirttime_test2(fwts_framework *fw)
+{
+
+	long ioret;
+	struct efi_settime settime;
+	uint64_t status;
+	struct efi_gettime gettime;
+
+	EFI_TIME oldtime;
+	EFI_TIME newtime;
+	EFI_TIME time;
+	EFI_TIME_CAPABILITIES efi_time_cap;
+
+	gettime.Capabilities = &efi_time_cap;
+	gettime.Time = &oldtime;
+	gettime.status = &status;
+	ioret = ioctl(fd, EFI_RUNTIME_GET_TIME, &gettime);
+
+	if (ioret == -1) {
+		fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeGetTime",
+			"Failed to get time with UEFI runtime service.");
+		return FWTS_ERROR;
+	}
+
+	/* refer to UEFI SCT 2.3 test items */
+	/* change year */
+	time = oldtime;
+	if (time.Year != 2012)
+		time.Year = 2012;
+	else
+		time.Year = 2016;
+
+	/* change month */
+	if (time.Month != 1)
+		time.Month = 1;
+	else
+		time.Month = 12;
+
+	/* Change daylight */
+	if (time.Daylight & FWTS_UEFI_TIME_ADJUST_DAYLIGHT)
+		time.Daylight &= ~FWTS_UEFI_TIME_ADJUST_DAYLIGHT;
+	else
+		time.Daylight |= FWTS_UEFI_TIME_ADJUST_DAYLIGHT;
+
+	/* Change time zone */
+	if (time.TimeZone != 0)
+		time.TimeZone = 0;
+	else
+		time.TimeZone = 1;
+
+	settime.Time = &time;
+	settime.status = &status;
+
+	ioret = ioctl(fd, EFI_RUNTIME_SET_TIME, &settime);
+	if (ioret == -1) {
+		fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeSetTime",
+			"Failed to set time with UEFI runtime service.");
+		return FWTS_ERROR;
+	}
+
+	sleep(1);
+
+	gettime.Time = &newtime;
+
+	ioret = ioctl(fd, EFI_RUNTIME_GET_TIME, &gettime);
+
+	if (ioret == -1) {
+		fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeGetTime",
+			"Failed to get time with UEFI runtime service.");
+		return FWTS_ERROR;
+	}
+
+	if (!((oldtime.Year == 2012) && (newtime.Year == 2016)) &&
+		!((oldtime.Year != 2012) && (newtime.Year == 2012))) {
+		fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeSetTime",
+			"Failed to set year with UEFI runtime service.");
+		return FWTS_ERROR;
+	}
+
+	if (!((oldtime.Month == 1) && (newtime.Month == 12)) &&
+		!((oldtime.Month != 1) && (newtime.Month == 1))) {
+		fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeSetTime",
+			"Failed to set month with UEFI runtime service.");
+		return FWTS_ERROR;
+	}
+
+	if (!((oldtime.Daylight == 1) && (newtime.Month == 12)) &&
+		!((oldtime.Month != 1) && (newtime.Month == 1))) {
+		fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeSetTime",
+			"Failed to set month with UEFI runtime service.");
+		return FWTS_ERROR;
+	}
+
+	if (!((oldtime.Daylight & FWTS_UEFI_TIME_ADJUST_DAYLIGHT) &&
+		(!(newtime.Daylight & FWTS_UEFI_TIME_ADJUST_DAYLIGHT))) &&
+		!((!(oldtime.Daylight & FWTS_UEFI_TIME_ADJUST_DAYLIGHT)) &&
+		(newtime.Daylight & FWTS_UEFI_TIME_ADJUST_DAYLIGHT))) {
+		fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeSetTime",
+			"Failed to set daylight with UEFI runtime service.");
+		return FWTS_ERROR;
+	}
+
+	if (!((oldtime.TimeZone == 0) && (newtime.TimeZone == 1)) &&
+	!((oldtime.TimeZone != 0) && (newtime.TimeZone == 0))) {
+		fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeSetTime",
+			"Failed to set timezone with UEFI runtime service.");
+		return FWTS_ERROR;
+	}
+
+	/* restore the previous time. */
+	settime.Time = &oldtime;
+	ioret = ioctl(fd, EFI_RUNTIME_SET_TIME, &settime);
+	if (ioret == -1) {
+		fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeSetTime",
+			"Failed to set time with UEFI runtime service.");
+		return FWTS_ERROR;
+	}
+
+	fwts_passed(fw, "Test passed.");
+
+	return FWTS_OK;
+}
+
+static fwts_framework_minor_test uefirttime_tests[] = {
+	{ uefirttime_test1, "Test UEFI RT service get time interface." },
+	{ uefirttime_test2, "Test UEFI RT service set time interface." },
+	{ NULL, NULL }
+};
+
+static fwts_framework_ops uefirttime_ops = {
+	.description = "UEFI Runtime service time interface tests.",
+	.init        = uefirttime_init,
+	.minor_tests = uefirttime_tests
+};
+
+FWTS_REGISTER(uefirttime, &uefirttime_ops, FWTS_TEST_ANYTIME, FWTS_FLAG_UNSAFE | FWTS_FLAG_ROOT_PRIV);
-- 
1.7.9.5




More information about the fwts-devel mailing list