/*- * Copyright (c) 2002 by Thomas Moestl . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include "pathnames.h" #include "ofw_util.h" /* Constants controlling the layout of the output. */ #define LVLINDENT 2 #define NAMEINDENT 2 #define DUMPINDENT 4 #define CHARSPERLINE 60 #define BYTESPERLINE (CHARSPERLINE / 3) /* Maximum supported property size. */ #define PROPBUFLEN 8192 #define OFW_IOCTL(fd, cmd, val) do { \ if (ioctl(fd, cmd, val) == -1) \ err(1, "ioctl(..., " #cmd ", ...) failed"); \ } while (0) int ofw_open(void) { int fd; if ((fd = open(PATH_DEV_OPENFIRM, O_RDONLY)) == -1) err(1, "could not open " PATH_DEV_OPENFIRM); return (fd); } void ofw_close(int fd) { close(fd); } phandle_t ofw_root(int fd) { return (ofw_peer(fd, 0)); } phandle_t ofw_peer(int fd, phandle_t node) { phandle_t rv; rv = node; OFW_IOCTL(fd, OFIOCGETNEXT, &rv); return (rv); } phandle_t ofw_child(int fd, phandle_t node) { phandle_t rv; rv = node; OFW_IOCTL(fd, OFIOCGETCHILD, &rv); return (rv); } phandle_t ofw_finddevice(int fd, char *name) { struct ofiocdesc d; d.of_nodeid = 0; d.of_namelen = strlen(name); d.of_name = name; d.of_buflen = 0; d.of_buf = NULL; if (ioctl(fd, OFIOCFINDDEVICE, &d) == -1) { if (errno == ENOENT) err(2, "Node '%s' not found", name); else err(1, "ioctl(..., OFIOCFINDDEVICE, ...) failed"); } return (d.of_nodeid); } int ofw_firstprop(int fd, phandle_t node, char *buf, int buflen) { return (ofw_nextprop(fd, node, NULL, buf, buflen)); } int ofw_nextprop(int fd, phandle_t node, char *prev, char *buf, int buflen) { struct ofiocdesc d; d.of_nodeid = node; d.of_namelen = prev != NULL ? strlen(prev) : 0; d.of_name = prev; d.of_buflen = buflen; d.of_buf = buf; if (ioctl(fd, OFIOCNEXTPROP, &d) == -1) { if (errno == ENOENT) return (0); else err(1, "ioctl(..., OFIOCNEXTPROP, ...) failed"); } return (d.of_buflen); } int ofw_getprop(int fd, phandle_t node, const char *name, void *buf, int buflen) { struct ofiocdesc d; d.of_nodeid = node; d.of_namelen = strlen(name); d.of_name = name; d.of_buflen = buflen; d.of_buf = buf; OFW_IOCTL(fd, OFIOCGET, &d); return (d.of_buflen); } static void ofw_indent(int level) { int i; for (i = 0; i < level; i++) putchar(' '); } static void ofw_dump_properties(int fd, phandle_t n, int level, char *pmatch, int raw, int str) { static char pbuf[PROPBUFLEN]; static char visbuf[PROPBUFLEN * 4 + 1]; static char printbuf[CHARSPERLINE + 1]; char prop[32]; int nlen, len, i, j, max, vlen; unsigned int b; for (nlen = ofw_firstprop(fd, n, prop, sizeof(prop)); nlen != 0; nlen = ofw_nextprop(fd, n, prop, prop, sizeof(prop))) { if (pmatch != NULL && strcmp(pmatch, prop) != 0) continue; len = ofw_getprop(fd, n, prop, pbuf, sizeof(pbuf) - 1); if (raw) write(STDOUT_FILENO, pbuf, len); else if (str) { pbuf[len] = '\0'; printf("%s\n", pbuf); } else { ofw_indent(level * LVLINDENT + NAMEINDENT); printf("%s:\n", prop); /* Print in hex. */ for (i = 0; i < len; i += BYTESPERLINE) { max = len - i; max = max > BYTESPERLINE ? BYTESPERLINE : max; ofw_indent(level * LVLINDENT + DUMPINDENT); for (j = 0; j < max; j++) { b = (unsigned char)pbuf[i + j]; printf("%02x ", b); } printf("\n"); } /* * strvis() and print if it looks like it is * zero-terminated. */ if (pbuf[len - 1] == '\0' && strlen(pbuf) == (unsigned)len - 1) { vlen = strvis(visbuf, pbuf, VIS_TAB | VIS_NL); for (i = 0; i < vlen; i += CHARSPERLINE) { ofw_indent(level * LVLINDENT + DUMPINDENT); strlcpy(printbuf, &visbuf[i], sizeof(printbuf)); printf("'%s'\n", printbuf); } } } } } static void ofw_dump_node(int fd, phandle_t n, int level, int rec, int prop, char *pmatch, int raw, int str) { static char nbuf[PROPBUFLEN]; phandle_t c; if (!(raw || str)) { ofw_indent(level * LVLINDENT); printf("Node %#lx", (unsigned long)n); if (ofw_getprop(fd, n, "name", nbuf, sizeof(nbuf) - 1) > 0) printf(": %s\n", nbuf); else putchar('\n'); } if (prop) ofw_dump_properties(fd, n, level, pmatch, raw, str); if (rec) { for (c = ofw_child(fd, n); c != 0; c = ofw_peer(fd, c)) { ofw_dump_node(fd, c, level + 1, rec, prop, pmatch, raw, str); } } } void ofw_dump(int fd, char *start, int rec, int prop, char *pmatch, int raw, int str) { phandle_t n; n = start == NULL ? ofw_root(fd) : ofw_finddevice(fd, start); ofw_dump_node(fd, n, 0, rec, prop, pmatch, raw, str); }