diff options
Diffstat (limited to 'usr.sbin/ofwdump/ofwdump.c')
| -rw-r--r-- | usr.sbin/ofwdump/ofwdump.c | 249 | 
1 files changed, 249 insertions, 0 deletions
| diff --git a/usr.sbin/ofwdump/ofwdump.c b/usr.sbin/ofwdump/ofwdump.c new file mode 100644 index 000000000000..335ae38afa5d --- /dev/null +++ b/usr.sbin/ofwdump/ofwdump.c @@ -0,0 +1,249 @@ +/*- + * Copyright (c) 2002 by Thomas Moestl <tmm@FreeBSD.org>. + * 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 <sys/cdefs.h> +#include <dev/ofw/openfirm.h> +#include <dev/ofw/openfirmio.h> + +#include <err.h> +#include <fcntl.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sysexits.h> +#include <unistd.h> +#include <vis.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) + +static void	usage(void); +static void	ofw_indent(int); +static void	ofw_dump_properties(int, phandle_t, int, bool, bool); +static void	ofw_dump_property(int fd, phandle_t n, int level, +		    const char *prop, bool raw, bool str); +static void	ofw_dump(int, const char *, bool, bool, const char *, bool, bool); + +static void +usage(void) +{ + +	fprintf(stderr, +	    "usage: ofwdump -a [-p | -P property] [-R | -S]\n" +	    "       ofwdump [-p | -P property] [-r] [-R | -S] [--] nodes\n"); +	exit(EX_USAGE); +} + +int +main(int argc, char *argv[]) +{ +	int opt, i, fd; +	bool aflag, pflag, rflag, Rflag, Sflag; +	char *Parg; + +	aflag = pflag = rflag = Rflag = Sflag = false; +	Parg = NULL; +	while ((opt = getopt(argc, argv, "-aprP:RS")) != -1) { +		if (opt == '-') +			break; +		switch (opt) { +		case 'a': +			aflag = true; +			rflag = true; +			break; +		case 'p': +			if (Parg != NULL) +				usage(); +			pflag = true; +			break; +		case 'r': +			rflag = true; +			break; +		case 'P': +			if (pflag) +				usage(); +			pflag = true; +			Parg = optarg; +			break; +		case 'R': +			if (Sflag) +				usage(); +			Rflag = true; +			break; +		case 'S': +			if (Rflag) +				usage(); +			Sflag = true; +			break; +		case '?': +		default: +			usage(); +			/* NOTREACHED */ +		} +	} +	argc -= optind; +	argv += optind; + +	fd = ofw_open(O_RDONLY); +	if (aflag) { +		if (argc != 0) +			usage(); +		ofw_dump(fd, NULL, rflag, pflag, Parg, Rflag, Sflag); +	} else { +		/* +		 * For the sake of scripts, usage() is not called here if +		 * argc == 0. +		 */ +		for (i = 0; i < argc; i++) +			ofw_dump(fd, argv[i], rflag, pflag, Parg, Rflag, Sflag); +	} +	ofw_close(fd); +	return (EX_OK); +} + +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, bool raw, bool str) +{ +	int nlen; +	char prop[OFIOCSUGGPROPNAMELEN]; + +	for (nlen = ofw_firstprop(fd, n, prop, sizeof(prop)); nlen != 0; +	     nlen = ofw_nextprop(fd, n, prop, prop, sizeof(prop))) +		ofw_dump_property(fd, n, level, prop, raw, str); +} + +static void +ofw_dump_property(int fd, phandle_t n, int level, const char *prop, bool raw, +    bool str) +{ +	static void *pbuf = NULL; +	static char *visbuf = NULL; +	static char printbuf[CHARSPERLINE + 1]; +	static int pblen = 0, vblen = 0; +	int len, i, j, max, vlen; + +	len = ofw_getprop_alloc(fd, n, prop, &pbuf, &pblen, 1); +	if (len < 0) +		return; +	if (raw) +		write(STDOUT_FILENO, pbuf, len); +	else if (str) +		printf("%.*s\n", len, (char *)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++) +				printf("%02x ", +				    ((unsigned char *)pbuf)[i + j]); +			printf("\n"); +		} +		/* +		 * strvis() and print if it looks like it is +		 * zero-terminated. +		 */ +		if (((char *)pbuf)[len - 1] == '\0' && +		    strlen(pbuf) == (unsigned)len - 1) { +			if (vblen < (len - 1) * 4 + 1) { +				if (visbuf != NULL) +					free(visbuf); +				vblen = (OFIOCMAXVALUE + len) * 4 + 1; +					if ((visbuf = malloc(vblen)) == NULL) +						err(EX_OSERR, +						    "malloc() failed"); +			} +			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, +    const char *pmatch, bool raw, bool str) +{ +	static void *nbuf = NULL; +	static int nblen = 0; +	int plen; +	phandle_t c; + +	if (!(raw || str)) { +		ofw_indent(level * LVLINDENT); +		printf("Node %#lx", (unsigned long)n); +		plen = ofw_getprop_alloc(fd, n, "name", &nbuf, &nblen, 1); +		if (plen > 0) +			printf(": %.*s\n", (int)plen, (char *)nbuf); +		else +			putchar('\n'); +	} +	if (prop) { +		if (pmatch) +			ofw_dump_property(fd, n, level, pmatch, raw, str); +		else +			ofw_dump_properties(fd, n, level, 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); +		} +	} +} + +static void +ofw_dump(int fd, const char *start, bool rec, bool prop, const char *pmatch, +    bool raw, bool 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); +} | 
