summaryrefslogtreecommitdiffstats
path: root/core/test
diff options
context:
space:
mode:
authorAlistair Popple <alistair@popple.id.au>2018-02-09 13:42:38 +1100
committerStewart Smith <stewart@linux.vnet.ibm.com>2018-02-13 01:30:10 -0600
commit55c13bd1231a51e0109eeadc17cbbf46fa649f02 (patch)
treec9c1842251a1cc34f016a85391664ae2121f7d4f /core/test
parentb94fbeaf137c3981976699ef5dcc8cf95088413a (diff)
downloadblackbird-skiboot-55c13bd1231a51e0109eeadc17cbbf46fa649f02.tar.gz
blackbird-skiboot-55c13bd1231a51e0109eeadc17cbbf46fa649f02.zip
core/device.c: Fix dt_find_compatible_node
dt_find_compatible_node() and dt_find_compatible_node_on_chip() are used to find device nodes under a parent/root node with a given compatible property. dt_next(root, prev) is used to walk the child nodes of the given parent and takes two arguments - root contains the parent node to walk whilst prev contains the previous child to search from so that it can be used as an iterator over all children nodes. The first iteration of dt_find_compatible_node(root, prev) calls dt_next(root, root) which is not a well defined operation as prev is assumed to be child of the root node. The result is that when a node contains no children it will start returning the parent nodes siblings until it hits the top of the tree at which point a NULL derefence is attempted when looking for the root nodes parent. Dereferencing NULL can result in undesirable data exceptions during system boot and untimely non-hilarious system crashes. dt_next() should not be called with prev == root. Instead we add a check to dt_next() such that passing prev = NULL will cause it to start iterating from the first child node (if any). Also add a unit test for this case to run-device.c. Signed-off-by: Alistair Popple <alistair@popple.id.au> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'core/test')
-rw-r--r--core/test/run-device.c31
1 files changed, 26 insertions, 5 deletions
diff --git a/core/test/run-device.c b/core/test/run-device.c
index 326be3ff..c3e46793 100644
--- a/core/test/run-device.c
+++ b/core/test/run-device.c
@@ -323,14 +323,27 @@ int main(void)
gc1 = dt_new(c1, "coprocessor1");
dt_add_property_strings(gc1, "compatible",
"specific-fake-coprocessor");
+ gc2 = dt_new(gc1, "coprocessor2");
+ dt_add_property_strings(gc2, "compatible",
+ "specific-fake-coprocessor");
+ gc3 = dt_new(c1, "coprocessor3");
+ dt_add_property_strings(gc3, "compatible",
+ "specific-fake-coprocessor");
- gc2 = dt_new(c1, "node-without-compatible");
- assert(__dt_find_property(gc2, "compatible") == NULL);
- assert(!dt_node_is_compatible(gc2, "any-property"));
assert(dt_find_compatible_node(root, NULL, "generic-fake-bus") == c2);
assert(dt_find_compatible_node(root, c2, "generic-fake-bus") == NULL);
+ /* we can find all compatible nodes */
+ assert(dt_find_compatible_node(c1, NULL, "specific-fake-coprocessor") == gc1);
+ assert(dt_find_compatible_node(c1, gc1, "specific-fake-coprocessor") == gc2);
+ assert(dt_find_compatible_node(c1, gc2, "specific-fake-coprocessor") == gc3);
+ assert(dt_find_compatible_node(c1, gc3, "specific-fake-coprocessor") == NULL);
+ assert(dt_find_compatible_node(root, NULL, "specific-fake-coprocessor") == gc1);
+ assert(dt_find_compatible_node(root, gc1, "specific-fake-coprocessor") == gc2);
+ assert(dt_find_compatible_node(root, gc2, "specific-fake-coprocessor") == gc3);
+ assert(dt_find_compatible_node(root, gc3, "specific-fake-coprocessor") == NULL);
+
/* we can find the coprocessor once on the cpu */
assert(dt_find_compatible_node_on_chip(root,
NULL,
@@ -339,6 +352,14 @@ int main(void)
assert(dt_find_compatible_node_on_chip(root,
gc1,
"specific-fake-coprocessor",
+ 0xcafe) == gc2);
+ assert(dt_find_compatible_node_on_chip(root,
+ gc2,
+ "specific-fake-coprocessor",
+ 0xcafe) == gc3);
+ assert(dt_find_compatible_node_on_chip(root,
+ gc3,
+ "specific-fake-coprocessor",
0xcafe) == NULL);
/* we can't find the coprocessor on the bus */
@@ -349,9 +370,9 @@ int main(void)
/* Test phandles. We override the automatically generated one. */
phandle = 0xf00;
- dt_add_property(gc2, "phandle", (const void *)&phandle, 4);
+ dt_add_property(gc3, "phandle", (const void *)&phandle, 4);
assert(last_phandle == 0xf00);
- assert(dt_find_by_phandle(root, 0xf00) == gc2);
+ assert(dt_find_by_phandle(root, 0xf00) == gc3);
assert(dt_find_by_phandle(root, 0xf0f) == NULL);
dt_free(root);
OpenPOWER on IntegriCloud