[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