]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/eeprom/ofw_options.c
Add missing break statements in r351004.
[FreeBSD/FreeBSD.git] / usr.sbin / eeprom / ofw_options.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2004 Marius Strobl
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
25  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 /*
32  * Handlers for Open Firmware /options node.
33  */
34
35 #include <sys/types.h>
36
37 #include <dev/ofw/openfirm.h>
38
39 #include <err.h>
40 #include <fcntl.h>
41 #include <readpassphrase.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <sysexits.h>
46 #include <unistd.h>
47
48 #include "ofw_options.h"
49 #include "ofw_util.h"
50
51 #define OFWO_LOGO       512
52 #define OFWO_MAXPROP    31
53 #define OFWO_MAXPWD     8
54
55 struct ofwo_extabent {
56         const char      *ex_prop;
57         int             (*ex_handler)(const struct ofwo_extabent *, int,
58                             const void *, int, const char *);
59 };
60
61 static int      ofwo_oemlogo(const struct ofwo_extabent *, int, const void *,
62                     int, const char *);
63 static int      ofwo_secmode(const struct ofwo_extabent *, int, const void *,
64                     int, const char *);
65 static int      ofwo_secpwd(const struct ofwo_extabent *, int, const void *,
66                     int, const char *);
67
68 static const struct ofwo_extabent ofwo_extab[] = {
69         { "oem-logo",                   ofwo_oemlogo },
70         { "security-mode",              ofwo_secmode },
71         { "security-password",          ofwo_secpwd },
72         { NULL,                         NULL }
73 };
74
75 static int      ofwo_setpass(int);
76 static int      ofwo_setstr(int, const void *, int, const char *, const char *);
77
78 static __inline void
79 ofwo_printprop(const char *prop, const char* buf, int buflen)
80 {
81
82         printf("%s: %.*s\n", prop, buflen, buf);
83 }
84
85 static int
86 ofwo_oemlogo(const struct ofwo_extabent *exent, int fd, const void *buf,
87     int buflen, const char *val)
88 {
89         int lfd;
90         char logo[OFWO_LOGO + 1];
91
92         if (val) {
93                 if (val[0] == '\0')
94                         ofw_setprop(fd, ofw_optnode(fd), exent->ex_prop, "", 1);
95                 else {
96                         if ((lfd = open(val, O_RDONLY)) == -1) {
97                                 warn("could not open '%s'", val);
98                                 return (EX_USAGE);
99                         }
100                         if (read(lfd, logo, OFWO_LOGO) != OFWO_LOGO ||
101                             lseek(lfd, 0, SEEK_END) != OFWO_LOGO) {
102                                 close(lfd);
103                                 warnx("logo '%s' has wrong size.", val);
104                                 return (EX_USAGE);
105                         }
106                         close(lfd);
107                         logo[OFWO_LOGO] = '\0';
108                         if (ofw_setprop(fd, ofw_optnode(fd), exent->ex_prop,
109                             logo, OFWO_LOGO + 1) != OFWO_LOGO)
110                                 errx(EX_IOERR, "writing logo failed.");
111                 }
112         } else
113                 if (buflen != 0)
114                         printf("%s: <logo data>\n", exent->ex_prop);
115                 else
116                         ofwo_printprop(exent->ex_prop, (const char *)buf,
117                             buflen);
118         return (EX_OK);
119 }
120
121 static int
122 ofwo_secmode(const struct ofwo_extabent *exent, int fd, const void *buf,
123     int buflen, const char *val)
124 {
125         int res;
126
127         if (val) {
128                 if (strcmp(val, "full") == 0 || strcmp(val, "command") == 0) {
129                         if ((res = ofwo_setpass(fd)) != EX_OK)
130                                 return (res);
131                         if ((res = ofwo_setstr(fd, buf, buflen, exent->ex_prop,
132                             val)) != EX_OK)
133                                 ofw_setprop(fd, ofw_optnode(fd),
134                                     "security-password", "", 1);
135                         return (res);
136                 }
137                 if (strcmp(val, "none") == 0) {
138                         ofw_setprop(fd, ofw_optnode(fd), "security-password",
139                             "", 1);
140                         return (ofwo_setstr(fd, buf, buflen, exent->ex_prop,
141                             val));
142                 }
143                 return (EX_DATAERR);
144         } else
145                 ofwo_printprop(exent->ex_prop, (const char *)buf, buflen);
146         return (EX_OK);
147 }
148
149 static int
150 ofwo_secpwd(const struct ofwo_extabent *exent, int fd, const void *buf,
151     int buflen, const char *val)
152 {
153         void *pbuf;
154         int len, pblen, rv;
155
156         pblen = 0;
157         rv = EX_OK;
158         pbuf = NULL;
159         if (val) {
160                 len = ofw_getprop_alloc(fd, ofw_optnode(fd), "security-mode",
161                     &pbuf, &pblen, 1);
162                 if (len <= 0 || strncmp("none", (char *)pbuf, len) == 0) {
163                         rv = EX_CONFIG;
164                         warnx("no security mode set.");
165                 } else if (strncmp("command", (char *)pbuf, len) == 0 ||
166                     strncmp("full", (char *)pbuf, len) == 0) {
167                         rv = ofwo_setpass(fd);
168                 } else {
169                         rv = EX_CONFIG;
170                         warnx("invalid security mode.");
171                 }
172         } else
173                 ofwo_printprop(exent->ex_prop, (const char *)buf, buflen);
174         if (pbuf != NULL)
175                 free(pbuf);
176         return (rv);
177 }
178
179 static int
180 ofwo_setpass(int fd)
181 {
182         char pwd1[OFWO_MAXPWD + 1], pwd2[OFWO_MAXPWD + 1];
183
184         if (readpassphrase("New password:", pwd1, sizeof(pwd1),
185             RPP_ECHO_OFF | RPP_REQUIRE_TTY) == NULL ||
186             readpassphrase("Retype new password:", pwd2, sizeof(pwd2),
187             RPP_ECHO_OFF | RPP_REQUIRE_TTY) == NULL)
188                 errx(EX_USAGE, "failed to get password.");
189         if (strlen(pwd1) == 0) {
190                 printf("Password unchanged.\n");
191                 return (EX_OK);
192         }
193         if (strcmp(pwd1, pwd2) != 0) {
194                 printf("Mismatch - password unchanged.\n");
195                 return (EX_USAGE);
196         }
197         ofw_setprop(fd, ofw_optnode(fd), "security-password", pwd1,
198             strlen(pwd1) + 1);
199         return (EX_OK);
200 }
201
202 static int
203 ofwo_setstr(int fd, const void *buf, int buflen, const char *prop,
204     const char *val)
205 {
206         void *pbuf;
207         int len, pblen, rv;
208         phandle_t optnode;
209         char *oval;
210
211         pblen = 0;
212         rv = EX_OK;
213         pbuf = NULL;
214         optnode = ofw_optnode(fd);
215         ofw_setprop(fd, optnode, prop, val, strlen(val) + 1);
216         len = ofw_getprop_alloc(fd, optnode, prop, &pbuf, &pblen, 1);
217         if (len < 0 || strncmp(val, (char *)pbuf, len) != 0) {
218                 /*
219                  * The value is too long for this property and the OFW has
220                  * truncated it to fit or the value is illegal and a legal
221                  * one has been written instead (e.g. attempted to write
222                  * "foobar" to a "true"/"false"-property) - try to recover
223                  * the old value.
224                  */
225                 rv = EX_DATAERR;
226                 if ((oval = malloc(buflen + 1)) == NULL)
227                         err(EX_OSERR, "malloc() failed.");
228                 strncpy(oval, buf, buflen);
229                 oval[buflen] = '\0';
230                 len = ofw_setprop(fd, optnode, prop, oval, buflen + 1);
231                 if (len != buflen)
232                         errx(EX_IOERR, "recovery of old value failed.");
233                 free(oval);
234                 goto out;
235         }
236         printf("%s: %.*s%s->%s%.*s\n", prop, buflen, (const char *)buf,
237             buflen > 0 ? " " : "", len > 0 ? " " : "", len, (char *)pbuf);
238 out:
239         if (pbuf != NULL)
240                 free(pbuf);
241         return (rv);
242 }
243
244 void
245 ofwo_dump(void)
246 {
247         void *pbuf;
248         int fd, len, nlen, pblen;
249         phandle_t optnode;
250         char prop[OFWO_MAXPROP + 1];
251         const struct ofwo_extabent *ex;
252
253         pblen = 0;
254         pbuf = NULL;
255         fd = ofw_open(O_RDONLY);
256         optnode = ofw_optnode(fd);
257         for (nlen = ofw_firstprop(fd, optnode, prop, sizeof(prop)); nlen != 0;
258             nlen = ofw_nextprop(fd, optnode, prop, prop, sizeof(prop))) {
259                 len = ofw_getprop_alloc(fd, optnode, prop, &pbuf, &pblen, 1);
260                 if (len < 0)
261                         continue;
262                 if (strcmp(prop, "name") == 0)
263                         continue;
264                 for (ex = ofwo_extab; ex->ex_prop != NULL; ++ex)
265                         if (strcmp(ex->ex_prop, prop) == 0)
266                                 break;
267                 if (ex->ex_prop != NULL)
268                         (*ex->ex_handler)(ex, fd, pbuf, len, NULL);
269                 else
270                         ofwo_printprop(prop, (char *)pbuf, len);
271         }
272         if (pbuf != NULL)
273                 free(pbuf);
274         ofw_close(fd);
275 }
276
277 int
278 ofwo_action(const char *prop, const char *val)
279 {
280         void *pbuf;
281         int fd, len, pblen, rv;
282         const struct ofwo_extabent *ex;
283
284         pblen = 0;
285         rv = EX_OK;
286         pbuf = NULL;
287         if (strcmp(prop, "name") == 0)
288                 return (EX_UNAVAILABLE);
289         if (val)
290                 fd = ofw_open(O_RDWR);
291         else
292                 fd = ofw_open(O_RDONLY);
293         len = ofw_getprop_alloc(fd, ofw_optnode(fd), prop, &pbuf, &pblen, 1);
294         if (len < 0) {
295                 rv = EX_UNAVAILABLE;
296                 goto out;
297         }
298         for (ex = ofwo_extab; ex->ex_prop != NULL; ++ex)
299                 if (strcmp(ex->ex_prop, prop) == 0)
300                         break;
301         if (ex->ex_prop != NULL)
302                 rv = (*ex->ex_handler)(ex, fd, pbuf, len, val);
303         else if (val)
304                 rv = ofwo_setstr(fd, pbuf, len, prop, val);
305         else
306                 ofwo_printprop(prop, (char *)pbuf, len);
307 out:
308         if (pbuf != NULL)
309                 free(pbuf);
310         ofw_close(fd);
311         return (rv);
312 }