1105401Stmm/*- 2105401Stmm * Copyright (c) 2002 by Thomas Moestl <tmm@FreeBSD.org>. 3105401Stmm * All rights reserved. 4105401Stmm * 5105401Stmm * Redistribution and use in source and binary forms, with or without 6105401Stmm * modification, are permitted provided that the following conditions 7105401Stmm * are met: 8105401Stmm * 1. Redistributions of source code must retain the above copyright 9105401Stmm * notice, this list of conditions and the following disclaimer. 10105401Stmm * 2. Redistributions in binary form must reproduce the above copyright 11105401Stmm * notice, this list of conditions and the following disclaimer in the 12105401Stmm * documentation and/or other materials provided with the distribution. 13105401Stmm * 14105401Stmm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15105401Stmm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16105401Stmm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17105401Stmm * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 18105401Stmm * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19105401Stmm * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20105401Stmm * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21105401Stmm * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22105401Stmm * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 23105401Stmm * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24105401Stmm */ 25105401Stmm 26105401Stmm#include <sys/cdefs.h> 27105401Stmm__FBSDID("$FreeBSD: releng/11.0/usr.sbin/ofwdump/ofwdump.c 277256 2015-01-16 18:42:49Z nwhitehorn $"); 28105401Stmm 29129589Smarius#include <dev/ofw/openfirm.h> 30129589Smarius#include <dev/ofw/openfirmio.h> 31129589Smarius 32129589Smarius#include <err.h> 33129589Smarius#include <fcntl.h> 34105401Stmm#include <stdio.h> 35105401Stmm#include <stdlib.h> 36129589Smarius#include <string.h> 37129589Smarius#include <sysexits.h> 38105401Stmm#include <unistd.h> 39129589Smarius#include <vis.h> 40105401Stmm 41105401Stmm#include "ofw_util.h" 42105401Stmm 43129589Smarius/* Constants controlling the layout of the output. */ 44129589Smarius#define LVLINDENT 2 45129589Smarius#define NAMEINDENT 2 46129589Smarius#define DUMPINDENT 4 47129589Smarius#define CHARSPERLINE 60 48129589Smarius#define BYTESPERLINE (CHARSPERLINE / 3) 49105401Stmm 50129589Smariusstatic void usage(void); 51129589Smariusstatic void ofw_indent(int); 52277256Snwhitehornstatic void ofw_dump_properties(int, phandle_t, int, int, int); 53277256Snwhitehornstatic void ofw_dump_property(int fd, phandle_t n, int level, 54277256Snwhitehorn const char *prop, int raw, int str); 55129589Smariusstatic void ofw_dump(int, const char *, int, int, const char *, int, int); 56129589Smarius 57129589Smariusstatic void 58105401Stmmusage(void) 59105401Stmm{ 60105401Stmm 61105401Stmm fprintf(stderr, 62105401Stmm "usage: ofwdump -a [-p | -P property] [-R | -S]\n" 63105401Stmm " ofwdump [-p | -P property] [-r] [-R | -S] [--] nodes\n"); 64129589Smarius exit(EX_USAGE); 65105401Stmm} 66105401Stmm 67105401Stmmint 68105401Stmmmain(int argc, char *argv[]) 69105401Stmm{ 70105401Stmm int opt, i, fd; 71105401Stmm int aflag, pflag, rflag, Rflag, Sflag; 72105401Stmm char *Parg; 73105401Stmm 74105401Stmm aflag = pflag = rflag = Rflag = Sflag = 0; 75105401Stmm Parg = NULL; 76105401Stmm while ((opt = getopt(argc, argv, "-aprP:RS")) != -1) { 77105401Stmm if (opt == '-') 78105401Stmm break; 79105401Stmm switch (opt) { 80105401Stmm case 'a': 81105401Stmm aflag = 1; 82105401Stmm rflag = 1; 83105401Stmm break; 84105401Stmm case 'p': 85105401Stmm if (Parg != NULL) 86105401Stmm usage(); 87105401Stmm pflag = 1; 88105401Stmm break; 89105401Stmm case 'r': 90105401Stmm rflag = 1; 91105401Stmm break; 92105401Stmm case 'P': 93105401Stmm if (pflag) 94105401Stmm usage(); 95105401Stmm pflag = 1; 96105401Stmm Parg = optarg; 97105401Stmm break; 98105401Stmm case 'R': 99105401Stmm if (Sflag) 100105401Stmm usage(); 101105401Stmm Rflag = 1; 102105401Stmm break; 103105401Stmm case 'S': 104105401Stmm if (Rflag) 105105401Stmm usage(); 106105401Stmm Sflag = 1; 107105401Stmm break; 108129589Smarius case '?': 109105401Stmm default: 110105401Stmm usage(); 111129589Smarius /* NOTREACHED */ 112105401Stmm } 113105401Stmm } 114105401Stmm argc -= optind; 115105401Stmm argv += optind; 116105401Stmm 117129589Smarius fd = ofw_open(O_RDONLY); 118105401Stmm if (aflag) { 119105401Stmm if (argc != 0) 120105401Stmm usage(); 121105401Stmm ofw_dump(fd, NULL, rflag, pflag, Parg, Rflag, Sflag); 122105401Stmm } else { 123129589Smarius /* 124129589Smarius * For the sake of scripts, usage() is not called here if 125129589Smarius * argc == 0. 126129589Smarius */ 127105401Stmm for (i = 0; i < argc; i++) 128105401Stmm ofw_dump(fd, argv[i], rflag, pflag, Parg, Rflag, Sflag); 129105401Stmm } 130105401Stmm ofw_close(fd); 131129589Smarius return (EX_OK); 132105401Stmm} 133129589Smarius 134129589Smariusstatic void 135129589Smariusofw_indent(int level) 136129589Smarius{ 137129589Smarius int i; 138129589Smarius 139129589Smarius for (i = 0; i < level; i++) 140129589Smarius putchar(' '); 141129589Smarius} 142129589Smarius 143129589Smariusstatic void 144277256Snwhitehornofw_dump_properties(int fd, phandle_t n, int level, int raw, int str) 145277256Snwhitehorn{ 146277256Snwhitehorn int nlen; 147277256Snwhitehorn char prop[32]; 148277256Snwhitehorn 149277256Snwhitehorn for (nlen = ofw_firstprop(fd, n, prop, sizeof(prop)); nlen != 0; 150277256Snwhitehorn nlen = ofw_nextprop(fd, n, prop, prop, sizeof(prop))) 151277256Snwhitehorn ofw_dump_property(fd, n, level, prop, raw, str); 152277256Snwhitehorn} 153277256Snwhitehorn 154277256Snwhitehornstatic void 155277256Snwhitehornofw_dump_property(int fd, phandle_t n, int level, const char *prop, int raw, 156129589Smarius int str) 157129589Smarius{ 158129589Smarius static void *pbuf = NULL; 159129589Smarius static char *visbuf = NULL; 160129589Smarius static char printbuf[CHARSPERLINE + 1]; 161129589Smarius static int pblen = 0, vblen = 0; 162277256Snwhitehorn int len, i, j, max, vlen; 163129589Smarius 164277256Snwhitehorn len = ofw_getprop_alloc(fd, n, prop, &pbuf, &pblen, 1); 165277256Snwhitehorn if (len < 0) 166277256Snwhitehorn return; 167277256Snwhitehorn if (raw) 168277256Snwhitehorn write(STDOUT_FILENO, pbuf, len); 169277256Snwhitehorn else if (str) 170277256Snwhitehorn printf("%.*s\n", len, (char *)pbuf); 171277256Snwhitehorn else { 172277256Snwhitehorn ofw_indent(level * LVLINDENT + NAMEINDENT); 173277256Snwhitehorn printf("%s:\n", prop); 174277256Snwhitehorn /* Print in hex. */ 175277256Snwhitehorn for (i = 0; i < len; i += BYTESPERLINE) { 176277256Snwhitehorn max = len - i; 177277256Snwhitehorn max = max > BYTESPERLINE ? BYTESPERLINE : max; 178277256Snwhitehorn ofw_indent(level * LVLINDENT + DUMPINDENT); 179277256Snwhitehorn for (j = 0; j < max; j++) 180277256Snwhitehorn printf("%02x ", 181277256Snwhitehorn ((unsigned char *)pbuf)[i + j]); 182277256Snwhitehorn printf("\n"); 183277256Snwhitehorn } 184277256Snwhitehorn /* 185277256Snwhitehorn * strvis() and print if it looks like it is 186277256Snwhitehorn * zero-terminated. 187277256Snwhitehorn */ 188277256Snwhitehorn if (((char *)pbuf)[len - 1] == '\0' && 189277256Snwhitehorn strlen(pbuf) == (unsigned)len - 1) { 190277256Snwhitehorn if (vblen < (len - 1) * 4 + 1) { 191277256Snwhitehorn if (visbuf != NULL) 192277256Snwhitehorn free(visbuf); 193277256Snwhitehorn vblen = (OFIOCMAXVALUE + len) * 4 + 1; 194129589Smarius if ((visbuf = malloc(vblen)) == NULL) 195129589Smarius err(EX_OSERR, 196129589Smarius "malloc() failed"); 197129589Smarius } 198277256Snwhitehorn vlen = strvis(visbuf, pbuf, VIS_TAB | VIS_NL); 199277256Snwhitehorn for (i = 0; i < vlen; i += CHARSPERLINE) { 200277256Snwhitehorn ofw_indent(level * LVLINDENT + 201277256Snwhitehorn DUMPINDENT); 202277256Snwhitehorn strlcpy(printbuf, &visbuf[i], 203277256Snwhitehorn sizeof(printbuf)); 204277256Snwhitehorn printf("'%s'\n", printbuf); 205277256Snwhitehorn } 206129589Smarius } 207129589Smarius } 208129589Smarius} 209129589Smarius 210129589Smariusstatic void 211129589Smariusofw_dump_node(int fd, phandle_t n, int level, int rec, int prop, 212129589Smarius const char *pmatch, int raw, int str) 213129589Smarius{ 214129589Smarius static void *nbuf = NULL; 215129589Smarius static int nblen = 0; 216129589Smarius int plen; 217129589Smarius phandle_t c; 218129589Smarius 219129589Smarius if (!(raw || str)) { 220129589Smarius ofw_indent(level * LVLINDENT); 221129589Smarius printf("Node %#lx", (unsigned long)n); 222129589Smarius plen = ofw_getprop_alloc(fd, n, "name", &nbuf, &nblen, 1); 223129589Smarius if (plen > 0) 224129589Smarius printf(": %.*s\n", (int)plen, (char *)nbuf); 225129589Smarius else 226129589Smarius putchar('\n'); 227129589Smarius } 228277256Snwhitehorn if (prop) { 229277256Snwhitehorn if (pmatch) 230277256Snwhitehorn ofw_dump_property(fd, n, level, pmatch, raw, str); 231277256Snwhitehorn else 232277256Snwhitehorn ofw_dump_properties(fd, n, level, raw, str); 233277256Snwhitehorn } 234129589Smarius if (rec) { 235129589Smarius for (c = ofw_child(fd, n); c != 0; c = ofw_peer(fd, c)) { 236129589Smarius ofw_dump_node(fd, c, level + 1, rec, prop, pmatch, 237129589Smarius raw, str); 238129589Smarius } 239129589Smarius } 240129589Smarius} 241129589Smarius 242129589Smariusstatic void 243129589Smariusofw_dump(int fd, const char *start, int rec, int prop, const char *pmatch, 244129589Smarius int raw, int str) 245129589Smarius{ 246129589Smarius phandle_t n; 247129589Smarius 248129589Smarius n = start == NULL ? ofw_root(fd) : ofw_finddevice(fd, start); 249129589Smarius ofw_dump_node(fd, n, 0, rec, prop, pmatch, raw, str); 250129589Smarius} 251