1 /* $NetBSD: ofhandlers.c,v 1.4 2008/04/28 20:24:15 martin 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 BARF("OFIOCGETOPTNODE", strerror(errno)); 111 112 memset(&ofio_buf[0], 0, sizeof(ofio_buf)); 113 memset(&ofio, 0, sizeof(ofio)); 114 ofio.of_nodeid = optnode; 115 ofio.of_name = keyword; 116 ofio.of_namelen = strlen(ofio.of_name); 117 118 if (arg) { 119 if (verbose) { 120 printf("old: "); 121 122 ofio.of_buf = &ofio_buf[0]; 123 ofio.of_buflen = sizeof(ofio_buf); 124 if (ioctl(fd, OFIOCGET, (char *)&ofio) < 0) 125 BARF("OFIOCGET", strerror(errno)); 126 127 if (ofio.of_buflen <= 0) { 128 printf("nothing available for %s\n", keyword); 129 goto out; 130 } 131 132 if (ex->ex_keyword != NULL) 133 (*ex->ex_handler)(ex, &ofio, NULL); 134 else 135 printf("%s\n", ofio.of_buf); 136 } 137 out: 138 if (ex->ex_keyword != NULL) 139 (*ex->ex_handler)(ex, &ofio, arg); 140 else { 141 ofio.of_buf = arg; 142 ofio.of_buflen = strlen(arg); 143 } 144 145 if (ioctl(fd, OFIOCSET, (char *)&ofio) < 0) 146 BARF("invalid keyword", keyword); 147 148 if (verbose) { 149 printf("new: "); 150 if (ex->ex_keyword != NULL) 151 (*ex->ex_handler)(ex, &ofio, NULL); 152 else 153 printf("%s\n", ofio.of_buf); 154 } 155 } else { 156 ofio.of_buf = &ofio_buf[0]; 157 ofio.of_buflen = sizeof(ofio_buf); 158 if (ioctl(fd, OFIOCGET, (char *)&ofio) < 0) 159 BARF("OFIOCGET", strerror(errno)); 160 161 if (ofio.of_buflen <= 0) { 162 (void)snprintf(err_str, sizeof err_str, 163 "nothing available for %s", keyword); 164 return (err_str); 165 } 166 167 if (ex->ex_keyword != NULL) 168 (*ex->ex_handler)(ex, &ofio, NULL); 169 else 170 printf("%s=%s\n", keyword, ofio.of_buf); 171 } 172 173 (void)close(fd); 174 return (NULL); 175 } 176 177 /* ARGSUSED */ 178 static void 179 of_notsupp(exent, ofiop, arg) 180 struct extabent *exent; 181 struct ofiocdesc *ofiop; 182 char *arg; 183 { 184 185 warnx("property `%s' not yet supported", exent->ex_keyword); 186 } 187 188 static void 189 of_uint32h(exent, ofiop, arg) 190 struct extabent *exent; 191 struct ofiocdesc *ofiop; 192 char *arg; 193 { 194 195 printf("%s=0x%08x\n", exent->ex_keyword, *(uint32_t *)ofiop->of_buf); 196 } 197 198 static void 199 of_uint32d(exent, ofiop, arg) 200 struct extabent *exent; 201 struct ofiocdesc *ofiop; 202 char *arg; 203 { 204 205 printf("%s=%d\n", exent->ex_keyword, *(uint32_t *)ofiop->of_buf); 206 } 207 208 /* 209 * XXX: This code is quite ugly. You have been warned. 210 * (Really! This is the only way I could get it to work!) 211 */ 212 void 213 of_dump() 214 { 215 struct ofiocdesc ofio1, ofio2; 216 struct extabent *ex; 217 char buf1[BUFSIZE], buf2[BUFSIZE], buf3[BUFSIZE], buf4[BUFSIZE]; 218 int fd, optnode; 219 220 if ((fd = open(path_openfirm, O_RDONLY, 0640)) < 0) 221 err(1, "open: %s", path_openfirm); 222 223 if (ioctl(fd, OFIOCGETOPTNODE, (char *)&optnode) < 0) 224 err(1, "OFIOCGETOPTNODE"); 225 226 memset(&ofio1, 0, sizeof(ofio1)); 227 228 /* This will grab the first property name from OPIOCNEXTPROP. */ 229 memset(buf1, 0, sizeof(buf1)); 230 memset(buf2, 0, sizeof(buf2)); 231 232 ofio1.of_nodeid = ofio2.of_nodeid = optnode; 233 234 ofio1.of_name = buf1; 235 ofio1.of_buf = buf2; 236 237 ofio2.of_name = buf3; 238 ofio2.of_buf = buf4; 239 240 /* 241 * For reference: ofio1 is for obtaining the name. Pass the 242 * name of the last property read in of_name, and the next one 243 * will be returned in of_buf. To get the first name, pass 244 * an empty string. There are no more properties when an 245 * empty string is returned. 246 * 247 * ofio2 is for obtaining the value associated with that name. 248 * For some crazy reason, it seems as if we need to do all 249 * of that gratuitious zapping and copying. *sigh* 250 */ 251 for (;;) { 252 ofio1.of_namelen = strlen(ofio1.of_name); 253 ofio1.of_buflen = sizeof(buf2); 254 255 if (ioctl(fd, OFIOCNEXTPROP, (char *)&ofio1) < 0) { 256 close(fd); 257 return; 258 /* err(1, "ioctl: OFIOCNEXTPROP"); */ 259 } 260 261 /* 262 * The name of the property we wish to get the 263 * value for has been stored in the value field 264 * of ofio1. If the length of the name is 0, there 265 * are no more properties left. 266 */ 267 strcpy(ofio2.of_name, ofio1.of_buf); /* XXX strcpy is safe */ 268 ofio2.of_namelen = strlen(ofio2.of_name); 269 270 if (ofio2.of_namelen == 0) { 271 (void)close(fd); 272 return; 273 } 274 275 memset(ofio2.of_buf, 0, sizeof(buf4)); 276 ofio2.of_buflen = sizeof(buf4); 277 278 if (ioctl(fd, OFIOCGET, (char *)&ofio2) < 0) 279 err(1, "ioctl: OFIOCGET"); 280 281 for (ex = ofextab; ex->ex_keyword != NULL; ++ex) 282 if (strcmp(ex->ex_keyword, ofio2.of_name) == 0) 283 break; 284 285 if (ex->ex_keyword != NULL) 286 (*ex->ex_handler)(ex, &ofio2, NULL); 287 else 288 printf("%s=%s\n", ofio2.of_name, ofio2.of_buf); 289 290 /* 291 * Place the name of the last read value back into 292 * ofio1 so that we may obtain the next name. 293 */ 294 memset(ofio1.of_name, 0, sizeof(buf1)); 295 memset(ofio1.of_buf, 0, sizeof(buf2)); 296 strcpy(ofio1.of_name, ofio2.of_name); /* XXX strcpy is safe */ 297 } 298 /* NOTREACHED */ 299 } 300