]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/eeprom/ofw_options.c
This commit was generated by cvs2svn to compensate for changes in r160157,
[FreeBSD/FreeBSD.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)(struct ofwo_extabent *, int, const void *,
56                             int, const char *);
57 };
58
59 static int      ofwo_oemlogo(struct ofwo_extabent *, int, const void *, int,
60                     const char *);
61 static int      ofwo_secmode(struct ofwo_extabent *, int, const void *, int,
62                     const char *);
63 static int      ofwo_secpwd(struct ofwo_extabent *, int, const void *, int,
64                     const char *);
65
66 static struct ofwo_extabent 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 *,
75                             const char *);
76
77 static __inline void
78 ofwo_printprop(const char *prop, const char* buf, int buflen)
79 {
80
81         printf("%s: %.*s\n", prop, buflen, buf);
82 }
83
84 static int
85 ofwo_oemlogo(struct ofwo_extabent *exent, int fd, const void *buf, int buflen,
86     const char *val)
87 {
88         int lfd;
89         char logo[OFWO_LOGO + 1];
90
91         if (val) {
92                 if (val[0] == '\0')
93                         ofw_setprop(fd, ofw_optnode(fd), exent->ex_prop, "", 1);
94                 else {
95                         if ((lfd = open(val, O_RDONLY)) == -1) {
96                                 warn("could not open '%s'", val);
97                                 return (EX_USAGE);
98                         }
99                         if (read(lfd, logo, OFWO_LOGO) != OFWO_LOGO ||
100                             lseek(lfd, 0, SEEK_END) != OFWO_LOGO) {
101                                 close(lfd);
102                                 warnx("logo '%s' has wrong size.", val);
103                                 return (EX_USAGE);
104                         }
105                         close(lfd);
106                         logo[OFWO_LOGO] = '\0';
107                         if (ofw_setprop(fd, ofw_optnode(fd), exent->ex_prop,
108                             logo, OFWO_LOGO + 1) != OFWO_LOGO)
109                                 errx(EX_IOERR, "writing logo failed.");
110                 }
111         } else
112                 if (buflen != 0)
113                         printf("%s: <logo data>\n", exent->ex_prop);
114                 else
115                         ofwo_printprop(exent->ex_prop, (const char *)buf,
116                             buflen);
117         return (EX_OK);
118 }
119
120 static int
121 ofwo_secmode(struct ofwo_extabent *exent, int fd, const void *buf, int buflen,
122     const char *val)
123 {
124         int res;
125
126         if (val) {
127                 if (strcmp(val, "full") == 0 || strcmp(val, "command") == 0) {
128                         if ((res = ofwo_setpass(fd)) != EX_OK)
129                                 return (res);
130                         if ((res = ofwo_setstr(fd, buf, buflen, exent->ex_prop,
131                             val)) != EX_OK)
132                                 ofw_setprop(fd, ofw_optnode(fd),
133                                     "security-password", "", 1);
134                         return (res);
135                 }
136                 if (strcmp(val, "none") == 0) {
137                         ofw_setprop(fd, ofw_optnode(fd), "security-password",
138                             "", 1);
139                         return (ofwo_setstr(fd, buf, buflen, exent->ex_prop,
140                             val));
141                 }
142                 return (EX_DATAERR);
143         } else
144                 ofwo_printprop(exent->ex_prop, (const char *)buf, buflen);
145         return (EX_OK);
146 }
147
148 static int
149 ofwo_secpwd(struct ofwo_extabent *exent, int fd __unused,
150     const void *buf __unused, __unused int buflen, const char *val)
151 {
152         void *pbuf;
153         int len, pblen, rv;
154
155         pblen = 0;
156         rv = EX_OK;
157         pbuf = NULL;
158         if (val) {
159                 len = ofw_getprop_alloc(fd, ofw_optnode(fd), "security-mode",
160                     &pbuf, &pblen, 1);
161                 if (len <= 0 || strncmp("none", (char *)pbuf, len) == 0) {
162                         rv = EX_CONFIG;
163                         warnx("no security mode set.");
164                 } else if (strncmp("command", (char *)pbuf, len) == 0 ||
165                     strncmp("full", (char *)pbuf, len) == 0) {
166                         rv = ofwo_setpass(fd);
167                 } else {
168                         rv = EX_CONFIG;
169                         warnx("invalid security mode.");
170                 }
171         } else
172                 ofwo_printprop(exent->ex_prop, (const char *)buf, buflen);
173         if (pbuf != NULL)
174                 free(pbuf);
175         return (rv);
176 }
177
178 static int
179 ofwo_setpass(int fd)
180 {
181         char pwd1[OFWO_MAXPWD + 1], pwd2[OFWO_MAXPWD + 1];
182
183         if (readpassphrase("New password:", pwd1, sizeof(pwd1),
184             RPP_ECHO_OFF | RPP_REQUIRE_TTY) == NULL ||
185             readpassphrase("Retype new password:", pwd2, sizeof(pwd2),
186             RPP_ECHO_OFF | RPP_REQUIRE_TTY) == NULL)
187                 errx(EX_USAGE, "failed to get password.");
188         if (strlen(pwd1) == 0) {
189                 printf("Password unchanged.\n");
190                 return (EX_OK);
191         }
192         if (strcmp(pwd1, pwd2) != 0) {
193                 printf("Mismatch - password unchanged.\n");
194                 return (EX_USAGE);
195         }
196         ofw_setprop(fd, ofw_optnode(fd), "security-password", pwd1,
197             strlen(pwd1) + 1);
198         return (EX_OK);
199 }
200
201 static int
202 ofwo_setstr(int fd, const void *buf, int buflen, const char *prop,
203     const char *val)
204 {
205         void *pbuf;
206         int len, pblen, rv;
207         phandle_t optnode;
208         char *oval;
209
210         pblen = 0;
211         rv = EX_OK;
212         pbuf = NULL;
213         optnode = ofw_optnode(fd);
214         ofw_setprop(fd, optnode, prop, val, strlen(val) + 1);
215         len = ofw_getprop_alloc(fd, optnode, prop, &pbuf, &pblen, 1);
216         if (len < 0 || strncmp(val, (char *)pbuf, len) != 0) {
217                 /*
218                  * The value is too long for this property and the OFW has
219                  * truncated it to fit or the value is illegal and a legal
220                  * one has been written instead (e.g. attempted to write
221                  * "foobar" to a "true"/"false"-property) - try to recover
222                  * the old value.
223                  */
224                 rv = EX_DATAERR;
225                 if ((oval = malloc(buflen + 1)) == NULL)
226                         err(EX_OSERR, "malloc() failed.");
227                 strncpy(oval, buf, buflen);
228                 oval[buflen] = '\0';
229                 len = ofw_setprop(fd, optnode, prop, oval, buflen + 1);
230                 if (len != buflen)
231                         errx(EX_IOERR, "recovery of old value failed.");
232                 free(oval);
233                 goto out;
234         }
235         printf("%s: %.*s%s->%s%.*s\n", prop, buflen, (const char *)buf,
236             buflen > 0 ? " " : "", len > 0 ? " " : "", len, (char *)pbuf);
237 out:
238         if (pbuf != NULL)
239                 free(pbuf);
240         return (rv);
241 }
242
243 void
244 ofwo_dump(void)
245 {
246         void *pbuf;
247         int fd, len, nlen, pblen;
248         phandle_t optnode;
249         char prop[OFWO_MAXPROP + 1];
250         struct ofwo_extabent *ex;
251
252         pblen = 0;
253         pbuf = NULL;
254         fd = ofw_open(O_RDONLY);
255         optnode = ofw_optnode(fd);
256         for (nlen = ofw_firstprop(fd, optnode, prop, sizeof(prop)); nlen != 0;
257              nlen = ofw_nextprop(fd, optnode, prop, prop, sizeof(prop))) {
258                 len = ofw_getprop_alloc(fd, optnode, prop, &pbuf, &pblen, 1);
259                 if (len < 0)
260                         continue;
261                 if (strcmp(prop, "name") == 0)
262                         continue;
263                 for (ex = ofwo_extab; ex->ex_prop != NULL; ++ex)
264                         if (strcmp(ex->ex_prop, prop) == 0)
265                                 break;
266                 if (ex->ex_prop != NULL)
267                         (*ex->ex_handler)(ex, fd, pbuf, len, NULL);
268                 else
269                         ofwo_printprop(prop, (char *)pbuf, len);
270         }
271         if (pbuf != NULL)
272                 free(pbuf);
273         ofw_close(fd);
274 }
275
276 int
277 ofwo_action(const char *prop, const char *val)
278 {
279         void *pbuf;
280         int fd, len, pblen, rv;
281         struct ofwo_extabent *ex;
282
283         pblen = 0;
284         rv = EX_OK;
285         pbuf = NULL;
286         if (strcmp(prop, "name") == 0)
287                 return (EX_UNAVAILABLE);
288         if (val)
289                 fd = ofw_open(O_RDWR);
290         else
291                 fd = ofw_open(O_RDONLY);
292         len = ofw_getprop_alloc(fd, ofw_optnode(fd), prop, &pbuf, &pblen, 1);
293         if (len < 0) {
294                 rv = EX_UNAVAILABLE;
295                 goto out;
296         }
297         for (ex = ofwo_extab; ex->ex_prop != NULL; ++ex)
298                 if (strcmp(ex->ex_prop, prop) == 0)
299                         break;
300         if (ex->ex_prop != NULL)
301                 rv = (*ex->ex_handler)(ex, fd, pbuf, len, val);
302         else if (val)
303                 rv = ofwo_setstr(fd, pbuf, len, prop, val);
304         else 
305                 ofwo_printprop(prop, (char *)pbuf, len);
306 out:
307         if (pbuf != NULL)
308                 free(pbuf);
309         ofw_close(fd);
310         return (rv);
311 }