diff mbox

uefi: uefirttime: Add tests to exercise invalid parameters

Message ID 1426610657-5692-1-git-send-email-colin.king@canonical.com
State Accepted
Headers show

Commit Message

Colin Ian King March 17, 2015, 4:44 p.m. UTC
From: Colin Ian King <colin.king@canonical.com>

Make the runtime date/time specific service tests exercise invalid
parameters, such as:

 * Null parameters
 * Illegal out of range values in paramaters

To facilitate the Null paramaters, the efi_runtime required some
changes to check for NULLs and pass these over to the run time services
appropriately.

Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
 efi_runtime/efi_runtime.c                          |  49 +-
 .../arg-show-tests-full-0001.log                   |  68 ++-
 src/uefi/uefirttime/uefirttime.c                   | 642 ++++++++++++++++++++-
 3 files changed, 733 insertions(+), 26 deletions(-)

Comments

Alex Hung March 18, 2015, 4:08 a.m. UTC | #1
On 03/18/2015 12:44 AM, Colin King wrote:
> From: Colin Ian King <colin.king@canonical.com>
> 
> Make the runtime date/time specific service tests exercise invalid
> parameters, such as:
> 
>  * Null parameters
>  * Illegal out of range values in paramaters
> 
> To facilitate the Null paramaters, the efi_runtime required some
> changes to check for NULLs and pass these over to the run time services
> appropriately.
> 
> Signed-off-by: Colin Ian King <colin.king@canonical.com>
> ---
>  efi_runtime/efi_runtime.c                          |  49 +-
>  .../arg-show-tests-full-0001.log                   |  68 ++-
>  src/uefi/uefirttime/uefirttime.c                   | 642 ++++++++++++++++++++-
>  3 files changed, 733 insertions(+), 26 deletions(-)
> 


Acked-by: Alex Hung <alex.hung@canonical.com>
Keng-Yu Lin March 18, 2015, 4:43 a.m. UTC | #2
On Wed, Mar 18, 2015 at 12:08 PM, Alex Hung <alex.hung@canonical.com> wrote:
> On 03/18/2015 12:44 AM, Colin King wrote:
>> From: Colin Ian King <colin.king@canonical.com>
>>
>> Make the runtime date/time specific service tests exercise invalid
>> parameters, such as:
>>
>>  * Null parameters
>>  * Illegal out of range values in paramaters
>>
>> To facilitate the Null paramaters, the efi_runtime required some
>> changes to check for NULLs and pass these over to the run time services
>> appropriately.
>>
>> Signed-off-by: Colin Ian King <colin.king@canonical.com>
>> ---
>>  efi_runtime/efi_runtime.c                          |  49 +-
>>  .../arg-show-tests-full-0001.log                   |  68 ++-
>>  src/uefi/uefirttime/uefirttime.c                   | 642 ++++++++++++++++++++-
>>  3 files changed, 733 insertions(+), 26 deletions(-)
>>
>
>
> Acked-by: Alex Hung <alex.hung@canonical.com>
>
Acked-by: Keng-Yu Lin <kengyu@canonical.com>
diff mbox

Patch

diff --git a/efi_runtime/efi_runtime.c b/efi_runtime/efi_runtime.c
index 2708b4b..638a817 100644
--- a/efi_runtime/efi_runtime.c
+++ b/efi_runtime/efi_runtime.c
@@ -348,30 +348,37 @@  static long efi_runtime_get_time(unsigned long arg)
 {
 	struct efi_gettime __user *pgettime;
 	struct efi_gettime  pgettime_local;
-	EFI_TIME_CAPABILITIES __user *cap_local;
 	efi_status_t status;
 	efi_time_cap_t cap;
 	efi_time_t eft;
 
-	status = efi.get_time(&eft, &cap);
 	pgettime = (struct efi_gettime __user *)arg;
 	if (copy_from_user(&pgettime_local, pgettime, sizeof(pgettime_local)))
 		return -EFAULT;
 
-	cap_local = (EFI_TIME_CAPABILITIES *)pgettime_local.Capabilities;
+	status = efi.get_time(pgettime_local.Time ? &eft : NULL,
+			      pgettime_local.Capabilities ? &cap : NULL);
+
 	if (put_user(status, pgettime_local.status))
 		return -EFAULT;
 	if (status != EFI_SUCCESS) {
 		printk(KERN_ERR "efitime: can't read time\n");
 		return -EINVAL;
 	}
-	if (put_user(cap.resolution,
+	if (pgettime_local.Capabilities) {
+		EFI_TIME_CAPABILITIES __user *cap_local;
+
+		cap_local = (EFI_TIME_CAPABILITIES *)pgettime_local.Capabilities;
+		if (put_user(cap.resolution,
 				&(cap_local->Resolution)) ||
 				put_user(cap.accuracy, &(cap_local->Accuracy)) ||
 				put_user(cap.sets_to_zero,&(cap_local->SetsToZero)))
-		return -EFAULT;
-	return copy_to_user(pgettime_local.Time, &eft,
+			return -EFAULT;
+	}
+	if (pgettime_local.Time)
+		return copy_to_user(pgettime_local.Time, &eft,
 			sizeof(EFI_TIME)) ? -EFAULT : 0;
+	return 0;
 }
 
 static long efi_runtime_set_time(unsigned long arg)
@@ -406,24 +413,27 @@  static long efi_runtime_get_waketime(unsigned long arg)
 	EFI_TIME efi_time;
 	efi_time_t eft;
 
-	status = efi.get_wakeup_time((efi_bool_t *)&enabled,
-					(efi_bool_t *)&pending, &eft);
-
 	pgetwakeuptime = (struct efi_getwakeuptime __user *)arg;
-
 	if (copy_from_user(&pgetwakeuptime_local, pgetwakeuptime, sizeof(pgetwakeuptime_local)))
 		return -EFAULT;
+
+	status = efi.get_wakeup_time(
+		pgetwakeuptime_local.Enabled ? (efi_bool_t *)&enabled : NULL,
+		pgetwakeuptime_local.Pending ? (efi_bool_t *)&pending : NULL,
+		pgetwakeuptime_local.Time ? &eft : NULL);
+
 	if (put_user(status, pgetwakeuptime_local.status))
 		return -EFAULT;
 	if (status != EFI_SUCCESS)
 		return -EINVAL;
-	if (put_user(enabled, pgetwakeuptime_local.Enabled) ||
-				put_user(pending, pgetwakeuptime_local.Pending))
+	if (pgetwakeuptime_local.Enabled && put_user(enabled, pgetwakeuptime_local.Enabled))
 		return -EFAULT;
 	convert_from_efi_time(&eft, &efi_time);
 
-	return copy_to_user(pgetwakeuptime_local.Time, &efi_time,
+	if (pgetwakeuptime_local.Time)
+		return copy_to_user(pgetwakeuptime_local.Time, &efi_time,
 			sizeof(EFI_TIME)) ? -EFAULT : 0;
+	return 0;
 }
 
 static long efi_runtime_set_waketime(unsigned long arg)
@@ -441,12 +451,15 @@  static long efi_runtime_set_waketime(unsigned long arg)
 		return -EFAULT;
 
 	enabled = psetwakeuptime_local.Enabled;
-	if (copy_from_user(&efi_time, psetwakeuptime_local.Time, sizeof(EFI_TIME)))
-		return -EFAULT;
-
-	convert_to_efi_time(&eft, &efi_time);
+	if (psetwakeuptime_local.Time) {
+		if (copy_from_user(&efi_time, psetwakeuptime_local.Time, sizeof(EFI_TIME)))
+			return -EFAULT;
 
-	status = efi.set_wakeup_time(enabled, &eft);
+		convert_to_efi_time(&eft, &efi_time);
+		status = efi.set_wakeup_time(enabled, &eft);
+	} else {
+		status = efi.set_wakeup_time(enabled, NULL);
+	}
 
 	if (put_user(status, psetwakeuptime_local.status))
 		return -EFAULT;
diff --git a/fwts-test/arg-show-tests-full-0001/arg-show-tests-full-0001.log b/fwts-test/arg-show-tests-full-0001/arg-show-tests-full-0001.log
index d190aef..7c2d7f2 100644
--- a/fwts-test/arg-show-tests-full-0001/arg-show-tests-full-0001.log
+++ b/fwts-test/arg-show-tests-full-0001/arg-show-tests-full-0001.log
@@ -371,11 +371,42 @@  Unsafe tests:
  uefirtmisc      (2 tests):
   Test for UEFI miscellaneous runtime service interfaces.
   Stress test for UEFI miscellaneous runtime service interfaces.
- uefirttime      (4 tests):
+ uefirttime      (35 tests):
   Test UEFI RT service get time interface.
+  Test UEFI RT service get time interface, NULL time parameter.
+  Test UEFI RT service get time interface, NULL time and NULL capabilties parameters.
   Test UEFI RT service set time interface.
+  Test UEFI RT service set time interface, invalid year 1899.
+  Test UEFI RT service set time interface, invalid year 10000.
+  Test UEFI RT service set time interface, invalid month 0.
+  Test UEFI RT service set time interface, invalid month 13.
+  Test UEFI RT service set time interface, invalid day 0.
+  Test UEFI RT service set time interface, invalid day 32.
+  Test UEFI RT service set time interface, invalid hour 24.
+  Test UEFI RT service set time interface, invalid minute 60.
+  Test UEFI RT service set time interface, invalid second 60.
+  Test UEFI RT service set time interface, invalid nanosecond 1000000000.
+  Test UEFI RT service set time interface, invalid timezone -1441.
+  Test UEFI RT service set time interface, invalid timezone 1441.
   Test UEFI RT service get wakeup time interface.
+  Test UEFI RT service get wakeup time interface, NULL enabled parameter.
+  Test UEFI RT service get wakeup time interface, NULL pending parameter.
+  Test UEFI RT service get wakeup time interface, NULL time parameter.
+  Test UEFI RT service get wakeup time interface, NULL enabled, pending and time parameters.
   Test UEFI RT service set wakeup time interface.
+  Test UEFI RT service set wakeup time interface, NULL time parameter.
+  Test UEFI RT service set wakeup time interface, invalid year 1899.
+  Test UEFI RT service set wakeup time interface, invalid year 10000.
+  Test UEFI RT service set wakeup time interface, invalid month 0.
+  Test UEFI RT service set wakeup time interface, invalid month 13.
+  Test UEFI RT service set wakeup time interface, invalid day 0.
+  Test UEFI RT service set wakeup time interface, invalid day 32.
+  Test UEFI RT service set wakeup time interface, invalid hour 24.
+  Test UEFI RT service set wakeup time interface, invalid minute 60.
+  Test UEFI RT service set wakeup time interface, invalid second 60.
+  Test UEFI RT service set wakeup time interface, invalid nanosecond 1000000000.
+  Test UEFI RT service set wakeup time interface, invalid timezone -1441.
+  Test UEFI RT service set wakeup time interface, invalid timezone 1441.
  uefirtvariable  (7 tests):
   Test UEFI RT service get variable interface.
   Test UEFI RT service get next variable name interface.
@@ -409,11 +440,42 @@  UEFI tests:
  uefirtmisc      (2 tests):
   Test for UEFI miscellaneous runtime service interfaces.
   Stress test for UEFI miscellaneous runtime service interfaces.
- uefirttime      (4 tests):
+ uefirttime      (35 tests):
   Test UEFI RT service get time interface.
+  Test UEFI RT service get time interface, NULL time parameter.
+  Test UEFI RT service get time interface, NULL time and NULL capabilties parameters.
   Test UEFI RT service set time interface.
+  Test UEFI RT service set time interface, invalid year 1899.
+  Test UEFI RT service set time interface, invalid year 10000.
+  Test UEFI RT service set time interface, invalid month 0.
+  Test UEFI RT service set time interface, invalid month 13.
+  Test UEFI RT service set time interface, invalid day 0.
+  Test UEFI RT service set time interface, invalid day 32.
+  Test UEFI RT service set time interface, invalid hour 24.
+  Test UEFI RT service set time interface, invalid minute 60.
+  Test UEFI RT service set time interface, invalid second 60.
+  Test UEFI RT service set time interface, invalid nanosecond 1000000000.
+  Test UEFI RT service set time interface, invalid timezone -1441.
+  Test UEFI RT service set time interface, invalid timezone 1441.
   Test UEFI RT service get wakeup time interface.
+  Test UEFI RT service get wakeup time interface, NULL enabled parameter.
+  Test UEFI RT service get wakeup time interface, NULL pending parameter.
+  Test UEFI RT service get wakeup time interface, NULL time parameter.
+  Test UEFI RT service get wakeup time interface, NULL enabled, pending and time parameters.
   Test UEFI RT service set wakeup time interface.
+  Test UEFI RT service set wakeup time interface, NULL time parameter.
+  Test UEFI RT service set wakeup time interface, invalid year 1899.
+  Test UEFI RT service set wakeup time interface, invalid year 10000.
+  Test UEFI RT service set wakeup time interface, invalid month 0.
+  Test UEFI RT service set wakeup time interface, invalid month 13.
+  Test UEFI RT service set wakeup time interface, invalid day 0.
+  Test UEFI RT service set wakeup time interface, invalid day 32.
+  Test UEFI RT service set wakeup time interface, invalid hour 24.
+  Test UEFI RT service set wakeup time interface, invalid minute 60.
+  Test UEFI RT service set wakeup time interface, invalid second 60.
+  Test UEFI RT service set wakeup time interface, invalid nanosecond 1000000000.
+  Test UEFI RT service set wakeup time interface, invalid timezone -1441.
+  Test UEFI RT service set wakeup time interface, invalid timezone 1441.
  uefirtvariable  (7 tests):
   Test UEFI RT service get variable interface.
   Test UEFI RT service get next variable name interface.
@@ -423,4 +485,4 @@  UEFI tests:
   Test UEFI RT service set variable interface stress test.
   Test UEFI RT service query variable info interface stress test.
 
-Total of 338 tests
+Total of 400 tests
diff --git a/src/uefi/uefirttime/uefirttime.c b/src/uefi/uefirttime/uefirttime.c
index cddf853..8e26958 100644
--- a/src/uefi/uefirttime/uefirttime.c
+++ b/src/uefi/uefirttime/uefirttime.c
@@ -28,6 +28,8 @@ 
 #include "efi_runtime.h"
 #include "fwts_efi_module.h"
 
+#define UEFI_IGNORE_UNSET_BITS	(0)
+
 #define IS_LEAP(year) \
 		((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
 
@@ -225,8 +227,51 @@  static int uefirttime_test1(fwts_framework *fw)
 	return FWTS_OK;
 }
 
+static int uefirttime_test_gettime_invalid(
+	fwts_framework *fw,
+	EFI_TIME *efi_time,
+	EFI_TIME_CAPABILITIES *efi_time_cap)
+{
+	long ioret;
+	struct efi_gettime gettime;
+	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) {
+		if (status == EFI_INVALID_PARAMETER) {
+			fwts_passed(fw, "UEFI runtime service GetTime interface test "
+				"passed, returned EFI_INVALID_PARAMETER as expected.");
+			return FWTS_OK;
+		} else {
+			fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeGetTime",
+				"Failed to get correct return status from UEFI runtime service, expecting EFI_INVALID_PARAMETER.");
+			fwts_uefi_print_status_info(fw, status);
+			return FWTS_ERROR;
+		}
+	}
+	fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeGetTime",
+		"Failed to get error return status from UEFI runtime service, expected EFI_INAVLID_PARAMETER.");
+	return FWTS_ERROR;
+}
+
 static int uefirttime_test2(fwts_framework *fw)
 {
+	EFI_TIME_CAPABILITIES efi_time_cap;
+
+	return uefirttime_test_gettime_invalid(fw, NULL, &efi_time_cap);
+}
+
+static int uefirttime_test3(fwts_framework *fw)
+{
+	return uefirttime_test_gettime_invalid(fw, NULL, NULL);
+}
+
+static int uefirttime_test4(fwts_framework *fw)
+{
 
 	long ioret;
 	struct efi_settime settime;
@@ -345,7 +390,219 @@  static int uefirttime_test2(fwts_framework *fw)
 	return FWTS_OK;
 }
 
-static int uefirttime_test3(fwts_framework *fw)
+static int uefirttime_test_settime_invalid(
+	fwts_framework *fw,
+	struct efi_settime *settime)
+{
+	long ioret;
+	uint64_t status;
+
+	settime->status = &status;
+
+	ioret = ioctl(fd, EFI_RUNTIME_SET_TIME, settime);
+	if (ioret == -1) {
+		if (status == EFI_INVALID_PARAMETER) {
+			fwts_passed(fw, "UEFI runtime service SetTime interface test "
+				"passed, returned EFI_INVALID_PARAMETER as expected.");
+			return FWTS_OK;
+		} else {
+			fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeSetTime",
+				"Failed to get correct return status from UEFI runtime service, expecting EFI_INVALID_PARAMETER.");
+			fwts_uefi_print_status_info(fw, status);
+			return FWTS_ERROR;
+		}
+	}
+	fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeSetTime",
+		"Failed to get error return status from UEFI runtime service, expected EFI_INVALID_PARAMETER.");
+	return FWTS_ERROR;
+}
+
+static int uefirttime_test_settime_invalid_time(
+	fwts_framework *fw,
+	EFI_TIME *time)
+{
+	struct efi_gettime gettime;
+	struct efi_settime settime;
+	EFI_TIME oldtime, newtime;
+	uint64_t status;
+	int ret, ioret;
+
+	gettime.Time = &oldtime;
+	gettime.status = &status;
+	gettime.Capabilities = NULL;
+
+	ioret = ioctl(fd, EFI_RUNTIME_GET_TIME, &gettime);
+	if (ioret == -1) {
+		fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeGetTime",
+			"Failed to get wakeup time with UEFI runtime service.");
+		fwts_uefi_print_status_info(fw, status);
+		return FWTS_ERROR;
+	}
+
+	memcpy(&newtime, &oldtime, sizeof(EFI_TIME));
+	if (time->Year != 0xffff)
+		newtime.Year = time->Year;
+	if (time->Month != 0xff)
+		newtime.Month = time->Month;
+	if (time->Day != 0xff)
+		newtime.Day = time->Day;
+	if (time->Hour != 0xff)
+		newtime.Hour = time->Hour;
+	if (time->Minute != 0xff)
+		newtime.Minute = time->Minute;
+	if (time->Second != 0xff)
+		newtime.Second = time->Second;
+	if (time->Nanosecond != 0xffffffff)
+		newtime.Nanosecond = time->Nanosecond;
+	if ((uint16_t)time->TimeZone != 0xffff)
+		newtime.TimeZone = time->TimeZone;
+
+	settime.Time = &newtime;
+	settime.status = &status;
+
+	ret = uefirttime_test_settime_invalid(fw, &settime);
+
+	/* Restore original time */
+	settime.Time = &oldtime;
+	settime.status = &status;
+	ioret = ioctl(fd, EFI_RUNTIME_SET_TIME, &settime);
+	if (ioret == -1) {
+		fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeSetTime",
+			"Failed to set wakeup time with UEFI runtime service.");
+		fwts_uefi_print_status_info(fw, status);
+		return FWTS_ERROR;
+	}
+	return ret;
+}
+
+static int uefirttime_test5(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.Year = 1899;
+	return uefirttime_test_settime_invalid_time(fw, &time);
+}
+
+static int uefirttime_test6(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.Year = 10000;
+	return uefirttime_test_settime_invalid_time(fw, &time);
+}
+
+static int uefirttime_test7(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.Month = 0;
+	return uefirttime_test_settime_invalid_time(fw, &time);
+}
+
+static int uefirttime_test8(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.Month = 13;
+	return uefirttime_test_settime_invalid_time(fw, &time);
+}
+
+static int uefirttime_test9(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.Day = 0;
+	return uefirttime_test_settime_invalid_time(fw, &time);
+}
+
+static int uefirttime_test10(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.Day = 32;
+	return uefirttime_test_settime_invalid_time(fw, &time);
+}
+
+static int uefirttime_test11(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.Hour = 24;
+	return uefirttime_test_settime_invalid_time(fw, &time);
+}
+
+static int uefirttime_test12(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.Minute = 60;
+	return uefirttime_test_settime_invalid_time(fw, &time);
+}
+
+static int uefirttime_test13(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.Second = 60;
+	return uefirttime_test_settime_invalid_time(fw, &time);
+}
+
+static int uefirttime_test14(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.Nanosecond = 1000000000;
+	return uefirttime_test_settime_invalid_time(fw, &time);
+}
+
+static int uefirttime_test15(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.TimeZone = -1441;
+	return uefirttime_test_settime_invalid_time(fw, &time);
+}
+
+static int uefirttime_test16(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.TimeZone = 1441;
+	return uefirttime_test_settime_invalid_time(fw, &time);
+}
+
+#if UEFI_IGNORE_UNSET_BITS
+/*
+ *  The UEFI spec states that just two bits are allowed, and all other bits
+ *  must be zero, but I have yet to find a compliant implementation that
+ *  flags up an invalid paramater if the bits are non zero. It seems that
+ *  implementations just examine the bits they expect and don't care. For
+ *  now, we will ignore this test
+ */
+static int uefirttime_test17(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	/* Section 7.3, Daylight states all other bits must be zero */
+	time.Daylight = ~(FWTS_UEFI_TIME_ADJUST_DAYLIGHT | FWTS_UEFI_TIME_IN_DAYLIGHT);
+	return uefirttime_test_settime_invalid_time(fw, &time);
+}
+#endif
+
+static int uefirttime_test18(fwts_framework *fw)
 {
 	long ioret;
 	struct efi_getwakeuptime getwakeuptime;
@@ -360,6 +617,11 @@  static int uefirttime_test3(fwts_framework *fw)
 
 	ioret = ioctl(fd, EFI_RUNTIME_GET_WAKETIME, &getwakeuptime);
 	if (ioret == -1) {
+		if (status == EFI_UNSUPPORTED) {
+			fwts_skipped(fw, "Skipping test, GetWakeupTime runtime "
+				"service is not supported on this platform.");
+			return FWTS_OK;
+		}
 		fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeGetWakeupTime",
 			"Failed to get wakeup time with UEFI runtime service.");
 		fwts_uefi_print_status_info(fw, status);
@@ -374,9 +636,87 @@  static int uefirttime_test3(fwts_framework *fw)
 	return FWTS_OK;
 }
 
-static int uefirttime_test4(fwts_framework *fw)
+static int uefirttime_test_getwaketime_invalid(
+	fwts_framework *fw,
+	struct efi_getwakeuptime *getwakeuptime)
+{
+	long ioret;
+	uint64_t status;
+	getwakeuptime->status = &status;
+
+	ioret = ioctl(fd, EFI_RUNTIME_GET_WAKETIME, getwakeuptime);
+	if (ioret == -1) {
+		if (status == EFI_INVALID_PARAMETER ||
+		    status == EFI_UNSUPPORTED) {
+			fwts_passed(fw, "UEFI runtime service GetTimeWakeupTime interface test "
+				"passed, returned EFI_INVALID_PARAMETER or "
+				"EFI_UNSUPPORTED as expected.");
+			return FWTS_OK;
+		} else {
+			fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeGetWakeupTime",
+				"Failed to get correct return status from UEFI "
+				"runtime service, expecting EFI_INVALID_PARAMETER "
+				"or EFI_UNSUPPORTED.");
+			fwts_uefi_print_status_info(fw, status);
+			return FWTS_ERROR;
+		}
+	}
+	fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeGetWakeupTime",
+		"Failed to get error return status from UEFI runtime service, expected EFI_INVALID_PARAMETER.");
+	return FWTS_ERROR;
+}
+
+static int uefirttime_test19(fwts_framework *fw)
+{
+	struct efi_getwakeuptime getwakeuptime;
+	EFI_TIME efi_time;
+	uint8_t pending;
+
+	getwakeuptime.Enabled = NULL;
+	getwakeuptime.Pending = &pending;
+	getwakeuptime.Time = &efi_time;
+
+	return uefirttime_test_getwaketime_invalid(fw, &getwakeuptime);
+}
+
+static int uefirttime_test20(fwts_framework *fw)
+{
+	struct efi_getwakeuptime getwakeuptime;
+	EFI_TIME efi_time;
+	uint8_t enabled;
+
+	getwakeuptime.Enabled = &enabled;
+	getwakeuptime.Pending = NULL;
+	getwakeuptime.Time = &efi_time;
+
+	return uefirttime_test_getwaketime_invalid(fw, &getwakeuptime);
+}
+
+static int uefirttime_test21(fwts_framework *fw)
+{
+	struct efi_getwakeuptime getwakeuptime;
+	uint8_t enabled, pending;
+
+	getwakeuptime.Enabled = &enabled;
+	getwakeuptime.Pending = &pending;
+	getwakeuptime.Time = NULL;
+
+	return uefirttime_test_getwaketime_invalid(fw, &getwakeuptime);
+}
+
+static int uefirttime_test22(fwts_framework *fw)
 {
+	struct efi_getwakeuptime getwakeuptime;
+
+	getwakeuptime.Enabled = NULL;
+	getwakeuptime.Pending = NULL;
+	getwakeuptime.Time = NULL;
+
+	return uefirttime_test_getwaketime_invalid(fw, &getwakeuptime);
+}
 
+static int uefirttime_test23(fwts_framework *fw)
+{
 	long ioret;
 	struct efi_setwakeuptime setwakeuptime;
 	uint64_t status;
@@ -411,6 +751,11 @@  static int uefirttime_test4(fwts_framework *fw)
 
 	ioret = ioctl(fd, EFI_RUNTIME_SET_WAKETIME, &setwakeuptime);
 	if (ioret == -1) {
+		if (status == EFI_UNSUPPORTED) {
+			fwts_skipped(fw, "Skipping test, GetWakeupTime runtime "
+				"service is not supported on this platform.");
+			return FWTS_OK;
+		}
 		fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeSetWakeupTime",
 			"Failed to set wakeup time with UEFI runtime service.");
 		fwts_uefi_print_status_info(fw, status);
@@ -426,6 +771,11 @@  static int uefirttime_test4(fwts_framework *fw)
 
 	ioret = ioctl(fd, EFI_RUNTIME_GET_WAKETIME, &getwakeuptime);
 	if (ioret == -1) {
+		if (status == EFI_UNSUPPORTED) {
+			fwts_skipped(fw, "Skipping test, GetWakeupTime runtime "
+				"service is not supported on this platform.");
+			return FWTS_OK;
+		}
 		fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeGetWakeupTime",
 			"Failed to get wakeup time with UEFI runtime service.");
 		fwts_uefi_print_status_info(fw, status);
@@ -465,6 +815,11 @@  static int uefirttime_test4(fwts_framework *fw)
 
 	ioret = ioctl(fd, EFI_RUNTIME_GET_WAKETIME, &getwakeuptime);
 	if (ioret == -1) {
+		if (status == EFI_UNSUPPORTED) {
+			fwts_skipped(fw, "Skipping test, GetWakeupTime runtime "
+				"service is not supported on this platform.");
+			return FWTS_OK;
+		}
 		fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeGetWakeupTime",
 			"Failed to get wakeup time with UEFI runtime service.");
 		fwts_uefi_print_status_info(fw, status);
@@ -482,11 +837,288 @@  static int uefirttime_test4(fwts_framework *fw)
 	return FWTS_OK;
 }
 
+static int uefirttime_test_setwakeuptime_invalid(
+	fwts_framework *fw,
+	struct efi_setwakeuptime *setwakeuptime
+)
+{
+	long ioret;
+	uint64_t status;
+
+	setwakeuptime->status = &status;
+
+	ioret = ioctl(fd, EFI_RUNTIME_SET_WAKETIME, setwakeuptime);
+	if (ioret == -1) {
+		if (status == EFI_UNSUPPORTED) {
+			fwts_skipped(fw, "Skipping test, GetWakeupTime runtime "
+				"service is not supported on this platform.");
+			return FWTS_OK;
+		}
+		if (status == EFI_INVALID_PARAMETER) {
+			fwts_passed(fw, "UEFI runtime service SetTimeWakeupTime interface test "
+				"passed, returned EFI_INVALID_PARAMETER as expected.");
+			return FWTS_OK;
+		} else {
+			fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeSetWakeupTime",
+				"Failed to get correct return status from UEFI runtime service, "
+				"expecting EFI_INVALID_PARAMETER.");
+			fwts_uefi_print_status_info(fw, status);
+			return FWTS_ERROR;
+		}
+	}
+	fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeSetWakeupTime",
+		"Failed to get error return status from UEFI runtime service, expected EFI_INVALID_PARAMETER.");
+	return FWTS_ERROR;
+}
+
+static int uefirttime_test24(fwts_framework *fw)
+{
+	struct efi_setwakeuptime setwakeuptime;
+
+	setwakeuptime.Time = NULL;
+	return uefirttime_test_setwakeuptime_invalid(fw, &setwakeuptime);
+}
+
+static int uefirttime_test_setwakeuptime_invalid_time(
+	fwts_framework *fw,
+	EFI_TIME *time)
+{
+	struct efi_getwakeuptime getwakeuptime;
+	struct efi_setwakeuptime setwakeuptime;
+	EFI_TIME oldtime, newtime;
+	uint64_t status;
+	uint8_t pending, enabled;
+	int ret, ioret;
+
+	getwakeuptime.Enabled = &enabled;
+	getwakeuptime.Pending = &pending;
+	getwakeuptime.Time = &oldtime;
+	getwakeuptime.status = &status;
+
+	ioret = ioctl(fd, EFI_RUNTIME_GET_WAKETIME, &getwakeuptime);
+	if (ioret == -1) {
+		if (status == EFI_UNSUPPORTED) {
+			fwts_skipped(fw, "Skipping test, GetWakeupTime runtime "
+				"service is not supported on this platform.");
+			return FWTS_OK;
+		}
+		fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeGetWakeupTime",
+			"Failed to get wakeup time with UEFI runtime service.");
+		fwts_uefi_print_status_info(fw, status);
+		return FWTS_ERROR;
+	}
+
+	memcpy(&newtime, &oldtime, sizeof(EFI_TIME));
+	if (time->Year != 0xffff)
+		newtime.Year = time->Year;
+	if (time->Month != 0xff)
+		newtime.Month = time->Month;
+	if (time->Day != 0xff)
+		newtime.Day = time->Day;
+	if (time->Hour != 0xff)
+		newtime.Hour = time->Hour;
+	if (time->Minute != 0xff)
+		newtime.Minute = time->Minute;
+	if (time->Second != 0xff)
+		newtime.Second = time->Second;
+	if (time->Nanosecond != 0xffffffff)
+		newtime.Nanosecond = time->Nanosecond;
+	if ((uint16_t)time->TimeZone != 0xffff)
+		newtime.TimeZone = time->TimeZone;
+
+	setwakeuptime.Time = &newtime;
+	setwakeuptime.status = &status;
+	setwakeuptime.Enabled = true;
+
+	ret = uefirttime_test_setwakeuptime_invalid(fw, &setwakeuptime);
+
+	/* Restore original time */
+	setwakeuptime.Time = &oldtime;
+	setwakeuptime.status = &status;
+	setwakeuptime.Enabled = true;
+	ioret = ioctl(fd, EFI_RUNTIME_SET_WAKETIME, &setwakeuptime);
+	if (ioret == -1) {
+		fwts_failed(fw, LOG_LEVEL_HIGH, "UEFIRuntimeSetWakeupTime",
+			"Failed to set wakeup time with UEFI runtime service.");
+		fwts_uefi_print_status_info(fw, status);
+		return FWTS_ERROR;
+	}
+	return ret;
+}
+
+static int uefirttime_test25(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.Year = 1899;
+	return uefirttime_test_setwakeuptime_invalid_time(fw, &time);
+}
+
+static int uefirttime_test26(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.Year = 10000;
+	return uefirttime_test_setwakeuptime_invalid_time(fw, &time);
+}
+
+static int uefirttime_test27(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.Month = 0;
+	return uefirttime_test_setwakeuptime_invalid_time(fw, &time);
+}
+
+static int uefirttime_test28(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.Month = 13;
+	return uefirttime_test_setwakeuptime_invalid_time(fw, &time);
+}
+
+static int uefirttime_test29(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.Day = 0;
+	return uefirttime_test_setwakeuptime_invalid_time(fw, &time);
+}
+
+static int uefirttime_test30(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.Day = 32;
+	return uefirttime_test_setwakeuptime_invalid_time(fw, &time);
+}
+
+static int uefirttime_test31(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.Hour = 24;
+	return uefirttime_test_setwakeuptime_invalid_time(fw, &time);
+}
+
+static int uefirttime_test32(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.Minute = 60;
+	return uefirttime_test_setwakeuptime_invalid_time(fw, &time);
+}
+
+static int uefirttime_test33(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.Second = 60;
+	return uefirttime_test_setwakeuptime_invalid_time(fw, &time);
+}
+
+static int uefirttime_test34(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.Nanosecond = 1000000000;
+	return uefirttime_test_setwakeuptime_invalid_time(fw, &time);
+}
+
+static int uefirttime_test35(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.TimeZone = -1441;
+	return uefirttime_test_setwakeuptime_invalid_time(fw, &time);
+}
+
+static int uefirttime_test36(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	time.TimeZone = 1441;
+	return uefirttime_test_setwakeuptime_invalid_time(fw, &time);
+}
+
+#if UEFI_IGNORE_UNSET_BITS
+/*
+ *  The UEFI spec states that just two bits are allowed, and all other bits
+ *  must be zero, but I have yet to find a compliant implementation that
+ *  flags up an invalid paramater if the bits are non zero. It seems that
+ *  implementations just examine the bits they expect and don't care. For
+ *  now, we will ignore this test
+ */
+static int uefirttime_test37(fwts_framework *fw)
+{
+	EFI_TIME time;
+
+	memset(&time, 0xff, sizeof(EFI_TIME));
+	/* Section 7.3, Daylight states all other bits must be zero */
+	time.Daylight = ~(FWTS_UEFI_TIME_ADJUST_DAYLIGHT | FWTS_UEFI_TIME_IN_DAYLIGHT);
+	return uefirttime_test_setwakeuptime_invalid_time(fw, &time);
+}
+#endif
+
 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." },
-	{ uefirttime_test3, "Test UEFI RT service get wakeup time interface." },
-	{ uefirttime_test4, "Test UEFI RT service set wakeup time interface." },
+	{ uefirttime_test2, "Test UEFI RT service get time interface, NULL time parameter." },
+	{ uefirttime_test3, "Test UEFI RT service get time interface, NULL time and NULL capabilties parameters." },
+
+	{ uefirttime_test4, "Test UEFI RT service set time interface." },
+	{ uefirttime_test5, "Test UEFI RT service set time interface, invalid year 1899." },
+	{ uefirttime_test6, "Test UEFI RT service set time interface, invalid year 10000." },
+	{ uefirttime_test7, "Test UEFI RT service set time interface, invalid month 0." },
+	{ uefirttime_test8, "Test UEFI RT service set time interface, invalid month 13." },
+	{ uefirttime_test9, "Test UEFI RT service set time interface, invalid day 0." },
+	{ uefirttime_test10, "Test UEFI RT service set time interface, invalid day 32." },
+	{ uefirttime_test11, "Test UEFI RT service set time interface, invalid hour 24." },
+	{ uefirttime_test12, "Test UEFI RT service set time interface, invalid minute 60." },
+	{ uefirttime_test13, "Test UEFI RT service set time interface, invalid second 60." },
+	{ uefirttime_test14, "Test UEFI RT service set time interface, invalid nanosecond 1000000000." },
+	{ uefirttime_test15, "Test UEFI RT service set time interface, invalid timezone -1441." },
+	{ uefirttime_test16, "Test UEFI RT service set time interface, invalid timezone 1441." },
+#if UEFI_IGNORE_UNSET_BITS
+	{ uefirttime_test17, "Test UEFI RT service set time interface, invalid daylight 0xfc." },
+#endif
+
+	{ uefirttime_test18, "Test UEFI RT service get wakeup time interface." },
+	{ uefirttime_test19, "Test UEFI RT service get wakeup time interface, NULL enabled parameter." },
+	{ uefirttime_test20, "Test UEFI RT service get wakeup time interface, NULL pending parameter." },
+	{ uefirttime_test21, "Test UEFI RT service get wakeup time interface, NULL time parameter." },
+	{ uefirttime_test22, "Test UEFI RT service get wakeup time interface, NULL enabled, pending and time parameters." },
+
+	{ uefirttime_test23, "Test UEFI RT service set wakeup time interface." },
+	{ uefirttime_test24, "Test UEFI RT service set wakeup time interface, NULL time parameter." },
+	{ uefirttime_test25, "Test UEFI RT service set wakeup time interface, invalid year 1899." },
+	{ uefirttime_test26, "Test UEFI RT service set wakeup time interface, invalid year 10000." },
+	{ uefirttime_test27, "Test UEFI RT service set wakeup time interface, invalid month 0." },
+	{ uefirttime_test28, "Test UEFI RT service set wakeup time interface, invalid month 13." },
+	{ uefirttime_test29, "Test UEFI RT service set wakeup time interface, invalid day 0." },
+	{ uefirttime_test30, "Test UEFI RT service set wakeup time interface, invalid day 32." },
+	{ uefirttime_test31, "Test UEFI RT service set wakeup time interface, invalid hour 24." },
+	{ uefirttime_test32, "Test UEFI RT service set wakeup time interface, invalid minute 60." },
+	{ uefirttime_test33, "Test UEFI RT service set wakeup time interface, invalid second 60." },
+	{ uefirttime_test34, "Test UEFI RT service set wakeup time interface, invalid nanosecond 1000000000." },
+	{ uefirttime_test35, "Test UEFI RT service set wakeup time interface, invalid timezone -1441." },
+	{ uefirttime_test36, "Test UEFI RT service set wakeup time interface, invalid timezone 1441." },
+#if UEFI_IGNORE_UNSET_BITS
+	{ uefirttime_test37, "Test UEFI RT service set wakeup time interface, invalid daylight 0xfc." },
+#endif
+
 	{ NULL, NULL }
 };