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