1 /*- 2 * Copyright (c) 2002 by Thomas Moestl <tmm@FreeBSD.org>. 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 #include <dev/ofw/openfirm.h> 28 #include <dev/ofw/openfirmio.h> 29 30 #include <err.h> 31 #include <fcntl.h> 32 #include <stdbool.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <sysexits.h> 37 #include <unistd.h> 38 #include <vis.h> 39 40 #include "ofw_util.h" 41 42 /* Constants controlling the layout of the output. */ 43 #define LVLINDENT 2 44 #define NAMEINDENT 2 45 #define DUMPINDENT 4 46 #define CHARSPERLINE 60 47 #define BYTESPERLINE (CHARSPERLINE / 3) 48 49 static void usage(void); 50 static void ofw_indent(int); 51 static void ofw_dump_properties(int, phandle_t, int, bool, bool); 52 static void ofw_dump_property(int fd, phandle_t n, int level, 53 const char *prop, bool raw, bool str); 54 static void ofw_dump(int, const char *, bool, bool, const char *, bool, bool); 55 56 static void 57 usage(void) 58 { 59 60 fprintf(stderr, 61 "usage: ofwdump -a [-p | -P property] [-R | -S]\n" 62 " ofwdump [-p | -P property] [-r] [-R | -S] [--] nodes\n"); 63 exit(EX_USAGE); 64 } 65 66 int 67 main(int argc, char *argv[]) 68 { 69 int opt, i, fd; 70 bool aflag, pflag, rflag, Rflag, Sflag; 71 char *Parg; 72 73 aflag = pflag = rflag = Rflag = Sflag = false; 74 Parg = NULL; 75 while ((opt = getopt(argc, argv, "-aprP:RS")) != -1) { 76 if (opt == '-') 77 break; 78 switch (opt) { 79 case 'a': 80 aflag = true; 81 rflag = true; 82 break; 83 case 'p': 84 if (Parg != NULL) 85 usage(); 86 pflag = true; 87 break; 88 case 'r': 89 rflag = true; 90 break; 91 case 'P': 92 if (pflag) 93 usage(); 94 pflag = true; 95 Parg = optarg; 96 break; 97 case 'R': 98 if (Sflag) 99 usage(); 100 Rflag = true; 101 break; 102 case 'S': 103 if (Rflag) 104 usage(); 105 Sflag = true; 106 break; 107 case '?': 108 default: 109 usage(); 110 /* NOTREACHED */ 111 } 112 } 113 argc -= optind; 114 argv += optind; 115 116 fd = ofw_open(O_RDONLY); 117 if (aflag) { 118 if (argc != 0) 119 usage(); 120 ofw_dump(fd, NULL, rflag, pflag, Parg, Rflag, Sflag); 121 } else { 122 /* 123 * For the sake of scripts, usage() is not called here if 124 * argc == 0. 125 */ 126 for (i = 0; i < argc; i++) 127 ofw_dump(fd, argv[i], rflag, pflag, Parg, Rflag, Sflag); 128 } 129 ofw_close(fd); 130 return (EX_OK); 131 } 132 133 static void 134 ofw_indent(int level) 135 { 136 int i; 137 138 for (i = 0; i < level; i++) 139 putchar(' '); 140 } 141 142 static void 143 ofw_dump_properties(int fd, phandle_t n, int level, bool raw, bool str) 144 { 145 int nlen; 146 char prop[OFIOCSUGGPROPNAMELEN]; 147 148 for (nlen = ofw_firstprop(fd, n, prop, sizeof(prop)); nlen != 0; 149 nlen = ofw_nextprop(fd, n, prop, prop, sizeof(prop))) 150 ofw_dump_property(fd, n, level, prop, raw, str); 151 } 152 153 static void 154 ofw_dump_property(int fd, phandle_t n, int level, const char *prop, bool raw, 155 bool str) 156 { 157 static void *pbuf = NULL; 158 static char *visbuf = NULL; 159 static char printbuf[CHARSPERLINE + 1]; 160 static int pblen = 0, vblen = 0; 161 int len, i, j, max, vlen; 162 163 len = ofw_getprop_alloc(fd, n, prop, &pbuf, &pblen, 1); 164 if (len < 0) 165 return; 166 if (raw) 167 write(STDOUT_FILENO, pbuf, len); 168 else if (str) 169 printf("%.*s\n", len, (char *)pbuf); 170 else { 171 ofw_indent(level * LVLINDENT + NAMEINDENT); 172 printf("%s:\n", prop); 173 /* Print in hex. */ 174 for (i = 0; i < len; i += BYTESPERLINE) { 175 max = len - i; 176 max = max > BYTESPERLINE ? BYTESPERLINE : max; 177 ofw_indent(level * LVLINDENT + DUMPINDENT); 178 for (j = 0; j < max; j++) 179 printf("%02x ", 180 ((unsigned char *)pbuf)[i + j]); 181 printf("\n"); 182 } 183 /* 184 * strvis() and print if it looks like it is 185 * zero-terminated. 186 */ 187 if (((char *)pbuf)[len - 1] == '\0' && 188 strlen(pbuf) == (unsigned)len - 1) { 189 if (vblen < (len - 1) * 4 + 1) { 190 if (visbuf != NULL) 191 free(visbuf); 192 vblen = (OFIOCMAXVALUE + len) * 4 + 1; 193 if ((visbuf = malloc(vblen)) == NULL) 194 err(EX_OSERR, 195 "malloc() failed"); 196 } 197 vlen = strvis(visbuf, pbuf, VIS_TAB | VIS_NL); 198 for (i = 0; i < vlen; i += CHARSPERLINE) { 199 ofw_indent(level * LVLINDENT + 200 DUMPINDENT); 201 strlcpy(printbuf, &visbuf[i], 202 sizeof(printbuf)); 203 printf("'%s'\n", printbuf); 204 } 205 } 206 } 207 } 208 209 static void 210 ofw_dump_node(int fd, phandle_t n, int level, int rec, int prop, 211 const char *pmatch, bool raw, bool str) 212 { 213 static void *nbuf = NULL; 214 static int nblen = 0; 215 int plen; 216 phandle_t c; 217 218 if (!(raw || str)) { 219 ofw_indent(level * LVLINDENT); 220 printf("Node %#lx", (unsigned long)n); 221 plen = ofw_getprop_alloc(fd, n, "name", &nbuf, &nblen, 1); 222 if (plen > 0) 223 printf(": %.*s\n", (int)plen, (char *)nbuf); 224 else 225 putchar('\n'); 226 } 227 if (prop) { 228 if (pmatch) 229 ofw_dump_property(fd, n, level, pmatch, raw, str); 230 else 231 ofw_dump_properties(fd, n, level, raw, str); 232 } 233 if (rec) { 234 for (c = ofw_child(fd, n); c != 0; c = ofw_peer(fd, c)) { 235 ofw_dump_node(fd, c, level + 1, rec, prop, pmatch, 236 raw, str); 237 } 238 } 239 } 240 241 static void 242 ofw_dump(int fd, const char *start, bool rec, bool prop, const char *pmatch, 243 bool raw, bool str) 244 { 245 phandle_t n; 246 247 n = start == NULL ? ofw_root(fd) : ofw_finddevice(fd, start); 248 ofw_dump_node(fd, n, 0, rec, prop, pmatch, raw, str); 249 } 250