/trunk/kernel/genarch/include/ofw/ofw_tree.h |
---|
30,6 → 30,7 |
#define KERN_OFW_TREE_H_ |
#include <arch/types.h> |
#include <typedefs.h> |
#define OFW_TREE_PROPERTY_MAX_NAMELEN 32 |
42,6 → 43,8 |
ofw_tree_node_t *peer; |
ofw_tree_node_t *child; |
char *da_name; /**< Disambigued name. */ |
unsigned properties; /**< Number of properties. */ |
ofw_tree_property_t *property; |
}; |
53,4 → 56,9 |
void *value; |
}; |
extern void ofw_tree_init(ofw_tree_node_t *root); |
extern void ofw_tree_print(void); |
extern const char *ofw_tree_node_name(const ofw_tree_node_t *node); |
extern ofw_tree_node_t *ofw_tree_lookup(const char *path); |
#endif |
/trunk/kernel/genarch/Makefile.inc |
---|
92,5 → 92,5 |
## OpenFirmware Device Tree |
ifeq ($(CONFIG_OFW_TREE), y) |
GENARCH_SOURCES += \ |
genarch/src/ofw/ofw_tree,c |
genarch/src/ofw/ofw_tree.c |
endif |
/trunk/kernel/genarch/src/ofw/ofw_tree.c |
---|
35,5 → 35,120 |
* |
*/ |
#include <genarch/ofw/ofw_tree.h> |
#include <arch/memstr.h> |
#include <func.h> |
#include <print.h> |
#include <panic.h> |
#define PATH_MAX_LEN 80 |
#define NAME_BUF_LEN 50 |
static ofw_tree_node_t *ofw_root; |
void ofw_tree_init(ofw_tree_node_t *root) |
{ |
ofw_root = root; |
} |
/** Return value of the 'name' property. |
* |
* @param node Node of interest. |
* |
* @return Value of the 'name' property belonging to the node. |
*/ |
const char *ofw_tree_node_name(const ofw_tree_node_t *node) |
{ |
int i; |
for (i = 0; i < node->properties; i++) { |
if (strncmp(node->property[i].name, "name", strlen("name")) == 0) { |
if (node->property[i].size < 2) |
panic("Invalid name property.\n"); |
return node->property[i].value; |
} |
} |
panic("Node without name property.\n"); |
} |
/** Lookup child of given name. |
* |
* @param node Node whose child is being looked up. |
* @param da_name Disambigued name of the child being looked up. |
* |
* @return NULL if there is no such child or pointer to the matching child node. |
*/ |
static ofw_tree_node_t *ofw_tree_find_child(ofw_tree_node_t *node, const char *da_name) |
{ |
ofw_tree_node_t *cur; |
for (cur = node->child; cur; cur = cur->peer) { |
if (strncmp(cur->da_name, da_name, strlen(da_name)) == 0) |
return cur; |
} |
return NULL; |
} |
/** Lookup OpenFirmware node by its path. |
* |
* @param path Path to the node. |
* |
* @return NULL if there is no such node or pointer to the leaf node. |
*/ |
ofw_tree_node_t *ofw_tree_lookup(const char *path) |
{ |
char buf[NAME_BUF_LEN+1]; |
ofw_tree_node_t *node = ofw_root; |
index_t i, j; |
if (path[0] != '/') |
return NULL; |
for (i = 1; i < strlen(path) && node; i = j + 1) { |
for (j = i; j < strlen(path) && path[j] != '/'; j++) |
; |
if (i == j) /* skip extra slashes */ |
continue; |
memcpy(buf, &path[i], j - i); |
buf[j - i] = '\0'; |
node = ofw_tree_find_child(node, buf); |
} |
return node; |
} |
/** Recursively print subtree rooted in a node. |
* |
* @param node Root of the subtree. |
* @param path Current path, NULL for the very root of the entire tree. |
*/ |
static void ofw_tree_node_print(const ofw_tree_node_t *node, const char *path) |
{ |
char p[PATH_MAX_LEN]; |
if (node->parent) { |
snprintf(p, PATH_MAX_LEN, "%s/%s", path, node->da_name); |
printf("%s\n", p); |
} else { |
snprintf(p, PATH_MAX_LEN, "%s", node->da_name); |
printf("/\n"); |
} |
if (node->child) |
ofw_tree_node_print(node->child, p); |
if (node->peer) |
ofw_tree_node_print(node->peer, path); |
} |
/** Print the structure of the OpenFirmware device tree. */ |
void ofw_tree_print(void) |
{ |
ofw_tree_node_print(ofw_root, NULL); |
} |
/** @} |
*/ |
/trunk/kernel/arch/sparc64/Makefile.inc |
---|
60,7 → 60,11 |
CONFIG_FB = y |
## Compile with support for OpenFirmware device tree. |
# |
CONFIG_OFW_TREE = y |
ifeq ($(MACHINE),enterprise) |
## Compile with support for z8530 controller. |
# |
/trunk/kernel/arch/sparc64/src/sparc64.c |
---|
45,6 → 45,7 |
#include <arch/asm.h> |
#include <arch/mm/page.h> |
#include <arch/stack.h> |
#include <genarch/ofw/ofw_tree.h> |
#include <userspace.h> |
bootinfo_t bootinfo; |
64,6 → 65,8 |
/* Copy boot allocations info. */ |
ballocs.base = bootinfo.ballocs.base; |
ballocs.size = bootinfo.ballocs.size; |
ofw_tree_init(bootinfo.ofw_root); |
} |
void arch_pre_mm_init(void) |
/trunk/boot/genarch/ofw_tree.h |
---|
43,6 → 43,8 |
ofw_tree_node_t *peer; |
ofw_tree_node_t *child; |
char *da_name; /**< Disambigued name. */ |
unsigned properties; /**< Number of properties. */ |
ofw_tree_property_t *property; |
}; |
/trunk/boot/genarch/ofw.h |
---|
102,7 → 102,7 |
extern void ofw_write(const char *str, const int len); |
extern int ofw_get_property(const phandle device, const char *name, const void *buf, const int buflen); |
extern int ofw_get_property(const phandle device, const char *name, void *buf, const int buflen); |
extern int ofw_get_proplen(const phandle device, const char *name); |
extern int ofw_next_property(const phandle device, char *previous, char *buf); |
110,6 → 110,8 |
extern phandle ofw_get_peer_node(const phandle node); |
extern phandle ofw_find_device(const char *name); |
extern int ofw_package_to_path(const phandle device, char *buf, const int buflen); |
extern int ofw(ofw_args_t *arg); |
extern unsigned int ofw_get_address_cells(const phandle device); |
extern unsigned int ofw_get_size_cells(const phandle device); |
/trunk/boot/genarch/ofw_tree.c |
---|
31,7 → 31,10 |
#include <types.h> |
#include <string.h> |
#include <balloc.h> |
#include <asm.h> |
#define MAX_PATH_LEN 256 |
static ofw_tree_node_t *ofw_tree_node_alloc(void) |
{ |
return balloc(sizeof(ofw_tree_node_t), sizeof(ofw_tree_node_t)); |
61,10 → 64,13 |
static void ofw_tree_node_process(ofw_tree_node_t *current_node, |
ofw_tree_node_t *parent_node, phandle current) |
{ |
static char path[MAX_PATH_LEN+1]; |
static char name[OFW_TREE_PROPERTY_MAX_NAMELEN]; |
phandle peer; |
phandle child; |
unsigned properties = 0; |
char name[OFW_TREE_PROPERTY_MAX_NAMELEN]; |
size_t len; |
int i; |
/* |
* Initialize node. |
76,6 → 82,26 |
current_node->property = NULL; |
/* |
* Get the disambigued name. |
*/ |
len = ofw_package_to_path(current, path, MAX_PATH_LEN); |
if (len == -1) |
return; |
path[len] = '\0'; |
for (i = len - 1; i >= 0 && path[i] != '/'; i--) |
; |
i++; /* do not include '/' */ |
len -= i; |
current_node->da_name = ofw_tree_space_alloc(len + 1); /* add space for trailing '\0' */ |
if (!current_node->da_name) |
return; |
memcpy(current_node->da_name, &path[i], len); |
current_node->da_name[len] = '\0'; |
/* |
* Recursively process the potential peer node. |
*/ |
peer = ofw_get_peer_node(current); |
84,7 → 110,7 |
peer_node = ofw_tree_node_alloc(); |
if (peer_node) { |
ofw_tree_node_process(peer_node, current_node, peer); |
ofw_tree_node_process(peer_node, parent_node, peer); |
current_node->peer = peer_node; |
} |
} |
120,8 → 146,6 |
if (!current_node->property) |
return; |
int i = 0; |
name[0] = '\0'; |
for (i = 0; ofw_next_property(current, name, name) == 1; i++) { |
size_t size; |
/trunk/boot/genarch/ofw.c |
---|
114,7 → 114,7 |
return ofw_call("finddevice", 1, 1, NULL, name); |
} |
int ofw_get_property(const phandle device, const char *name, const void *buf, const int buflen) |
int ofw_get_property(const phandle device, const char *name, void *buf, const int buflen) |
{ |
return ofw_call("getprop", 4, 1, NULL, device, name, buf, buflen); |
} |
129,6 → 129,11 |
return ofw_call("nextprop", 3, 1, NULL, device, previous, buf); |
} |
int ofw_package_to_path(const phandle device, char *buf, const int buflen) |
{ |
return ofw_call("package-to-path", 3, 1, NULL, device, buf, buflen); |
} |
unsigned int ofw_get_address_cells(const phandle device) |
{ |
unsigned int ret = 1; |