binman: Add support for adding TPL binaries

Add support for U-Boot's TPL and TPL device tree. Also fix a few comments
in the other device-tree entries.

Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/tools/binman/README.entries b/tools/binman/README.entries
index 1b75ca0..c6e7b22 100644
--- a/tools/binman/README.entries
+++ b/tools/binman/README.entries
@@ -365,7 +365,7 @@
 binary which loads before U-Boot proper, typically into on-chip SRAM. It is
 responsible for locating, loading and jumping to U-Boot. Note that SPL is
 not relocatable so must be loaded to the correct address in SRAM, or written
-to run from the correct address is direct flash execution is possible (e.g.
+to run from the correct address if direct flash execution is possible (e.g.
 on x86 devices).
 
 SPL can access binman symbols at runtime. See:
@@ -433,6 +433,42 @@
 
 
 
+Entry: u-boot-tpl: U-Boot TPL binary
+------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of u-boot-tpl.bin (default 'tpl/u-boot-tpl.bin')
+
+This is the U-Boot TPL (Tertiary Program Loader) binary. This is a small
+binary which loads before SPL, typically into on-chip SRAM. It is
+responsible for locating, loading and jumping to SPL, the next-stage
+loader. Note that SPL is not relocatable so must be loaded to the correct
+address in SRAM, or written to run from the correct address if direct
+flash execution is possible (e.g. on x86 devices).
+
+SPL can access binman symbols at runtime. See:
+
+    'Access to binman entry offsets at run time (symbols)'
+
+in the binman README for more information.
+
+The ELF file 'tpl/u-boot-tpl' must also be available for this to work, since
+binman uses that to look up symbols to write into the TPL binary.
+
+
+
+Entry: u-boot-tpl-dtb: U-Boot TPL device tree
+---------------------------------------------
+
+Properties / Entry arguments:
+    - filename: Filename of u-boot.dtb (default 'tpl/u-boot-tpl.dtb')
+
+This is the TPL device tree, containing configuration information for
+TPL. TPL needs this to know what devices are present and which drivers
+to activate.
+
+
+
 Entry: u-boot-ucode: U-Boot microcode block
 -------------------------------------------
 
diff --git a/tools/binman/etype/u_boot_spl.py b/tools/binman/etype/u_boot_spl.py
index 0e99a2d..ab78714 100644
--- a/tools/binman/etype/u_boot_spl.py
+++ b/tools/binman/etype/u_boot_spl.py
@@ -20,7 +20,7 @@
     binary which loads before U-Boot proper, typically into on-chip SRAM. It is
     responsible for locating, loading and jumping to U-Boot. Note that SPL is
     not relocatable so must be loaded to the correct address in SRAM, or written
-    to run from the correct address is direct flash execution is possible (e.g.
+    to run from the correct address if direct flash execution is possible (e.g.
     on x86 devices).
 
     SPL can access binman symbols at runtime. See:
diff --git a/tools/binman/etype/u_boot_spl_dtb.py b/tools/binman/etype/u_boot_spl_dtb.py
index 6a30edc..cb29ba3 100644
--- a/tools/binman/etype/u_boot_spl_dtb.py
+++ b/tools/binman/etype/u_boot_spl_dtb.py
@@ -2,7 +2,7 @@
 # Copyright (c) 2016 Google, Inc
 # Written by Simon Glass <sjg@chromium.org>
 #
-# Entry-type module for U-Boot device tree
+# Entry-type module for U-Boot device tree in SPL (Secondary Program Loader)
 #
 
 from entry import Entry
diff --git a/tools/binman/etype/u_boot_tpl.py b/tools/binman/etype/u_boot_tpl.py
new file mode 100644
index 0000000..4d4bb92
--- /dev/null
+++ b/tools/binman/etype/u_boot_tpl.py
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2016 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for tpl/u-boot-tpl.bin
+#
+
+import elf
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_u_boot_tpl(Entry_blob):
+    """U-Boot TPL binary
+
+    Properties / Entry arguments:
+        - filename: Filename of u-boot-tpl.bin (default 'tpl/u-boot-tpl.bin')
+
+    This is the U-Boot TPL (Tertiary Program Loader) binary. This is a small
+    binary which loads before SPL, typically into on-chip SRAM. It is
+    responsible for locating, loading and jumping to SPL, the next-stage
+    loader. Note that SPL is not relocatable so must be loaded to the correct
+    address in SRAM, or written to run from the correct address if direct
+    flash execution is possible (e.g. on x86 devices).
+
+    SPL can access binman symbols at runtime. See:
+
+        'Access to binman entry offsets at run time (symbols)'
+
+    in the binman README for more information.
+
+    The ELF file 'tpl/u-boot-tpl' must also be available for this to work, since
+    binman uses that to look up symbols to write into the TPL binary.
+    """
+    def __init__(self, section, etype, node):
+        Entry_blob.__init__(self, section, etype, node)
+        self.elf_fname = 'tpl/u-boot-tpl'
+
+    def GetDefaultFilename(self):
+        return 'tpl/u-boot-tpl.bin'
+
+    def WriteSymbols(self, section):
+        elf.LookupAndWriteSymbols(self.elf_fname, self, section)
diff --git a/tools/binman/etype/u_boot_tpl_dtb.py b/tools/binman/etype/u_boot_tpl_dtb.py
new file mode 100644
index 0000000..9c4e668
--- /dev/null
+++ b/tools/binman/etype/u_boot_tpl_dtb.py
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# Entry-type module for U-Boot device tree in TPL (Tertiary Program Loader)
+#
+
+from entry import Entry
+from blob import Entry_blob
+
+class Entry_u_boot_tpl_dtb(Entry_blob):
+    """U-Boot TPL device tree
+
+    Properties / Entry arguments:
+        - filename: Filename of u-boot.dtb (default 'tpl/u-boot-tpl.dtb')
+
+    This is the TPL device tree, containing configuration information for
+    TPL. TPL needs this to know what devices are present and which drivers
+    to activate.
+    """
+    def __init__(self, section, etype, node):
+        Entry_blob.__init__(self, section, etype, node)
+
+    def GetDefaultFilename(self):
+        return 'tpl/u-boot-tpl.dtb'
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index a6de4cb..d098685 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -30,11 +30,13 @@
 U_BOOT_DATA           = '1234'
 U_BOOT_IMG_DATA       = 'img'
 U_BOOT_SPL_DATA       = '56780123456789abcde'
+U_BOOT_TPL_DATA       = 'tpl'
 BLOB_DATA             = '89'
 ME_DATA               = '0abcd'
 VGA_DATA              = 'vga'
 U_BOOT_DTB_DATA       = 'udtb'
 U_BOOT_SPL_DTB_DATA   = 'spldtb'
+U_BOOT_TPL_DTB_DATA   = 'tpldtb'
 X86_START16_DATA      = 'start16'
 X86_START16_SPL_DATA  = 'start16spl'
 U_BOOT_NODTB_DATA     = 'nodtb with microcode pointer somewhere in here'
@@ -82,11 +84,11 @@
         TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
         TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
         TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
+        TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
         TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
         TestFunctional._MakeInputFile('me.bin', ME_DATA)
         TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
-        TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
-        TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
+        self._ResetDtbs()
         TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
         TestFunctional._MakeInputFile('spl/u-boot-x86-16bit-spl.bin',
                                       X86_START16_SPL_DATA)
@@ -126,6 +128,12 @@
         """Remove the temporary output directory"""
         tools._FinaliseForTest()
 
+    @classmethod
+    def _ResetDtbs(self):
+        TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
+        TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
+        TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
+
     def _RunBinman(self, *args, **kwargs):
         """Run binman using the command line
 
@@ -257,7 +265,7 @@
         finally:
             # Put the test file back
             if use_real_dtb:
-                TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
+                self._ResetDtbs()
 
     def _DoReadFile(self, fname, use_real_dtb=False):
         """Helper function which discards the device-tree binary
@@ -1345,6 +1353,14 @@
         self.assertIn("Node '/binman/vblock': Cannot find entry for node "
                       "'other'", str(e.exception))
 
+    def testTpl(self):
+        """Test that an image with TPL and ots device tree can be created"""
+        # ELF file with a '__bss_size' symbol
+        with open(self.TestFile('bss_data')) as fd:
+            TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
+        data = self._DoReadFile('78_u_boot_tpl.dts')
+        self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tools/binman/test/78_u_boot_tpl.dts b/tools/binman/test/78_u_boot_tpl.dts
new file mode 100644
index 0000000..6c60b4c
--- /dev/null
+++ b/tools/binman/test/78_u_boot_tpl.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+/ {
+	binman {
+		u-boot-tpl {
+		};
+		u-boot-tpl-dtb {
+		};
+	};
+};