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