1 /* $NetBSD: ofhandlers.c,v 1.1 2006/08/16 03:24:57 macallan Exp $ */ 2 3 /*- 4 * Copyright (c) 1996 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/types.h> 40 #include <sys/ioctl.h> 41 #include <err.h> 42 #include <errno.h> 43 #include <fcntl.h> 44 #include <string.h> 45 #include <stdio.h> 46 #include <string.h> 47 #include <unistd.h> 48 49 #include <dev/ofw/openfirmio.h> 50 51 #include "defs.h" 52 53 extern char *path_openfirm; 54 extern int eval; 55 extern int verbose; 56 57 static char err_str[BUFSIZE]; 58 59 static void of_notsupp (struct extabent *, struct ofiocdesc *, char *); 60 61 /* 62 * There are several known fields that I either don't know how to 63 * deal with or require special treatment. 64 */ 65 static struct extabent ofextab[] = { 66 { "security-password", of_notsupp }, 67 { "security-mode", of_notsupp }, 68 { "oem-logo", of_notsupp }, 69 { NULL, of_notsupp }, 70 }; 71 72 #define BARF(str1, str2) { \ 73 snprintf(err_str, sizeof err_str, "%s: %s", (str1), (str2)); \ 74 ++eval; \ 75 return (err_str); \ 76 }; 77 78 void 79 of_action(keyword, arg) 80 char *keyword, *arg; 81 { 82 char *cp; 83 84 if ((cp = of_handler(keyword, arg)) != NULL) 85 warnx("%s", cp); 86 return; 87 } 88 89 char * 90 of_handler(keyword, arg) 91 char *keyword, *arg; 92 { 93 struct ofiocdesc ofio; 94 struct extabent *ex; 95 char ofio_buf[BUFSIZE]; 96 int fd, optnode; 97 98 if ((fd = open(path_openfirm, arg ? O_RDWR : O_RDONLY, 0640)) < 0) 99 BARF(path_openfirm, strerror(errno)); 100 101 /* Check to see if it's a special-case keyword. */ 102 for (ex = ofextab; ex->ex_keyword != NULL; ++ex) 103 if (strcmp(ex->ex_keyword, keyword) == 0) 104 break; 105 106 if (ioctl(fd, OFIOCGETOPTNODE, (char *)&optnode) < 0) 107 BARF("OFIOCGETOPTNODE", strerror(errno)); 108 109 memset(&ofio_buf[0], 0, sizeof(ofio_buf)); 110 memset(&ofio, 0, sizeof(ofio)); 111 ofio.of_nodeid = optnode; 112 ofio.of_name = keyword; 113 ofio.of_namelen = strlen(ofio.of_name); 114 115 if (arg) { 116 if (verbose) { 117 printf("old: "); 118 119 ofio.of_buf = &ofio_buf[0]; 120 ofio.of_buflen = sizeof(ofio_buf); 121 if (ioctl(fd, OFIOCGET, (char *)&ofio) < 0) 122 BARF("OFIOCGET", strerror(errno)); 123 124 if (ofio.of_buflen <= 0) { 125 printf("nothing available for %s\n", keyword); 126 goto out; 127 } 128 129 if (ex->ex_keyword != NULL) 130 (*ex->ex_handler)(ex, &ofio, NULL); 131 else 132 printf("%s\n", ofio.of_buf); 133 } 134 out: 135 if (ex->ex_keyword != NULL) 136 (*ex->ex_handler)(ex, &ofio, arg); 137 else { 138 ofio.of_buf = arg; 139 ofio.of_buflen = strlen(arg); 140 } 141 142 if (ioctl(fd, OFIOCSET, (char *)&ofio) < 0) 143 BARF("invalid keyword", keyword); 144 145 if (verbose) { 146 printf("new: "); 147 if (ex->ex_keyword != NULL) 148 (*ex->ex_handler)(ex, &ofio, NULL); 149 else 150 printf("%s\n", ofio.of_buf); 151 } 152 } else { 153 ofio.of_buf = &ofio_buf[0]; 154 ofio.of_buflen = sizeof(ofio_buf); 155 if (ioctl(fd, OFIOCGET, (char *)&ofio) < 0) 156 BARF("OFIOCGET", strerror(errno)); 157 158 if (ofio.of_buflen <= 0) { 159 (void)snprintf(err_str, sizeof err_str, 160 "nothing available for %s", keyword); 161 return (err_str); 162 } 163 164 if (ex->ex_keyword != NULL) 165 (*ex->ex_handler)(ex, &ofio, NULL); 166 else 167 printf("%s=%s\n", keyword, ofio.of_buf); 168 } 169 170 (void)close(fd); 171 return (NULL); 172 } 173 174 /* ARGSUSED */ 175 static void 176 of_notsupp(exent, ofiop, arg) 177 struct extabent *exent; 178 struct ofiocdesc *ofiop; 179 char *arg; 180 { 181 182 warnx("property `%s' not yet supported", exent->ex_keyword); 183 } 184 185 /* 186 * XXX: This code is quite ugly. You have been warned. 187 * (Really! This is the only way I could get it to work!) 188 */ 189 void 190 of_dump() 191 { 192 struct ofiocdesc ofio1, ofio2; 193 struct extabent *ex; 194 char buf1[BUFSIZE], buf2[BUFSIZE], buf3[BUFSIZE], buf4[BUFSIZE]; 195 int fd, optnode; 196 197 if ((fd = open(path_openfirm, O_RDONLY, 0640)) < 0) 198 err(1, "open: %s", path_openfirm); 199 200 if (ioctl(fd, OFIOCGETOPTNODE, (char *)&optnode) < 0) 201 err(1, "OFIOCGETOPTNODE"); 202 203 memset(&ofio1, 0, sizeof(ofio1)); 204 205 /* This will grab the first property name from OPIOCNEXTPROP. */ 206 memset(buf1, 0, sizeof(buf1)); 207 memset(buf2, 0, sizeof(buf2)); 208 209 ofio1.of_nodeid = ofio2.of_nodeid = optnode; 210 211 ofio1.of_name = buf1; 212 ofio1.of_buf = buf2; 213 214 ofio2.of_name = buf3; 215 ofio2.of_buf = buf4; 216 217 /* 218 * For reference: ofio1 is for obtaining the name. Pass the 219 * name of the last property read in of_name, and the next one 220 * will be returned in of_buf. To get the first name, pass 221 * an empty string. There are no more properties when an 222 * empty string is returned. 223 * 224 * ofio2 is for obtaining the value associated with that name. 225 * For some crazy reason, it seems as if we need to do all 226 * of that gratuitious zapping and copying. *sigh* 227 */ 228 for (;;) { 229 ofio1.of_namelen = strlen(ofio1.of_name); 230 ofio1.of_buflen = sizeof(buf2); 231 232 if (ioctl(fd, OFIOCNEXTPROP, (char *)&ofio1) < 0) { 233 close(fd); 234 return; 235 /* err(1, "ioctl: OFIOCNEXTPROP"); */ 236 } 237 238 /* 239 * The name of the property we wish to get the 240 * value for has been stored in the value field 241 * of ofio1. If the length of the name is 0, there 242 * are no more properties left. 243 */ 244 strcpy(ofio2.of_name, ofio1.of_buf); /* XXX strcpy is safe */ 245 ofio2.of_namelen = strlen(ofio2.of_name); 246 247 if (ofio2.of_namelen == 0) { 248 (void)close(fd); 249 return; 250 } 251 252 memset(ofio2.of_buf, 0, sizeof(buf4)); 253 ofio2.of_buflen = sizeof(buf4); 254 255 if (ioctl(fd, OFIOCGET, (char *)&ofio2) < 0) 256 err(1, "ioctl: OFIOCGET"); 257 258 for (ex = ofextab; ex->ex_keyword != NULL; ++ex) 259 if (strcmp(ex->ex_keyword, ofio2.of_name) == 0) 260 break; 261 262 if (ex->ex_keyword != NULL) 263 (*ex->ex_handler)(ex, &ofio2, NULL); 264 else 265 printf("%s=%s\n", ofio2.of_name, ofio2.of_buf); 266 267 /* 268 * Place the name of the last read value back into 269 * ofio1 so that we may obtain the next name. 270 */ 271 memset(ofio1.of_name, 0, sizeof(buf1)); 272 memset(ofio1.of_buf, 0, sizeof(buf2)); 273 strcpy(ofio1.of_name, ofio2.of_name); /* XXX strcpy is safe */ 274 } 275 /* NOTREACHED */ 276 } 277