binman: Add support for adding a name prefix to entries

Sometimes we have several sections which repeat the same entries (e.g. for
a read-only and read-write version of the same section). It is useful to
be able to tell these entries apart by name.

Add a new 'name-prefix' property for sections, which causes all entries
within that section to have a given name prefix.

Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/tools/binman/README b/tools/binman/README
index 64e529f..42ed444 100644
--- a/tools/binman/README
+++ b/tools/binman/README
@@ -417,11 +417,13 @@
 	binman {
 		section@0 {
 			read-only;
+			name-prefix = "ro-";
 			size = <0x100000>;
 			u-boot {
 			};
 		};
 		section@1 {
+			name-prefix = "rw-";
 			size = <0x100000>;
 			u-boot {
 			};
@@ -437,6 +439,12 @@
 	Indicates that this section is read-only. This has no impact on binman's
 	operation, but his property can be read at run time.
 
+name-prefix:
+	This string is prepended to all the names of the binaries in the
+	section. In the example above, the 'u-boot' binaries which actually be
+	renamed to 'ro-u-boot' and 'rw-u-boot'. This can be useful to
+	distinguish binaries with otherwise identical names.
+
 
 Special properties
 ------------------
diff --git a/tools/binman/bsection.py b/tools/binman/bsection.py
index e0960d4..3f30f6e 100644
--- a/tools/binman/bsection.py
+++ b/tools/binman/bsection.py
@@ -41,6 +41,8 @@
              memory address (like 0xff800000) is the first entry position.
              This causes _skip_at_start to be set to the starting memory
              address.
+        _name_prefix: Prefix to add to the name of all entries within this
+            section
         _entries: OrderedDict() of entries
     """
     def __init__(self, name, node, test=False):
@@ -58,6 +60,7 @@
         self._sort = False
         self._skip_at_start = 0
         self._end_4gb = False
+        self._name_prefix = ''
         self._entries = OrderedDict()
         if not test:
             self._ReadNode()
@@ -79,10 +82,13 @@
             self._Raise("Section size must be provided when using end-at-4gb")
         if self._end_4gb:
             self._skip_at_start = 0x100000000 - self._size
+        self._name_prefix = fdt_util.GetString(self._node, 'name-prefix')
 
     def _ReadEntries(self):
         for node in self._node.subnodes:
-            self._entries[node.name] = Entry.Create(self, node)
+            entry = Entry.Create(self, node)
+            entry.SetPrefix(self._name_prefix)
+            self._entries[node.name] = entry
 
     def CheckSize(self):
         """Check that the section contents does not exceed its size, etc."""
diff --git a/tools/binman/entry.py b/tools/binman/entry.py
index 3811d33..e4d688c 100644
--- a/tools/binman/entry.py
+++ b/tools/binman/entry.py
@@ -48,11 +48,11 @@
         pad_after: Number of pad bytes after the contents, 0 if none
         data: Contents of entry (string of bytes)
     """
-    def __init__(self, section, etype, node, read_node=True):
+    def __init__(self, section, etype, node, read_node=True, name_prefix=''):
         self.section = section
         self.etype = etype
         self._node = node
-        self.name = node and node.name or 'none'
+        self.name = node and (name_prefix + node.name) or 'none'
         self.pos = None
         self.size = None
         self.contents_size = 0
@@ -129,6 +129,15 @@
         self.align_end = fdt_util.GetInt(self._node, 'align-end')
         self.pos_unset = fdt_util.GetBool(self._node, 'pos-unset')
 
+    def SetPrefix(self, prefix):
+        """Set the name prefix for a node
+
+        Args:
+            prefix: Prefix to set, or '' to not use a prefix
+        """
+        if prefix:
+            self.name = prefix + self.name
+
     def ObtainContents(self):
         """Figure out the contents of an entry.
 
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 61bbb53..eb8a079 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -950,5 +950,15 @@
  00000000  00000004  u-boot
 ''', map_data)
 
+    def testNamePrefix(self):
+        """Tests that name prefixes are used"""
+        _, _, map_data = self._DoReadFileDtb('56_name_prefix.dts', map=True)
+        self.assertEqual('''Position      Size  Name
+00000000  00000010  section@0
+ 00000000  00000004  ro-u-boot
+00000010  00000010  section@1
+ 00000000  00000004  rw-u-boot
+''', map_data)
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/tools/binman/test/56_name_prefix.dts b/tools/binman/test/56_name_prefix.dts
new file mode 100644
index 0000000..f38c80e
--- /dev/null
+++ b/tools/binman/test/56_name_prefix.dts
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	binman {
+		pad-byte = <0x26>;
+		size = <0x28>;
+		section@0 {
+			read-only;
+			name-prefix = "ro-";
+			size = <0x10>;
+			pad-byte = <0x21>;
+
+			u-boot {
+			};
+		};
+		section@1 {
+			name-prefix = "rw-";
+			size = <0x10>;
+			pad-byte = <0x61>;
+
+			u-boot {
+			};
+		};
+	};
+};