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 __FBSDID("$FreeBSD$"); 28 29 #include <dev/ofw/openfirm.h> 30 #include <dev/ofw/openfirmio.h> 31 32 #include <err.h> 33 #include <fcntl.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <sysexits.h> 38 #include <unistd.h> 39 #include <vis.h> 40 41 #include "ofw_util.h" 42 43 /* Constants controlling the layout of the output. */ 44 #define LVLINDENT 2 45 #define NAMEINDENT 2 46 #define DUMPINDENT 4 47 #define CHARSPERLINE 60 48 #define BYTESPERLINE (CHARSPERLINE / 3) 49 50 static void usage(void); 51 static void ofw_indent(int); 52 static void ofw_dump_properties(int, phandle_t, int, const char *, int, 53 int); 54 static void ofw_dump(int, const char *, int, int, const char *, int, int); 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 int aflag, pflag, rflag, Rflag, Sflag; 71 char *Parg; 72 73 aflag = pflag = rflag = Rflag = Sflag = 0; 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 = 1; 81 rflag = 1; 82 break; 83 case 'p': 84 if (Parg != NULL) 85 usage(); 86 pflag = 1; 87 break; 88 case 'r': 89 rflag = 1; 90 break; 91 case 'P': 92 if (pflag) 93 usage(); 94 pflag = 1; 95 Parg = optarg; 96 break; 97 case 'R': 98 if (Sflag) 99 usage(); 100 Rflag = 1; 101 break; 102 case 'S': 103 if (Rflag) 104 usage(); 105 Sflag = 1; 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, const char *pmatch, int raw, 144 int str) 145 { 146 static void *pbuf = NULL; 147 static char *visbuf = NULL; 148 static char printbuf[CHARSPERLINE + 1]; 149 static int pblen = 0, vblen = 0; 150 char prop[32]; 151 int nlen, len, i, j, max, vlen; 152 153 for (nlen = ofw_firstprop(fd, n, prop, sizeof(prop)); nlen != 0; 154 nlen = ofw_nextprop(fd, n, prop, prop, sizeof(prop))) { 155 if (pmatch != NULL && strcmp(pmatch, prop) != 0) 156 continue; 157 len = ofw_getprop_alloc(fd, n, prop, &pbuf, &pblen, 1); 158 if (len < 0) 159 continue; 160 if (raw) 161 write(STDOUT_FILENO, pbuf, len); 162 else if (str) 163 printf("%.*s\n", len, (char *)pbuf); 164 else { 165 ofw_indent(level * LVLINDENT + NAMEINDENT); 166 printf("%s:\n", prop); 167 /* Print in hex. */ 168 for (i = 0; i < len; i += BYTESPERLINE) { 169 max = len - i; 170 max = max > BYTESPERLINE ? BYTESPERLINE : max; 171 ofw_indent(level * LVLINDENT + DUMPINDENT); 172 for (j = 0; j < max; j++) 173 printf("%02x ", 174 ((unsigned char *)pbuf)[i + j]); 175 printf("\n"); 176 } 177 /* 178 * strvis() and print if it looks like it is 179 * zero-terminated. 180 */ 181 if (((char *)pbuf)[len - 1] == '\0' && 182 strlen(pbuf) == (unsigned)len - 1) { 183 if (vblen < (len - 1) * 4 + 1) { 184 if (visbuf != NULL) 185 free(visbuf); 186 vblen = (OFIOCMAXVALUE + len) * 4 + 1; 187 if ((visbuf = malloc(vblen)) == NULL) 188 err(EX_OSERR, 189 "malloc() failed"); 190 } 191 vlen = strvis(visbuf, pbuf, VIS_TAB | VIS_NL); 192 for (i = 0; i < vlen; i += CHARSPERLINE) { 193 ofw_indent(level * LVLINDENT + 194 DUMPINDENT); 195 strlcpy(printbuf, &visbuf[i], 196 sizeof(printbuf)); 197 printf("'%s'\n", printbuf); 198 } 199 } 200 } 201 } 202 } 203 204 static void 205 ofw_dump_node(int fd, phandle_t n, int level, int rec, int prop, 206 const char *pmatch, int raw, int str) 207 { 208 static void *nbuf = NULL; 209 static int nblen = 0; 210 int plen; 211 phandle_t c; 212 213 if (!(raw || str)) { 214 ofw_indent(level * LVLINDENT); 215 printf("Node %#lx", (unsigned long)n); 216 plen = ofw_getprop_alloc(fd, n, "name", &nbuf, &nblen, 1); 217 if (plen > 0) 218 printf(": %.*s\n", (int)plen, (char *)nbuf); 219 else 220 putchar('\n'); 221 } 222 if (prop) 223 ofw_dump_properties(fd, n, level, pmatch, raw, str); 224 if (rec) { 225 for (c = ofw_child(fd, n); c != 0; c = ofw_peer(fd, c)) { 226 ofw_dump_node(fd, c, level + 1, rec, prop, pmatch, 227 raw, str); 228 } 229 } 230 } 231 232 static void 233 ofw_dump(int fd, const char *start, int rec, int prop, const char *pmatch, 234 int raw, int str) 235 { 236 phandle_t n; 237 238 n = start == NULL ? ofw_root(fd) : ofw_finddevice(fd, start); 239 ofw_dump_node(fd, n, 0, rec, prop, pmatch, raw, str); 240 } 241