diff options
Diffstat (limited to 'scripts/dtc/livetree.c')
| -rw-r--r-- | scripts/dtc/livetree.c | 128 | 
1 files changed, 114 insertions, 14 deletions
diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c index 26d0e1e60c0..b61465fb2f3 100644 --- a/scripts/dtc/livetree.c +++ b/scripts/dtc/livetree.c @@ -29,16 +29,27 @@ void add_label(struct label **labels, char *label)  	struct label *new;  	/* Make sure the label isn't already there */ -	for_each_label(*labels, new) -		if (streq(new->label, label)) +	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;  } +void delete_labels(struct label **labels) +{ +	struct label *label; + +	for_each_label(*labels, label) +		label->deleted = 1; +} +  struct property *build_property(char *name, struct data val)  {  	struct property *new = xmalloc(sizeof(*new)); @@ -51,6 +62,18 @@ struct property *build_property(char *name, struct data val)  	return new;  } +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; +} +  struct property *chain_property(struct property *first, struct property *list)  {  	assert(first->next == NULL); @@ -91,6 +114,17 @@ struct node *build_node(struct property *proplist, struct node *children)  	return new;  } +struct node *build_node_delete(void) +{ +	struct node *new = xmalloc(sizeof(*new)); + +	memset(new, 0, sizeof(*new)); + +	new->deleted = 1; + +	return new; +} +  struct node *name_node(struct node *node, char *name)  {  	assert(node->name == NULL); @@ -106,8 +140,10 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)  	struct node *new_child, *old_child;  	struct label *l; +	old_node->deleted = 0; +  	/* Add new node labels to old node */ -	for_each_label(new_node->labels, l) +	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 @@ -118,14 +154,21 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)  		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(old_node, old_prop) { +		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(new_prop->labels, l) +				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; @@ -146,8 +189,14 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)  		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(old_node, old_child) { +		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; @@ -155,7 +204,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)  			}  		} -		/* if no collision occurred, add child to the old node. */ +		/* if no collision occured, add child to the old node. */  		if (new_child)  			add_child(old_node, new_child);  	} @@ -188,6 +237,25 @@ void add_property(struct node *node, struct property *prop)  	*p = prop;  } +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; +	} +} + +void delete_property(struct property *prop) +{ +	prop->deleted = 1; +	delete_labels(&prop->labels); +} +  void add_child(struct node *parent, struct node *child)  {  	struct node **p; @@ -202,6 +270,32 @@ void add_child(struct node *parent, struct node *child)  	*p = child;  } +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; +	} +} + +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); +} +  struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)  {  	struct reserve_info *new = xmalloc(sizeof(*new)); @@ -353,8 +447,11 @@ struct node *get_node_by_path(struct node *tree, const char *path)  	const char *p;  	struct node *child; -	if (!path || ! (*path)) +	if (!path || ! (*path)) { +		if (tree->deleted) +			return NULL;  		return tree; +	}  	while (path[0] == '/')  		path++; @@ -397,8 +494,11 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)  	assert((phandle != 0) && (phandle != -1)); -	if (tree->phandle == phandle) +	if (tree->phandle == phandle) { +		if (tree->deleted) +			return NULL;  		return tree; +	}  	for_each_child(tree, child) {  		node = get_node_by_phandle(child, phandle); @@ -535,7 +635,7 @@ static void sort_properties(struct node *node)  	int n = 0, i = 0;  	struct property *prop, **tbl; -	for_each_property(node, prop) +	for_each_property_withdel(node, prop)  		n++;  	if (n == 0) @@ -543,7 +643,7 @@ static void sort_properties(struct node *node)  	tbl = xmalloc(n * sizeof(*tbl)); -	for_each_property(node, prop) +	for_each_property_withdel(node, prop)  		tbl[i++] = prop;  	qsort(tbl, n, sizeof(*tbl), cmp_prop); @@ -571,7 +671,7 @@ static void sort_subnodes(struct node *node)  	int n = 0, i = 0;  	struct node *subnode, **tbl; -	for_each_child(node, subnode) +	for_each_child_withdel(node, subnode)  		n++;  	if (n == 0) @@ -579,7 +679,7 @@ static void sort_subnodes(struct node *node)  	tbl = xmalloc(n * sizeof(*tbl)); -	for_each_child(node, subnode) +	for_each_child_withdel(node, subnode)  		tbl[i++] = subnode;  	qsort(tbl, n, sizeof(*tbl), cmp_subnode); @@ -598,7 +698,7 @@ static void sort_node(struct node *node)  	sort_properties(node);  	sort_subnodes(node); -	for_each_child(node, c) +	for_each_child_withdel(node, c)  		sort_node(c);  }  |