HelenOS sources
This source file includes following definitions.
- ofw_tree_init
- ofw_tree_getprop
- ofw_tree_node_name
- ofw_tree_find_child
- ofw_tree_find_child_by_device_type
- ofw_tree_find_node_by_handle
- ofw_tree_find_peer_by_device_type
- ofw_tree_find_peer_by_name
- ofw_tree_lookup
- ofw_tree_walk_by_device_type_internal
- ofw_tree_walk_by_device_type
- ofw_sysinfo_properties
- ofw_tree_node_sysinfo
- ofw_sysinfo_map
#include <genarch/ofw/ofw_tree.h>
#include <stdlib.h>
#include <sysinfo/sysinfo.h>
#include <memw.h>
#include <str.h>
#include <panic.h>
#include <stdio.h>
#define PATH_MAX_LEN 256
#define NAME_BUF_LEN 50
static ofw_tree_node_t *ofw_root;
void ofw_tree_init(ofw_tree_node_t *root)
{
ofw_root = root;
}
ofw_tree_property_t *ofw_tree_getprop(const ofw_tree_node_t *node,
const char *name)
{
for (size_t i = 0; i < node->properties; i++) {
if (str_cmp(node->property[i].name, name) == 0)
return &node->property[i];
}
return NULL;
}
const char *ofw_tree_node_name(const ofw_tree_node_t *node)
{
ofw_tree_property_t *prop = ofw_tree_getprop(node, "name");
if ((!prop) || (prop->size < 2))
return NULL;
return prop->value;
}
ofw_tree_node_t *ofw_tree_find_child(ofw_tree_node_t *node,
const char *name)
{
for (ofw_tree_node_t *cur = node->child; cur; cur = cur->peer) {
if (str_cmp(cur->da_name, name) == 0)
return cur;
}
for (ofw_tree_node_t *cur = node->child; cur; cur = cur->peer) {
if (str_cmp(ofw_tree_node_name(cur), name) == 0)
return cur;
}
return NULL;
}
ofw_tree_node_t *ofw_tree_find_child_by_device_type(ofw_tree_node_t *node,
const char *dtype)
{
for (ofw_tree_node_t *cur = node->child; cur; cur = cur->peer) {
ofw_tree_property_t *prop =
ofw_tree_getprop(cur, "device_type");
if ((!prop) || (!prop->value))
continue;
if (str_cmp(prop->value, dtype) == 0)
return cur;
}
return NULL;
}
ofw_tree_node_t *ofw_tree_find_node_by_handle(ofw_tree_node_t *root,
phandle handle)
{
for (ofw_tree_node_t *cur = root; cur; cur = cur->peer) {
if (cur->node_handle == handle)
return cur;
if (cur->child) {
ofw_tree_node_t *node =
ofw_tree_find_node_by_handle(cur->child, handle);
if (node)
return node;
}
}
return NULL;
}
ofw_tree_node_t *ofw_tree_find_peer_by_device_type(ofw_tree_node_t *node,
const char *dtype)
{
for (ofw_tree_node_t *cur = node->peer; cur; cur = cur->peer) {
ofw_tree_property_t *prop =
ofw_tree_getprop(cur, "device_type");
if ((!prop) || (!prop->value))
continue;
if (str_cmp(prop->value, dtype) == 0)
return cur;
}
return NULL;
}
ofw_tree_node_t *ofw_tree_find_peer_by_name(ofw_tree_node_t *node,
const char *name)
{
for (ofw_tree_node_t *cur = node->peer; cur; cur = cur->peer) {
ofw_tree_property_t *prop =
ofw_tree_getprop(cur, "name");
if ((!prop) || (!prop->value))
continue;
if (str_cmp(prop->value, name) == 0)
return cur;
}
return NULL;
}
ofw_tree_node_t *ofw_tree_lookup(const char *path)
{
if (path[0] != '/')
return NULL;
ofw_tree_node_t *node = ofw_root;
size_t j;
for (size_t i = 1; (i < str_size(path)) && (node); i = j + 1) {
j = i;
while (j < str_size(path) && path[j] != '/')
j++;
if (i == j)
continue;
char buf[NAME_BUF_LEN + 1];
memcpy(buf, &path[i], j - i);
buf[j - i] = 0;
node = ofw_tree_find_child(node, buf);
}
return node;
}
static bool ofw_tree_walk_by_device_type_internal(ofw_tree_node_t *node,
const char *dtype, ofw_tree_walker_t walker, void *arg)
{
for (ofw_tree_node_t *cur = node; cur; cur = cur->peer) {
ofw_tree_property_t *prop =
ofw_tree_getprop(cur, "device_type");
if ((prop) && (prop->value) && (str_cmp(prop->value, dtype) == 0)) {
bool ret = walker(cur, arg);
if (!ret)
return false;
}
if (cur->child) {
bool ret =
ofw_tree_walk_by_device_type_internal(cur->child, dtype, walker, arg);
if (!ret)
return false;
}
}
return true;
}
void ofw_tree_walk_by_device_type(const char *dtype, ofw_tree_walker_t walker,
void *arg)
{
(void) ofw_tree_walk_by_device_type_internal(ofw_root, dtype, walker, arg);
}
static void *ofw_sysinfo_properties(struct sysinfo_item *item, size_t *size,
bool dry_run, void *data)
{
ofw_tree_node_t *node = (ofw_tree_node_t *) data;
*size = 0;
for (size_t i = 0; i < node->properties; i++)
*size += str_size(node->property[i].name) + 1 +
sizeof(node->property[i].size) + node->property[i].size;
if (dry_run)
return NULL;
void *dump = malloc(*size);
if (dump == NULL) {
*size = 0;
return NULL;
}
size_t pos = 0;
for (size_t i = 0; i < node->properties; i++) {
str_cpy(dump + pos, *size - pos, node->property[i].name);
pos += str_size(node->property[i].name) + 1;
memcpy(dump + pos, &node->property[i].size,
sizeof(node->property[i].size));
pos += sizeof(node->property[i].size);
memcpy(dump + pos, node->property[i].value,
node->property[i].size);
pos += node->property[i].size;
}
return ((void *) dump);
}
static void ofw_tree_node_sysinfo(ofw_tree_node_t *node, const char *path)
{
char *cur_path = malloc(PATH_MAX_LEN);
if (!cur_path)
panic("Not enough memory to process OFW tree.");
for (ofw_tree_node_t *cur = node; cur; cur = cur->peer) {
if ((cur->parent) && (path))
snprintf(cur_path, PATH_MAX_LEN, "%s.%s", path, cur->da_name);
else if (!str_size(cur->da_name))
snprintf(cur_path, PATH_MAX_LEN, "firmware.ofw");
else
snprintf(cur_path, PATH_MAX_LEN, "firmware.%s", cur->da_name);
sysinfo_set_item_gen_data(cur_path, NULL, ofw_sysinfo_properties,
(void *) cur);
if (cur->child)
ofw_tree_node_sysinfo(cur->child, cur_path);
}
free(cur_path);
}
void ofw_sysinfo_map(void)
{
ofw_tree_node_sysinfo(ofw_root, NULL);
}
HelenOS homepage, sources at GitHub