1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2023 Johannes Totz
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/efiio.h>
29 #include <err.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <stdbool.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sysexits.h>
37 #include <unistd.h>
38
39 static void
usage(void)40 usage(void)
41 {
42 fprintf(stderr, "Usage:\n"
43 " efiwake -- print out current "
44 "EFI time and wake time\n"
45 " efiwake -d -- disable wake time\n"
46 " efiwake -e yyyy-mm-ddThh:mm:ss -- enable wake time\n"
47 );
48 exit(EX_USAGE);
49 }
50
51 int
main(int argc,char ** argv)52 main(int argc, char **argv)
53 {
54 struct efi_tm now;
55 struct efi_waketime_ioc waketime;
56 int ch, error, efi_fd;
57 bool disable = false, enable = false;
58
59 memset(&waketime, 0, sizeof(waketime));
60
61 while ((ch = getopt(argc, argv, "de:")) != -1) {
62 switch (ch) {
63 case 'd':
64 disable = true;
65 break;
66 case 'e':
67 if (sscanf(optarg,
68 "%hu-%02hhu-%02hhuT%02hhu:%02hhu:%02hhu",
69 &waketime.waketime.tm_year,
70 &waketime.waketime.tm_mon,
71 &waketime.waketime.tm_mday,
72 &waketime.waketime.tm_hour,
73 &waketime.waketime.tm_min,
74 &waketime.waketime.tm_sec) != 6) {
75 usage();
76 }
77 enable = true;
78 break;
79 case '?':
80 default:
81 usage();
82 }
83 }
84 argc -= optind;
85 argv += optind;
86
87 if (argc > 0)
88 usage();
89 if (disable && enable)
90 usage();
91
92 efi_fd = open("/dev/efi", O_RDWR);
93 if (efi_fd < 0)
94 err(EX_OSERR, "cannot open /dev/efi");
95
96 error = ioctl(efi_fd, EFIIOC_GET_TIME, &now);
97 if (error != 0)
98 err(EX_OSERR, "cannot get EFI time");
99
100 /* EFI's time can be different from kernel's time. */
101 printf("Current EFI time: %u-%02u-%02uT%02u:%02u:%02u\n",
102 now.tm_year, now.tm_mon, now.tm_mday, now.tm_hour, now.tm_min,
103 now.tm_sec);
104
105 if (disable) {
106 /*
107 * It's tempting to preserve the current timer value.
108 * However, wonky EFI implementations sometimes return bogus
109 * dates for the wake timer and would then fail disabling it
110 * here.
111 * A safe timer value is the current EFI time.
112 */
113 waketime.waketime = now;
114 waketime.enabled = 0;
115 error = ioctl(efi_fd, EFIIOC_SET_WAKETIME, &waketime);
116 if (error != 0)
117 err(EX_OSERR, "cannot disable EFI wake time");
118 }
119 if (enable) {
120 waketime.enabled = 1;
121 error = ioctl(efi_fd, EFIIOC_SET_WAKETIME, &waketime);
122 if (error != 0)
123 err(EX_OSERR, "cannot enable EFI wake time");
124 }
125
126 /* Confirm to user what the wake time has been set to. */
127 error = ioctl(efi_fd, EFIIOC_GET_WAKETIME, &waketime);
128 if (error != 0)
129 err(EX_OSERR, "cannot get EFI wake time");
130
131 printf("EFI wake time: %u-%02u-%02uT%02u:%02u:%02u; "
132 "enabled=%i, pending=%i\n",
133 waketime.waketime.tm_year, waketime.waketime.tm_mon,
134 waketime.waketime.tm_mday, waketime.waketime.tm_hour,
135 waketime.waketime.tm_min, waketime.waketime.tm_sec,
136 waketime.enabled, waketime.pending);
137
138 close(efi_fd);
139 return (0);
140 }
141