]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/efiwake/efiwake.c
ldns: Upgrade to 1.8.3.
[FreeBSD/FreeBSD.git] / usr.sbin / efiwake / efiwake.c
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
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
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 }