Subject: Re: How to use /dev/openfirm?
To: gabriel rosenkoetter <gr@eclipsed.net>
From: Nathan J. Williams <nathanw@MIT.EDU>
List: port-macppc
Date: 07/29/2001 18:38:41
--=-=-=


gabriel rosenkoetter <gr@eclipsed.net> writes:

> (If you end up finding documentation or working out the details
> yourself, writing something up for the mail archives and, ideally,
> the FAQ would rock.)

Well, there's not much documentation, but with a little UTSL'ing I was
able to produce the following program to walk the ofw tree and print
all devices (nodes?) and their properties.

Be warned that using the -n option (intended for doing things like
"walkopenfirm -n /pci@f2000000" will actually crash the system if you
don't feed it an exactly correct OFW path. I don't recommend it. I
also think this is a bug, but I don't even know whose bug it is
yet....

        - Nathan


--=-=-=
Content-Disposition: attachment; filename=walkopenfirm.c


#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>

#include <sys/ioctl.h>
#include <dev/ofw/openfirmio.h>

#define OFWPATH "/dev/openfirm"

#define BUFSIZE 16384

static void usage(void);
void walkdev(int fd, char *name);
void walknode(int fd, int nodeid, int level);
void printprop(struct ofiocdesc *node, int level);

int
main(int argc, char *argv[])
{
	int ofwfd;
	char startnode[256];
	int ch;
	extern char *optarg;
	extern int optind;

	strcpy(startnode, "/");
	while((ch = getopt(argc, argv, "n:")) != -1)
		switch (ch) {
		case 'n':
			strcpy(startnode, optarg);
			break;
		case '?':
		default: 
			usage();
		}
	
	argc += optind;
	argv -= optind;

	ofwfd = open(OFWPATH, O_RDONLY, 0);
	if (ofwfd == -1)
		err(EXIT_FAILURE, "Couldn't open %s", OFWPATH);

	walkdev(ofwfd, startnode);

	close(ofwfd);

	return 0;

}

void
walkdev(int fd, char *name)
{
	struct ofiocdesc node;
	int ret;

	node.of_nodeid = 0;
	node.of_name = name;
	node.of_namelen = strlen(name);

	ret = ioctl(fd, OFIOCFINDDEVICE, &node);
	if (ret == -1)
		err(EXIT_FAILURE, "Couldn't find start node %s", name);
	
	walknode(fd, node.of_nodeid, 0);
	
}

void
walknode(int fd, int nodeid, int level)
{
	struct ofiocdesc ofc;
	char buf1[BUFSIZE], buf2[BUFSIZE];
	char *swap;
	int childnodeid;
	int ret;

	ofc.of_namelen = BUFSIZE;
	ofc.of_name = buf1;
	ofc.of_buf = buf2;


	while (nodeid != 0) {
		/* Get information about the node */
		ofc.of_nodeid = nodeid;
		strcpy(ofc.of_name, "name");
		ofc.of_namelen = strlen(ofc.of_name);

		ofc.of_buflen = BUFSIZE;
		ret = ioctl(fd, OFIOCGET, &ofc);
		if (ret == -1)
			err(EXIT_FAILURE, "Couldn't get name of %x", nodeid);
		printf("%*sNode %s\n", 
		    level, "", ofc.of_buf);

		/* Get all the properties */
		ofc.of_buflen = BUFSIZE;
		while (ioctl(fd, OFIOCNEXTPROP, &ofc) == 0) {
			ofc.of_buf[ofc.of_buflen] = '\0';
			printf("%*s  Property %-30s\n", level, "", 
			    ofc.of_buf);
			swap = ofc.of_name;
			ofc.of_name = ofc.of_buf;
			ofc.of_namelen = ofc.of_buflen;
			ofc.of_buf = swap;
			ofc.of_buflen = BUFSIZE;
			
			ret = ioctl(fd, OFIOCGET, &ofc);
			if (ret == -1)
				err(EXIT_FAILURE, "Couldn't get value "
				    "of property %s", ofc.of_name);
			printprop(&ofc, level);
					
			ofc.of_buflen = BUFSIZE;
		}
		if (errno != ENOENT)
			err(EXIT_FAILURE, "Error getting next property");

		/* Find the child pointer and walk it */
		childnodeid = nodeid;
		ret = ioctl(fd, OFIOCGETCHILD, &childnodeid);
		if (ret == -1)
			err(EXIT_FAILURE, "Couldn't get child of %x", nodeid);

		if (childnodeid != 0)
			walknode(fd, childnodeid, level + 2);

		/* Find the next sibling */
		ret = ioctl(fd, OFIOCGETNEXT, &nodeid);
		if (ret == -1)
			err(EXIT_FAILURE, "Couldn't get sibling of %x", 
			    nodeid);
	}

}

void
printprop(struct ofiocdesc *node, int level)
{
	int i, j;
	char strbuf[17];

	strbuf[16] = '\0';
	for (i = 0; i < node->of_buflen; i += 16) {
		printf("%*s", level + 2, "");
		for (j = 0; j < 16; j++) {
			if ((j % 4) == 0)
				printf(" ");
			if (i + j < node->of_buflen) {
				printf("%02x", node->of_buf[i+j]);
				strbuf[j] = isprint(node->of_buf[i+j]) ?
				    node->of_buf[i+j] : '.';
			} else {
				printf("  ");
				strbuf[j] = ' ';
			}

		}
		printf(" %s\n", strbuf);
	}
}


static void
usage(void)
{
	fprintf(stderr, "usage: walkopenfirm [-n startnode]\n");
	exit(1);
}


--=-=-=--