ofctl can write its OFW tree to a proplib. (reading from a proplib doesn't

quite work yet).
This commit is contained in:
matt 2007-06-03 03:01:41 +00:00
parent c75253c460
commit 91d658881f
2 changed files with 146 additions and 60 deletions

View File

@ -1,5 +1,5 @@
# from: @(#)Makefile 5.8 (Berkeley) 7/28/90
# $NetBSD: Makefile,v 1.3 2007/05/25 18:27:25 macallan Exp $
# $NetBSD: Makefile,v 1.4 2007/06/03 03:01:41 matt Exp $
.if ${MACHINE} == "sparc64" || ${MACHINE} == "macppc" || ${MACHINE} == "shark" \
|| ${MACHINE} == "sparc"
@ -8,6 +8,9 @@ PROG= ofctl
SRCS= ofctl.c
LDADD+= -lprop
DPADD+= ${LIBPROP}
.endif
MAN= ofctl.8

View File

@ -1,4 +1,4 @@
/* $NetBSD: ofctl.c,v 1.3 2007/05/25 18:27:05 macallan Exp $ */
/* $NetBSD: ofctl.c,v 1.4 2007/06/03 03:01:41 matt Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
@ -46,6 +46,8 @@
#include <sys/queue.h>
#include <dev/ofw/openfirmio.h>
#include <prop/proplib.h>
static void oflist(int, const char *, int, void *, size_t);
static void ofprop(int);
static void ofgetprop(int, char *);
@ -78,6 +80,7 @@ struct of_prop {
struct of_node of_root;
unsigned long of_node_count;
unsigned long of_prop_count;
prop_dictionary_t of_proplib;
int OF_parent(int);
int OF_child(int);
@ -90,14 +93,19 @@ int OF_nextprop(int, char *, void *);
struct of_prop *of_tree_getprop(int, char *);
static void
of_tree_mkprop(int fd, struct of_node *node, char *name)
of_tree_mkprop(struct of_node *node, prop_dictionary_t propdict,
prop_dictionary_keysym_t key)
{
struct ofiocdesc ofio;
struct of_prop *prop;
prop_data_t obj;
const char *name;
name = prop_dictionary_keysym_cstring_nocopy(key);
obj = prop_dictionary_get_keysym(propdict, key);
prop = malloc(sizeof(*prop) + strlen(name) + 1);
if (prop == NULL)
err(1, "malloc(%lu)", (unsigned long) sizeof(*prop));
err(1, "malloc(%zu)", sizeof(*prop) + strlen(name) + 1);
memset(prop, 0, sizeof(*prop));
prop->prop_name = (char *) (prop + 1);
@ -114,47 +122,24 @@ of_tree_mkprop(int fd, struct of_node *node, char *name)
of_prop_count++;
ofio.of_nodeid = node->of_nodeid;
ofio.of_name = name;
ofio.of_namelen = prop->prop_namelen;
ofio.of_buf = NULL;
ofio.of_buflen = 32;
again:
if (ofio.of_buf != NULL)
free(ofio.of_buf);
ofio.of_buf = malloc(ofio.of_buflen);
if (ofio.of_buf == NULL)
err(1, "malloc(%lu)", (unsigned long) ofio.of_buflen);
if (ioctl(fd, OFIOCGET, &ofio) < 0) {
if (errno == ENOMEM) {
ofio.of_buflen *= 2;
goto again;
}
warn("OFIOCGET(%d, \"%s\")", fd, name);
prop->prop_data = NULL;
prop->prop_length = 0;
free(ofio.of_buf);
return;
}
prop->prop_data = (u_int8_t *)ofio.of_buf;
prop->prop_length = ofio.of_buflen;
prop->prop_length = prop_data_size(obj);
if (prop->prop_length)
prop->prop_data = prop_data_data(obj);
}
static struct of_node *
of_tree_mknode(struct of_node *parent, int nodeid)
of_tree_mknode(struct of_node *parent)
{
struct of_node *newnode;
newnode = malloc(sizeof(*newnode));
if (newnode == NULL)
err(1, "malloc(%lu)", (unsigned long) sizeof(*newnode));
err(1, "malloc(%zu)", sizeof(*newnode));
of_node_count++;
memset(newnode, 0, sizeof(*newnode));
TAILQ_INIT(&newnode->of_children);
TAILQ_INIT(&newnode->of_properties);
newnode->of_nodeid = nodeid;
newnode->of_parent = parent;
TAILQ_INSERT_TAIL(&parent->of_children, newnode, of_sibling);
@ -163,20 +148,102 @@ of_tree_mknode(struct of_node *parent, int nodeid)
}
static void
of_tree_fill(int fd, struct of_node *node)
of_tree_fill(prop_dictionary_t dict, struct of_node *node)
{
int childid = node->of_nodeid;
prop_dictionary_t propdict;
prop_array_t propkeys;
prop_array_t children;
unsigned int i, count;
node->of_nodeid = prop_number_unsigned_integer_value(
prop_dictionary_get(dict, "node"));
propdict = prop_dictionary_get(dict, "properties");
propkeys = prop_dictionary_all_keys(propdict);
count = prop_array_count(propkeys);
for (i = 0; i < count; i++)
of_tree_mkprop(node, propdict, prop_array_get(propkeys, i));
children = prop_dictionary_get(dict, "children");
if (children) {
count = prop_array_count(children);
for (i = 0; i < count; i++) {
of_tree_fill(
prop_array_get(children, i),
of_tree_mknode(node));
}
}
}
static void
of_tree_init(prop_dictionary_t dict)
{
/*
* Initialize the root node of the OFW tree.
*/
TAILQ_INIT(&of_root.of_children);
TAILQ_INIT(&of_root.of_properties);
of_tree_fill(dict, &of_root);
}
static prop_object_t
of_proplib_mkprop(int fd, int nodeid, char *name)
{
struct ofiocdesc ofio;
prop_object_t obj;
ofio.of_nodeid = nodeid;
ofio.of_name = name;
ofio.of_namelen = strlen(name);
ofio.of_buf = NULL;
ofio.of_buflen = 32;
again:
if (ofio.of_buf != NULL)
free(ofio.of_buf);
ofio.of_buf = malloc(ofio.of_buflen);
if (ofio.of_buf == NULL)
err(1, "malloc(%zu)", ofio.of_buflen);
if (ioctl(fd, OFIOCGET, &ofio) < 0) {
if (errno == ENOMEM) {
ofio.of_buflen *= 2;
goto again;
}
warn("OFIOCGET(%d, \"%s\")", fd, name);
free(ofio.of_buf);
return NULL;
}
obj = prop_data_create_data(ofio.of_buf, ofio.of_buflen);
free(ofio.of_buf);
return obj;
}
static prop_dictionary_t
of_proplib_tree_fill(int fd, int nodeid)
{
int childid = nodeid;
struct ofiocdesc ofio;
char namebuf[33];
char newnamebuf[33];
prop_array_t children;
prop_dictionary_t dict, propdict;
prop_object_t obj;
ofio.of_nodeid = node->of_nodeid;
ofio.of_nodeid = nodeid;
ofio.of_name = namebuf;
ofio.of_namelen = 1;
ofio.of_buf = newnamebuf;
namebuf[0] = '\0';
dict = prop_dictionary_create();
prop_dictionary_set(dict, "node",
prop_number_create_unsigned_integer(nodeid));
propdict = prop_dictionary_create();
for (;;) {
ofio.of_buflen = sizeof(newnamebuf);
@ -192,36 +259,48 @@ of_tree_fill(int fd, struct of_node *node)
break;
newnamebuf[ofio.of_buflen] = '\0';
strcpy(namebuf, newnamebuf);
of_tree_mkprop(fd, node, namebuf);
obj = of_proplib_mkprop(fd, nodeid, namebuf);
if (obj)
prop_dictionary_set(propdict, namebuf, obj);
}
prop_dictionary_set(dict, "properties", propdict);
if (ioctl(fd, OFIOCGETCHILD, &childid) < 0)
err(1, "OFIOCGETCHILD(%d, %#x)", fd, childid);
children = NULL;
while (childid != 0) {
of_tree_fill(fd, of_tree_mknode(node, childid));
if (children == NULL)
children = prop_array_create();
prop_array_add(children, of_proplib_tree_fill(fd, childid));
if (ioctl(fd, OFIOCGETNEXT, &childid) < 0)
err(1, "OFIOCGETNEXT(%d, %#x)", fd, childid);
}
if (children != NULL) {
prop_array_make_immutable(children);
prop_dictionary_set(dict, "children", children);
}
return dict;
}
static void
of_tree_init(int fd)
static prop_dictionary_t
of_proplib_init(const char *file)
{
prop_dictionary_t dict;
int rootid = 0;
int fd;
fd = open(file, O_RDONLY);
if (fd < 0)
err(1, "%s", file);
if (ioctl(fd, OFIOCGETNEXT, &rootid) < 0)
err(1, "OFIOCGETNEXT(%d, %#x)", fd, rootid);
/*
* Initialize the root node of the OFW tree.
*/
TAILQ_INIT(&of_root.of_children);
TAILQ_INIT(&of_root.of_properties);
of_root.of_nodeid = rootid;
of_tree_fill(fd, &of_root);
dict = of_proplib_tree_fill(fd, rootid);
close(fd);
return dict;
}
static struct of_node *
@ -396,7 +475,6 @@ main(int argc, char **argv)
u_long of_buf[256];
char device_type[33];
int phandle;
int fd;
int errflag = 0;
int c;
int len;
@ -405,26 +483,32 @@ main(int argc, char **argv)
#else
const char *file = "/dev/openfirm";
#endif
const char *propfilein = NULL;
const char *propfileout = NULL;
while ((c = getopt(argc, argv, "f:lp")) != EOF) {
while ((c = getopt(argc, argv, "f:lpr:w:")) != EOF) {
switch (c) {
case 'l': lflag++; break;
case 'p': pflag++; break;
case 'f': file = optarg; break;
case 'r': propfilein = optarg; break;
case 'w': propfileout = optarg; break;
default: errflag++; break;
}
}
if (errflag)
#if 0
errx(1, "usage: ofctl [-lp] [-f file] [node...]\n");
#else
errx(1, "usage: ofctl [-p] [-f file] [node...]\n");
#endif
fd = open(file, O_RDONLY);
if (fd < 0)
err(1, "%s", file);
errx(1, "usage: ofctl [-pl] [-f file] [-r propfile] [-w propfile] [node...]\n");
of_tree_init(fd);
if (propfilein != NULL) {
of_proplib = prop_dictionary_internalize_from_file(propfilein);
} else {
of_proplib = of_proplib_init(file);
}
if (propfileout)
prop_dictionary_externalize_to_file(of_proplib, propfileout);
of_tree_init(of_proplib);
printf("[Caching %lu nodes and %lu properties]\n",
of_node_count, of_prop_count);
@ -457,7 +541,6 @@ main(int argc, char **argv)
printf("%s: OF_finddevice not yet implemented\n", argv[optind]);
#endif
}
close(fd);
exit(0);
}