| Open Firmware Device Tree Unittest | 
 | ---------------------------------- | 
 |  | 
 | Author: Gaurav Minocha <gaurav.minocha.os@gmail.com> | 
 |  | 
 | 1. Introduction | 
 |  | 
 | This document explains how the test data required for executing OF unittest | 
 | is attached to the live tree dynamically, independent of the machine's | 
 | architecture. | 
 |  | 
 | It is recommended to read the following documents before moving ahead. | 
 |  | 
 | [1] Documentation/devicetree/usage-model.txt | 
 | [2] http://www.devicetree.org/Device_Tree_Usage | 
 |  | 
 | OF Selftest has been designed to test the interface (include/linux/of.h) | 
 | provided to device driver developers to fetch the device information..etc. | 
 | from the unflattened device tree data structure. This interface is used by | 
 | most of the device drivers in various use cases. | 
 |  | 
 |  | 
 | 2. Test-data | 
 |  | 
 | The Device Tree Source file (drivers/of/unittest-data/testcases.dts) contains | 
 | the test data required for executing the unit tests automated in | 
 | drivers/of/unittest.c. Currently, following Device Tree Source Include files | 
 | (.dtsi) are included in testcases.dts: | 
 |  | 
 | drivers/of/unittest-data/tests-interrupts.dtsi | 
 | drivers/of/unittest-data/tests-platform.dtsi | 
 | drivers/of/unittest-data/tests-phandle.dtsi | 
 | drivers/of/unittest-data/tests-match.dtsi | 
 |  | 
 | When the kernel is build with OF_SELFTEST enabled, then the following make rule | 
 |  | 
 | $(obj)/%.dtb: $(src)/%.dts FORCE | 
 | 	$(call if_changed_dep, dtc) | 
 |  | 
 | is used to compile the DT source file (testcases.dts) into a binary blob | 
 | (testcases.dtb), also referred as flattened DT. | 
 |  | 
 | After that, using the following rule the binary blob above is wrapped as an | 
 | assembly file (testcases.dtb.S). | 
 |  | 
 | $(obj)/%.dtb.S: $(obj)/%.dtb | 
 | 	$(call cmd, dt_S_dtb) | 
 |  | 
 | The assembly file is compiled into an object file (testcases.dtb.o), and is | 
 | linked into the kernel image. | 
 |  | 
 |  | 
 | 2.1. Adding the test data | 
 |  | 
 | Un-flattened device tree structure: | 
 |  | 
 | Un-flattened device tree consists of connected device_node(s) in form of a tree | 
 | structure described below. | 
 |  | 
 | // following struct members are used to construct the tree | 
 | struct device_node { | 
 |     ... | 
 |     struct  device_node *parent; | 
 |     struct  device_node *child; | 
 |     struct  device_node *sibling; | 
 |     ... | 
 |  }; | 
 |  | 
 | Figure 1, describes a generic structure of machine's un-flattened device tree | 
 | considering only child and sibling pointers. There exists another pointer, | 
 | *parent, that is used to traverse the tree in the reverse direction. So, at | 
 | a particular level the child node and all the sibling nodes will have a parent | 
 | pointer pointing to a common node (e.g. child1, sibling2, sibling3, sibling4's | 
 | parent points to root node) | 
 |  | 
 | root ('/') | 
 |    | | 
 | child1 -> sibling2 -> sibling3 -> sibling4 -> null | 
 |    |         |           |           | | 
 |    |         |           |          null | 
 |    |         |           | | 
 |    |         |        child31 -> sibling32 -> null | 
 |    |         |           |          | | 
 |    |         |          null       null | 
 |    |         | | 
 |    |      child21 -> sibling22 -> sibling23 -> null | 
 |    |         |          |            | | 
 |    |        null       null         null | 
 |    | | 
 | child11 -> sibling12 -> sibling13 -> sibling14 -> null | 
 |    |           |           |            | | 
 |    |           |           |           null | 
 |    |           |           | | 
 |   null        null       child131 -> null | 
 |                            | | 
 |                           null | 
 |  | 
 | Figure 1: Generic structure of un-flattened device tree | 
 |  | 
 |  | 
 | Before executing OF unittest, it is required to attach the test data to | 
 | machine's device tree (if present). So, when selftest_data_add() is called, | 
 | at first it reads the flattened device tree data linked into the kernel image | 
 | via the following kernel symbols: | 
 |  | 
 | __dtb_testcases_begin - address marking the start of test data blob | 
 | __dtb_testcases_end   - address marking the end of test data blob | 
 |  | 
 | Secondly, it calls of_fdt_unflatten_tree() to unflatten the flattened | 
 | blob. And finally, if the machine's device tree (i.e live tree) is present, | 
 | then it attaches the unflattened test data tree to the live tree, else it | 
 | attaches itself as a live device tree. | 
 |  | 
 | attach_node_and_children() uses of_attach_node() to attach the nodes into the | 
 | live tree as explained below. To explain the same, the test data tree described | 
 |  in Figure 2 is attached to the live tree described in Figure 1. | 
 |  | 
 | root ('/') | 
 |     | | 
 |  testcase-data | 
 |     | | 
 |  test-child0 -> test-sibling1 -> test-sibling2 -> test-sibling3 -> null | 
 |     |               |                |                | | 
 |  test-child01      null             null             null | 
 |  | 
 |  | 
 | Figure 2: Example test data tree to be attached to live tree. | 
 |  | 
 | According to the scenario above, the live tree is already present so it isn't | 
 | required to attach the root('/') node. All other nodes are attached by calling | 
 | of_attach_node() on each node. | 
 |  | 
 | In the function of_attach_node(), the new node is attached as the child of the | 
 | given parent in live tree. But, if parent already has a child then the new node | 
 | replaces the current child and turns it into its sibling. So, when the testcase | 
 | data node is attached to the live tree above (Figure 1), the final structure is | 
 |  as shown in Figure 3. | 
 |  | 
 | root ('/') | 
 |    | | 
 | testcase-data -> child1 -> sibling2 -> sibling3 -> sibling4 -> null | 
 |    |               |          |           |           | | 
 |  (...)             |          |           |          null | 
 |                    |          |         child31 -> sibling32 -> null | 
 |                    |          |           |           | | 
 |                    |          |          null        null | 
 |                    |          | | 
 |                    |        child21 -> sibling22 -> sibling23 -> null | 
 |                    |          |           |            | | 
 |                    |         null        null         null | 
 |                    | | 
 |                 child11 -> sibling12 -> sibling13 -> sibling14 -> null | 
 |                    |          |            |            | | 
 |                   null       null          |           null | 
 |                                            | | 
 |                                         child131 -> null | 
 |                                            | | 
 |                                           null | 
 | ----------------------------------------------------------------------- | 
 |  | 
 | root ('/') | 
 |    | | 
 | testcase-data -> child1 -> sibling2 -> sibling3 -> sibling4 -> null | 
 |    |               |          |           |           | | 
 |    |             (...)      (...)       (...)        null | 
 |    | | 
 | test-sibling3 -> test-sibling2 -> test-sibling1 -> test-child0 -> null | 
 |    |                |                   |                | | 
 |   null             null                null         test-child01 | 
 |  | 
 |  | 
 | Figure 3: Live device tree structure after attaching the testcase-data. | 
 |  | 
 |  | 
 | Astute readers would have noticed that test-child0 node becomes the last | 
 | sibling compared to the earlier structure (Figure 2). After attaching first | 
 | test-child0 the test-sibling1 is attached that pushes the child node | 
 | (i.e. test-child0) to become a sibling and makes itself a child node, | 
 |  as mentioned above. | 
 |  | 
 | If a duplicate node is found (i.e. if a node with same full_name property is | 
 | already present in the live tree), then the node isn't attached rather its | 
 | properties are updated to the live tree's node by calling the function | 
 | update_node_properties(). | 
 |  | 
 |  | 
 | 2.2. Removing the test data | 
 |  | 
 | Once the test case execution is complete, selftest_data_remove is called in | 
 | order to remove the device nodes attached initially (first the leaf nodes are | 
 | detached and then moving up the parent nodes are removed, and eventually the | 
 | whole tree). selftest_data_remove() calls detach_node_and_children() that uses | 
 | of_detach_node() to detach the nodes from the live device tree. | 
 |  | 
 | To detach a node, of_detach_node() either updates the child pointer of given | 
 | node's parent to its sibling or attaches the previous sibling to the given | 
 | node's sibling, as appropriate. That is it :) |