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$"); 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); 52129589Smariusstatic void ofw_dump_properties(int, phandle_t, int, const char *, int, 53129589Smarius int); 54129589Smariusstatic void ofw_dump(int, const char *, int, int, const char *, int, int); 55129589Smarius 56129589Smariusstatic void 57105401Stmmusage(void) 58105401Stmm{ 59105401Stmm 60105401Stmm fprintf(stderr, 61105401Stmm "usage: ofwdump -a [-p | -P property] [-R | -S]\n" 62105401Stmm " ofwdump [-p | -P property] [-r] [-R | -S] [--] nodes\n"); 63129589Smarius exit(EX_USAGE); 64105401Stmm} 65105401Stmm 66105401Stmmint 67105401Stmmmain(int argc, char *argv[]) 68105401Stmm{ 69105401Stmm int opt, i, fd; 70105401Stmm int aflag, pflag, rflag, Rflag, Sflag; 71105401Stmm char *Parg; 72105401Stmm 73105401Stmm aflag = pflag = rflag = Rflag = Sflag = 0; 74105401Stmm Parg = NULL; 75105401Stmm while ((opt = getopt(argc, argv, "-aprP:RS")) != -1) { 76105401Stmm if (opt == '-') 77105401Stmm break; 78105401Stmm switch (opt) { 79105401Stmm case 'a': 80105401Stmm aflag = 1; 81105401Stmm rflag = 1; 82105401Stmm break; 83105401Stmm case 'p': 84105401Stmm if (Parg != NULL) 85105401Stmm usage(); 86105401Stmm pflag = 1; 87105401Stmm break; 88105401Stmm case 'r': 89105401Stmm rflag = 1; 90105401Stmm break; 91105401Stmm case 'P': 92105401Stmm if (pflag) 93105401Stmm usage(); 94105401Stmm pflag = 1; 95105401Stmm Parg = optarg; 96105401Stmm break; 97105401Stmm case 'R': 98105401Stmm if (Sflag) 99105401Stmm usage(); 100105401Stmm Rflag = 1; 101105401Stmm break; 102105401Stmm case 'S': 103105401Stmm if (Rflag) 104105401Stmm usage(); 105105401Stmm Sflag = 1; 106105401Stmm break; 107129589Smarius case '?': 108105401Stmm default: 109105401Stmm usage(); 110129589Smarius /* NOTREACHED */ 111105401Stmm } 112105401Stmm } 113105401Stmm argc -= optind; 114105401Stmm argv += optind; 115105401Stmm 116129589Smarius fd = ofw_open(O_RDONLY); 117105401Stmm if (aflag) { 118105401Stmm if (argc != 0) 119105401Stmm usage(); 120105401Stmm ofw_dump(fd, NULL, rflag, pflag, Parg, Rflag, Sflag); 121105401Stmm } else { 122129589Smarius /* 123129589Smarius * For the sake of scripts, usage() is not called here if 124129589Smarius * argc == 0. 125129589Smarius */ 126105401Stmm for (i = 0; i < argc; i++) 127105401Stmm ofw_dump(fd, argv[i], rflag, pflag, Parg, Rflag, Sflag); 128105401Stmm } 129105401Stmm ofw_close(fd); 130129589Smarius return (EX_OK); 131105401Stmm} 132129589Smarius 133129589Smariusstatic void 134129589Smariusofw_indent(int level) 135129589Smarius{ 136129589Smarius int i; 137129589Smarius 138129589Smarius for (i = 0; i < level; i++) 139129589Smarius putchar(' '); 140129589Smarius} 141129589Smarius 142129589Smariusstatic void 143129589Smariusofw_dump_properties(int fd, phandle_t n, int level, const char *pmatch, int raw, 144129589Smarius int str) 145129589Smarius{ 146129589Smarius static void *pbuf = NULL; 147129589Smarius static char *visbuf = NULL; 148129589Smarius static char printbuf[CHARSPERLINE + 1]; 149129589Smarius static int pblen = 0, vblen = 0; 150129589Smarius char prop[32]; 151129589Smarius int nlen, len, i, j, max, vlen; 152129589Smarius 153129589Smarius for (nlen = ofw_firstprop(fd, n, prop, sizeof(prop)); nlen != 0; 154129589Smarius nlen = ofw_nextprop(fd, n, prop, prop, sizeof(prop))) { 155129589Smarius if (pmatch != NULL && strcmp(pmatch, prop) != 0) 156129589Smarius continue; 157129589Smarius len = ofw_getprop_alloc(fd, n, prop, &pbuf, &pblen, 1); 158129589Smarius if (len < 0) 159129589Smarius continue; 160129589Smarius if (raw) 161129589Smarius write(STDOUT_FILENO, pbuf, len); 162129589Smarius else if (str) 163129589Smarius printf("%.*s\n", len, (char *)pbuf); 164129589Smarius else { 165129589Smarius ofw_indent(level * LVLINDENT + NAMEINDENT); 166129589Smarius printf("%s:\n", prop); 167129589Smarius /* Print in hex. */ 168129589Smarius for (i = 0; i < len; i += BYTESPERLINE) { 169129589Smarius max = len - i; 170129589Smarius max = max > BYTESPERLINE ? BYTESPERLINE : max; 171129589Smarius ofw_indent(level * LVLINDENT + DUMPINDENT); 172129589Smarius for (j = 0; j < max; j++) 173129589Smarius printf("%02x ", 174129589Smarius ((unsigned char *)pbuf)[i + j]); 175129589Smarius printf("\n"); 176129589Smarius } 177129589Smarius /* 178129589Smarius * strvis() and print if it looks like it is 179129589Smarius * zero-terminated. 180129589Smarius */ 181129589Smarius if (((char *)pbuf)[len - 1] == '\0' && 182129589Smarius strlen(pbuf) == (unsigned)len - 1) { 183129589Smarius if (vblen < (len - 1) * 4 + 1) { 184129589Smarius if (visbuf != NULL) 185129589Smarius free(visbuf); 186129589Smarius vblen = (OFIOCMAXVALUE + len) * 4 + 1; 187129589Smarius if ((visbuf = malloc(vblen)) == NULL) 188129589Smarius err(EX_OSERR, 189129589Smarius "malloc() failed"); 190129589Smarius } 191129589Smarius vlen = strvis(visbuf, pbuf, VIS_TAB | VIS_NL); 192129589Smarius for (i = 0; i < vlen; i += CHARSPERLINE) { 193129589Smarius ofw_indent(level * LVLINDENT + 194129589Smarius DUMPINDENT); 195129589Smarius strlcpy(printbuf, &visbuf[i], 196129589Smarius sizeof(printbuf)); 197129589Smarius printf("'%s'\n", printbuf); 198129589Smarius } 199129589Smarius } 200129589Smarius } 201129589Smarius } 202129589Smarius} 203129589Smarius 204129589Smariusstatic void 205129589Smariusofw_dump_node(int fd, phandle_t n, int level, int rec, int prop, 206129589Smarius const char *pmatch, int raw, int str) 207129589Smarius{ 208129589Smarius static void *nbuf = NULL; 209129589Smarius static int nblen = 0; 210129589Smarius int plen; 211129589Smarius phandle_t c; 212129589Smarius 213129589Smarius if (!(raw || str)) { 214129589Smarius ofw_indent(level * LVLINDENT); 215129589Smarius printf("Node %#lx", (unsigned long)n); 216129589Smarius plen = ofw_getprop_alloc(fd, n, "name", &nbuf, &nblen, 1); 217129589Smarius if (plen > 0) 218129589Smarius printf(": %.*s\n", (int)plen, (char *)nbuf); 219129589Smarius else 220129589Smarius putchar('\n'); 221129589Smarius } 222129589Smarius if (prop) 223129589Smarius ofw_dump_properties(fd, n, level, pmatch, raw, str); 224129589Smarius if (rec) { 225129589Smarius for (c = ofw_child(fd, n); c != 0; c = ofw_peer(fd, c)) { 226129589Smarius ofw_dump_node(fd, c, level + 1, rec, prop, pmatch, 227129589Smarius raw, str); 228129589Smarius } 229129589Smarius } 230129589Smarius} 231129589Smarius 232129589Smariusstatic void 233129589Smariusofw_dump(int fd, const char *start, int rec, int prop, const char *pmatch, 234129589Smarius int raw, int str) 235129589Smarius{ 236129589Smarius phandle_t n; 237129589Smarius 238129589Smarius n = start == NULL ? ofw_root(fd) : ofw_finddevice(fd, start); 239129589Smarius ofw_dump_node(fd, n, 0, rec, prop, pmatch, raw, str); 240129589Smarius} 241