Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F154681638
D36714.id120946.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D36714.id120946.diff
View Options
diff --git a/sys/dev/efidev/efidev.c b/sys/dev/efidev/efidev.c
--- a/sys/dev/efidev/efidev.c
+++ b/sys/dev/efidev/efidev.c
@@ -90,6 +90,21 @@
error = efi_set_time(tm);
break;
}
+ case EFIIOC_GET_WAKETIME:
+ {
+ struct efi_waketime_ioc *wt = (struct efi_waketime_ioc *)addr;
+
+ error = efi_get_waketime(&wt->enabled, &wt->pending,
+ &wt->waketime);
+ break;
+ }
+ case EFIIOC_SET_WAKETIME:
+ {
+ struct efi_waketime_ioc *wt = (struct efi_waketime_ioc *)addr;
+
+ error = efi_set_waketime(wt->enabled, &wt->waketime);
+ break;
+ }
case EFIIOC_VAR_GET:
{
struct efi_var_ioc *ev = (struct efi_var_ioc *)addr;
diff --git a/sys/dev/efidev/efirt.c b/sys/dev/efidev/efirt.c
--- a/sys/dev/efidev/efirt.c
+++ b/sys/dev/efidev/efirt.c
@@ -32,6 +32,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_acpi.h"
+
#include <sys/param.h>
#include <sys/efi.h>
#include <sys/eventhandler.h>
@@ -61,6 +63,10 @@
#include <vm/pmap.h>
#include <vm/vm_map.h>
+#ifdef DEV_ACPI
+#include <contrib/dev/acpica/include/acpi.h>
+#endif
+
#define EFI_TABLE_ALLOC_MAX 0x800000
static struct efi_systbl *efi_systbl;
@@ -571,6 +577,71 @@
return (error);
}
+static int
+get_waketime(uint8_t *enabled, uint8_t *pending, struct efi_tm *tm)
+{
+ struct efirt_callinfo ec;
+ int error;
+#ifdef DEV_ACPI
+ UINT32 acpiRtcEnabled;
+#endif
+
+ if (efi_runtime == NULL)
+ return (ENXIO);
+
+ EFI_TIME_LOCK();
+ bzero(&ec, sizeof(ec));
+ ec.ec_name = "rt_getwaketime";
+ ec.ec_argcnt = 3;
+ ec.ec_arg1 = (uintptr_t)enabled;
+ ec.ec_arg2 = (uintptr_t)pending;
+ ec.ec_arg3 = (uintptr_t)tm;
+ ec.ec_fptr = EFI_RT_METHOD_PA(rt_getwaketime);
+ error = efi_call(&ec);
+ EFI_TIME_UNLOCK();
+
+#ifdef DEV_ACPI
+ if (error == 0) {
+ error = AcpiReadBitRegister(ACPI_BITREG_RT_CLOCK_ENABLE,
+ &acpiRtcEnabled);
+ if (ACPI_SUCCESS(error)) {
+ *enabled = *enabled && acpiRtcEnabled;
+ }
+ }
+#endif
+
+ return (error);
+}
+
+static int
+set_waketime(uint8_t enable, struct efi_tm *tm)
+{
+ struct efirt_callinfo ec;
+ int error;
+
+ if (efi_runtime == NULL)
+ return (ENXIO);
+
+ EFI_TIME_LOCK();
+ bzero(&ec, sizeof(ec));
+ ec.ec_name = "rt_setwaketime";
+ ec.ec_argcnt = 2;
+ ec.ec_arg1 = (uintptr_t)enable;
+ ec.ec_arg2 = (uintptr_t)tm;
+ ec.ec_fptr = EFI_RT_METHOD_PA(rt_setwaketime);
+ error = efi_call(&ec);
+ EFI_TIME_UNLOCK();
+
+#ifdef DEV_ACPI
+ if (error == 0) {
+ error = AcpiWriteBitRegister(ACPI_BITREG_RT_CLOCK_ENABLE,
+ (enable != 0) ? 1 : 0);
+ }
+#endif
+
+ return (error);
+}
+
static int
get_time_capabilities(struct efi_tmcap *tmcap)
{
@@ -713,6 +784,8 @@
.get_time_capabilities = get_time_capabilities,
.reset_system = reset_system,
.set_time = set_time,
+ .get_waketime = get_waketime,
+ .set_waketime = set_waketime,
.var_get = var_get,
.var_nextname = var_nextname,
.var_set = var_set,
diff --git a/sys/sys/efi.h b/sys/sys/efi.h
--- a/sys/sys/efi.h
+++ b/sys/sys/efi.h
@@ -254,6 +254,9 @@
int (*get_time_capabilities)(struct efi_tmcap *);
int (*reset_system)(enum efi_reset);
int (*set_time)(struct efi_tm *);
+ int (*get_waketime)(uint8_t *enabled, uint8_t *pending,
+ struct efi_tm *tm);
+ int (*set_waketime)(uint8_t enable, struct efi_tm *tm);
int (*var_get)(uint16_t *, struct uuid *, uint32_t *, size_t *,
void *);
int (*var_nextname)(size_t *, uint16_t *, struct uuid *);
@@ -319,6 +322,21 @@
return (active_efi_ops->set_time(tm));
}
+static inline int efi_get_waketime(uint8_t *enabled, uint8_t *pending,
+ struct efi_tm *tm)
+{
+ if (active_efi_ops->get_waketime == NULL)
+ return (ENXIO);
+ return (active_efi_ops->get_waketime(enabled, pending, tm));
+}
+
+static inline int efi_set_waketime(uint8_t enable, struct efi_tm *tm)
+{
+ if (active_efi_ops->set_waketime == NULL)
+ return (ENXIO);
+ return (active_efi_ops->set_waketime(enable, tm));
+}
+
static inline int efi_var_get(uint16_t *name, struct uuid *vendor,
uint32_t *attrib, size_t *datasize, void *data)
{
diff --git a/sys/sys/efiio.h b/sys/sys/efiio.h
--- a/sys/sys/efiio.h
+++ b/sys/sys/efiio.h
@@ -50,11 +50,20 @@
size_t datasize; /* Number of *bytes* in the data */
};
+struct efi_waketime_ioc
+{
+ struct efi_tm waketime;
+ uint8_t enabled;
+ uint8_t pending;
+};
+
#define EFIIOC_GET_TABLE _IOWR('E', 1, struct efi_get_table_ioc)
#define EFIIOC_GET_TIME _IOR('E', 2, struct efi_tm)
#define EFIIOC_SET_TIME _IOW('E', 3, struct efi_tm)
#define EFIIOC_VAR_GET _IOWR('E', 4, struct efi_var_ioc)
#define EFIIOC_VAR_NEXT _IOWR('E', 5, struct efi_var_ioc)
#define EFIIOC_VAR_SET _IOWR('E', 6, struct efi_var_ioc)
+#define EFIIOC_GET_WAKETIME _IOR('E', 7, struct efi_waketime_ioc)
+#define EFIIOC_SET_WAKETIME _IOW('E', 8, struct efi_waketime_ioc)
#endif /* _SYS_EFIIO_H_ */
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile
--- a/usr.sbin/Makefile
+++ b/usr.sbin/Makefile
@@ -129,7 +129,7 @@
.endif
SUBDIR.${MK_CXGBETOOL}+= cxgbetool
SUBDIR.${MK_DIALOG}+= bsdconfig
-SUBDIR.${MK_EFI}+= efivar efidp efibootmgr efitable
+SUBDIR.${MK_EFI}+= efivar efidp efibootmgr efitable efiwake
.if ${MK_OPENSSL} != "no"
SUBDIR.${MK_EFI}+= uefisign
.endif
diff --git a/usr.sbin/efiwake/Makefile b/usr.sbin/efiwake/Makefile
new file mode 100644
--- /dev/null
+++ b/usr.sbin/efiwake/Makefile
@@ -0,0 +1,13 @@
+# $FreeBSD$
+
+PACKAGE= efi-tools
+
+PROG= efiwake
+MAN=
+
+SRCS= efiwake.c
+
+EFIBOOT=${SRCTOP}/stand/efi
+CFLAGS+=-I${EFIBOOT}/include
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/efiwake/efiwake.c b/usr.sbin/efiwake/efiwake.c
new file mode 100644
--- /dev/null
+++ b/usr.sbin/efiwake/efiwake.c
@@ -0,0 +1,134 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2023 Johannes Totz
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <sys/efiio.h>
+
+static void usage(void)
+{
+ printf("Usage:\n"
+ " efiwake -- print out current EFI time and wake time\n"
+ " efiwake -d -- disable wake time\n"
+ " efiwake -e yyyy-mm-ddThh:mm:ss -- enable wake time\n"
+ );
+
+ exit(EX_USAGE);
+}
+
+int main(int argc, char **argv)
+{
+ struct efi_waketime_ioc waketime;
+ int error, ch;
+ bool enable = false, disable = false;
+
+ memset(&waketime, 0, sizeof(waketime));
+
+ while ((ch = getopt(argc, argv, "de:")) != -1) {
+ switch (ch) {
+ case 'd':
+ disable = true;
+ break;
+ case 'e':
+ if (sscanf(optarg,
+ "%hu-%02hhu-%02hhuT%02hhu:%02hhu:%02hhu",
+ &waketime.waketime.tm_year, &waketime.waketime.tm_mon,
+ &waketime.waketime.tm_mday, &waketime.waketime.tm_hour,
+ &waketime.waketime.tm_min, &waketime.waketime.tm_sec)
+ != 6) {
+ usage();
+ }
+ enable = true;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0)
+ usage();
+ if (disable && enable)
+ usage();
+
+ int efi_fd = open("/dev/efi", O_RDWR);
+ if (efi_fd < 0)
+ err(EX_OSERR, "cannot open /dev/efi");
+
+ struct efi_tm now;
+ error = ioctl(efi_fd, EFIIOC_GET_TIME, &now);
+ if (error != 0)
+ err(EX_OSERR, "cannot get EFI time");
+
+ /* EFI's time can be different from kernel's time. */
+ printf("Current EFI time: %u-%02u-%02uT%02u:%02u:%02u\n",
+ now.tm_year, now.tm_mon, now.tm_mday, now.tm_hour, now.tm_min,
+ now.tm_sec);
+
+ if (disable) {
+ /* It's tempting to preserve the current timer value.
+ * However, wonky EFI implementations sometimes return bogus
+ * dates for the wake timer and would then fail disabling it
+ * here.
+ * A safe timer value is the current EFI time.
+ */
+ waketime.waketime = now;
+ waketime.enabled = 0;
+ error = ioctl(efi_fd, EFIIOC_SET_WAKETIME, &waketime);
+ if (error != 0)
+ err(EX_OSERR, "cannot disable EFI wake time");
+ }
+ if (enable) {
+ waketime.enabled = 1;
+ error = ioctl(efi_fd, EFIIOC_SET_WAKETIME, &waketime);
+ if (error != 0)
+ err(EX_OSERR, "cannot enable EFI wake time");
+ }
+
+ /* Confirm to user what the wake time has been set to. */
+ error = ioctl(efi_fd, EFIIOC_GET_WAKETIME, &waketime);
+ if (error != 0)
+ err(EX_OSERR, "cannot get EFI wake time");
+
+ printf("EFI wake time: %u-%02u-%02uT%02u:%02u:%02u; enabled=%i, pending=%i\n",
+ waketime.waketime.tm_year, waketime.waketime.tm_mon,
+ waketime.waketime.tm_mday, waketime.waketime.tm_hour,
+ waketime.waketime.tm_min, waketime.waketime.tm_sec,
+ waketime.enabled, waketime.pending);
+
+ close(efi_fd);
+ return (0);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Apr 30, 5:22 AM (17 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32453784
Default Alt Text
D36714.id120946.diff (9 KB)
Attached To
Mode
D36714: EFI wake time
Attached
Detach File
Event Timeline
Log In to Comment