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