Release 4.10 scripts/dtc/livetree.c
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include "dtc.h"
/*
* Tree building functions
*/
void add_label(struct label **labels, char *label)
{
struct label *new;
/* Make sure the label isn't already there */
for_each_label_withdel(*labels, new)
if (streq(new->label, label)) {
new->deleted = 0;
return;
}
new = xmalloc(sizeof(*new));
memset(new, 0, sizeof(*new));
new->label = label;
new->next = *labels;
*labels = new;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
john bonesio | john bonesio | 67 | 75.28% | 1 | 50.00% |
stephen warren | stephen warren | 22 | 24.72% | 1 | 50.00% |
| Total | 89 | 100.00% | 2 | 100.00% |
void delete_labels(struct label **labels)
{
struct label *label;
for_each_label(*labels, label)
label->deleted = 1;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
stephen warren | stephen warren | 28 | 100.00% | 1 | 100.00% |
| Total | 28 | 100.00% | 1 | 100.00% |
struct property *build_property(char *name, struct data val)
{
struct property *new = xmalloc(sizeof(*new));
memset(new, 0, sizeof(*new));
new->name = name;
new->val = val;
return new;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david gibson | david gibson | 44 | 77.19% | 1 | 50.00% |
john bonesio | john bonesio | 13 | 22.81% | 1 | 50.00% |
| Total | 57 | 100.00% | 2 | 100.00% |
struct property *build_property_delete(char *name)
{
struct property *new = xmalloc(sizeof(*new));
memset(new, 0, sizeof(*new));
new->name = name;
new->deleted = 1;
return new;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
stephen warren | stephen warren | 53 | 100.00% | 1 | 100.00% |
| Total | 53 | 100.00% | 1 | 100.00% |
struct property *chain_property(struct property *first, struct property *list)
{
assert(first->next == NULL);
first->next = list;
return first;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david gibson | david gibson | 35 | 100.00% | 1 | 100.00% |
| Total | 35 | 100.00% | 1 | 100.00% |
struct property *reverse_properties(struct property *first)
{
struct property *p = first;
struct property *head = NULL;
struct property *next;
while (p) {
next = p->next;
p->next = head;
head = p;
p = next;
}
return head;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david gibson | david gibson | 60 | 100.00% | 1 | 100.00% |
| Total | 60 | 100.00% | 1 | 100.00% |
struct node *build_node(struct property *proplist, struct node *children)
{
struct node *new = xmalloc(sizeof(*new));
struct node *child;
memset(new, 0, sizeof(*new));
new->proplist = reverse_properties(proplist);
new->children = children;
for_each_child(new, child) {
child->parent = new;
}
return new;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david gibson | david gibson | 81 | 100.00% | 1 | 100.00% |
| Total | 81 | 100.00% | 1 | 100.00% |
struct node *build_node_delete(void)
{
struct node *new = xmalloc(sizeof(*new));
memset(new, 0, sizeof(*new));
new->deleted = 1;
return new;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
stephen warren | stephen warren | 45 | 100.00% | 1 | 100.00% |
| Total | 45 | 100.00% | 1 | 100.00% |
struct node *name_node(struct node *node, char *name)
{
assert(node->name == NULL);
node->name = name;
return node;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david gibson | david gibson | 34 | 100.00% | 1 | 100.00% |
| Total | 34 | 100.00% | 1 | 100.00% |
struct node *merge_nodes(struct node *old_node, struct node *new_node)
{
struct property *new_prop, *old_prop;
struct node *new_child, *old_child;
struct label *l;
old_node->deleted = 0;
/* Add new node labels to old node */
for_each_label_withdel(new_node->labels, l)
add_label(&old_node->labels, l->label);
/* Move properties from the new node to the old node. If there
* is a collision, replace the old value with the new */
while (new_node->proplist) {
/* Pop the property off the list */
new_prop = new_node->proplist;
new_node->proplist = new_prop->next;
new_prop->next = NULL;
if (new_prop->deleted) {
delete_property_by_name(old_node, new_prop->name);
free(new_prop);
continue;
}
/* Look for a collision, set new value if there is */
for_each_property_withdel(old_node, old_prop) {
if (streq(old_prop->name, new_prop->name)) {
/* Add new labels to old property */
for_each_label_withdel(new_prop->labels, l)
add_label(&old_prop->labels, l->label);
old_prop->val = new_prop->val;
old_prop->deleted = 0;
free(new_prop);
new_prop = NULL;
break;
}
}
/* if no collision occurred, add property to the old node. */
if (new_prop)
add_property(old_node, new_prop);
}
/* Move the override child nodes into the primary node. If
* there is a collision, then merge the nodes. */
while (new_node->children) {
/* Pop the child node off the list */
new_child = new_node->children;
new_node->children = new_child->next_sibling;
new_child->parent = NULL;
new_child->next_sibling = NULL;
if (new_child->deleted) {
delete_node_by_name(old_node, new_child->name);
free(new_child);
continue;
}
/* Search for a collision. Merge if there is */
for_each_child_withdel(old_node, old_child) {
if (streq(old_child->name, new_child->name)) {
merge_nodes(old_child, new_child);
new_child = NULL;
break;
}
}
/* if no collision occured, add child to the old node. */
if (new_child)
add_child(old_node, new_child);
}
/* The new node contents are now merged into the old node. Free
* the new node. */
free(new_node);
return old_node;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
john bonesio | john bonesio | 186 | 59.81% | 1 | 25.00% |
stephen warren | stephen warren | 63 | 20.26% | 1 | 25.00% |
david gibson | david gibson | 62 | 19.94% | 2 | 50.00% |
| Total | 311 | 100.00% | 4 | 100.00% |
struct node *chain_node(struct node *first, struct node *list)
{
assert(first->next_sibling == NULL);
first->next_sibling = list;
return first;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david gibson | david gibson | 29 | 82.86% | 1 | 50.00% |
john bonesio | john bonesio | 6 | 17.14% | 1 | 50.00% |
| Total | 35 | 100.00% | 2 | 100.00% |
void add_property(struct node *node, struct property *prop)
{
struct property **p;
prop->next = NULL;
p = &node->proplist;
while (*p)
p = &((*p)->next);
*p = prop;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
john bonesio | john bonesio | 32 | 57.14% | 1 | 50.00% |
david gibson | david gibson | 24 | 42.86% | 1 | 50.00% |
| Total | 56 | 100.00% | 2 | 100.00% |
void delete_property_by_name(struct node *node, char *name)
{
struct property *prop = node->proplist;
while (prop) {
if (!strcmp(prop->name, name)) {
delete_property(prop);
return;
}
prop = prop->next;
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
stephen warren | stephen warren | 55 | 100.00% | 1 | 100.00% |
| Total | 55 | 100.00% | 1 | 100.00% |
void delete_property(struct property *prop)
{
prop->deleted = 1;
delete_labels(&prop->labels);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
stephen warren | stephen warren | 24 | 100.00% | 1 | 100.00% |
| Total | 24 | 100.00% | 1 | 100.00% |
void add_child(struct node *parent, struct node *child)
{
struct node **p;
child->next_sibling = NULL;
child->parent = parent;
p = &parent->children;
while (*p)
p = &((*p)->next_sibling);
*p = child;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
john bonesio | john bonesio | 45 | 72.58% | 1 | 50.00% |
david gibson | david gibson | 17 | 27.42% | 1 | 50.00% |
| Total | 62 | 100.00% | 2 | 100.00% |
void delete_node_by_name(struct node *parent, char *name)
{
struct node *node = parent->children;
while (node) {
if (!strcmp(node->name, name)) {
delete_node(node);
return;
}
node = node->next_sibling;
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
stephen warren | stephen warren | 55 | 100.00% | 1 | 100.00% |
| Total | 55 | 100.00% | 1 | 100.00% |
void delete_node(struct node *node)
{
struct property *prop;
struct node *child;
node->deleted = 1;
for_each_child(node, child)
delete_node(child);
for_each_property(node, prop)
delete_property(prop);
delete_labels(&node->labels);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
stephen warren | stephen warren | 56 | 100.00% | 1 | 100.00% |
| Total | 56 | 100.00% | 1 | 100.00% |
struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
{
struct reserve_info *new = xmalloc(sizeof(*new));
memset(new, 0, sizeof(*new));
new->re.address = address;
new->re.size = size;
return new;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
john bonesio | john bonesio | 59 | 100.00% | 1 | 100.00% |
| Total | 59 | 100.00% | 1 | 100.00% |
struct reserve_info *chain_reserve_entry(struct reserve_info *first,
struct reserve_info *list)
{
assert(first->next == NULL);
first->next = list;
return first;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
john bonesio | john bonesio | 35 | 100.00% | 1 | 100.00% |
| Total | 35 | 100.00% | 1 | 100.00% |
struct reserve_info *add_reserve_entry(struct reserve_info *list,
struct reserve_info *new)
{
struct reserve_info *last;
new->next = NULL;
if (! list)
return new;
for (last = list; last->next; last = last->next)
;
last->next = new;
return list;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
john bonesio | john bonesio | 62 | 100.00% | 1 | 100.00% |
| Total | 62 | 100.00% | 1 | 100.00% |
struct boot_info *build_boot_info(struct reserve_info *reservelist,
struct node *tree, uint32_t boot_cpuid_phys)
{
struct boot_info *bi;
bi = xmalloc(sizeof(*bi));
bi->reservelist = reservelist;
bi->dt = tree;
bi->boot_cpuid_phys = boot_cpuid_phys;
return bi;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
john bonesio | john bonesio | 46 | 80.70% | 1 | 33.33% |
david gibson | david gibson | 11 | 19.30% | 2 | 66.67% |
| Total | 57 | 100.00% | 3 | 100.00% |
/*
* Tree accessor functions
*/
const char *get_unitname(struct node *node)
{
if (node->name[node->basenamelen] == '\0')
return "";
else
return node->name + node->basenamelen + 1;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david gibson | david gibson | 40 | 100.00% | 1 | 100.00% |
| Total | 40 | 100.00% | 1 | 100.00% |
struct property *get_property(struct node *node, const char *propname)
{
struct property *prop;
for_each_property(node, prop)
if (streq(prop->name, propname))
return prop;
return NULL;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david gibson | david gibson | 45 | 100.00% | 1 | 100.00% |
| Total | 45 | 100.00% | 1 | 100.00% |
cell_t propval_cell(struct property *prop)
{
assert(prop->val.len == sizeof(cell_t));
return fdt32_to_cpu(*((cell_t *)prop->val.val));
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david gibson | david gibson | 41 | 100.00% | 2 | 100.00% |
| Total | 41 | 100.00% | 2 | 100.00% |
struct property *get_property_by_label(struct node *tree, const char *label,
struct node **node)
{
struct property *prop;
struct node *c;
*node = tree;
for_each_property(tree, prop) {
struct label *l;
for_each_label(prop->labels, l)
if (streq(l->label, label))
return prop;
}
for_each_child(tree, c) {
prop = get_property_by_label(c, label, node);
if (prop)
return prop;
}
*node = NULL;
return NULL;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
john bonesio | john bonesio | 95 | 90.48% | 1 | 50.00% |
david gibson | david gibson | 10 | 9.52% | 1 | 50.00% |
| Total | 105 | 100.00% | 2 | 100.00% |
struct marker *get_marker_label(struct node *tree, const char *label,
struct node **node, struct property **prop)
{
struct marker *m;
struct property *p;
struct node *c;
*node = tree;
for_each_property(tree, p) {
*prop = p;
m = p->val.markers;
for_each_marker_of_type(m, LABEL)
if (streq(m->ref, label))
return m;
}
for_each_child(tree, c) {
m = get_marker_label(c, label, node, prop);
if (m)
return m;
}
*prop = NULL;
*node = NULL;
return NULL;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
john bonesio | john bonesio | 131 | 100.00% | 1 | 100.00% |
| Total | 131 | 100.00% | 1 | 100.00% |
struct node *get_subnode(struct node *node, const char *nodename)
{
struct node *child;
for_each_child(node, child)
if (streq(child->name, nodename))
return child;
return NULL;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david gibson | david gibson | 29 | 64.44% | 1 | 50.00% |
john bonesio | john bonesio | 16 | 35.56% | 1 | 50.00% |
| Total | 45 | 100.00% | 2 | 100.00% |
struct node *get_node_by_path(struct node *tree, const char *path)
{
const char *p;
struct node *child;
if (!path || ! (*path)) {
if (tree->deleted)
return NULL;
return tree;
}
while (path[0] == '/')
path++;
p = strchr(path, '/');
for_each_child(tree, child) {
if (p && strneq(path, child->name, p-path))
return get_node_by_path(child, p+1);
else if (!p && streq(path, child->name))
return child;
}
return NULL;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david gibson | david gibson | 118 | 91.47% | 1 | 50.00% |
stephen warren | stephen warren | 11 | 8.53% | 1 | 50.00% |
| Total | 129 | 100.00% | 2 | 100.00% |
struct node *get_node_by_label(struct node *tree, const char *label)
{
struct node *child, *node;
struct label *l;
assert(label && (strlen(label) > 0));
for_each_label(tree->labels, l)
if (streq(l->label, label))
return tree;
for_each_child(tree, child) {
node = get_node_by_label(child, label);
if (node)
return node;
}
return NULL;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david gibson | david gibson | 79 | 86.81% | 1 | 50.00% |
john bonesio | john bonesio | 12 | 13.19% | 1 | 50.00% |
| Total | 91 | 100.00% | 2 | 100.00% |
struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
{
struct node *child, *node;
assert((phandle != 0) && (phandle != -1));
if (tree->phandle == phandle) {
if (tree->deleted)
return NULL;
return tree;
}
for_each_child(tree, child) {
node = get_node_by_phandle(child, phandle);
if (node)
return node;
}
return NULL;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david gibson | david gibson | 77 | 87.50% | 1 | 50.00% |
stephen warren | stephen warren | 11 | 12.50% | 1 | 50.00% |
| Total | 88 | 100.00% | 2 | 100.00% |
struct node *get_node_by_ref(struct node *tree, const char *ref)
{
if (streq(ref, "/"))
return tree;
else if (ref[0] == '/')
return get_node_by_path(tree, ref);
else
return get_node_by_label(tree, ref);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david gibson | david gibson | 43 | 76.79% | 1 | 50.00% |
rob herring | rob herring | 13 | 23.21% | 1 | 50.00% |
| Total | 56 | 100.00% | 2 | 100.00% |
cell_t get_node_phandle(struct node *root, struct node *node)
{
static cell_t phandle = 1; /* FIXME: ick, static local */
if ((node->phandle != 0) && (node->phandle != -1))
return node->phandle;
while (get_node_by_phandle(root, phandle))
phandle++;
node->phandle = phandle;
if (!get_property(node, "linux,phandle")
&& (phandle_format & PHANDLE_LEGACY))
add_property(node,
build_property("linux,phandle",
data_append_cell(empty_data, phandle)));
if (!get_property(node, "phandle")
&& (phandle_format & PHANDLE_EPAPR))
add_property(node,
build_property("phandle",
data_append_cell(empty_data, phandle)));
/* If the node *does* have a phandle property, we must
* be dealing with a self-referencing phandle, which will be
* fixed up momentarily in the caller */
return node->phandle;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
david gibson | david gibson | 83 | 61.03% | 1 | 50.00% |
john bonesio | john bonesio | 53 | 38.97% | 1 | 50.00% |
| Total | 136 | 100.00% | 2 | 100.00% |
uint32_t guess_boot_cpuid(struct node *tree)
{
struct node *cpus, *bootcpu;
struct property *reg;
cpus = get_node_by_path(tree, "/cpus");
if (!cpus)
return 0;
bootcpu = cpus->children;
if (!bootcpu)
return 0;
reg = get_property(bootcpu, "reg");
if (!reg || (reg->val.len != sizeof(uint32_t)))
return 0;
/* FIXME: Sanity check node? */
return propval_cell(reg);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
john bonesio | john bonesio | 91 | 100.00% | 1 | 100.00% |
| Total | 91 | 100.00% | 1 | 100.00% |
static int cmp_reserve_info(const void *ax, const void *bx)
{
const struct reserve_info *a, *b;
a = *((const struct reserve_info * const *)ax);
b = *((const struct reserve_info * const *)bx);
if (a->re.address < b->re.address)
return -1;
else if (a->re.address > b->re.address)
return 1;
else if (a->re.size < b->re.size)
return -1;
else if (a->re.size > b->re.size)
return 1;
else
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
john bonesio | john bonesio | 132 | 100.00% | 1 | 100.00% |
| Total | 132 | 100.00% | 1 | 100.00% |
static void sort_reserve_entries(struct boot_info *bi)
{
struct reserve_info *ri, **tbl;
int n = 0, i = 0;
for (ri = bi->reservelist;
ri;
ri = ri->next)
n++;
if (n == 0)
return;
tbl = xmalloc(n * sizeof(*tbl));
for (ri = bi->reservelist;
ri;
ri = ri->next)
tbl[i++] = ri;
qsort(tbl, n, sizeof(*tbl), cmp_reserve_info);
bi->reservelist = tbl[0];
for (i = 0; i < (n-1); i++)
tbl[i]->next = tbl[i+1];
tbl[n-1]->next = NULL;
free(tbl);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
john bonesio | john bonesio | 163 | 100.00% | 1 | 100.00% |
| Total | 163 | 100.00% | 1 | 100.00% |
static int cmp_prop(const void *ax, const void *bx)
{
const struct property *a, *b;
a = *((const struct property * const *)ax);
b = *((const struct property * const *)bx);
return strcmp(a->name, b->name);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
john bonesio | john bonesio | 67 | 100.00% | 1 | 100.00% |
| Total | 67 | 100.00% | 1 | 100.00% |
static void sort_properties(struct node *node)
{
int n = 0, i = 0;
struct property *prop, **tbl;
for_each_property_withdel(node, prop)
n++;
if (n == 0)
return;
tbl = xmalloc(n * sizeof(*tbl));
for_each_property_withdel(node, prop)
tbl[i++] = prop;
qsort(tbl, n, sizeof(*tbl), cmp_prop);
node->proplist = tbl[0];
for (i = 0; i < (n-1); i++)
tbl[i]->next = tbl[i+1];
tbl[n-1]->next = NULL;
free(tbl);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
john bonesio | john bonesio | 141 | 98.60% | 1 | 50.00% |
stephen warren | stephen warren | 2 | 1.40% | 1 | 50.00% |
| Total | 143 | 100.00% | 2 | 100.00% |
static int cmp_subnode(const void *ax, const void *bx)
{
const struct node *a, *b;
a = *((const struct node * const *)ax);
b = *((const struct node * const *)bx);
return strcmp(a->name, b->name);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
john bonesio | john bonesio | 67 | 100.00% | 1 | 100.00% |
| Total | 67 | 100.00% | 1 | 100.00% |
static void sort_subnodes(struct node *node)
{
int n = 0, i = 0;
struct node *subnode, **tbl;
for_each_child_withdel(node, subnode)
n++;
if (n ==