Merge tag 'dm-pull-27apr20' of git://git.denx.de/u-boot-dm

Move Python tools to use absolute paths
Minor buildman fixes for new features
Make libfdt code more similar to upsteam
diff --git a/Makefile b/Makefile
index 6039720..68fecb4 100644
--- a/Makefile
+++ b/Makefile
@@ -512,7 +512,7 @@
 
 no-dot-config-targets := clean clobber mrproper distclean \
 			 help %docs check% coccicheck \
-			 ubootversion backup tests check qcheck
+			 ubootversion backup tests check qcheck tcheck
 
 config-targets := 0
 mixed-targets  := 0
@@ -2113,6 +2113,7 @@
 	@echo  ''
 	@echo  '  check           - Run all automated tests that use sandbox'
 	@echo  '  qcheck          - Run quick automated tests that use sandbox'
+	@echo  '  tcheck          - Run quick automated tests on tools'
 	@echo  ''
 	@echo  'Other generic targets:'
 	@echo  '  all		  - Build all necessary images depending on configuration'
@@ -2158,6 +2159,9 @@
 qcheck:
 	$(srctree)/test/run quick
 
+tcheck:
+	$(srctree)/test/run tools
+
 # Documentation targets
 # ---------------------------------------------------------------------------
 DOC_TARGETS := xmldocs latexdocs pdfdocs htmldocs epubdocs cleandocs \
diff --git a/common/Makefile b/common/Makefile
index 3471c47..2e7a090 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -110,6 +110,7 @@
 obj-$(CONFIG_ANDROID_AB) += android_ab.o
 obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.o
 obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o
+obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += fdt_region.o
 obj-$(CONFIG_$(SPL_TPL_)FIT) += image-fit.o
 obj-$(CONFIG_$(SPL_)MULTI_DTB_FIT) += boot_fit.o common_fit.o
 obj-$(CONFIG_$(SPL_TPL_)IMAGE_SIGN_INFO) += image-sig.o
diff --git a/lib/libfdt/fdt_region.c b/common/fdt_region.c
similarity index 99%
rename from lib/libfdt/fdt_region.c
rename to common/fdt_region.c
index 7e9fa92..bf0a9be 100644
--- a/lib/libfdt/fdt_region.c
+++ b/common/fdt_region.c
@@ -6,6 +6,7 @@
  */
 
 #include <linux/libfdt_env.h>
+#include <fdt_region.h>
 
 #ifndef USE_HOSTCC
 #include <fdt.h>
diff --git a/common/image-fit-sig.c b/common/image-fit-sig.c
index 490566c..3e73578 100644
--- a/common/image-fit-sig.c
+++ b/common/image-fit-sig.c
@@ -11,6 +11,7 @@
 #include <malloc.h>
 DECLARE_GLOBAL_DATA_PTR;
 #endif /* !USE_HOSTCC*/
+#include <fdt_region.h>
 #include <image.h>
 #include <u-boot/rsa.h>
 #include <u-boot/rsa-checksum.h>
diff --git a/common/log.c b/common/log.c
index ffb3cd6..c5b9b48 100644
--- a/common/log.c
+++ b/common/log.c
@@ -233,7 +233,7 @@
 	ldev = log_device_find_by_name(drv_name);
 	if (!ldev)
 		return -ENOENT;
-	filt = (struct log_filter *)calloc(1, sizeof(*filt));
+	filt = calloc(1, sizeof(*filt));
 	if (!filt)
 		return -ENOMEM;
 
diff --git a/include/fdt_region.h b/include/fdt_region.h
new file mode 100644
index 0000000..ff7a1cc
--- /dev/null
+++ b/include/fdt_region.h
@@ -0,0 +1,304 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _FDT_REGION_H
+#define _FDT_REGION_H
+
+#ifndef SWIG /* Not available in Python */
+struct fdt_region {
+	int offset;
+	int size;
+};
+
+/*
+ * Flags for fdt_find_regions()
+ *
+ * Add a region for the string table (always the last region)
+ */
+#define FDT_REG_ADD_STRING_TAB		(1 << 0)
+
+/*
+ * Add all supernodes of a matching node/property, useful for creating a
+ * valid subset tree
+ */
+#define FDT_REG_SUPERNODES		(1 << 1)
+
+/* Add the FDT_BEGIN_NODE tags of subnodes, including their names */
+#define FDT_REG_DIRECT_SUBNODES	(1 << 2)
+
+/* Add all subnodes of a matching node */
+#define FDT_REG_ALL_SUBNODES		(1 << 3)
+
+/* Add a region for the mem_rsvmap table (always the first region) */
+#define FDT_REG_ADD_MEM_RSVMAP		(1 << 4)
+
+/* Indicates what an fdt part is (node, property, value) */
+#define FDT_IS_NODE			(1 << 0)
+#define FDT_IS_PROP			(1 << 1)
+#define FDT_IS_VALUE			(1 << 2)	/* not supported */
+#define FDT_IS_COMPAT			(1 << 3)	/* used internally */
+#define FDT_NODE_HAS_PROP		(1 << 4)	/* node contains prop */
+
+#define FDT_ANY_GLOBAL		(FDT_IS_NODE | FDT_IS_PROP | FDT_IS_VALUE | \
+					FDT_IS_COMPAT)
+#define FDT_IS_ANY			0x1f		/* all the above */
+
+/* We set a reasonable limit on the number of nested nodes */
+#define FDT_MAX_DEPTH			32
+
+/* Decribes what we want to include from the current tag */
+enum want_t {
+	WANT_NOTHING,
+	WANT_NODES_ONLY,		/* No properties */
+	WANT_NODES_AND_PROPS,		/* Everything for one level */
+	WANT_ALL_NODES_AND_PROPS	/* Everything for all levels */
+};
+
+/* Keeps track of the state at parent nodes */
+struct fdt_subnode_stack {
+	int offset;		/* Offset of node */
+	enum want_t want;	/* The 'want' value here */
+	int included;		/* 1 if we included this node, 0 if not */
+};
+
+struct fdt_region_ptrs {
+	int depth;			/* Current tree depth */
+	int done;			/* What we have completed scanning */
+	enum want_t want;		/* What we are currently including */
+	char *end;			/* Pointer to end of full node path */
+	int nextoffset;			/* Next node offset to check */
+};
+
+/* The state of our finding algortihm */
+struct fdt_region_state {
+	struct fdt_subnode_stack stack[FDT_MAX_DEPTH];	/* node stack */
+	struct fdt_region *region;	/* Contains list of regions found */
+	int count;			/* Numnber of regions found */
+	const void *fdt;		/* FDT blob */
+	int max_regions;		/* Maximum regions to find */
+	int can_merge;		/* 1 if we can merge with previous region */
+	int start;			/* Start position of current region */
+	struct fdt_region_ptrs ptrs;	/* Pointers for what we are up to */
+};
+
+/**
+ * fdt_find_regions() - find regions in device tree
+ *
+ * Given a list of nodes to include and properties to exclude, find
+ * the regions of the device tree which describe those included parts.
+ *
+ * The intent is to get a list of regions which will be invariant provided
+ * those parts are invariant. For example, if you request a list of regions
+ * for all nodes but exclude the property "data", then you will get the
+ * same region contents regardless of any change to "data" properties.
+ *
+ * This function can be used to produce a byte-stream to send to a hashing
+ * function to verify that critical parts of the FDT have not changed.
+ *
+ * Nodes which are given in 'inc' are included in the region list, as
+ * are the names of the immediate subnodes nodes (but not the properties
+ * or subnodes of those subnodes).
+ *
+ * For eaxample "/" means to include the root node, all root properties
+ * and the FDT_BEGIN_NODE and FDT_END_NODE of all subnodes of /. The latter
+ * ensures that we capture the names of the subnodes. In a hashing situation
+ * it prevents the root node from changing at all Any change to non-excluded
+ * properties, names of subnodes or number of subnodes would be detected.
+ *
+ * When used with FITs this provides the ability to hash and sign parts of
+ * the FIT based on different configurations in the FIT. Then it is
+ * impossible to change anything about that configuration (include images
+ * attached to the configuration), but it may be possible to add new
+ * configurations, new images or new signatures within the existing
+ * framework.
+ *
+ * Adding new properties to a device tree may result in the string table
+ * being extended (if the new property names are different from those
+ * already added). This function can optionally include a region for
+ * the string table so that this can be part of the hash too.
+ *
+ * The device tree header is not included in the list.
+ *
+ * @fdt:	Device tree to check
+ * @inc:	List of node paths to included
+ * @inc_count:	Number of node paths in list
+ * @exc_prop:	List of properties names to exclude
+ * @exc_prop_count:	Number of properties in exclude list
+ * @region:	Returns list of regions
+ * @max_region:	Maximum length of region list
+ * @path:	Pointer to a temporary string for the function to use for
+ *		building path names
+ * @path_len:	Length of path, must be large enough to hold the longest
+ *		path in the tree
+ * @add_string_tab:	1 to add a region for the string table
+ * @return number of regions in list. If this is >max_regions then the
+ * region array was exhausted. You should increase max_regions and try
+ * the call again.
+ */
+int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
+		     char * const exc_prop[], int exc_prop_count,
+		     struct fdt_region region[], int max_regions,
+		     char *path, int path_len, int add_string_tab);
+
+/**
+ * fdt_first_region() - find regions in device tree
+ *
+ * Given a nodes and properties to include and properties to exclude, find
+ * the regions of the device tree which describe those included parts.
+ *
+ * The use for this function is twofold. Firstly it provides a convenient
+ * way of performing a structure-aware grep of the tree. For example it is
+ * possible to grep for a node and get all the properties associated with
+ * that node. Trees can be subsetted easily, by specifying the nodes that
+ * are required, and then writing out the regions returned by this function.
+ * This is useful for small resource-constrained systems, such as boot
+ * loaders, which want to use an FDT but do not need to know about all of
+ * it.
+ *
+ * Secondly it makes it easy to hash parts of the tree and detect changes.
+ * The intent is to get a list of regions which will be invariant provided
+ * those parts are invariant. For example, if you request a list of regions
+ * for all nodes but exclude the property "data", then you will get the
+ * same region contents regardless of any change to "data" properties.
+ *
+ * This function can be used to produce a byte-stream to send to a hashing
+ * function to verify that critical parts of the FDT have not changed.
+ * Note that semantically null changes in order could still cause false
+ * hash misses. Such reordering might happen if the tree is regenerated
+ * from source, and nodes are reordered (the bytes-stream will be emitted
+ * in a different order and many hash functions will detect this). However
+ * if an existing tree is modified using libfdt functions, such as
+ * fdt_add_subnode() and fdt_setprop(), then this problem is avoided.
+ *
+ * The nodes/properties to include/exclude are defined by a function
+ * provided by the caller. This function is called for each node and
+ * property, and must return:
+ *
+ *    0 - to exclude this part
+ *    1 - to include this part
+ *   -1 - for FDT_IS_PROP only: no information is available, so include
+ *		if its containing node is included
+ *
+ * The last case is only used to deal with properties. Often a property is
+ * included if its containing node is included - this is the case where
+ * -1 is returned.. However if the property is specifically required to be
+ * included/excluded, then 0 or 1 can be returned. Note that including a
+ * property when the FDT_REG_SUPERNODES flag is given will force its
+ * containing node to be included since it is not valid to have a property
+ * that is not in a node.
+ *
+ * Using the information provided, the inclusion of a node can be controlled
+ * either by a node name or its compatible string, or any other property
+ * that the function can determine.
+ *
+ * As an example, including node "/" means to include the root node and all
+ * root properties. A flag provides a way of also including supernodes (of
+ * which there is none for the root node), and another flag includes
+ * immediate subnodes, so in this case we would get the FDT_BEGIN_NODE and
+ * FDT_END_NODE of all subnodes of /.
+ *
+ * The subnode feature helps in a hashing situation since it prevents the
+ * root node from changing at all. Any change to non-excluded properties,
+ * names of subnodes or number of subnodes would be detected.
+ *
+ * When used with FITs this provides the ability to hash and sign parts of
+ * the FIT based on different configurations in the FIT. Then it is
+ * impossible to change anything about that configuration (include images
+ * attached to the configuration), but it may be possible to add new
+ * configurations, new images or new signatures within the existing
+ * framework.
+ *
+ * Adding new properties to a device tree may result in the string table
+ * being extended (if the new property names are different from those
+ * already added). This function can optionally include a region for
+ * the string table so that this can be part of the hash too. This is always
+ * the last region.
+ *
+ * The FDT also has a mem_rsvmap table which can also be included, and is
+ * always the first region if so.
+ *
+ * The device tree header is not included in the region list. Since the
+ * contents of the FDT are changing (shrinking, often), the caller will need
+ * to regenerate the header anyway.
+ *
+ * @fdt:	Device tree to check
+ * @h_include:	Function to call to determine whether to include a part or
+ *		not:
+ *
+ *		@priv: Private pointer as passed to fdt_find_regions()
+ *		@fdt: Pointer to FDT blob
+ *		@offset: Offset of this node / property
+ *		@type: Type of this part, FDT_IS_...
+ *		@data: Pointer to data (node name, property name, compatible
+ *			string, value (not yet supported)
+ *		@size: Size of data, or 0 if none
+ *		@return 0 to exclude, 1 to include, -1 if no information is
+ *		available
+ * @priv:	Private pointer passed to h_include
+ * @region:	Returns list of regions, sorted by offset
+ * @max_regions: Maximum length of region list
+ * @path:	Pointer to a temporary string for the function to use for
+ *		building path names
+ * @path_len:	Length of path, must be large enough to hold the longest
+ *		path in the tree
+ * @flags:	Various flags that control the region algortihm, see
+ *		FDT_REG_...
+ * @return number of regions in list. If this is >max_regions then the
+ * region array was exhausted. You should increase max_regions and try
+ * the call again. Only the first max_regions elements are available in the
+ * array.
+ *
+ * On error a -ve value is return, which can be:
+ *
+ *	-FDT_ERR_BADSTRUCTURE (too deep or more END tags than BEGIN tags
+ *	-FDT_ERR_BADLAYOUT
+ *	-FDT_ERR_NOSPACE (path area is too small)
+ */
+int fdt_first_region(const void *fdt,
+		     int (*h_include)(void *priv, const void *fdt, int offset,
+				      int type, const char *data, int size),
+		     void *priv, struct fdt_region *region,
+		     char *path, int path_len, int flags,
+		     struct fdt_region_state *info);
+
+/** fdt_next_region() - find next region
+ *
+ * See fdt_first_region() for full description. This function finds the
+ * next region according to the provided parameters, which must be the same
+ * as passed to fdt_first_region().
+ *
+ * This function can additionally return -FDT_ERR_NOTFOUND when there are no
+ * more regions
+ */
+int fdt_next_region(const void *fdt,
+		    int (*h_include)(void *priv, const void *fdt, int offset,
+				     int type, const char *data, int size),
+		    void *priv, struct fdt_region *region,
+		    char *path, int path_len, int flags,
+		    struct fdt_region_state *info);
+
+/**
+ * fdt_add_alias_regions() - find aliases that point to existing regions
+ *
+ * Once a device tree grep is complete some of the nodes will be present
+ * and some will have been dropped. This function checks all the alias nodes
+ * to figure out which points point to nodes which are still present. These
+ * aliases need to be kept, along with the nodes they reference.
+ *
+ * Given a list of regions function finds the aliases that still apply and
+ * adds more regions to the list for these. This function is called after
+ * fdt_next_region() has finished returning regions and requires the same
+ * state.
+ *
+ * @fdt:	Device tree file to reference
+ * @region:	List of regions that will be kept
+ * @count:	Number of regions
+ * @max_regions: Number of entries that can fit in @region
+ * @info:	Region state as returned from fdt_next_region()
+ * @return new number of regions in @region (i.e. count + the number added)
+ * or -FDT_ERR_NOSPACE if there was not enough space.
+ */
+int fdt_add_alias_regions(const void *fdt, struct fdt_region *region, int count,
+			  int max_regions, struct fdt_region_state *info);
+#endif /* SWIG */
+
+#endif /* _FDT_REGION_H */
diff --git a/include/linux/libfdt.h b/include/linux/libfdt.h
index eeb2344..39dbc88 100644
--- a/include/linux/libfdt.h
+++ b/include/linux/libfdt.h
@@ -8,305 +8,6 @@
 #include "../../scripts/dtc/libfdt/libfdt.h"
 
 /* U-Boot local hacks */
-
-#ifndef SWIG /* Not available in Python */
-struct fdt_region {
-	int offset;
-	int size;
-};
-
-/*
- * Flags for fdt_find_regions()
- *
- * Add a region for the string table (always the last region)
- */
-#define FDT_REG_ADD_STRING_TAB		(1 << 0)
-
-/*
- * Add all supernodes of a matching node/property, useful for creating a
- * valid subset tree
- */
-#define FDT_REG_SUPERNODES		(1 << 1)
-
-/* Add the FDT_BEGIN_NODE tags of subnodes, including their names */
-#define FDT_REG_DIRECT_SUBNODES	(1 << 2)
-
-/* Add all subnodes of a matching node */
-#define FDT_REG_ALL_SUBNODES		(1 << 3)
-
-/* Add a region for the mem_rsvmap table (always the first region) */
-#define FDT_REG_ADD_MEM_RSVMAP		(1 << 4)
-
-/* Indicates what an fdt part is (node, property, value) */
-#define FDT_IS_NODE			(1 << 0)
-#define FDT_IS_PROP			(1 << 1)
-#define FDT_IS_VALUE			(1 << 2)	/* not supported */
-#define FDT_IS_COMPAT			(1 << 3)	/* used internally */
-#define FDT_NODE_HAS_PROP		(1 << 4)	/* node contains prop */
-
-#define FDT_ANY_GLOBAL		(FDT_IS_NODE | FDT_IS_PROP | FDT_IS_VALUE | \
-					FDT_IS_COMPAT)
-#define FDT_IS_ANY			0x1f		/* all the above */
-
-/* We set a reasonable limit on the number of nested nodes */
-#define FDT_MAX_DEPTH			32
-
-/* Decribes what we want to include from the current tag */
-enum want_t {
-	WANT_NOTHING,
-	WANT_NODES_ONLY,		/* No properties */
-	WANT_NODES_AND_PROPS,		/* Everything for one level */
-	WANT_ALL_NODES_AND_PROPS	/* Everything for all levels */
-};
-
-/* Keeps track of the state at parent nodes */
-struct fdt_subnode_stack {
-	int offset;		/* Offset of node */
-	enum want_t want;	/* The 'want' value here */
-	int included;		/* 1 if we included this node, 0 if not */
-};
-
-struct fdt_region_ptrs {
-	int depth;			/* Current tree depth */
-	int done;			/* What we have completed scanning */
-	enum want_t want;		/* What we are currently including */
-	char *end;			/* Pointer to end of full node path */
-	int nextoffset;			/* Next node offset to check */
-};
-
-/* The state of our finding algortihm */
-struct fdt_region_state {
-	struct fdt_subnode_stack stack[FDT_MAX_DEPTH];	/* node stack */
-	struct fdt_region *region;	/* Contains list of regions found */
-	int count;			/* Numnber of regions found */
-	const void *fdt;		/* FDT blob */
-	int max_regions;		/* Maximum regions to find */
-	int can_merge;		/* 1 if we can merge with previous region */
-	int start;			/* Start position of current region */
-	struct fdt_region_ptrs ptrs;	/* Pointers for what we are up to */
-};
-
-/**
- * fdt_find_regions() - find regions in device tree
- *
- * Given a list of nodes to include and properties to exclude, find
- * the regions of the device tree which describe those included parts.
- *
- * The intent is to get a list of regions which will be invariant provided
- * those parts are invariant. For example, if you request a list of regions
- * for all nodes but exclude the property "data", then you will get the
- * same region contents regardless of any change to "data" properties.
- *
- * This function can be used to produce a byte-stream to send to a hashing
- * function to verify that critical parts of the FDT have not changed.
- *
- * Nodes which are given in 'inc' are included in the region list, as
- * are the names of the immediate subnodes nodes (but not the properties
- * or subnodes of those subnodes).
- *
- * For eaxample "/" means to include the root node, all root properties
- * and the FDT_BEGIN_NODE and FDT_END_NODE of all subnodes of /. The latter
- * ensures that we capture the names of the subnodes. In a hashing situation
- * it prevents the root node from changing at all Any change to non-excluded
- * properties, names of subnodes or number of subnodes would be detected.
- *
- * When used with FITs this provides the ability to hash and sign parts of
- * the FIT based on different configurations in the FIT. Then it is
- * impossible to change anything about that configuration (include images
- * attached to the configuration), but it may be possible to add new
- * configurations, new images or new signatures within the existing
- * framework.
- *
- * Adding new properties to a device tree may result in the string table
- * being extended (if the new property names are different from those
- * already added). This function can optionally include a region for
- * the string table so that this can be part of the hash too.
- *
- * The device tree header is not included in the list.
- *
- * @fdt:	Device tree to check
- * @inc:	List of node paths to included
- * @inc_count:	Number of node paths in list
- * @exc_prop:	List of properties names to exclude
- * @exc_prop_count:	Number of properties in exclude list
- * @region:	Returns list of regions
- * @max_region:	Maximum length of region list
- * @path:	Pointer to a temporary string for the function to use for
- *		building path names
- * @path_len:	Length of path, must be large enough to hold the longest
- *		path in the tree
- * @add_string_tab:	1 to add a region for the string table
- * @return number of regions in list. If this is >max_regions then the
- * region array was exhausted. You should increase max_regions and try
- * the call again.
- */
-int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
-		     char * const exc_prop[], int exc_prop_count,
-		     struct fdt_region region[], int max_regions,
-		     char *path, int path_len, int add_string_tab);
-
-/**
- * fdt_first_region() - find regions in device tree
- *
- * Given a nodes and properties to include and properties to exclude, find
- * the regions of the device tree which describe those included parts.
- *
- * The use for this function is twofold. Firstly it provides a convenient
- * way of performing a structure-aware grep of the tree. For example it is
- * possible to grep for a node and get all the properties associated with
- * that node. Trees can be subsetted easily, by specifying the nodes that
- * are required, and then writing out the regions returned by this function.
- * This is useful for small resource-constrained systems, such as boot
- * loaders, which want to use an FDT but do not need to know about all of
- * it.
- *
- * Secondly it makes it easy to hash parts of the tree and detect changes.
- * The intent is to get a list of regions which will be invariant provided
- * those parts are invariant. For example, if you request a list of regions
- * for all nodes but exclude the property "data", then you will get the
- * same region contents regardless of any change to "data" properties.
- *
- * This function can be used to produce a byte-stream to send to a hashing
- * function to verify that critical parts of the FDT have not changed.
- * Note that semantically null changes in order could still cause false
- * hash misses. Such reordering might happen if the tree is regenerated
- * from source, and nodes are reordered (the bytes-stream will be emitted
- * in a different order and many hash functions will detect this). However
- * if an existing tree is modified using libfdt functions, such as
- * fdt_add_subnode() and fdt_setprop(), then this problem is avoided.
- *
- * The nodes/properties to include/exclude are defined by a function
- * provided by the caller. This function is called for each node and
- * property, and must return:
- *
- *    0 - to exclude this part
- *    1 - to include this part
- *   -1 - for FDT_IS_PROP only: no information is available, so include
- *		if its containing node is included
- *
- * The last case is only used to deal with properties. Often a property is
- * included if its containing node is included - this is the case where
- * -1 is returned.. However if the property is specifically required to be
- * included/excluded, then 0 or 1 can be returned. Note that including a
- * property when the FDT_REG_SUPERNODES flag is given will force its
- * containing node to be included since it is not valid to have a property
- * that is not in a node.
- *
- * Using the information provided, the inclusion of a node can be controlled
- * either by a node name or its compatible string, or any other property
- * that the function can determine.
- *
- * As an example, including node "/" means to include the root node and all
- * root properties. A flag provides a way of also including supernodes (of
- * which there is none for the root node), and another flag includes
- * immediate subnodes, so in this case we would get the FDT_BEGIN_NODE and
- * FDT_END_NODE of all subnodes of /.
- *
- * The subnode feature helps in a hashing situation since it prevents the
- * root node from changing at all. Any change to non-excluded properties,
- * names of subnodes or number of subnodes would be detected.
- *
- * When used with FITs this provides the ability to hash and sign parts of
- * the FIT based on different configurations in the FIT. Then it is
- * impossible to change anything about that configuration (include images
- * attached to the configuration), but it may be possible to add new
- * configurations, new images or new signatures within the existing
- * framework.
- *
- * Adding new properties to a device tree may result in the string table
- * being extended (if the new property names are different from those
- * already added). This function can optionally include a region for
- * the string table so that this can be part of the hash too. This is always
- * the last region.
- *
- * The FDT also has a mem_rsvmap table which can also be included, and is
- * always the first region if so.
- *
- * The device tree header is not included in the region list. Since the
- * contents of the FDT are changing (shrinking, often), the caller will need
- * to regenerate the header anyway.
- *
- * @fdt:	Device tree to check
- * @h_include:	Function to call to determine whether to include a part or
- *		not:
- *
- *		@priv: Private pointer as passed to fdt_find_regions()
- *		@fdt: Pointer to FDT blob
- *		@offset: Offset of this node / property
- *		@type: Type of this part, FDT_IS_...
- *		@data: Pointer to data (node name, property name, compatible
- *			string, value (not yet supported)
- *		@size: Size of data, or 0 if none
- *		@return 0 to exclude, 1 to include, -1 if no information is
- *		available
- * @priv:	Private pointer passed to h_include
- * @region:	Returns list of regions, sorted by offset
- * @max_regions: Maximum length of region list
- * @path:	Pointer to a temporary string for the function to use for
- *		building path names
- * @path_len:	Length of path, must be large enough to hold the longest
- *		path in the tree
- * @flags:	Various flags that control the region algortihm, see
- *		FDT_REG_...
- * @return number of regions in list. If this is >max_regions then the
- * region array was exhausted. You should increase max_regions and try
- * the call again. Only the first max_regions elements are available in the
- * array.
- *
- * On error a -ve value is return, which can be:
- *
- *	-FDT_ERR_BADSTRUCTURE (too deep or more END tags than BEGIN tags
- *	-FDT_ERR_BADLAYOUT
- *	-FDT_ERR_NOSPACE (path area is too small)
- */
-int fdt_first_region(const void *fdt,
-		     int (*h_include)(void *priv, const void *fdt, int offset,
-				      int type, const char *data, int size),
-		     void *priv, struct fdt_region *region,
-		     char *path, int path_len, int flags,
-		     struct fdt_region_state *info);
-
-/** fdt_next_region() - find next region
- *
- * See fdt_first_region() for full description. This function finds the
- * next region according to the provided parameters, which must be the same
- * as passed to fdt_first_region().
- *
- * This function can additionally return -FDT_ERR_NOTFOUND when there are no
- * more regions
- */
-int fdt_next_region(const void *fdt,
-		    int (*h_include)(void *priv, const void *fdt, int offset,
-				     int type, const char *data, int size),
-		    void *priv, struct fdt_region *region,
-		    char *path, int path_len, int flags,
-		    struct fdt_region_state *info);
-
-/**
- * fdt_add_alias_regions() - find aliases that point to existing regions
- *
- * Once a device tree grep is complete some of the nodes will be present
- * and some will have been dropped. This function checks all the alias nodes
- * to figure out which points point to nodes which are still present. These
- * aliases need to be kept, along with the nodes they reference.
- *
- * Given a list of regions function finds the aliases that still apply and
- * adds more regions to the list for these. This function is called after
- * fdt_next_region() has finished returning regions and requires the same
- * state.
- *
- * @fdt:	Device tree file to reference
- * @region:	List of regions that will be kept
- * @count:	Number of regions
- * @max_regions: Number of entries that can fit in @region
- * @info:	Region state as returned from fdt_next_region()
- * @return new number of regions in @region (i.e. count + the number added)
- * or -FDT_ERR_NOSPACE if there was not enough space.
- */
-int fdt_add_alias_regions(const void *fdt, struct fdt_region *region, int count,
-			  int max_regions, struct fdt_region_state *info);
-#endif /* SWIG */
-
 extern struct fdt_header *working_fdt;  /* Pointer to the working fdt */
 
 #endif /* _INCLUDE_LIBFDT_H_ */
diff --git a/lib/libfdt/Makefile b/lib/libfdt/Makefile
index 5d3ae4e..1fe50ec 100644
--- a/lib/libfdt/Makefile
+++ b/lib/libfdt/Makefile
@@ -3,9 +3,9 @@
 # (C) Copyright 2000-2007
 # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 
-# Use upstream code.
 obj-y += \
 	fdt.o \
+	fdt_ro.o \
 	fdt_wip.o \
 	fdt_strerror.o \
 	fdt_sw.o \
@@ -15,12 +15,5 @@
 
 obj-$(CONFIG_OF_LIBFDT_OVERLAY) += fdt_overlay.o
 
-# Locally modified for U-Boot.
-# TODO: split out the local modifiction.
-obj-y += fdt_ro.o
-
-# U-Boot own file
-obj-y += fdt_region.o
-
 ccflags-y := -I$(srctree)/scripts/dtc/libfdt \
 	-DFDT_ASSUME_MASK=$(CONFIG_$(SPL_TPL_)OF_LIBFDT_ASSUME_MASK)
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index be03aea..7ede074 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -1,925 +1,2 @@
-// SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause
-/*
- * libfdt - Flat Device Tree manipulation
- * Copyright (C) 2006 David Gibson, IBM Corporation.
- */
 #include <linux/libfdt_env.h>
-
-#ifndef USE_HOSTCC
-#include <fdt.h>
-#include <linux/libfdt.h>
-#else
-#include "fdt_host.h"
-#endif
-
-#include "libfdt_internal.h"
-
-static int fdt_nodename_eq_(const void *fdt, int offset,
-			    const char *s, int len)
-{
-	int olen;
-	const char *p = fdt_get_name(fdt, offset, &olen);
-
-	if (!p || (fdt_chk_extra() && olen < len))
-		/* short match */
-		return 0;
-
-	if (memcmp(p, s, len) != 0)
-		return 0;
-
-	if (p[len] == '\0')
-		return 1;
-	else if (!memchr(s, '@', len) && (p[len] == '@'))
-		return 1;
-	else
-		return 0;
-}
-
-const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
-{
-	int32_t totalsize;
-	uint32_t absoffset;
-	size_t len;
-	int err;
-	const char *s, *n;
-
-	if (!fdt_chk_extra()) {
-		s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
-
-		if (lenp)
-			*lenp = strlen(s);
-		return s;
-	}
-	totalsize = fdt_ro_probe_(fdt);
-	err = totalsize;
-	if (totalsize < 0)
-		goto fail;
-
-	err = -FDT_ERR_BADOFFSET;
-	absoffset = stroffset + fdt_off_dt_strings(fdt);
-	if (absoffset >= totalsize)
-		goto fail;
-	len = totalsize - absoffset;
-
-	if (fdt_magic(fdt) == FDT_MAGIC) {
-		if (stroffset < 0)
-			goto fail;
-		if (!fdt_chk_version() || fdt_version(fdt) >= 17) {
-			if (stroffset >= fdt_size_dt_strings(fdt))
-				goto fail;
-			if ((fdt_size_dt_strings(fdt) - stroffset) < len)
-				len = fdt_size_dt_strings(fdt) - stroffset;
-		}
-	} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
-		if ((stroffset >= 0)
-		    || (stroffset < -fdt_size_dt_strings(fdt)))
-			goto fail;
-		if ((-stroffset) < len)
-			len = -stroffset;
-	} else {
-		err = -FDT_ERR_INTERNAL;
-		goto fail;
-	}
-
-	s = (const char *)fdt + absoffset;
-	n = memchr(s, '\0', len);
-	if (!n) {
-		/* missing terminating NULL */
-		err = -FDT_ERR_TRUNCATED;
-		goto fail;
-	}
-
-	if (lenp)
-		*lenp = n - s;
-	return s;
-
-fail:
-	if (lenp)
-		*lenp = err;
-	return NULL;
-}
-
-const char *fdt_string(const void *fdt, int stroffset)
-{
-	return fdt_get_string(fdt, stroffset, NULL);
-}
-
-static int fdt_string_eq_(const void *fdt, int stroffset,
-			  const char *s, int len)
-{
-	int slen;
-	const char *p = fdt_get_string(fdt, stroffset, &slen);
-
-	return p && (slen == len) && (memcmp(p, s, len) == 0);
-}
-
-int fdt_find_max_phandle(const void *fdt, uint32_t *phandle)
-{
-	uint32_t max = 0;
-	int offset = -1;
-
-	while (true) {
-		uint32_t value;
-
-		offset = fdt_next_node(fdt, offset, NULL);
-		if (offset < 0) {
-			if (offset == -FDT_ERR_NOTFOUND)
-				break;
-
-			return offset;
-		}
-
-		value = fdt_get_phandle(fdt, offset);
-
-		if (value > max)
-			max = value;
-	}
-
-	if (phandle)
-		*phandle = max;
-
-	return 0;
-}
-
-int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
-{
-	uint32_t max;
-	int err;
-
-	err = fdt_find_max_phandle(fdt, &max);
-	if (err < 0)
-		return err;
-
-	if (max == FDT_MAX_PHANDLE)
-		return -FDT_ERR_NOPHANDLES;
-
-	if (phandle)
-		*phandle = max + 1;
-
-	return 0;
-}
-
-static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
-{
-	int offset = n * sizeof(struct fdt_reserve_entry);
-	int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
-
-	if (fdt_chk_extra()) {
-		if (absoffset < fdt_off_mem_rsvmap(fdt))
-			return NULL;
-		if (absoffset > fdt_totalsize(fdt) -
-		    sizeof(struct fdt_reserve_entry))
-			return NULL;
-	}
-	return fdt_mem_rsv_(fdt, n);
-}
-
-int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
-{
-	const struct fdt_reserve_entry *re;
-
-	FDT_RO_PROBE(fdt);
-	re = fdt_mem_rsv(fdt, n);
-	if (fdt_chk_extra() && !re)
-		return -FDT_ERR_BADOFFSET;
-
-	*address = fdt64_to_cpu(re->address);
-	*size = fdt64_to_cpu(re->size);
-	return 0;
-}
-
-int fdt_num_mem_rsv(const void *fdt)
-{
-	int i;
-	const struct fdt_reserve_entry *re;
-
-	for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
-		if (fdt64_to_cpu(re->size) == 0)
-			return i;
-	}
-	return -FDT_ERR_TRUNCATED;
-}
-
-static int nextprop_(const void *fdt, int offset)
-{
-	uint32_t tag;
-	int nextoffset;
-
-	do {
-		tag = fdt_next_tag(fdt, offset, &nextoffset);
-
-		switch (tag) {
-		case FDT_END:
-			if (nextoffset >= 0)
-				return -FDT_ERR_BADSTRUCTURE;
-			else
-				return nextoffset;
-
-		case FDT_PROP:
-			return offset;
-		}
-		offset = nextoffset;
-	} while (tag == FDT_NOP);
-
-	return -FDT_ERR_NOTFOUND;
-}
-
-int fdt_subnode_offset_namelen(const void *fdt, int offset,
-			       const char *name, int namelen)
-{
-	int depth;
-
-	FDT_RO_PROBE(fdt);
-
-	for (depth = 0;
-	     (offset >= 0) && (depth >= 0);
-	     offset = fdt_next_node(fdt, offset, &depth))
-		if ((depth == 1)
-		    && fdt_nodename_eq_(fdt, offset, name, namelen))
-			return offset;
-
-	if (depth < 0)
-		return -FDT_ERR_NOTFOUND;
-	return offset; /* error */
-}
-
-int fdt_subnode_offset(const void *fdt, int parentoffset,
-		       const char *name)
-{
-	return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
-}
-
-int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
-{
-	const char *end = path + namelen;
-	const char *p = path;
-	int offset = 0;
-
-	FDT_RO_PROBE(fdt);
-
-	/* see if we have an alias */
-	if (*path != '/') {
-		const char *q = memchr(path, '/', end - p);
-
-		if (!q)
-			q = end;
-
-		p = fdt_get_alias_namelen(fdt, p, q - p);
-		if (!p)
-			return -FDT_ERR_BADPATH;
-		offset = fdt_path_offset(fdt, p);
-
-		p = q;
-	}
-
-	while (p < end) {
-		const char *q;
-
-		while (*p == '/') {
-			p++;
-			if (p == end)
-				return offset;
-		}
-		q = memchr(p, '/', end - p);
-		if (! q)
-			q = end;
-
-		offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);
-		if (offset < 0)
-			return offset;
-
-		p = q;
-	}
-
-	return offset;
-}
-
-int fdt_path_offset(const void *fdt, const char *path)
-{
-	return fdt_path_offset_namelen(fdt, path, strlen(path));
-}
-
-const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
-{
-	const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset);
-	const char *nameptr;
-	int err;
-
-	if (fdt_chk_extra() &&
-	    (((err = fdt_ro_probe_(fdt)) < 0)
-	     || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)))
-		goto fail;
-
-	nameptr = nh->name;
-
-	if (fdt_chk_version() && fdt_version(fdt) < 0x10) {
-		/*
-		 * For old FDT versions, match the naming conventions of V16:
-		 * give only the leaf name (after all /). The actual tree
-		 * contents are loosely checked.
-		 */
-		const char *leaf;
-		leaf = strrchr(nameptr, '/');
-		if (leaf == NULL) {
-			err = -FDT_ERR_BADSTRUCTURE;
-			goto fail;
-		}
-		nameptr = leaf+1;
-	}
-
-	if (len)
-		*len = strlen(nameptr);
-
-	return nameptr;
-
- fail:
-	if (len)
-		*len = err;
-	return NULL;
-}
-
-int fdt_first_property_offset(const void *fdt, int nodeoffset)
-{
-	int offset;
-
-	if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
-		return offset;
-
-	return nextprop_(fdt, offset);
-}
-
-int fdt_next_property_offset(const void *fdt, int offset)
-{
-	if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0)
-		return offset;
-
-	return nextprop_(fdt, offset);
-}
-
-static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
-						              int offset,
-						              int *lenp)
-{
-	int err;
-	const struct fdt_property *prop;
-
-	if (fdt_chk_basic() && (err = fdt_check_prop_offset_(fdt, offset)) < 0) {
-		if (lenp)
-			*lenp = err;
-		return NULL;
-	}
-
-	prop = fdt_offset_ptr_(fdt, offset);
-
-	if (lenp)
-		*lenp = fdt32_to_cpu(prop->len);
-
-	return prop;
-}
-
-const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
-						      int offset,
-						      int *lenp)
-{
-	/* Prior to version 16, properties may need realignment
-	 * and this API does not work. fdt_getprop_*() will, however. */
-
-	if (fdt_chk_version() && fdt_version(fdt) < 0x10) {
-		if (lenp)
-			*lenp = -FDT_ERR_BADVERSION;
-		return NULL;
-	}
-
-	return fdt_get_property_by_offset_(fdt, offset, lenp);
-}
-
-static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
-						            int offset,
-						            const char *name,
-						            int namelen,
-							    int *lenp,
-							    int *poffset)
-{
-	for (offset = fdt_first_property_offset(fdt, offset);
-	     (offset >= 0);
-	     (offset = fdt_next_property_offset(fdt, offset))) {
-		const struct fdt_property *prop;
-
-		prop = fdt_get_property_by_offset_(fdt, offset, lenp);
-		if (fdt_chk_extra() && !prop) {
-			offset = -FDT_ERR_INTERNAL;
-			break;
-		}
-		if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
-				   name, namelen)) {
-			if (poffset)
-				*poffset = offset;
-			return prop;
-		}
-	}
-
-	if (lenp)
-		*lenp = offset;
-	return NULL;
-}
-
-
-const struct fdt_property *fdt_get_property_namelen(const void *fdt,
-						    int offset,
-						    const char *name,
-						    int namelen, int *lenp)
-{
-	/* Prior to version 16, properties may need realignment
-	 * and this API does not work. fdt_getprop_*() will, however. */
-	if (fdt_chk_version() && fdt_version(fdt) < 0x10) {
-		if (lenp)
-			*lenp = -FDT_ERR_BADVERSION;
-		return NULL;
-	}
-
-	return fdt_get_property_namelen_(fdt, offset, name, namelen, lenp,
-					 NULL);
-}
-
-
-const struct fdt_property *fdt_get_property(const void *fdt,
-					    int nodeoffset,
-					    const char *name, int *lenp)
-{
-	return fdt_get_property_namelen(fdt, nodeoffset, name,
-					strlen(name), lenp);
-}
-
-const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
-				const char *name, int namelen, int *lenp)
-{
-	int poffset;
-	const struct fdt_property *prop;
-
-	prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp,
-					 &poffset);
-	if (!prop)
-		return NULL;
-
-	/* Handle realignment */
-	if (fdt_chk_version() && fdt_version(fdt) < 0x10 &&
-	    (poffset + sizeof(*prop)) % 8 && fdt32_to_cpu(prop->len) >= 8)
-		return prop->data + 4;
-	return prop->data;
-}
-
-const void *fdt_getprop_by_offset(const void *fdt, int offset,
-				  const char **namep, int *lenp)
-{
-	const struct fdt_property *prop;
-
-	prop = fdt_get_property_by_offset_(fdt, offset, lenp);
-	if (!prop)
-		return NULL;
-	if (namep) {
-		const char *name;
-		int namelen;
-
-		if (fdt_chk_extra()) {
-			name = fdt_get_string(fdt, fdt32_to_cpu(prop->nameoff),
-					      &namelen);
-			if (!name) {
-				if (lenp)
-					*lenp = namelen;
-				return NULL;
-			}
-			*namep = name;
-		} else {
-			*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
-		}
-	}
-
-	/* Handle realignment */
-	if (fdt_chk_version() && fdt_version(fdt) < 0x10 &&
-	    (offset + sizeof(*prop)) % 8 && fdt32_to_cpu(prop->len) >= 8)
-		return prop->data + 4;
-	return prop->data;
-}
-
-const void *fdt_getprop(const void *fdt, int nodeoffset,
-			const char *name, int *lenp)
-{
-	return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp);
-}
-
-uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
-{
-	const fdt32_t *php;
-	int len;
-
-	/* FIXME: This is a bit sub-optimal, since we potentially scan
-	 * over all the properties twice. */
-	php = fdt_getprop(fdt, nodeoffset, "phandle", &len);
-	if (!php || (len != sizeof(*php))) {
-		php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
-		if (!php || (len != sizeof(*php)))
-			return 0;
-	}
-
-	return fdt32_to_cpu(*php);
-}
-
-const char *fdt_get_alias_namelen(const void *fdt,
-				  const char *name, int namelen)
-{
-	int aliasoffset;
-
-	aliasoffset = fdt_path_offset(fdt, "/aliases");
-	if (aliasoffset < 0)
-		return NULL;
-
-	return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
-}
-
-const char *fdt_get_alias(const void *fdt, const char *name)
-{
-	return fdt_get_alias_namelen(fdt, name, strlen(name));
-}
-
-int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
-{
-	int pdepth = 0, p = 0;
-	int offset, depth, namelen;
-	const char *name;
-
-	FDT_RO_PROBE(fdt);
-
-	if (buflen < 2)
-		return -FDT_ERR_NOSPACE;
-
-	for (offset = 0, depth = 0;
-	     (offset >= 0) && (offset <= nodeoffset);
-	     offset = fdt_next_node(fdt, offset, &depth)) {
-		while (pdepth > depth) {
-			do {
-				p--;
-			} while (buf[p-1] != '/');
-			pdepth--;
-		}
-
-		if (pdepth >= depth) {
-			name = fdt_get_name(fdt, offset, &namelen);
-			if (!name)
-				return namelen;
-			if ((p + namelen + 1) <= buflen) {
-				memcpy(buf + p, name, namelen);
-				p += namelen;
-				buf[p++] = '/';
-				pdepth++;
-			}
-		}
-
-		if (offset == nodeoffset) {
-			if (pdepth < (depth + 1))
-				return -FDT_ERR_NOSPACE;
-
-			if (p > 1) /* special case so that root path is "/", not "" */
-				p--;
-			buf[p] = '\0';
-			return 0;
-		}
-	}
-
-	if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
-		return -FDT_ERR_BADOFFSET;
-	else if (offset == -FDT_ERR_BADOFFSET)
-		return -FDT_ERR_BADSTRUCTURE;
-
-	return offset; /* error from fdt_next_node() */
-}
-
-int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
-				 int supernodedepth, int *nodedepth)
-{
-	int offset, depth;
-	int supernodeoffset = -FDT_ERR_INTERNAL;
-
-	FDT_RO_PROBE(fdt);
-
-	if (supernodedepth < 0)
-		return -FDT_ERR_NOTFOUND;
-
-	for (offset = 0, depth = 0;
-	     (offset >= 0) && (offset <= nodeoffset);
-	     offset = fdt_next_node(fdt, offset, &depth)) {
-		if (depth == supernodedepth)
-			supernodeoffset = offset;
-
-		if (offset == nodeoffset) {
-			if (nodedepth)
-				*nodedepth = depth;
-
-			if (supernodedepth > depth)
-				return -FDT_ERR_NOTFOUND;
-			else
-				return supernodeoffset;
-		}
-	}
-
-	if (fdt_chk_extra()) {
-		if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
-			return -FDT_ERR_BADOFFSET;
-		else if (offset == -FDT_ERR_BADOFFSET)
-			return -FDT_ERR_BADSTRUCTURE;
-	}
-
-	return offset; /* error from fdt_next_node() */
-}
-
-int fdt_node_depth(const void *fdt, int nodeoffset)
-{
-	int nodedepth;
-	int err;
-
-	err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
-	if (err)
-		return (!fdt_chk_extra() || err < 0) ? err : -FDT_ERR_INTERNAL;
-	return nodedepth;
-}
-
-int fdt_parent_offset(const void *fdt, int nodeoffset)
-{
-	int nodedepth = fdt_node_depth(fdt, nodeoffset);
-
-	if (nodedepth < 0)
-		return nodedepth;
-	return fdt_supernode_atdepth_offset(fdt, nodeoffset,
-					    nodedepth - 1, NULL);
-}
-
-int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
-				  const char *propname,
-				  const void *propval, int proplen)
-{
-	int offset;
-	const void *val;
-	int len;
-
-	FDT_RO_PROBE(fdt);
-
-	/* FIXME: The algorithm here is pretty horrible: we scan each
-	 * property of a node in fdt_getprop(), then if that didn't
-	 * find what we want, we scan over them again making our way
-	 * to the next node.  Still it's the easiest to implement
-	 * approach; performance can come later. */
-	for (offset = fdt_next_node(fdt, startoffset, NULL);
-	     offset >= 0;
-	     offset = fdt_next_node(fdt, offset, NULL)) {
-		val = fdt_getprop(fdt, offset, propname, &len);
-		if (val && (len == proplen)
-		    && (memcmp(val, propval, len) == 0))
-			return offset;
-	}
-
-	return offset; /* error from fdt_next_node() */
-}
-
-int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
-{
-	int offset;
-
-	if ((phandle == 0) || (phandle == -1))
-		return -FDT_ERR_BADPHANDLE;
-
-	FDT_RO_PROBE(fdt);
-
-	/* FIXME: The algorithm here is pretty horrible: we
-	 * potentially scan each property of a node in
-	 * fdt_get_phandle(), then if that didn't find what
-	 * we want, we scan over them again making our way to the next
-	 * node.  Still it's the easiest to implement approach;
-	 * performance can come later. */
-	for (offset = fdt_next_node(fdt, -1, NULL);
-	     offset >= 0;
-	     offset = fdt_next_node(fdt, offset, NULL)) {
-		if (fdt_get_phandle(fdt, offset) == phandle)
-			return offset;
-	}
-
-	return offset; /* error from fdt_next_node() */
-}
-
-int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
-{
-	int len = strlen(str);
-	const char *p;
-
-	while (listlen >= len) {
-		if (memcmp(str, strlist, len+1) == 0)
-			return 1;
-		p = memchr(strlist, '\0', listlen);
-		if (!p)
-			return 0; /* malformed strlist.. */
-		listlen -= (p-strlist) + 1;
-		strlist = p + 1;
-	}
-	return 0;
-}
-
-int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property)
-{
-	const char *list, *end;
-	int length, count = 0;
-
-	list = fdt_getprop(fdt, nodeoffset, property, &length);
-	if (!list)
-		return length;
-
-	end = list + length;
-
-	while (list < end) {
-		length = strnlen(list, end - list) + 1;
-
-		/* Abort if the last string isn't properly NUL-terminated. */
-		if (list + length > end)
-			return -FDT_ERR_BADVALUE;
-
-		list += length;
-		count++;
-	}
-
-	return count;
-}
-
-int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
-			  const char *string)
-{
-	int length, len, idx = 0;
-	const char *list, *end;
-
-	list = fdt_getprop(fdt, nodeoffset, property, &length);
-	if (!list)
-		return length;
-
-	len = strlen(string) + 1;
-	end = list + length;
-
-	while (list < end) {
-		length = strnlen(list, end - list) + 1;
-
-		/* Abort if the last string isn't properly NUL-terminated. */
-		if (list + length > end)
-			return -FDT_ERR_BADVALUE;
-
-		if (length == len && memcmp(list, string, length) == 0)
-			return idx;
-
-		list += length;
-		idx++;
-	}
-
-	return -FDT_ERR_NOTFOUND;
-}
-
-const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
-			       const char *property, int idx,
-			       int *lenp)
-{
-	const char *list, *end;
-	int length;
-
-	list = fdt_getprop(fdt, nodeoffset, property, &length);
-	if (!list) {
-		if (lenp)
-			*lenp = length;
-
-		return NULL;
-	}
-
-	end = list + length;
-
-	while (list < end) {
-		length = strnlen(list, end - list) + 1;
-
-		/* Abort if the last string isn't properly NUL-terminated. */
-		if (list + length > end) {
-			if (lenp)
-				*lenp = -FDT_ERR_BADVALUE;
-
-			return NULL;
-		}
-
-		if (idx == 0) {
-			if (lenp)
-				*lenp = length - 1;
-
-			return list;
-		}
-
-		list += length;
-		idx--;
-	}
-
-	if (lenp)
-		*lenp = -FDT_ERR_NOTFOUND;
-
-	return NULL;
-}
-
-int fdt_node_check_compatible(const void *fdt, int nodeoffset,
-			      const char *compatible)
-{
-	const void *prop;
-	int len;
-
-	prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
-	if (!prop)
-		return len;
-
-	return !fdt_stringlist_contains(prop, len, compatible);
-}
-
-int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
-				  const char *compatible)
-{
-	int offset, err;
-
-	FDT_RO_PROBE(fdt);
-
-	/* FIXME: The algorithm here is pretty horrible: we scan each
-	 * property of a node in fdt_node_check_compatible(), then if
-	 * that didn't find what we want, we scan over them again
-	 * making our way to the next node.  Still it's the easiest to
-	 * implement approach; performance can come later. */
-	for (offset = fdt_next_node(fdt, startoffset, NULL);
-	     offset >= 0;
-	     offset = fdt_next_node(fdt, offset, NULL)) {
-		err = fdt_node_check_compatible(fdt, offset, compatible);
-		if ((err < 0) && (err != -FDT_ERR_NOTFOUND))
-			return err;
-		else if (err == 0)
-			return offset;
-	}
-
-	return offset; /* error from fdt_next_node() */
-}
-
-#if !defined(CHECK_LEVEL) || CHECK_LEVEL > 0
-int fdt_check_full(const void *fdt, size_t bufsize)
-{
-	int err;
-	int num_memrsv;
-	int offset, nextoffset = 0;
-	uint32_t tag;
-	unsigned depth = 0;
-	const void *prop;
-	const char *propname;
-
-	if (bufsize < FDT_V1_SIZE)
-		return -FDT_ERR_TRUNCATED;
-	err = fdt_check_header(fdt);
-	if (err != 0)
-		return err;
-	if (bufsize < fdt_totalsize(fdt))
-		return -FDT_ERR_TRUNCATED;
-
-	num_memrsv = fdt_num_mem_rsv(fdt);
-	if (num_memrsv < 0)
-		return num_memrsv;
-
-	while (1) {
-		offset = nextoffset;
-		tag = fdt_next_tag(fdt, offset, &nextoffset);
-
-		if (nextoffset < 0)
-			return nextoffset;
-
-		switch (tag) {
-		case FDT_NOP:
-			break;
-
-		case FDT_END:
-			if (depth != 0)
-				return -FDT_ERR_BADSTRUCTURE;
-			return 0;
-
-		case FDT_BEGIN_NODE:
-			depth++;
-			if (depth > INT_MAX)
-				return -FDT_ERR_BADSTRUCTURE;
-			break;
-
-		case FDT_END_NODE:
-			if (depth == 0)
-				return -FDT_ERR_BADSTRUCTURE;
-			depth--;
-			break;
-
-		case FDT_PROP:
-			prop = fdt_getprop_by_offset(fdt, offset, &propname,
-						     &err);
-			if (!prop)
-				return err;
-			break;
-
-		default:
-			return -FDT_ERR_INTERNAL;
-		}
-	}
-}
-#endif
+#include "../../scripts/dtc/libfdt/fdt_ro.c"
diff --git a/test/run b/test/run
index d635622..27331a8 100755
--- a/test/run
+++ b/test/run
@@ -15,22 +15,29 @@
 
 # SKip slow tests if requested
 [ "$1" == "quick" ] && mark_expr="not slow"
+[ "$1" == "quick" ] && skip=--skip-net-tests
+[ "$1" == "tools" ] && tools_only=y
 
 failures=0
 
-# Run all tests that the standard sandbox build can support
-run_test "sandbox" ./test/py/test.py --bd sandbox --build -m "${mark_expr}"
+if [ -z "$tools_only" ]; then
+	# Run all tests that the standard sandbox build can support
+	run_test "sandbox" ./test/py/test.py --bd sandbox --build \
+		-m "${mark_expr}"
+fi
 
 # Run tests which require sandbox_spl
 run_test "sandbox_spl" ./test/py/test.py --bd sandbox_spl --build \
-	-k 'test_ofplatdata or test_handoff'
+		-k 'test_ofplatdata or test_handoff'
 
-# Run tests for the flat-device-tree version of sandbox. This is a special
-# build which does not enable CONFIG_OF_LIVE for the live device tree, so we can
-# check that functionality is the same. The standard sandbox build (above) uses
-# CONFIG_OF_LIVE.
-run_test "sandbox_flattree" ./test/py/test.py --bd sandbox_flattree --build \
-	-k test_ut
+if [ -z "$tools_only" ]; then
+	# Run tests for the flat-device-tree version of sandbox. This is a special
+	# build which does not enable CONFIG_OF_LIVE for the live device tree, so we can
+	# check that functionality is the same. The standard sandbox build (above) uses
+	# CONFIG_OF_LIVE.
+	run_test "sandbox_flattree" ./test/py/test.py --bd sandbox_flattree \
+		--build -k test_ut
+fi
 
 # Set up a path to dtc (device-tree compiler) and libfdt.py, a library it
 # provides and which is built by the sandbox_spl config. Also set up the path
@@ -43,7 +50,6 @@
 run_test "binman" ./tools/binman/binman --toolpath ${TOOLS_DIR} test
 run_test "patman" ./tools/patman/patman --test
 
-[ "$1" == "quick" ] && skip=--skip-net-tests
 run_test "buildman" ./tools/buildman/buildman -t ${skip}
 run_test "fdt" ./tools/dtoc/test_fdt -t
 run_test "dtoc" ./tools/dtoc/dtoc -t
diff --git a/tools/Makefile b/tools/Makefile
index c2b2634..1f9144f 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -63,14 +63,8 @@
 
 # The following files are synced with upstream DTC.
 # Use synced versions from scripts/dtc/libfdt/.
-LIBFDT_SRCS_SYNCED := fdt.c fdt_wip.c fdt_sw.c fdt_rw.c \
-		fdt_strerror.c fdt_empty_tree.c fdt_addresses.c fdt_overlay.c
-# The following files are locally modified for U-Boot (unfotunately).
-# Use U-Boot own versions from lib/libfdt/.
-LIBFDT_SRCS_UNSYNCED := fdt_ro.c fdt_region.c
-
-LIBFDT_OBJS := $(addprefix libfdt/, $(patsubst %.c, %.o, $(LIBFDT_SRCS_SYNCED))) \
-	       $(addprefix lib/libfdt/, $(patsubst %.c, %.o, $(LIBFDT_SRCS_UNSYNCED)))
+LIBFDT_OBJS := $(addprefix libfdt/, fdt.o fdt_ro.o fdt_wip.o fdt_sw.o fdt_rw.o \
+		fdt_strerror.o fdt_empty_tree.o fdt_addresses.o fdt_overlay.o)
 
 RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := $(addprefix lib/rsa/, \
 					rsa-sign.o rsa-verify.o rsa-checksum.o \
@@ -87,6 +81,7 @@
 			$(FIT_OBJS-y) \
 			$(FIT_SIG_OBJS-y) \
 			$(FIT_CIPHER_OBJS-y) \
+			common/fdt_region.o \
 			common/bootm.o \
 			lib/crc32.o \
 			default_image.o \
@@ -211,7 +206,7 @@
 hostprogs-$(CONFIG_RISCV) += prelink-riscv
 
 hostprogs-y += fdtgrep
-fdtgrep-objs += $(LIBFDT_OBJS) fdtgrep.o
+fdtgrep-objs += $(LIBFDT_OBJS) common/fdt_region.o fdtgrep.o
 
 ifneq ($(TOOLS_ONLY),y)
 hostprogs-y += spl_size_limit
diff --git a/tools/binman/binman b/tools/binman/binman
index 979b7e4..11a5d8e 120000
--- a/tools/binman/binman
+++ b/tools/binman/binman
@@ -1 +1 @@
-binman.py
\ No newline at end of file
+main.py
\ No newline at end of file
diff --git a/tools/binman/binman.py b/tools/binman/binman.py
deleted file mode 100755
index 9e6fd72..0000000
--- a/tools/binman/binman.py
+++ /dev/null
@@ -1,202 +0,0 @@
-#!/usr/bin/env python3
-# SPDX-License-Identifier: GPL-2.0+
-
-# Copyright (c) 2016 Google, Inc
-# Written by Simon Glass <sjg@chromium.org>
-#
-# Creates binary images from input files controlled by a description
-#
-
-"""See README for more information"""
-
-from __future__ import print_function
-
-from distutils.sysconfig import get_python_lib
-import glob
-import multiprocessing
-import os
-import site
-import sys
-import traceback
-import unittest
-
-# Bring in the patman and dtoc libraries (but don't override the first path
-# in PYTHONPATH)
-our_path = os.path.dirname(os.path.realpath(__file__))
-for dirname in ['../patman', '../dtoc', '..', '../concurrencytest']:
-    sys.path.insert(2, os.path.join(our_path, dirname))
-
-# Bring in the libfdt module
-sys.path.insert(2, 'scripts/dtc/pylibfdt')
-sys.path.insert(2, os.path.join(our_path,
-                '../../build-sandbox_spl/scripts/dtc/pylibfdt'))
-
-# When running under python-coverage on Ubuntu 16.04, the dist-packages
-# directories are dropped from the python path. Add them in so that we can find
-# the elffile module. We could use site.getsitepackages() here but unfortunately
-# that is not available in a virtualenv.
-sys.path.append(get_python_lib())
-
-import cmdline
-import command
-use_concurrent = True
-try:
-    from concurrencytest import ConcurrentTestSuite, fork_for_tests
-except:
-    use_concurrent = False
-import control
-import test_util
-
-def RunTests(debug, verbosity, processes, test_preserve_dirs, args, toolpath):
-    """Run the functional tests and any embedded doctests
-
-    Args:
-        debug: True to enable debugging, which shows a full stack trace on error
-        verbosity: Verbosity level to use
-        test_preserve_dirs: True to preserve the input directory used by tests
-            so that it can be examined afterwards (only useful for debugging
-            tests). If a single test is selected (in args[0]) it also preserves
-            the output directory for this test. Both directories are displayed
-            on the command line.
-        processes: Number of processes to use to run tests (None=same as #CPUs)
-        args: List of positional args provided to binman. This can hold a test
-            name to execute (as in 'binman test testSections', for example)
-        toolpath: List of paths to use for tools
-    """
-    import cbfs_util_test
-    import elf_test
-    import entry_test
-    import fdt_test
-    import ftest
-    import image_test
-    import test
-    import doctest
-
-    result = unittest.TestResult()
-    for module in []:
-        suite = doctest.DocTestSuite(module)
-        suite.run(result)
-
-    sys.argv = [sys.argv[0]]
-    if debug:
-        sys.argv.append('-D')
-    if verbosity:
-        sys.argv.append('-v%d' % verbosity)
-    if toolpath:
-        for path in toolpath:
-            sys.argv += ['--toolpath', path]
-
-    # Run the entry tests first ,since these need to be the first to import the
-    # 'entry' module.
-    test_name = args and args[0] or None
-    suite = unittest.TestSuite()
-    loader = unittest.TestLoader()
-    for module in (entry_test.TestEntry, ftest.TestFunctional, fdt_test.TestFdt,
-                   elf_test.TestElf, image_test.TestImage,
-                   cbfs_util_test.TestCbfs):
-        # Test the test module about our arguments, if it is interested
-        if hasattr(module, 'setup_test_args'):
-            setup_test_args = getattr(module, 'setup_test_args')
-            setup_test_args(preserve_indir=test_preserve_dirs,
-                preserve_outdirs=test_preserve_dirs and test_name is not None,
-                toolpath=toolpath, verbosity=verbosity)
-        if test_name:
-            try:
-                suite.addTests(loader.loadTestsFromName(test_name, module))
-            except AttributeError:
-                continue
-        else:
-            suite.addTests(loader.loadTestsFromTestCase(module))
-    if use_concurrent and processes != 1:
-        concurrent_suite = ConcurrentTestSuite(suite,
-                fork_for_tests(processes or multiprocessing.cpu_count()))
-        concurrent_suite.run(result)
-    else:
-        suite.run(result)
-
-    # Remove errors which just indicate a missing test. Since Python v3.5 If an
-    # ImportError or AttributeError occurs while traversing name then a
-    # synthetic test that raises that error when run will be returned. These
-    # errors are included in the errors accumulated by result.errors.
-    if test_name:
-        errors = []
-        for test, err in result.errors:
-            if ("has no attribute '%s'" % test_name) not in err:
-                errors.append((test, err))
-            result.testsRun -= 1
-        result.errors = errors
-
-    print(result)
-    for test, err in result.errors:
-        print(test.id(), err)
-    for test, err in result.failures:
-        print(err, result.failures)
-    if result.skipped:
-        print('%d binman test%s SKIPPED:' %
-              (len(result.skipped), 's' if len(result.skipped) > 1 else ''))
-        for skip_info in result.skipped:
-            print('%s: %s' % (skip_info[0], skip_info[1]))
-    if result.errors or result.failures:
-        print('binman tests FAILED')
-        return 1
-    return 0
-
-def GetEntryModules(include_testing=True):
-    """Get a set of entry class implementations
-
-    Returns:
-        Set of paths to entry class filenames
-    """
-    glob_list = glob.glob(os.path.join(our_path, 'etype/*.py'))
-    return set([os.path.splitext(os.path.basename(item))[0]
-                for item in glob_list
-                if include_testing or '_testing' not in item])
-
-def RunTestCoverage():
-    """Run the tests and check that we get 100% coverage"""
-    glob_list = GetEntryModules(False)
-    all_set = set([os.path.splitext(os.path.basename(item))[0]
-                   for item in glob_list if '_testing' not in item])
-    test_util.RunTestCoverage('tools/binman/binman.py', None,
-            ['*test*', '*binman.py', 'tools/patman/*', 'tools/dtoc/*'],
-            args.build_dir, all_set)
-
-def RunBinman(args):
-    """Main entry point to binman once arguments are parsed
-
-    Args:
-        args: Command line arguments Namespace object
-    """
-    ret_code = 0
-
-    if not args.debug:
-        sys.tracebacklimit = 0
-
-    if args.cmd == 'test':
-        if args.test_coverage:
-            RunTestCoverage()
-        else:
-            ret_code = RunTests(args.debug, args.verbosity, args.processes,
-                                args.test_preserve_dirs, args.tests,
-                                args.toolpath)
-
-    elif args.cmd == 'entry-docs':
-        control.WriteEntryDocs(GetEntryModules())
-
-    else:
-        try:
-            ret_code = control.Binman(args)
-        except Exception as e:
-            print('binman: %s' % e)
-            if args.debug:
-                print()
-                traceback.print_exc()
-            ret_code = 1
-    return ret_code
-
-
-if __name__ == "__main__":
-    args = cmdline.ParseArgs(sys.argv[1:])
-
-    ret_code = RunBinman(args)
-    sys.exit(ret_code)
diff --git a/tools/binman/cbfs_util.py b/tools/binman/cbfs_util.py
index 99d7787..3997337 100644
--- a/tools/binman/cbfs_util.py
+++ b/tools/binman/cbfs_util.py
@@ -15,16 +15,14 @@
     with empty files, fixed-offset files
 """
 
-from __future__ import print_function
-
 from collections import OrderedDict
 import io
 import struct
 import sys
 
-import command
-import elf
-import tools
+from binman import elf
+from patman import command
+from patman import tools
 
 # Set to True to enable printing output while working
 DEBUG = False
diff --git a/tools/binman/cbfs_util_test.py b/tools/binman/cbfs_util_test.py
index ddc2e09..2c62c8a 100755
--- a/tools/binman/cbfs_util_test.py
+++ b/tools/binman/cbfs_util_test.py
@@ -9,8 +9,6 @@
 values and with cbfstool
 """
 
-from __future__ import print_function
-
 import io
 import os
 import shutil
@@ -18,11 +16,11 @@
 import tempfile
 import unittest
 
-import cbfs_util
-from cbfs_util import CbfsWriter
-import elf
-import test_util
-import tools
+from binman import cbfs_util
+from binman.cbfs_util import CbfsWriter
+from binman import elf
+from patman import test_util
+from patman import tools
 
 U_BOOT_DATA           = b'1234'
 U_BOOT_DTB_DATA       = b'udtb'
diff --git a/tools/binman/control.py b/tools/binman/control.py
index 68ad5fc..dc1dd2a 100644
--- a/tools/binman/control.py
+++ b/tools/binman/control.py
@@ -5,17 +5,15 @@
 # Creates binary images from input files controlled by a description
 #
 
-from __future__ import print_function
-
 from collections import OrderedDict
 import os
 import sys
-import tools
+from patman import tools
 
-import cbfs_util
-import command
-import elf
-import tout
+from binman import cbfs_util
+from binman import elf
+from patman import command
+from patman import tout
 
 # List of images we plan to create
 # Make this global so that it can be referenced from tests
@@ -62,7 +60,7 @@
             to show as missing even if it is present. Should be set to None in
             normal use.
     """
-    from entry import Entry
+    from binman.entry import Entry
     Entry.WriteDocs(modules, test_missing)
 
 
@@ -336,8 +334,8 @@
     """
     # Import these here in case libfdt.py is not available, in which case
     # the above help option still works.
-    import fdt
-    import fdt_util
+    from dtoc import fdt
+    from dtoc import fdt_util
     global images
 
     # Get the device tree ready by compiling it and copying the compiled
@@ -475,7 +473,7 @@
 
     # Put these here so that we can import this module without libfdt
     from image import Image
-    import state
+    from binman import state
 
     if args.cmd in ['ls', 'extract', 'replace']:
         try:
diff --git a/tools/binman/elf.py b/tools/binman/elf.py
index de1ce73..f88031c 100644
--- a/tools/binman/elf.py
+++ b/tools/binman/elf.py
@@ -5,10 +5,7 @@
 # Handle various things related to ELF images
 #
 
-from __future__ import print_function
-
 from collections import namedtuple, OrderedDict
-import command
 import io
 import os
 import re
@@ -16,8 +13,9 @@
 import struct
 import tempfile
 
-import tools
-import tout
+from patman import command
+from patman import tools
+from patman import tout
 
 ELF_TOOLS = True
 try:
diff --git a/tools/binman/elf_test.py b/tools/binman/elf_test.py
index ac26fd5..37e1b42 100644
--- a/tools/binman/elf_test.py
+++ b/tools/binman/elf_test.py
@@ -10,11 +10,11 @@
 import tempfile
 import unittest
 
-import command
-import elf
-import test_util
-import tools
-import tout
+from binman import elf
+from patman import command
+from patman import test_util
+from patman import tools
+from patman import tout
 
 binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
 
diff --git a/tools/binman/entry.py b/tools/binman/entry.py
index b6f1b2c..90ffd27 100644
--- a/tools/binman/entry.py
+++ b/tools/binman/entry.py
@@ -4,17 +4,15 @@
 # Base class for all entries
 #
 
-from __future__ import print_function
-
 from collections import namedtuple
 import importlib
 import os
 import sys
 
-import fdt_util
-import tools
-from tools import ToHex, ToHexSize
-import tout
+from dtoc import fdt_util
+from patman import tools
+from patman.tools import ToHex, ToHexSize
+from patman import tout
 
 modules = {}
 
@@ -65,7 +63,7 @@
     def __init__(self, section, etype, node, name_prefix=''):
         # Put this here to allow entry-docs and help to work without libfdt
         global state
-        import state
+        from binman import state
 
         self.section = section
         self.etype = etype
@@ -110,15 +108,11 @@
 
         # Import the module if we have not already done so.
         if not module:
-            old_path = sys.path
-            sys.path.insert(0, os.path.join(our_path, 'etype'))
             try:
-                module = importlib.import_module(module_name)
+                module = importlib.import_module('binman.etype.' + module_name)
             except ImportError as e:
                 raise ValueError("Unknown entry type '%s' in node '%s' (expected etype/%s.py, error '%s'" %
                                  (etype, node_path, module_name, e))
-            finally:
-                sys.path = old_path
             modules[module_name] = module
 
         # Look up the expected class name
@@ -592,9 +586,7 @@
             modules.remove('_testing')
         missing = []
         for name in modules:
-            if name.startswith('__'):
-                continue
-            module = Entry.Lookup(name, name)
+            module = Entry.Lookup('WriteDocs', name)
             docs = getattr(module, '__doc__')
             if test_missing == name:
                 docs = None
diff --git a/tools/binman/entry_test.py b/tools/binman/entry_test.py
index 277e10b..80802f3 100644
--- a/tools/binman/entry_test.py
+++ b/tools/binman/entry_test.py
@@ -9,10 +9,10 @@
 import sys
 import unittest
 
-import entry
-import fdt
-import fdt_util
-import tools
+from binman import entry
+from dtoc import fdt
+from dtoc import fdt_util
+from patman import tools
 
 class TestEntry(unittest.TestCase):
     def setUp(self):
@@ -37,11 +37,11 @@
             else:
                 reload(entry)
         else:
-            import entry
+            from binman import entry
 
     def testEntryContents(self):
         """Test the Entry bass class"""
-        import entry
+        from binman import entry
         base_entry = entry.Entry(None, None, None)
         self.assertEqual(True, base_entry.ObtainContents())
 
diff --git a/tools/binman/etype/__init__.py b/tools/binman/etype/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tools/binman/etype/__init__.py
+++ /dev/null
diff --git a/tools/binman/etype/_testing.py b/tools/binman/etype/_testing.py
index 25a6206..ed718ee 100644
--- a/tools/binman/etype/_testing.py
+++ b/tools/binman/etype/_testing.py
@@ -7,9 +7,9 @@
 
 from collections import OrderedDict
 
-from entry import Entry, EntryArg
-import fdt_util
-import tools
+from binman.entry import Entry, EntryArg
+from dtoc import fdt_util
+from patman import tools
 
 
 class Entry__testing(Entry):
diff --git a/tools/binman/etype/blob.py b/tools/binman/etype/blob.py
index d34c7b5..ede7a7a 100644
--- a/tools/binman/etype/blob.py
+++ b/tools/binman/etype/blob.py
@@ -5,10 +5,10 @@
 # Entry-type module for blobs, which are binary objects read from files
 #
 
-from entry import Entry
-import fdt_util
-import tools
-import tout
+from binman.entry import Entry
+from dtoc import fdt_util
+from patman import tools
+from patman import tout
 
 class Entry_blob(Entry):
     """Entry containing an arbitrary binary blob
diff --git a/tools/binman/etype/blob_dtb.py b/tools/binman/etype/blob_dtb.py
index b2afa06..6c06943 100644
--- a/tools/binman/etype/blob_dtb.py
+++ b/tools/binman/etype/blob_dtb.py
@@ -5,8 +5,8 @@
 # Entry-type module for U-Boot device tree files
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_blob_dtb(Entry_blob):
     """A blob that holds a device tree
@@ -18,7 +18,7 @@
     def __init__(self, section, etype, node):
         # Put this here to allow entry-docs and help to work without libfdt
         global state
-        import state
+        from binman import state
 
         Entry_blob.__init__(self, section, etype, node)
 
diff --git a/tools/binman/etype/blob_named_by_arg.py b/tools/binman/etype/blob_named_by_arg.py
index 344112b..3b4593f 100644
--- a/tools/binman/etype/blob_named_by_arg.py
+++ b/tools/binman/etype/blob_named_by_arg.py
@@ -8,8 +8,8 @@
 
 from collections import OrderedDict
 
-from blob import Entry_blob
-from entry import EntryArg
+from binman.etype.blob import Entry_blob
+from binman.entry import EntryArg
 
 
 class Entry_blob_named_by_arg(Entry_blob):
diff --git a/tools/binman/etype/cbfs.py b/tools/binman/etype/cbfs.py
index 35b7837..e9aed83 100644
--- a/tools/binman/etype/cbfs.py
+++ b/tools/binman/etype/cbfs.py
@@ -7,10 +7,10 @@
 
 from collections import OrderedDict
 
-import cbfs_util
-from cbfs_util import CbfsWriter
-from entry import Entry
-import fdt_util
+from binman import cbfs_util
+from binman.cbfs_util import CbfsWriter
+from binman.entry import Entry
+from dtoc import fdt_util
 
 class Entry_cbfs(Entry):
     """Entry containing a Coreboot Filesystem (CBFS)
@@ -165,7 +165,7 @@
     def __init__(self, section, etype, node):
         # Put this here to allow entry-docs and help to work without libfdt
         global state
-        import state
+        from binman import state
 
         Entry.__init__(self, section, etype, node)
         self._cbfs_arg = fdt_util.GetString(node, 'cbfs-arch', 'x86')
diff --git a/tools/binman/etype/cros_ec_rw.py b/tools/binman/etype/cros_ec_rw.py
index 261f865..0dbe14b 100644
--- a/tools/binman/etype/cros_ec_rw.py
+++ b/tools/binman/etype/cros_ec_rw.py
@@ -5,7 +5,7 @@
 # Entry-type module for a Chromium OS EC image (read-write section)
 #
 
-from blob_named_by_arg import Entry_blob_named_by_arg
+from binman.etype.blob_named_by_arg import Entry_blob_named_by_arg
 
 
 class Entry_cros_ec_rw(Entry_blob_named_by_arg):
diff --git a/tools/binman/etype/fdtmap.py b/tools/binman/etype/fdtmap.py
index 5dc08b8..aa88079 100644
--- a/tools/binman/etype/fdtmap.py
+++ b/tools/binman/etype/fdtmap.py
@@ -8,9 +8,9 @@
 image.
 """
 
-from entry import Entry
-import tools
-import tout
+from binman.entry import Entry
+from patman import tools
+from patman import tout
 
 FDTMAP_MAGIC   = b'_FDTMAP_'
 FDTMAP_HDR_LEN = 16
@@ -82,8 +82,8 @@
         global Fdt
 
         import libfdt
-        import state
-        from fdt import Fdt
+        from binman import state
+        from dtoc.fdt import Fdt
 
         Entry.__init__(self, section, etype, node)
 
diff --git a/tools/binman/etype/files.py b/tools/binman/etype/files.py
index 3473a2b..10ab585 100644
--- a/tools/binman/etype/files.py
+++ b/tools/binman/etype/files.py
@@ -9,9 +9,9 @@
 import glob
 import os
 
-from section import Entry_section
-import fdt_util
-import tools
+from binman.etype.section import Entry_section
+from dtoc import fdt_util
+from patman import tools
 
 
 class Entry_files(Entry_section):
@@ -30,7 +30,7 @@
     def __init__(self, section, etype, node):
         # Put this here to allow entry-docs and help to work without libfdt
         global state
-        import state
+        from binman import state
 
         Entry_section.__init__(self, section, etype, node)
         self._pattern = fdt_util.GetString(self._node, 'pattern')
diff --git a/tools/binman/etype/fill.py b/tools/binman/etype/fill.py
index 623b7f4..860410e 100644
--- a/tools/binman/etype/fill.py
+++ b/tools/binman/etype/fill.py
@@ -3,9 +3,9 @@
 # Written by Simon Glass <sjg@chromium.org>
 #
 
-from entry import Entry
-import fdt_util
-import tools
+from binman.entry import Entry
+from dtoc import fdt_util
+from patman import tools
 
 class Entry_fill(Entry):
     """An entry which is filled to a particular byte value
diff --git a/tools/binman/etype/fmap.py b/tools/binman/etype/fmap.py
index 835ba50..a43fac3 100644
--- a/tools/binman/etype/fmap.py
+++ b/tools/binman/etype/fmap.py
@@ -5,11 +5,11 @@
 # Entry-type module for a Flash map, as used by the flashrom SPI flash tool
 #
 
-from entry import Entry
-import fmap_util
-import tools
-from tools import ToHexSize
-import tout
+from binman.entry import Entry
+from binman import fmap_util
+from patman import tools
+from patman.tools import ToHexSize
+from patman import tout
 
 
 class Entry_fmap(Entry):
diff --git a/tools/binman/etype/gbb.py b/tools/binman/etype/gbb.py
index a94c0fc..dd10599 100644
--- a/tools/binman/etype/gbb.py
+++ b/tools/binman/etype/gbb.py
@@ -8,11 +8,11 @@
 
 from collections import OrderedDict
 
-import command
-from entry import Entry, EntryArg
+from patman import command
+from binman.entry import Entry, EntryArg
 
-import fdt_util
-import tools
+from dtoc import fdt_util
+from patman import tools
 
 # Build GBB flags.
 # (src/platform/vboot_reference/firmware/include/gbb_header.h)
diff --git a/tools/binman/etype/image_header.py b/tools/binman/etype/image_header.py
index b9327dd..176bdeb 100644
--- a/tools/binman/etype/image_header.py
+++ b/tools/binman/etype/image_header.py
@@ -11,8 +11,8 @@
 
 import struct
 
-from entry import Entry
-import fdt_util
+from binman.entry import Entry
+from dtoc import fdt_util
 
 IMAGE_HEADER_MAGIC = b'BinM'
 IMAGE_HEADER_LEN   = 8
diff --git a/tools/binman/etype/intel_cmc.py b/tools/binman/etype/intel_cmc.py
index fa6f779..5e6edbe 100644
--- a/tools/binman/etype/intel_cmc.py
+++ b/tools/binman/etype/intel_cmc.py
@@ -5,8 +5,8 @@
 # Entry-type module for Intel Chip Microcode binary blob
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_intel_cmc(Entry_blob):
     """Entry containing an Intel Chipset Micro Code (CMC) file
diff --git a/tools/binman/etype/intel_descriptor.py b/tools/binman/etype/intel_descriptor.py
index b647793..d4d7a26 100644
--- a/tools/binman/etype/intel_descriptor.py
+++ b/tools/binman/etype/intel_descriptor.py
@@ -7,8 +7,8 @@
 
 import struct
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 FD_SIGNATURE   = struct.pack('<L', 0x0ff0a55a)
 MAX_REGIONS    = 5
diff --git a/tools/binman/etype/intel_fit.py b/tools/binman/etype/intel_fit.py
index 2a34a05..ea482a6 100644
--- a/tools/binman/etype/intel_fit.py
+++ b/tools/binman/etype/intel_fit.py
@@ -7,7 +7,7 @@
 
 import struct
 
-from blob import Entry_blob
+from binman.etype.blob import Entry_blob
 
 class Entry_intel_fit(Entry_blob):
     """Intel Firmware Image Table (FIT)
diff --git a/tools/binman/etype/intel_fit_ptr.py b/tools/binman/etype/intel_fit_ptr.py
index 148b206..df118a6 100644
--- a/tools/binman/etype/intel_fit_ptr.py
+++ b/tools/binman/etype/intel_fit_ptr.py
@@ -7,7 +7,7 @@
 
 import struct
 
-from blob import Entry_blob
+from binman.etype.blob import Entry_blob
 
 class Entry_intel_fit_ptr(Entry_blob):
     """Intel Firmware Image Table (FIT) pointer
diff --git a/tools/binman/etype/intel_fsp.py b/tools/binman/etype/intel_fsp.py
index 00a78e7..7db3d96 100644
--- a/tools/binman/etype/intel_fsp.py
+++ b/tools/binman/etype/intel_fsp.py
@@ -5,8 +5,8 @@
 # Entry-type module for Intel Firmware Support Package binary blob
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_intel_fsp(Entry_blob):
     """Entry containing an Intel Firmware Support Package (FSP) file
diff --git a/tools/binman/etype/intel_fsp_m.py b/tools/binman/etype/intel_fsp_m.py
index bb1de73..51b4e7e 100644
--- a/tools/binman/etype/intel_fsp_m.py
+++ b/tools/binman/etype/intel_fsp_m.py
@@ -5,8 +5,8 @@
 # Entry-type module for Intel Firmware Support Package binary blob (M section)
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_intel_fsp_m(Entry_blob):
     """Entry containing Intel Firmware Support Package (FSP) memory init
diff --git a/tools/binman/etype/intel_fsp_s.py b/tools/binman/etype/intel_fsp_s.py
index 3d6900d..b3683e4 100644
--- a/tools/binman/etype/intel_fsp_s.py
+++ b/tools/binman/etype/intel_fsp_s.py
@@ -5,8 +5,8 @@
 # Entry-type module for Intel Firmware Support Package binary blob (S section)
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_intel_fsp_s(Entry_blob):
     """Entry containing Intel Firmware Support Package (FSP) silicon init
diff --git a/tools/binman/etype/intel_fsp_t.py b/tools/binman/etype/intel_fsp_t.py
index 813a81f..0f196f0 100644
--- a/tools/binman/etype/intel_fsp_t.py
+++ b/tools/binman/etype/intel_fsp_t.py
@@ -5,8 +5,8 @@
 # Entry-type module for Intel Firmware Support Package binary blob (T section)
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_intel_fsp_t(Entry_blob):
     """Entry containing Intel Firmware Support Package (FSP) temp ram init
diff --git a/tools/binman/etype/intel_ifwi.py b/tools/binman/etype/intel_ifwi.py
index 36aadc2..6a96f6b 100644
--- a/tools/binman/etype/intel_ifwi.py
+++ b/tools/binman/etype/intel_ifwi.py
@@ -7,10 +7,10 @@
 
 from collections import OrderedDict
 
-from entry import Entry
-from blob import Entry_blob
-import fdt_util
-import tools
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
+from dtoc import fdt_util
+from patman import tools
 
 class Entry_intel_ifwi(Entry_blob):
     """Entry containing an Intel Integrated Firmware Image (IFWI) file
diff --git a/tools/binman/etype/intel_me.py b/tools/binman/etype/intel_me.py
index c932ec5..41c9c6b 100644
--- a/tools/binman/etype/intel_me.py
+++ b/tools/binman/etype/intel_me.py
@@ -5,8 +5,8 @@
 # Entry-type module for Intel Management Engine binary blob
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_intel_me(Entry_blob):
     """Entry containing an Intel Management Engine (ME) file
diff --git a/tools/binman/etype/intel_mrc.py b/tools/binman/etype/intel_mrc.py
index 4dbc99a..854a4dd 100644
--- a/tools/binman/etype/intel_mrc.py
+++ b/tools/binman/etype/intel_mrc.py
@@ -5,8 +5,8 @@
 # Entry-type module for Intel Memory Reference Code binary blob
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_intel_mrc(Entry_blob):
     """Entry containing an Intel Memory Reference Code (MRC) file
diff --git a/tools/binman/etype/intel_refcode.py b/tools/binman/etype/intel_refcode.py
index 045db58..a1059f7 100644
--- a/tools/binman/etype/intel_refcode.py
+++ b/tools/binman/etype/intel_refcode.py
@@ -5,8 +5,8 @@
 # Entry-type module for Intel Memory Reference Code binary blob
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_intel_refcode(Entry_blob):
     """Entry containing an Intel Reference Code file
diff --git a/tools/binman/etype/intel_vbt.py b/tools/binman/etype/intel_vbt.py
index d93dd19..4d465ad 100644
--- a/tools/binman/etype/intel_vbt.py
+++ b/tools/binman/etype/intel_vbt.py
@@ -4,8 +4,8 @@
 # Entry-type module for Intel Video BIOS Table binary blob
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_intel_vbt(Entry_blob):
     """Entry containing an Intel Video BIOS Table (VBT) file
diff --git a/tools/binman/etype/intel_vga.py b/tools/binman/etype/intel_vga.py
index 40982c8..04cd72f 100644
--- a/tools/binman/etype/intel_vga.py
+++ b/tools/binman/etype/intel_vga.py
@@ -5,8 +5,8 @@
 # Entry-type module for x86 VGA ROM binary blob
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_intel_vga(Entry_blob):
     """Entry containing an Intel Video Graphics Adaptor (VGA) file
diff --git a/tools/binman/etype/powerpc_mpc85xx_bootpg_resetvec.py b/tools/binman/etype/powerpc_mpc85xx_bootpg_resetvec.py
index 59fedd2..cefd425 100644
--- a/tools/binman/etype/powerpc_mpc85xx_bootpg_resetvec.py
+++ b/tools/binman/etype/powerpc_mpc85xx_bootpg_resetvec.py
@@ -4,8 +4,8 @@
 # Entry-type module for the PowerPC mpc85xx bootpg and resetvec code for U-Boot
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_powerpc_mpc85xx_bootpg_resetvec(Entry_blob):
     """PowerPC mpc85xx bootpg + resetvec code for U-Boot
diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py
index 89b7bf6..91b8e0c 100644
--- a/tools/binman/etype/section.py
+++ b/tools/binman/etype/section.py
@@ -8,16 +8,14 @@
 images to be created.
 """
 
-from __future__ import print_function
-
 from collections import OrderedDict
 import re
 import sys
 
-from entry import Entry
-import fdt_util
-import tools
-import tout
+from binman.entry import Entry
+from dtoc import fdt_util
+from patman import tools
+from patman import tout
 
 
 class Entry_section(Entry):
diff --git a/tools/binman/etype/text.py b/tools/binman/etype/text.py
index da1813a..3577135 100644
--- a/tools/binman/etype/text.py
+++ b/tools/binman/etype/text.py
@@ -5,9 +5,9 @@
 
 from collections import OrderedDict
 
-from entry import Entry, EntryArg
-import fdt_util
-import tools
+from binman.entry import Entry, EntryArg
+from dtoc import fdt_util
+from patman import tools
 
 
 class Entry_text(Entry):
diff --git a/tools/binman/etype/u_boot.py b/tools/binman/etype/u_boot.py
index 23dd12c..ab1019b 100644
--- a/tools/binman/etype/u_boot.py
+++ b/tools/binman/etype/u_boot.py
@@ -5,8 +5,8 @@
 # Entry-type module for U-Boot binary
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_u_boot(Entry_blob):
     """U-Boot flat binary
diff --git a/tools/binman/etype/u_boot_dtb.py b/tools/binman/etype/u_boot_dtb.py
index 6c805a6..e983500 100644
--- a/tools/binman/etype/u_boot_dtb.py
+++ b/tools/binman/etype/u_boot_dtb.py
@@ -5,8 +5,8 @@
 # Entry-type module for U-Boot device tree
 #
 
-from entry import Entry
-from blob_dtb import Entry_blob_dtb
+from binman.entry import Entry
+from binman.etype.blob_dtb import Entry_blob_dtb
 
 class Entry_u_boot_dtb(Entry_blob_dtb):
     """U-Boot device tree
diff --git a/tools/binman/etype/u_boot_dtb_with_ucode.py b/tools/binman/etype/u_boot_dtb_with_ucode.py
index 6efd24a..aec1455 100644
--- a/tools/binman/etype/u_boot_dtb_with_ucode.py
+++ b/tools/binman/etype/u_boot_dtb_with_ucode.py
@@ -5,9 +5,9 @@
 # Entry-type module for U-Boot device tree with the microcode removed
 #
 
-from entry import Entry
-from blob_dtb import Entry_blob_dtb
-import tools
+from binman.entry import Entry
+from binman.etype.blob_dtb import Entry_blob_dtb
+from patman import tools
 
 class Entry_u_boot_dtb_with_ucode(Entry_blob_dtb):
     """A U-Boot device tree file, with the microcode removed
@@ -26,7 +26,7 @@
     def __init__(self, section, etype, node):
         # Put this here to allow entry-docs and help to work without libfdt
         global state
-        import state
+        from binman import state
 
         Entry_blob_dtb.__init__(self, section, etype, node)
         self.ucode_data = b''
@@ -44,7 +44,7 @@
 
     def ProcessFdt(self, fdt):
         # So the module can be loaded without it
-        import fdt
+        from dtoc import fdt
 
         # If the section does not need microcode, there is nothing to do
         ucode_dest_entry = self.section.FindEntryType(
diff --git a/tools/binman/etype/u_boot_elf.py b/tools/binman/etype/u_boot_elf.py
index f83860d..5f906e5 100644
--- a/tools/binman/etype/u_boot_elf.py
+++ b/tools/binman/etype/u_boot_elf.py
@@ -5,11 +5,11 @@
 # Entry-type module for U-Boot ELF image
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
-import fdt_util
-import tools
+from dtoc import fdt_util
+from patman import tools
 
 class Entry_u_boot_elf(Entry_blob):
     """U-Boot ELF image
diff --git a/tools/binman/etype/u_boot_img.py b/tools/binman/etype/u_boot_img.py
index 1ec0757..50cc71d 100644
--- a/tools/binman/etype/u_boot_img.py
+++ b/tools/binman/etype/u_boot_img.py
@@ -5,8 +5,8 @@
 # Entry-type module for U-Boot binary
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_u_boot_img(Entry_blob):
     """U-Boot legacy image
diff --git a/tools/binman/etype/u_boot_nodtb.py b/tools/binman/etype/u_boot_nodtb.py
index a4b95a4..e8c0e1a 100644
--- a/tools/binman/etype/u_boot_nodtb.py
+++ b/tools/binman/etype/u_boot_nodtb.py
@@ -5,8 +5,8 @@
 # Entry-type module for 'u-boot-nodtb.bin'
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_u_boot_nodtb(Entry_blob):
     """U-Boot flat binary without device tree appended
diff --git a/tools/binman/etype/u_boot_spl.py b/tools/binman/etype/u_boot_spl.py
index 7fedd00..a6fddbe 100644
--- a/tools/binman/etype/u_boot_spl.py
+++ b/tools/binman/etype/u_boot_spl.py
@@ -5,10 +5,9 @@
 # Entry-type module for spl/u-boot-spl.bin
 #
 
-import elf
-
-from entry import Entry
-from blob import Entry_blob
+from binman import elf
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_u_boot_spl(Entry_blob):
     """U-Boot SPL binary
diff --git a/tools/binman/etype/u_boot_spl_bss_pad.py b/tools/binman/etype/u_boot_spl_bss_pad.py
index 66a296a..a6a177a 100644
--- a/tools/binman/etype/u_boot_spl_bss_pad.py
+++ b/tools/binman/etype/u_boot_spl_bss_pad.py
@@ -7,11 +7,11 @@
 # to it will appear to SPL to be at the end of BSS rather than the start.
 #
 
-import command
-import elf
-from entry import Entry
-from blob import Entry_blob
-import tools
+from binman import elf
+from binman.entry import Entry
+from patman import command
+from binman.etype.blob import Entry_blob
+from patman import tools
 
 class Entry_u_boot_spl_bss_pad(Entry_blob):
     """U-Boot SPL binary padded with a BSS region
diff --git a/tools/binman/etype/u_boot_spl_dtb.py b/tools/binman/etype/u_boot_spl_dtb.py
index 1bcd449..a0761ee 100644
--- a/tools/binman/etype/u_boot_spl_dtb.py
+++ b/tools/binman/etype/u_boot_spl_dtb.py
@@ -5,8 +5,8 @@
 # Entry-type module for U-Boot device tree in SPL (Secondary Program Loader)
 #
 
-from entry import Entry
-from blob_dtb import Entry_blob_dtb
+from binman.entry import Entry
+from binman.etype.blob_dtb import Entry_blob_dtb
 
 class Entry_u_boot_spl_dtb(Entry_blob_dtb):
     """U-Boot SPL device tree
diff --git a/tools/binman/etype/u_boot_spl_elf.py b/tools/binman/etype/u_boot_spl_elf.py
index 24ee772..f99f74a 100644
--- a/tools/binman/etype/u_boot_spl_elf.py
+++ b/tools/binman/etype/u_boot_spl_elf.py
@@ -5,8 +5,8 @@
 # Entry-type module for U-Boot SPL ELF image
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_u_boot_spl_elf(Entry_blob):
     """U-Boot SPL ELF image
diff --git a/tools/binman/etype/u_boot_spl_nodtb.py b/tools/binman/etype/u_boot_spl_nodtb.py
index 41c1736..072b915 100644
--- a/tools/binman/etype/u_boot_spl_nodtb.py
+++ b/tools/binman/etype/u_boot_spl_nodtb.py
@@ -5,8 +5,8 @@
 # Entry-type module for 'u-boot-nodtb.bin'
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_u_boot_spl_nodtb(Entry_blob):
     """SPL binary without device tree appended
diff --git a/tools/binman/etype/u_boot_spl_with_ucode_ptr.py b/tools/binman/etype/u_boot_spl_with_ucode_ptr.py
index b650cf0..b1543a5 100644
--- a/tools/binman/etype/u_boot_spl_with_ucode_ptr.py
+++ b/tools/binman/etype/u_boot_spl_with_ucode_ptr.py
@@ -7,11 +7,7 @@
 
 import struct
 
-import command
-from entry import Entry
-from blob import Entry_blob
-from u_boot_with_ucode_ptr import Entry_u_boot_with_ucode_ptr
-import tools
+from binman.etype.u_boot_with_ucode_ptr import Entry_u_boot_with_ucode_ptr
 
 class Entry_u_boot_spl_with_ucode_ptr(Entry_u_boot_with_ucode_ptr):
     """U-Boot SPL with embedded microcode pointer
diff --git a/tools/binman/etype/u_boot_tpl.py b/tools/binman/etype/u_boot_tpl.py
index 1b69c4f..6562457 100644
--- a/tools/binman/etype/u_boot_tpl.py
+++ b/tools/binman/etype/u_boot_tpl.py
@@ -5,10 +5,9 @@
 # Entry-type module for tpl/u-boot-tpl.bin
 #
 
-import elf
-
-from entry import Entry
-from blob import Entry_blob
+from binman import elf
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_u_boot_tpl(Entry_blob):
     """U-Boot TPL binary
diff --git a/tools/binman/etype/u_boot_tpl_dtb.py b/tools/binman/etype/u_boot_tpl_dtb.py
index 81a3970..890155f 100644
--- a/tools/binman/etype/u_boot_tpl_dtb.py
+++ b/tools/binman/etype/u_boot_tpl_dtb.py
@@ -5,8 +5,8 @@
 # Entry-type module for U-Boot device tree in TPL (Tertiary Program Loader)
 #
 
-from entry import Entry
-from blob_dtb import Entry_blob_dtb
+from binman.entry import Entry
+from binman.etype.blob_dtb import Entry_blob_dtb
 
 class Entry_u_boot_tpl_dtb(Entry_blob_dtb):
     """U-Boot TPL device tree
diff --git a/tools/binman/etype/u_boot_tpl_dtb_with_ucode.py b/tools/binman/etype/u_boot_tpl_dtb_with_ucode.py
index ce19a49..ca1bf85 100644
--- a/tools/binman/etype/u_boot_tpl_dtb_with_ucode.py
+++ b/tools/binman/etype/u_boot_tpl_dtb_with_ucode.py
@@ -5,10 +5,7 @@
 # Entry-type module for U-Boot device tree with the microcode removed
 #
 
-import control
-from entry import Entry
-from u_boot_dtb_with_ucode import Entry_u_boot_dtb_with_ucode
-import tools
+from binman.etype.u_boot_dtb_with_ucode import Entry_u_boot_dtb_with_ucode
 
 class Entry_u_boot_tpl_dtb_with_ucode(Entry_u_boot_dtb_with_ucode):
     """U-Boot TPL with embedded microcode pointer
diff --git a/tools/binman/etype/u_boot_tpl_elf.py b/tools/binman/etype/u_boot_tpl_elf.py
index 9cc1cc2..7fa8e96 100644
--- a/tools/binman/etype/u_boot_tpl_elf.py
+++ b/tools/binman/etype/u_boot_tpl_elf.py
@@ -5,8 +5,8 @@
 # Entry-type module for U-Boot TPL ELF image
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_u_boot_tpl_elf(Entry_blob):
     """U-Boot TPL ELF image
diff --git a/tools/binman/etype/u_boot_tpl_with_ucode_ptr.py b/tools/binman/etype/u_boot_tpl_with_ucode_ptr.py
index 8d94dde..7f7fab7 100644
--- a/tools/binman/etype/u_boot_tpl_with_ucode_ptr.py
+++ b/tools/binman/etype/u_boot_tpl_with_ucode_ptr.py
@@ -7,11 +7,11 @@
 
 import struct
 
-import command
-from entry import Entry
-from blob import Entry_blob
-from u_boot_with_ucode_ptr import Entry_u_boot_with_ucode_ptr
-import tools
+from patman import command
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
+from binman.etype.u_boot_with_ucode_ptr import Entry_u_boot_with_ucode_ptr
+from patman import tools
 
 class Entry_u_boot_tpl_with_ucode_ptr(Entry_u_boot_with_ucode_ptr):
     """U-Boot TPL with embedded microcode pointer
diff --git a/tools/binman/etype/u_boot_ucode.py b/tools/binman/etype/u_boot_ucode.py
index dee8848..d9e1a60 100644
--- a/tools/binman/etype/u_boot_ucode.py
+++ b/tools/binman/etype/u_boot_ucode.py
@@ -5,9 +5,9 @@
 # Entry-type module for a U-Boot binary with an embedded microcode pointer
 #
 
-from entry import Entry
-from blob import Entry_blob
-import tools
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
+from patman import tools
 
 class Entry_u_boot_ucode(Entry_blob):
     """U-Boot microcode block
diff --git a/tools/binman/etype/u_boot_with_ucode_ptr.py b/tools/binman/etype/u_boot_with_ucode_ptr.py
index 960a5ef..06047b6 100644
--- a/tools/binman/etype/u_boot_with_ucode_ptr.py
+++ b/tools/binman/etype/u_boot_with_ucode_ptr.py
@@ -7,12 +7,12 @@
 
 import struct
 
-import command
-import elf
-from entry import Entry
-from blob import Entry_blob
-import fdt_util
-import tools
+from binman import elf
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
+from dtoc import fdt_util
+from patman import tools
+from patman import command
 
 class Entry_u_boot_with_ucode_ptr(Entry_blob):
     """U-Boot with embedded microcode pointer
diff --git a/tools/binman/etype/vblock.py b/tools/binman/etype/vblock.py
index 91fa2f7..5753de7 100644
--- a/tools/binman/etype/vblock.py
+++ b/tools/binman/etype/vblock.py
@@ -9,10 +9,10 @@
 from collections import OrderedDict
 import os
 
-from entry import Entry, EntryArg
+from binman.entry import Entry, EntryArg
 
-import fdt_util
-import tools
+from dtoc import fdt_util
+from patman import tools
 
 class Entry_vblock(Entry):
     """An entry which contains a Chromium OS verified boot block
diff --git a/tools/binman/etype/x86_reset16.py b/tools/binman/etype/x86_reset16.py
index 54eb814..ad864e5 100644
--- a/tools/binman/etype/x86_reset16.py
+++ b/tools/binman/etype/x86_reset16.py
@@ -5,8 +5,8 @@
 # Entry-type module for the 16-bit x86 reset code for U-Boot
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_x86_reset16(Entry_blob):
     """x86 16-bit reset code for U-Boot
diff --git a/tools/binman/etype/x86_reset16_spl.py b/tools/binman/etype/x86_reset16_spl.py
index 699a0c6..9a663f0 100644
--- a/tools/binman/etype/x86_reset16_spl.py
+++ b/tools/binman/etype/x86_reset16_spl.py
@@ -5,8 +5,8 @@
 # Entry-type module for the 16-bit x86 reset code for U-Boot
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_x86_reset16_spl(Entry_blob):
     """x86 16-bit reset code for U-Boot
diff --git a/tools/binman/etype/x86_reset16_tpl.py b/tools/binman/etype/x86_reset16_tpl.py
index 4eedb8d..864508f 100644
--- a/tools/binman/etype/x86_reset16_tpl.py
+++ b/tools/binman/etype/x86_reset16_tpl.py
@@ -5,8 +5,8 @@
 # Entry-type module for the 16-bit x86 reset code for U-Boot
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_x86_reset16_tpl(Entry_blob):
     """x86 16-bit reset code for U-Boot
diff --git a/tools/binman/etype/x86_start16.py b/tools/binman/etype/x86_start16.py
index 6736b69..d8345f6 100644
--- a/tools/binman/etype/x86_start16.py
+++ b/tools/binman/etype/x86_start16.py
@@ -5,8 +5,8 @@
 # Entry-type module for the 16-bit x86 start-up code for U-Boot
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_x86_start16(Entry_blob):
     """x86 16-bit start-up code for U-Boot
diff --git a/tools/binman/etype/x86_start16_spl.py b/tools/binman/etype/x86_start16_spl.py
index c8c7063..ad520d3 100644
--- a/tools/binman/etype/x86_start16_spl.py
+++ b/tools/binman/etype/x86_start16_spl.py
@@ -5,8 +5,8 @@
 # Entry-type module for the 16-bit x86 start-up code for U-Boot SPL
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_x86_start16_spl(Entry_blob):
     """x86 16-bit start-up code for SPL
diff --git a/tools/binman/etype/x86_start16_tpl.py b/tools/binman/etype/x86_start16_tpl.py
index 5261a8a..ccc8727 100644
--- a/tools/binman/etype/x86_start16_tpl.py
+++ b/tools/binman/etype/x86_start16_tpl.py
@@ -5,8 +5,8 @@
 # Entry-type module for the 16-bit x86 start-up code for U-Boot TPL
 #
 
-from entry import Entry
-from blob import Entry_blob
+from binman.entry import Entry
+from binman.etype.blob import Entry_blob
 
 class Entry_x86_start16_tpl(Entry_blob):
     """x86 16-bit start-up code for TPL
diff --git a/tools/binman/fdt_test.py b/tools/binman/fdt_test.py
index ac6f910..c491d40 100644
--- a/tools/binman/fdt_test.py
+++ b/tools/binman/fdt_test.py
@@ -9,10 +9,10 @@
 import tempfile
 import unittest
 
-import fdt
-from fdt import FdtScan
-import fdt_util
-import tools
+from dtoc import fdt
+from dtoc import fdt_util
+from dtoc.fdt import FdtScan
+from patman import tools
 
 class TestFdt(unittest.TestCase):
     @classmethod
diff --git a/tools/binman/fmap_util.py b/tools/binman/fmap_util.py
index d0f956b..25fe60a 100644
--- a/tools/binman/fmap_util.py
+++ b/tools/binman/fmap_util.py
@@ -10,7 +10,7 @@
 import struct
 import sys
 
-import tools
+from patman import tools
 
 # constants imported from lib/fmap.h
 FMAP_SIGNATURE = b'__FMAP__'
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 872b855..5e24920 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -6,8 +6,7 @@
 #
 #    python -m unittest func_test.TestFunctional.testHelp
 
-from __future__ import print_function
-
+import gzip
 import hashlib
 from optparse import OptionParser
 import os
@@ -17,24 +16,23 @@
 import tempfile
 import unittest
 
-import binman
-import cbfs_util
-import cmdline
-import command
-import control
-import elf
-import elf_test
-import fdt
-from etype import fdtmap
-from etype import image_header
-import fdt_util
-import fmap_util
-import test_util
-import gzip
+from binman import cbfs_util
+from binman import cmdline
+from binman import control
+from binman import elf
+from binman import elf_test
+from binman import fmap_util
+from binman import main
+from binman import state
+from dtoc import fdt
+from dtoc import fdt_util
+from binman.etype import fdtmap
+from binman.etype import image_header
 from image import Image
-import state
-import tools
-import tout
+from patman import command
+from patman import test_util
+from patman import tools
+from patman import tout
 
 # Contents of test files, corresponding to different entry types
 U_BOOT_DATA           = b'1234'
@@ -103,7 +101,7 @@
     @classmethod
     def setUpClass(cls):
         global entry
-        import entry
+        from binman import entry
 
         # Handle the case where argv[0] is 'python'
         cls._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
@@ -1290,8 +1288,8 @@
         with self.assertRaises(ValueError) as e:
             self._DoReadFile('057_unknown_contents.dts', True)
         self.assertIn("Image '/binman': Internal error: Could not complete "
-                "processing of contents: remaining [<_testing.Entry__testing ",
-                str(e.exception))
+                "processing of contents: remaining ["
+                "<binman.etype._testing.Entry__testing ", str(e.exception))
 
     def testBadChangeSize(self):
         """Test that trying to change the size of an entry fails"""
@@ -1338,7 +1336,8 @@
         with self.assertRaises(ValueError) as e:
             self._DoReadFileDtb('061_fdt_update_bad.dts', update_dtb=True)
         self.assertIn('Could not complete processing of Fdt: remaining '
-                      '[<_testing.Entry__testing', str(e.exception))
+                      '[<binman.etype._testing.Entry__testing',
+                        str(e.exception))
 
     def testEntryArgs(self):
         """Test passing arguments to entries from the command line"""
@@ -1430,14 +1429,14 @@
     def testEntryDocs(self):
         """Test for creation of entry documentation"""
         with test_util.capture_sys_output() as (stdout, stderr):
-            control.WriteEntryDocs(binman.GetEntryModules())
+            control.WriteEntryDocs(main.GetEntryModules())
         self.assertTrue(len(stdout.getvalue()) > 0)
 
     def testEntryDocsMissing(self):
         """Test handling of missing entry documentation"""
         with self.assertRaises(ValueError) as e:
             with test_util.capture_sys_output() as (stdout, stderr):
-                control.WriteEntryDocs(binman.GetEntryModules(), 'u_boot')
+                control.WriteEntryDocs(main.GetEntryModules(), 'u_boot')
         self.assertIn('Documentation is missing for modules: u_boot',
                       str(e.exception))
 
diff --git a/tools/binman/image.py b/tools/binman/image.py
index 2beab7f..523b274 100644
--- a/tools/binman/image.py
+++ b/tools/binman/image.py
@@ -5,8 +5,6 @@
 # Class for an image, the output of binman
 #
 
-from __future__ import print_function
-
 from collections import OrderedDict
 import fnmatch
 from operator import attrgetter
@@ -14,14 +12,14 @@
 import re
 import sys
 
-from entry import Entry
-from etype import fdtmap
-from etype import image_header
-from etype import section
-import fdt
-import fdt_util
-import tools
-import tout
+from binman.entry import Entry
+from binman.etype import fdtmap
+from binman.etype import image_header
+from binman.etype import section
+from dtoc import fdt
+from dtoc import fdt_util
+from patman import tools
+from patman import tout
 
 class Image(section.Entry_section):
     """A Image, representing an output from binman
diff --git a/tools/binman/image_test.py b/tools/binman/image_test.py
index 10f85d1..f85c3c5 100644
--- a/tools/binman/image_test.py
+++ b/tools/binman/image_test.py
@@ -7,7 +7,7 @@
 import unittest
 
 from image import Image
-from test_util import capture_sys_output
+from patman.test_util import capture_sys_output
 
 class TestImage(unittest.TestCase):
     def testInvalidFormat(self):
diff --git a/tools/binman/main.py b/tools/binman/main.py
new file mode 100755
index 0000000..efa7fa8
--- /dev/null
+++ b/tools/binman/main.py
@@ -0,0 +1,138 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0+
+
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Creates binary images from input files controlled by a description
+#
+
+"""See README for more information"""
+
+from distutils.sysconfig import get_python_lib
+import glob
+import os
+import site
+import sys
+import traceback
+import unittest
+
+# Bring in the patman and dtoc libraries (but don't override the first path
+# in PYTHONPATH)
+our_path = os.path.dirname(os.path.realpath(__file__))
+sys.path.insert(2, os.path.join(our_path, '..'))
+
+from patman import test_util
+
+# Bring in the libfdt module
+sys.path.insert(2, 'scripts/dtc/pylibfdt')
+sys.path.insert(2, os.path.join(our_path,
+                '../../build-sandbox_spl/scripts/dtc/pylibfdt'))
+
+# When running under python-coverage on Ubuntu 16.04, the dist-packages
+# directories are dropped from the python path. Add them in so that we can find
+# the elffile module. We could use site.getsitepackages() here but unfortunately
+# that is not available in a virtualenv.
+sys.path.append(get_python_lib())
+
+from binman import cmdline
+from binman import control
+from patman import test_util
+
+def RunTests(debug, verbosity, processes, test_preserve_dirs, args, toolpath):
+    """Run the functional tests and any embedded doctests
+
+    Args:
+        debug: True to enable debugging, which shows a full stack trace on error
+        verbosity: Verbosity level to use
+        test_preserve_dirs: True to preserve the input directory used by tests
+            so that it can be examined afterwards (only useful for debugging
+            tests). If a single test is selected (in args[0]) it also preserves
+            the output directory for this test. Both directories are displayed
+            on the command line.
+        processes: Number of processes to use to run tests (None=same as #CPUs)
+        args: List of positional args provided to binman. This can hold a test
+            name to execute (as in 'binman test testSections', for example)
+        toolpath: List of paths to use for tools
+    """
+    from binman import cbfs_util_test
+    from binman import elf_test
+    from binman import entry_test
+    from binman import fdt_test
+    from binman import ftest
+    from binman import image_test
+    from binman import test
+    import doctest
+
+    result = unittest.TestResult()
+    test_name = args and args[0] or None
+
+    # Run the entry tests first ,since these need to be the first to import the
+    # 'entry' module.
+    test_util.RunTestSuites(
+        result, debug, verbosity, test_preserve_dirs, processes, test_name,
+        toolpath,
+        [entry_test.TestEntry, ftest.TestFunctional, fdt_test.TestFdt,
+         elf_test.TestElf, image_test.TestImage, cbfs_util_test.TestCbfs])
+
+    return test_util.ReportResult('binman', test_name, result)
+
+def GetEntryModules(include_testing=True):
+    """Get a set of entry class implementations
+
+    Returns:
+        Set of paths to entry class filenames
+    """
+    glob_list = glob.glob(os.path.join(our_path, 'etype/*.py'))
+    return set([os.path.splitext(os.path.basename(item))[0]
+                for item in glob_list
+                if include_testing or '_testing' not in item])
+
+def RunTestCoverage():
+    """Run the tests and check that we get 100% coverage"""
+    glob_list = GetEntryModules(False)
+    all_set = set([os.path.splitext(os.path.basename(item))[0]
+                   for item in glob_list if '_testing' not in item])
+    test_util.RunTestCoverage('tools/binman/binman', None,
+            ['*test*', '*main.py', 'tools/patman/*', 'tools/dtoc/*'],
+            args.build_dir, all_set)
+
+def RunBinman(args):
+    """Main entry point to binman once arguments are parsed
+
+    Args:
+        args: Command line arguments Namespace object
+    """
+    ret_code = 0
+
+    if not args.debug:
+        sys.tracebacklimit = 0
+
+    if args.cmd == 'test':
+        if args.test_coverage:
+            RunTestCoverage()
+        else:
+            ret_code = RunTests(args.debug, args.verbosity, args.processes,
+                                args.test_preserve_dirs, args.tests,
+                                args.toolpath)
+
+    elif args.cmd == 'entry-docs':
+        control.WriteEntryDocs(GetEntryModules())
+
+    else:
+        try:
+            ret_code = control.Binman(args)
+        except Exception as e:
+            print('binman: %s' % e)
+            if args.debug:
+                print()
+                traceback.print_exc()
+            ret_code = 1
+    return ret_code
+
+
+if __name__ == "__main__":
+    args = cmdline.ParseArgs(sys.argv[1:])
+
+    ret_code = RunBinman(args)
+    sys.exit(ret_code)
diff --git a/tools/binman/state.py b/tools/binman/state.py
index d704ed2..36bc513 100644
--- a/tools/binman/state.py
+++ b/tools/binman/state.py
@@ -8,10 +8,10 @@
 import hashlib
 import re
 
-import fdt
+from dtoc import fdt
 import os
-import tools
-import tout
+from patman import tools
+from patman import tout
 
 # Records the device-tree files known to binman, keyed by entry type (e.g.
 # 'u-boot-spl-dtb'). These are the output FDT files, which can be updated by
@@ -167,8 +167,8 @@
     global output_fdt_info, main_dtb, fdt_path_prefix
     # Import these here in case libfdt.py is not available, in which case
     # the above help option still works.
-    import fdt
-    import fdt_util
+    from dtoc import fdt
+    from dtoc import fdt_util
 
     # If we are updating the DTBs we need to put these updated versions
     # where Entry_blob_dtb can find them. We can ignore 'u-boot.dtb'
diff --git a/tools/buildman/README b/tools/buildman/README
index f3a0dc7..b2f983c 100644
--- a/tools/buildman/README
+++ b/tools/buildman/README
@@ -1091,7 +1091,8 @@
 
    buildman -o /tmp/build --board sandbox -w
 
-This will write the full build into /tmp/build including object files.
+This will write the full build into /tmp/build including object files. You must
+specify the output directory with -o when using -w.
 
 
 Other options
diff --git a/tools/buildman/builder.py b/tools/buildman/builder.py
index 30ebe1d..f8e71de 100644
--- a/tools/buildman/builder.py
+++ b/tools/buildman/builder.py
@@ -17,12 +17,12 @@
 import threading
 import time
 
-import builderthread
-import command
-import gitutil
-import terminal
-from terminal import Print
-import toolchain
+from buildman import builderthread
+from buildman import toolchain
+from patman import command
+from patman import gitutil
+from patman import terminal
+from patman.terminal import Print
 
 """
 Theory of Operation
@@ -479,6 +479,9 @@
         Args:
             commit_upto: Commit number to use (0..self.count-1)
         """
+        if self.work_in_output:
+            return self._working_dir
+
         commit_dir = None
         if self.commits:
             commit = self.commits[commit_upto]
@@ -502,6 +505,8 @@
             target: Target name
         """
         output_dir = self._GetOutputDir(commit_upto)
+        if self.work_in_output:
+            return output_dir
         return os.path.join(output_dir, target)
 
     def GetDoneFile(self, commit_upto, target):
diff --git a/tools/buildman/builderthread.py b/tools/buildman/builderthread.py
index fc6e1ab..48fcd6c 100644
--- a/tools/buildman/builderthread.py
+++ b/tools/buildman/builderthread.py
@@ -9,8 +9,8 @@
 import sys
 import threading
 
-import command
-import gitutil
+from patman import command
+from patman import gitutil
 
 RETURN_CODE_RETRY = -1
 
@@ -280,8 +280,6 @@
             work_in_output: Use the output directory as the work directory and
                 don't write to a separate output directory.
         """
-        if work_in_output:
-            return
         # Fatal error
         if result.return_code < 0:
             return
@@ -333,7 +331,7 @@
 
             # Write out the image and function size information and an objdump
             env = result.toolchain.MakeEnvironment(self.builder.full_path)
-            with open(os.path.join(build_dir, 'env'), 'w') as fd:
+            with open(os.path.join(build_dir, 'out-env'), 'w') as fd:
                 for var in sorted(env.keys()):
                     print('%s="%s"' % (var, env[var]), file=fd)
             lines = []
@@ -379,7 +377,8 @@
                             capture_stderr=True, cwd=result.out_dir,
                             raise_on_error=False, env=env)
             ubootenv = os.path.join(result.out_dir, 'uboot.env')
-            self.CopyFiles(result.out_dir, build_dir, '', ['uboot.env'])
+            if not work_in_output:
+                self.CopyFiles(result.out_dir, build_dir, '', ['uboot.env'])
 
             # Write out the image sizes file. This is similar to the output
             # of binutil's 'size' utility, but it omits the header line and
@@ -391,17 +390,21 @@
                 with open(sizes, 'w') as fd:
                     print('\n'.join(lines), file=fd)
 
-        # Write out the configuration files, with a special case for SPL
-        for dirname in ['', 'spl', 'tpl']:
-            self.CopyFiles(result.out_dir, build_dir, dirname, ['u-boot.cfg',
-                'spl/u-boot-spl.cfg', 'tpl/u-boot-tpl.cfg', '.config',
-                'include/autoconf.mk', 'include/generated/autoconf.h'])
+        if not work_in_output:
+            # Write out the configuration files, with a special case for SPL
+            for dirname in ['', 'spl', 'tpl']:
+                self.CopyFiles(
+                    result.out_dir, build_dir, dirname,
+                    ['u-boot.cfg', 'spl/u-boot-spl.cfg', 'tpl/u-boot-tpl.cfg',
+                     '.config', 'include/autoconf.mk',
+                     'include/generated/autoconf.h'])
 
-        # Now write the actual build output
-        if keep_outputs:
-            self.CopyFiles(result.out_dir, build_dir, '', ['u-boot*', '*.bin',
-                '*.map', '*.img', 'MLO', 'SPL', 'include/autoconf.mk',
-                'spl/u-boot-spl*'])
+            # Now write the actual build output
+            if keep_outputs:
+                self.CopyFiles(
+                    result.out_dir, build_dir, '',
+                    ['u-boot*', '*.bin', '*.map', '*.img', 'MLO', 'SPL',
+                     'include/autoconf.mk', 'spl/u-boot-spl*'])
 
     def CopyFiles(self, out_dir, build_dir, dirname, patterns):
         """Copy files from the build directory to the output.
diff --git a/tools/buildman/buildman b/tools/buildman/buildman
index e4fba2d..11a5d8e 120000
--- a/tools/buildman/buildman
+++ b/tools/buildman/buildman
@@ -1 +1 @@
-buildman.py
\ No newline at end of file
+main.py
\ No newline at end of file
diff --git a/tools/buildman/cmdline.py b/tools/buildman/cmdline.py
index 1377b9d..680c072 100644
--- a/tools/buildman/cmdline.py
+++ b/tools/buildman/cmdline.py
@@ -76,8 +76,7 @@
           default=False, help="Do a dry run (describe actions, but do nothing)")
     parser.add_option('-N', '--no-subdirs', action='store_true', dest='no_subdirs',
           default=False, help="Don't create subdirectories when building current source for a single board")
-    parser.add_option('-o', '--output-dir', type='string',
-          dest='output_dir', default='..',
+    parser.add_option('-o', '--output-dir', type='string', dest='output_dir',
           help='Directory where all builds happen and buildman has its workspace (default is ../)')
     parser.add_option('-O', '--override-toolchain', type='string',
           help="Override host toochain to use for sandbox (e.g. 'clang-7')")
diff --git a/tools/buildman/control.py b/tools/buildman/control.py
index 30c030f..071c261 100644
--- a/tools/buildman/control.py
+++ b/tools/buildman/control.py
@@ -5,18 +5,18 @@
 import multiprocessing
 import os
 import shutil
+import subprocess
 import sys
 
-import board
-import bsettings
-from builder import Builder
-import gitutil
-import patchstream
-import terminal
-from terminal import Print
-import toolchain
-import command
-import subprocess
+from buildman import board
+from buildman import bsettings
+from buildman import toolchain
+from buildman.builder import Builder
+from patman import command
+from patman import gitutil
+from patman import patchstream
+from patman import terminal
+from patman.terminal import Print
 
 def GetPlural(count):
     """Returns a plural 's' if count is not 1"""
@@ -175,6 +175,10 @@
     if options.incremental:
         print(col.Color(col.RED,
                         'Warning: -I has been removed. See documentation'))
+    if not options.output_dir:
+        if options.work_in_output:
+            sys.exit(col.Color(col.RED, '-w requires that you specify -o'))
+        options.output_dir = '..'
 
     # Work out what subset of the boards we are building
     if not boards:
@@ -207,7 +211,7 @@
         sys.exit(col.Color(col.RED, 'No matching boards found'))
 
     if options.print_prefix:
-        err = ShowToolchainInfo(boards, toolchains)
+        err = ShowToolchainPrefix(boards, toolchains)
         if err:
             sys.exit(col.Color(col.RED, err))
         return 0
diff --git a/tools/buildman/func_test.py b/tools/buildman/func_test.py
index 1fbc6f6..418677f 100644
--- a/tools/buildman/func_test.py
+++ b/tools/buildman/func_test.py
@@ -8,15 +8,15 @@
 import tempfile
 import unittest
 
-import board
-import bsettings
-import cmdline
-import command
-import control
-import gitutil
-import terminal
-import toolchain
-import tools
+from buildman import board
+from buildman import bsettings
+from buildman import cmdline
+from buildman import control
+from buildman import toolchain
+from patman import command
+from patman import gitutil
+from patman import terminal
+from patman import tools
 
 settings_data = '''
 # Buildman settings file
@@ -546,6 +546,13 @@
         self.assertEqual(self._builder.count, self._total_builds)
         self.assertEqual(self._builder.fail, 0)
 
+    def testEnvironment(self):
+        """Test that the done and environment files are written to out-env"""
+        self._RunControl('-o', self._output_dir)
+        board0_dir = os.path.join(self._output_dir, 'current', 'board0')
+        self.assertTrue(os.path.exists(os.path.join(board0_dir, 'done')))
+        self.assertTrue(os.path.exists(os.path.join(board0_dir, 'out-env')))
+
     def testWorkInOutput(self):
         """Test the -w option which should write directly to the output dir"""
         board_list = board.Boards()
@@ -554,6 +561,10 @@
                          boards=board_list)
         self.assertTrue(
             os.path.exists(os.path.join(self._output_dir, 'u-boot')))
+        self.assertTrue(
+            os.path.exists(os.path.join(self._output_dir, 'done')))
+        self.assertTrue(
+            os.path.exists(os.path.join(self._output_dir, 'out-env')))
 
     def testWorkInOutputFail(self):
         """Test the -w option failures"""
@@ -569,3 +580,9 @@
             self._RunControl('-b', self._test_branch, '-o', self._output_dir,
                              '-w', clean_dir=False, boards=board_list)
         self.assertIn("single commit", str(e.exception))
+
+        board_list = board.Boards()
+        board_list.AddBoard(board.Board(*boards[0]))
+        with self.assertRaises(SystemExit) as e:
+            self._RunControl('-w', clean_dir=False)
+        self.assertIn("specify -o", str(e.exception))
diff --git a/tools/buildman/buildman.py b/tools/buildman/main.py
similarity index 76%
rename from tools/buildman/buildman.py
rename to tools/buildman/main.py
index 30a8690..2b71473 100755
--- a/tools/buildman/buildman.py
+++ b/tools/buildman/main.py
@@ -6,8 +6,7 @@
 
 """See README for more information"""
 
-from __future__ import print_function
-
+import doctest
 import multiprocessing
 import os
 import re
@@ -16,20 +15,18 @@
 
 # Bring in the patman libraries
 our_path = os.path.dirname(os.path.realpath(__file__))
-sys.path.insert(1, os.path.join(our_path, '../patman'))
+sys.path.insert(1, os.path.join(our_path, '..'))
 
 # Our modules
-import board
-import bsettings
-import builder
-import checkpatch
-import cmdline
-import control
-import doctest
-import gitutil
-import patchstream
-import terminal
-import toolchain
+from buildman import board
+from buildman import bsettings
+from buildman import builder
+from buildman import cmdline
+from buildman import control
+from buildman import toolchain
+from patman import patchstream
+from patman import gitutil
+from patman import terminal
 
 def RunTests(skip_net_tests):
     import func_test
@@ -37,7 +34,7 @@
     import doctest
 
     result = unittest.TestResult()
-    for module in ['toolchain', 'gitutil']:
+    for module in ['buildman.toolchain', 'patman.gitutil']:
         suite = doctest.DocTestSuite(module)
         suite.run(result)
 
diff --git a/tools/buildman/test.py b/tools/buildman/test.py
index d32b226..40811ba 100644
--- a/tools/buildman/test.py
+++ b/tools/buildman/test.py
@@ -11,18 +11,17 @@
 
 # Bring in the patman libraries
 our_path = os.path.dirname(os.path.realpath(__file__))
-sys.path.append(os.path.join(our_path, '../patman'))
 
-import board
-import bsettings
-import builder
-import control
-import command
-import commit
-import terminal
-import test_util
-import toolchain
-import tools
+from buildman import board
+from buildman import bsettings
+from buildman import builder
+from buildman import control
+from buildman import toolchain
+from patman import commit
+from patman import command
+from patman import terminal
+from patman import test_util
+from patman import tools
 
 use_network = True
 
@@ -583,7 +582,7 @@
                 url = self.toolchains.LocateArchUrl('arm')
             self.assertRegexpMatches(url, 'https://www.kernel.org/pub/tools/'
                     'crosstool/files/bin/x86_64/.*/'
-                    'x86_64-gcc-.*-nolibc_arm-.*linux-gnueabi.tar.xz')
+                    'x86_64-gcc-.*-nolibc[-_]arm-.*linux-gnueabi.tar.xz')
 
     def testGetEnvArgs(self):
         """Test the GetEnvArgs() function"""
diff --git a/tools/buildman/toolchain.py b/tools/buildman/toolchain.py
index 4456a80..acb5a29 100644
--- a/tools/buildman/toolchain.py
+++ b/tools/buildman/toolchain.py
@@ -10,10 +10,10 @@
 import tempfile
 import urllib.request, urllib.error, urllib.parse
 
-import bsettings
-import command
-import terminal
-import tools
+from buildman import bsettings
+from patman import command
+from patman import terminal
+from patman import tools
 
 (PRIORITY_FULL_PREFIX, PRIORITY_PREFIX_GCC, PRIORITY_PREFIX_GCC_PATH,
     PRIORITY_CALC) = list(range(4))
diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py
index 90a9e1a..ecfe062 100644
--- a/tools/dtoc/dtb_platdata.py
+++ b/tools/dtoc/dtb_platdata.py
@@ -15,9 +15,9 @@
 import copy
 import sys
 
-import fdt
-import fdt_util
-import tools
+from dtoc import fdt
+from dtoc import fdt_util
+from patman import tools
 
 # When we see these properties we ignore them - i.e. do not create a structure member
 PROP_IGNORE_LIST = [
diff --git a/tools/dtoc/dtoc b/tools/dtoc/dtoc
index 896ca44..11a5d8e 120000
--- a/tools/dtoc/dtoc
+++ b/tools/dtoc/dtoc
@@ -1 +1 @@
-dtoc.py
\ No newline at end of file
+main.py
\ No newline at end of file
diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py
index 1b7b730..188490b 100644
--- a/tools/dtoc/fdt.py
+++ b/tools/dtoc/fdt.py
@@ -8,10 +8,10 @@
 import struct
 import sys
 
-import fdt_util
+from dtoc import fdt_util
 import libfdt
 from libfdt import QUIET_NOTFOUND
-import tools
+from patman import tools
 
 # This deals with a device tree, presenting it as an assortment of Node and
 # Prop objects, representing nodes and properties, respectively. This file
diff --git a/tools/dtoc/fdt_util.py b/tools/dtoc/fdt_util.py
index b105fae..b040793 100644
--- a/tools/dtoc/fdt_util.py
+++ b/tools/dtoc/fdt_util.py
@@ -13,8 +13,8 @@
 import sys
 import tempfile
 
-import command
-import tools
+from patman import command
+from patman import tools
 
 def fdt32_to_cpu(val):
     """Convert a device tree cell to an integer
diff --git a/tools/dtoc/dtoc.py b/tools/dtoc/main.py
similarity index 94%
rename from tools/dtoc/dtoc.py
rename to tools/dtoc/main.py
index f31cba9..b94d9c3 100755
--- a/tools/dtoc/dtoc.py
+++ b/tools/dtoc/main.py
@@ -25,8 +25,6 @@
 see doc/driver-model/of-plat.rst
 """
 
-from __future__ import print_function
-
 from optparse import OptionParser
 import os
 import sys
@@ -34,15 +32,15 @@
 
 # Bring in the patman libraries
 our_path = os.path.dirname(os.path.realpath(__file__))
-sys.path.append(os.path.join(our_path, '../patman'))
+sys.path.append(os.path.join(our_path, '..'))
 
 # Bring in the libfdt module
 sys.path.insert(0, 'scripts/dtc/pylibfdt')
 sys.path.insert(0, os.path.join(our_path,
                 '../../build-sandbox_spl/scripts/dtc/pylibfdt'))
 
-import dtb_platdata
-import test_util
+from dtoc import dtb_platdata
+from patman import test_util
 
 def run_tests(args):
     """Run all the test we have for dtoc
@@ -79,7 +77,7 @@
 def RunTestCoverage():
     """Run the tests and check that we get 100% coverage"""
     sys.argv = [sys.argv[0]]
-    test_util.RunTestCoverage('tools/dtoc/dtoc.py', '/dtoc.py',
+    test_util.RunTestCoverage('tools/dtoc/dtoc', '/main.py',
             ['tools/patman/*.py', '*/fdt*', '*test*'], options.build_dir)
 
 
diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py
index d733b70..8498e83 100755
--- a/tools/dtoc/test_dtoc.py
+++ b/tools/dtoc/test_dtoc.py
@@ -9,22 +9,20 @@
 tool.
 """
 
-from __future__ import print_function
-
 import collections
 import os
 import struct
 import unittest
 
-import dtb_platdata
+from dtoc import dtb_platdata
 from dtb_platdata import conv_name_to_c
 from dtb_platdata import get_compat_name
 from dtb_platdata import get_value
 from dtb_platdata import tab_to
-import fdt
-import fdt_util
-import test_util
-import tools
+from dtoc import fdt
+from dtoc import fdt_util
+from patman import test_util
+from patman import tools
 
 our_path = os.path.dirname(os.path.realpath(__file__))
 
diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py
index 3316757..375e906 100755
--- a/tools/dtoc/test_fdt.py
+++ b/tools/dtoc/test_fdt.py
@@ -4,8 +4,6 @@
 # Written by Simon Glass <sjg@chromium.org>
 #
 
-from __future__ import print_function
-
 from optparse import OptionParser
 import glob
 import os
@@ -16,17 +14,16 @@
 
 # Bring in the patman libraries
 our_path = os.path.dirname(os.path.realpath(__file__))
-for dirname in ['../patman', '..']:
-    sys.path.insert(0, os.path.join(our_path, dirname))
+sys.path.insert(1, os.path.join(our_path, '..'))
 
-import command
-import fdt
+from dtoc import fdt
+from dtoc import fdt_util
+from dtoc.fdt_util import fdt32_to_cpu
 from fdt import TYPE_BYTE, TYPE_INT, TYPE_STRING, TYPE_BOOL, BytesToValue
-import fdt_util
-from fdt_util import fdt32_to_cpu
 import libfdt
-import test_util
-import tools
+from patman import command
+from patman import test_util
+from patman import tools
 
 def _GetPropertyValue(dtb, node, prop_name):
     """Low-level function to get the property value based on its offset
diff --git a/tools/fdtgrep.c b/tools/fdtgrep.c
index 2a8058f..7e168a1 100644
--- a/tools/fdtgrep.c
+++ b/tools/fdtgrep.c
@@ -17,6 +17,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <fdt_region.h>
 
 #include "fdt_host.h"
 #include "libfdt_internal.h"
diff --git a/tools/genboardscfg.py b/tools/genboardscfg.py
index 4f6382b..4ee7aa1 100755
--- a/tools/genboardscfg.py
+++ b/tools/genboardscfg.py
@@ -22,8 +22,7 @@
 import tempfile
 import time
 
-sys.path.insert(1, os.path.join(os.path.dirname(__file__), 'buildman'))
-import kconfiglib
+from buildman import kconfiglib
 
 ### constant variables ###
 OUTPUT_FILE = 'boards.cfg'
diff --git a/tools/image-host.c b/tools/image-host.c
index 5bb6896..9a83b7f 100644
--- a/tools/image-host.c
+++ b/tools/image-host.c
@@ -10,6 +10,7 @@
 
 #include "mkimage.h"
 #include <bootm.h>
+#include <fdt_region.h>
 #include <image.h>
 #include <version.h>
 
diff --git a/tools/libfdt/fdt_ro.c b/tools/libfdt/fdt_ro.c
new file mode 100644
index 0000000..8a9735a
--- /dev/null
+++ b/tools/libfdt/fdt_ro.c
@@ -0,0 +1,2 @@
+#include "fdt_host.h"
+#include "../scripts/dtc/libfdt/fdt_ro.c"
diff --git a/tools/moveconfig.py b/tools/moveconfig.py
index d8bf7fd..36361f9 100755
--- a/tools/moveconfig.py
+++ b/tools/moveconfig.py
@@ -314,11 +314,9 @@
 import threading
 import time
 
-sys.path.append(os.path.join(os.path.dirname(__file__), 'buildman'))
-sys.path.append(os.path.join(os.path.dirname(__file__), 'patman'))
-import bsettings
-import kconfiglib
-import toolchain
+from buildman import bsettings
+from buildman import kconfiglib
+from buildman import toolchain
 
 SHOW_GNU_MAKE = 'scripts/show-gnu-make'
 SLEEP_TIME=0.03
diff --git a/tools/patman/checkpatch.py b/tools/patman/checkpatch.py
index d47ea43..795b519 100644
--- a/tools/patman/checkpatch.py
+++ b/tools/patman/checkpatch.py
@@ -3,12 +3,14 @@
 #
 
 import collections
-import command
-import gitutil
 import os
 import re
 import sys
-import terminal
+
+from patman import command
+from patman import gitutil
+from patman import terminal
+from patman import tools
 
 def FindCheckPatch():
     top_level = gitutil.GetTopLevel()
diff --git a/tools/patman/command.py b/tools/patman/command.py
index 5fbd2c4..e67ac15 100644
--- a/tools/patman/command.py
+++ b/tools/patman/command.py
@@ -3,8 +3,9 @@
 #
 
 import os
-import cros_subprocess
-import tools
+
+from patman import cros_subprocess
+from patman import tools
 
 """Shell command ease-ups for Python."""
 
diff --git a/tools/patman/func_test.py b/tools/patman/func_test.py
index 76319ff..b7e2825 100644
--- a/tools/patman/func_test.py
+++ b/tools/patman/func_test.py
@@ -12,15 +12,12 @@
 import tempfile
 import unittest
 
-try:
-    from StringIO import StringIO
-except ImportError:
-    from io import StringIO
+from io import StringIO
 
-import gitutil
-import patchstream
-import settings
-import tools
+from patman import gitutil
+from patman import patchstream
+from patman import settings
+from patman import tools
 
 
 @contextlib.contextmanager
diff --git a/tools/patman/get_maintainer.py b/tools/patman/get_maintainer.py
index 0ffb55a..473f0fe 100644
--- a/tools/patman/get_maintainer.py
+++ b/tools/patman/get_maintainer.py
@@ -2,10 +2,11 @@
 # Copyright (c) 2012 The Chromium OS Authors.
 #
 
-import command
-import gitutil
 import os
 
+from patman import command
+from patman import gitutil
+
 def FindGetMaintainer():
     """Look for the get_maintainer.pl script.
 
diff --git a/tools/patman/gitutil.py b/tools/patman/gitutil.py
index a2a225c..770a051 100644
--- a/tools/patman/gitutil.py
+++ b/tools/patman/gitutil.py
@@ -2,17 +2,17 @@
 # Copyright (c) 2011 The Chromium OS Authors.
 #
 
-import command
 import re
 import os
-import series
 import subprocess
 import sys
-import terminal
 
-import checkpatch
-import settings
-import tools
+from patman import checkpatch
+from patman import command
+from patman import series
+from patman import settings
+from patman import terminal
+from patman import tools
 
 # True to use --no-decorate - we check this in Setup()
 use_no_decorate = True
diff --git a/tools/patman/patman.py b/tools/patman/main.py
similarity index 93%
rename from tools/patman/patman.py
rename to tools/patman/main.py
index 7f4ac9a..f3d9c0c 100755
--- a/tools/patman/patman.py
+++ b/tools/patman/main.py
@@ -12,19 +12,20 @@
 import sys
 import unittest
 
+if __name__ == "__main__":
+    # Allow 'from patman import xxx to work'
+    our_path = os.path.dirname(os.path.realpath(__file__))
+    sys.path.append(os.path.join(our_path, '..'))
+
 # Our modules
-try:
-    from patman import checkpatch, command, gitutil, patchstream, \
-        project, settings, terminal, test
-except ImportError:
-    import checkpatch
-    import command
-    import gitutil
-    import patchstream
-    import project
-    import settings
-    import terminal
-    import test
+from patman import checkpatch
+from patman import command
+from patman import gitutil
+from patman import patchstream
+from patman import project
+from patman import settings
+from patman import terminal
+from patman import test
 
 
 parser = OptionParser()
@@ -85,7 +86,7 @@
 # Run our meagre tests
 elif options.test:
     import doctest
-    import func_test
+    from patman import func_test
 
     sys.argv = [sys.argv[0]]
     result = unittest.TestResult()
diff --git a/tools/patman/patchstream.py b/tools/patman/patchstream.py
index df3eb74..4052975 100644
--- a/tools/patman/patchstream.py
+++ b/tools/patman/patchstream.py
@@ -9,10 +9,10 @@
 import shutil
 import tempfile
 
-import command
-import commit
-import gitutil
-from series import Series
+from patman import command
+from patman import commit
+from patman import gitutil
+from patman.series import Series
 
 # Tags that we detect and remove
 re_remove = re.compile('^BUG=|^TEST=|^BRANCH=|^Review URL:'
diff --git a/tools/patman/patman b/tools/patman/patman
index 6cc3d7a..11a5d8e 120000
--- a/tools/patman/patman
+++ b/tools/patman/patman
@@ -1 +1 @@
-patman.py
\ No newline at end of file
+main.py
\ No newline at end of file
diff --git a/tools/patman/project.py b/tools/patman/project.py
index 1d9cfc0..2dfc303 100644
--- a/tools/patman/project.py
+++ b/tools/patman/project.py
@@ -4,7 +4,7 @@
 
 import os.path
 
-import gitutil
+from patman import gitutil
 
 def DetectProject():
     """Autodetect the name of the current project.
diff --git a/tools/patman/series.py b/tools/patman/series.py
index 6d9d48b..e5e28ce 100644
--- a/tools/patman/series.py
+++ b/tools/patman/series.py
@@ -2,16 +2,14 @@
 # Copyright (c) 2011 The Chromium OS Authors.
 #
 
-from __future__ import print_function
-
 import itertools
 import os
 
-import get_maintainer
-import gitutil
-import settings
-import terminal
-import tools
+from patman import get_maintainer
+from patman import gitutil
+from patman import settings
+from patman import terminal
+from patman import tools
 
 # Series-xxx tags that we understand
 valid_series = ['to', 'cc', 'version', 'changes', 'prefix', 'notes', 'name',
diff --git a/tools/patman/settings.py b/tools/patman/settings.py
index 5dc83a8..ca74fc6 100644
--- a/tools/patman/settings.py
+++ b/tools/patman/settings.py
@@ -2,8 +2,6 @@
 # Copyright (c) 2011 The Chromium OS Authors.
 #
 
-from __future__ import print_function
-
 try:
     import configparser as ConfigParser
 except:
@@ -12,9 +10,9 @@
 import os
 import re
 
-import command
-import gitutil
-import tools
+from patman import command
+from patman import gitutil
+from patman import tools
 
 """Default settings per-project.
 
@@ -36,10 +34,7 @@
     - Merge general default settings/aliases with project-specific ones.
 
     # Sample config used for tests below...
-    >>> try:
-    ...     from StringIO import StringIO
-    ... except ImportError:
-    ...     from io import StringIO
+    >>> from io import StringIO
     >>> sample_config = '''
     ... [alias]
     ... me: Peter P. <likesspiders@example.com>
diff --git a/tools/patman/terminal.py b/tools/patman/terminal.py
index 5c9e3ee..c709438 100644
--- a/tools/patman/terminal.py
+++ b/tools/patman/terminal.py
@@ -7,8 +7,6 @@
 This module handles terminal interaction including ANSI color codes.
 """
 
-from __future__ import print_function
-
 import os
 import re
 import shutil
diff --git a/tools/patman/test.py b/tools/patman/test.py
index 889e186..e7f709e 100644
--- a/tools/patman/test.py
+++ b/tools/patman/test.py
@@ -8,11 +8,11 @@
 import tempfile
 import unittest
 
-import checkpatch
-import gitutil
-import patchstream
-import series
-import commit
+from patman import checkpatch
+from patman import gitutil
+from patman import patchstream
+from patman import series
+from patman import commit
 
 
 class TestPatch(unittest.TestCase):
diff --git a/tools/patman/test_util.py b/tools/patman/test_util.py
index 09f258c..4d28d9f 100644
--- a/tools/patman/test_util.py
+++ b/tools/patman/test_util.py
@@ -3,21 +3,23 @@
 # Copyright (c) 2016 Google, Inc
 #
 
-from __future__ import print_function
-
 from contextlib import contextmanager
 import glob
+import multiprocessing
 import os
 import sys
+import unittest
 
-import command
+from patman import command
+from patman import test_util
 
+from io import StringIO
+
+use_concurrent = True
 try:
-  from StringIO import StringIO
-except ImportError:
-  from io import StringIO
-
-PYTHON = 'python%d' % sys.version_info[0]
+    from concurrencytest import ConcurrentTestSuite, fork_for_tests
+except:
+    use_concurrent = False
 
 
 def RunTestCoverage(prog, filter_fname, exclude_list, build_dir, required=None):
@@ -46,12 +48,15 @@
         glob_list = []
     glob_list += exclude_list
     glob_list += ['*libfdt.py', '*site-packages*', '*dist-packages*']
-    test_cmd = 'test' if 'binman.py' in prog else '-t'
-    cmd = ('PYTHONPATH=$PYTHONPATH:%s/sandbox_spl/tools %s-coverage run '
-           '--omit "%s" %s %s -P1' % (build_dir, PYTHON, ','.join(glob_list),
+    test_cmd = 'test' if 'binman' in prog else '-t'
+    prefix = ''
+    if build_dir:
+        prefix = 'PYTHONPATH=$PYTHONPATH:%s/sandbox_spl/tools ' % build_dir
+    cmd = ('%spython3-coverage run '
+           '--omit "%s" %s %s -P1' % (prefix, ','.join(glob_list),
                                       prog, test_cmd))
     os.system(cmd)
-    stdout = command.Output('%s-coverage' % PYTHON, 'report')
+    stdout = command.Output('python3-coverage', 'report')
     lines = stdout.splitlines()
     if required:
         # Convert '/path/to/name.py' just the module name 'name'
@@ -70,8 +75,8 @@
     print(coverage)
     if coverage != '100%':
         print(stdout)
-        print("Type '%s-coverage html' to get a report in "
-              'htmlcov/index.html' % PYTHON)
+        print("Type 'python3-coverage html' to get a report in "
+              'htmlcov/index.html')
         print('Coverage error: %s, but should be 100%%' % coverage)
         ok = False
     if not ok:
@@ -90,3 +95,95 @@
         yield capture_out, capture_err
     finally:
         sys.stdout, sys.stderr = old_out, old_err
+
+
+def ReportResult(toolname:str, test_name: str, result: unittest.TestResult):
+    """Report the results from a suite of tests
+
+    Args:
+        toolname: Name of the tool that ran the tests
+        test_name: Name of test that was run, or None for all
+        result: A unittest.TestResult object containing the results
+    """
+    # Remove errors which just indicate a missing test. Since Python v3.5 If an
+    # ImportError or AttributeError occurs while traversing name then a
+    # synthetic test that raises that error when run will be returned. These
+    # errors are included in the errors accumulated by result.errors.
+    if test_name:
+        errors = []
+
+        for test, err in result.errors:
+            if ("has no attribute '%s'" % test_name) not in err:
+                errors.append((test, err))
+            result.testsRun -= 1
+        result.errors = errors
+
+    print(result)
+    for test, err in result.errors:
+        print(test.id(), err)
+    for test, err in result.failures:
+        print(err, result.failures)
+    if result.skipped:
+        print('%d binman test%s SKIPPED:' %
+              (len(result.skipped), 's' if len(result.skipped) > 1 else ''))
+        for skip_info in result.skipped:
+            print('%s: %s' % (skip_info[0], skip_info[1]))
+    if result.errors or result.failures:
+        print('binman tests FAILED')
+        return 1
+    return 0
+
+
+def RunTestSuites(result, debug, verbosity, test_preserve_dirs, processes,
+                  test_name, toolpath, test_class_list):
+    """Run a series of test suites and collect the results
+
+    Args:
+        result: A unittest.TestResult object to add the results to
+        debug: True to enable debugging, which shows a full stack trace on error
+        verbosity: Verbosity level to use (0-4)
+        test_preserve_dirs: True to preserve the input directory used by tests
+            so that it can be examined afterwards (only useful for debugging
+            tests). If a single test is selected (in args[0]) it also preserves
+            the output directory for this test. Both directories are displayed
+            on the command line.
+        processes: Number of processes to use to run tests (None=same as #CPUs)
+        test_name: Name of test to run, or None for all
+        toolpath: List of paths to use for tools
+        test_class_list: List of test classes to run
+    """
+    for module in []:
+        suite = doctest.DocTestSuite(module)
+        suite.run(result)
+
+    sys.argv = [sys.argv[0]]
+    if debug:
+        sys.argv.append('-D')
+    if verbosity:
+        sys.argv.append('-v%d' % verbosity)
+    if toolpath:
+        for path in toolpath:
+            sys.argv += ['--toolpath', path]
+
+    suite = unittest.TestSuite()
+    loader = unittest.TestLoader()
+    for module in test_class_list:
+        # Test the test module about our arguments, if it is interested
+        if hasattr(module, 'setup_test_args'):
+            setup_test_args = getattr(module, 'setup_test_args')
+            setup_test_args(preserve_indir=test_preserve_dirs,
+                preserve_outdirs=test_preserve_dirs and test_name is not None,
+                toolpath=toolpath, verbosity=verbosity)
+        if test_name:
+            try:
+                suite.addTests(loader.loadTestsFromName(test_name, module))
+            except AttributeError:
+                continue
+        else:
+            suite.addTests(loader.loadTestsFromTestCase(module))
+    if use_concurrent and processes != 1:
+        concurrent_suite = ConcurrentTestSuite(suite,
+                fork_for_tests(processes or multiprocessing.cpu_count()))
+        concurrent_suite.run(result)
+    else:
+        suite.run(result)
diff --git a/tools/patman/tools.py b/tools/patman/tools.py
index 3feddb2..b50370d 100644
--- a/tools/patman/tools.py
+++ b/tools/patman/tools.py
@@ -3,9 +3,6 @@
 # Copyright (c) 2016 Google, Inc
 #
 
-from __future__ import print_function
-
-import command
 import glob
 import os
 import shutil
@@ -13,7 +10,8 @@
 import sys
 import tempfile
 
-import tout
+from patman import command
+from patman import tout
 
 # Output directly (generally this is temporary)
 outdir = None
diff --git a/tools/patman/tout.py b/tools/patman/tout.py
index 2a38485..c7e3272 100644
--- a/tools/patman/tout.py
+++ b/tools/patman/tout.py
@@ -4,11 +4,9 @@
 # Terminal output logging.
 #
 
-from __future__ import print_function
-
 import sys
 
-import terminal
+from patman import terminal
 
 # Output verbosity levels that we support
 ERROR, WARNING, NOTICE, INFO, DETAIL, DEBUG = range(6)
diff --git a/tools/rmboard.py b/tools/rmboard.py
index df4f04b..06c3562 100755
--- a/tools/rmboard.py
+++ b/tools/rmboard.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/python3
 # SPDX-License-Identifier: GPL-2.0+
 # Copyright 2019 Google LLC
 #
@@ -23,8 +23,6 @@
 Search for ## to update the commit message manually.
 """
 
-from __future__ import print_function
-
 import glob
 import os
 import re
@@ -32,9 +30,8 @@
 
 # Bring in the patman libraries
 our_path = os.path.dirname(os.path.realpath(__file__))
-sys.path.append(os.path.join(our_path, '../tools/patman'))
 
-import command
+from patman import command
 
 def rm_kconfig_include(path):
     """Remove a path from Kconfig files