diff options
author | Alistair Popple <alistair@popple.id.au> | 2018-02-09 13:42:38 +1100 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2018-02-13 01:30:10 -0600 |
commit | 55c13bd1231a51e0109eeadc17cbbf46fa649f02 (patch) | |
tree | c9c1842251a1cc34f016a85391664ae2121f7d4f /core/test | |
parent | b94fbeaf137c3981976699ef5dcc8cf95088413a (diff) | |
download | blackbird-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.c | 31 |
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); |