binman: Support FDT update for CBFS
[oweals/u-boot.git] / tools / binman / ftest.py
index 1abb768e640977dcaae50d1094393908cb9f5d5e..999d8884acacc3ecdafe4a161c61815f46009c6e 100644 (file)
@@ -6,6 +6,8 @@
 #
 #    python -m unittest func_test.TestFunctional.testHelp
 
+from __future__ import print_function
+
 import hashlib
 from optparse import OptionParser
 import os
@@ -16,6 +18,7 @@ import tempfile
 import unittest
 
 import binman
+import cbfs_util
 import cmdline
 import command
 import control
@@ -24,41 +27,44 @@ import fdt
 import fdt_util
 import fmap_util
 import test_util
+import gzip
 import state
 import tools
 import tout
 
 # Contents of test files, corresponding to different entry types
-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'
-X86_START16_TPL_DATA  = 'start16tpl'
-U_BOOT_NODTB_DATA     = 'nodtb with microcode pointer somewhere in here'
-U_BOOT_SPL_NODTB_DATA = 'splnodtb with microcode pointer somewhere in here'
-U_BOOT_TPL_NODTB_DATA = 'tplnodtb with microcode pointer somewhere in here'
-FSP_DATA              = 'fsp'
-CMC_DATA              = 'cmc'
-VBT_DATA              = 'vbt'
-MRC_DATA              = 'mrc'
+U_BOOT_DATA           = b'1234'
+U_BOOT_IMG_DATA       = b'img'
+U_BOOT_SPL_DATA       = b'56780123456789abcde'
+U_BOOT_TPL_DATA       = b'tpl'
+BLOB_DATA             = b'89'
+ME_DATA               = b'0abcd'
+VGA_DATA              = b'vga'
+U_BOOT_DTB_DATA       = b'udtb'
+U_BOOT_SPL_DTB_DATA   = b'spldtb'
+U_BOOT_TPL_DTB_DATA   = b'tpldtb'
+X86_START16_DATA      = b'start16'
+X86_START16_SPL_DATA  = b'start16spl'
+X86_START16_TPL_DATA  = b'start16tpl'
+PPC_MPC85XX_BR_DATA   = b'ppcmpc85xxbr'
+U_BOOT_NODTB_DATA     = b'nodtb with microcode pointer somewhere in here'
+U_BOOT_SPL_NODTB_DATA = b'splnodtb with microcode pointer somewhere in here'
+U_BOOT_TPL_NODTB_DATA = b'tplnodtb with microcode pointer somewhere in here'
+FSP_DATA              = b'fsp'
+CMC_DATA              = b'cmc'
+VBT_DATA              = b'vbt'
+MRC_DATA              = b'mrc'
 TEXT_DATA             = 'text'
 TEXT_DATA2            = 'text2'
 TEXT_DATA3            = 'text3'
-CROS_EC_RW_DATA       = 'ecrw'
-GBB_DATA              = 'gbbd'
-BMPBLK_DATA           = 'bmp'
-VBLOCK_DATA           = 'vblk'
-FILES_DATA            = ("sorry I'm late\nOh, don't bother apologising, I'm " +
-                         "sorry you're alive\n")
-COMPRESS_DATA         = 'data to compress'
+CROS_EC_RW_DATA       = b'ecrw'
+GBB_DATA              = b'gbbd'
+BMPBLK_DATA           = b'bmp'
+VBLOCK_DATA           = b'vblk'
+FILES_DATA            = (b"sorry I'm late\nOh, don't bother apologising, I'm " +
+                         b"sorry you're alive\n")
+COMPRESS_DATA         = b'compress xxxxxxxxxxxxxxxxxxxxxx data'
+REFCODE_DATA          = b'refcode'
 
 
 class TestFunctional(unittest.TestCase):
@@ -97,6 +103,7 @@ class TestFunctional(unittest.TestCase):
         TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
         self._ResetDtbs()
         TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
+        TestFunctional._MakeInputFile('u-boot-br.bin', PPC_MPC85XX_BR_DATA)
         TestFunctional._MakeInputFile('spl/u-boot-x86-16bit-spl.bin',
                                       X86_START16_SPL_DATA)
         TestFunctional._MakeInputFile('tpl/u-boot-x86-16bit-tpl.bin',
@@ -113,14 +120,14 @@ class TestFunctional(unittest.TestCase):
         TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
         TestFunctional._MakeInputDir('devkeys')
         TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
-        self._output_setup = False
+        TestFunctional._MakeInputFile('refcode.bin', REFCODE_DATA)
 
         # ELF file with a '_dt_ucode_base_size' symbol
-        with open(self.TestFile('u_boot_ucode_ptr')) as fd:
+        with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
             TestFunctional._MakeInputFile('u-boot', fd.read())
 
         # Intel flash descriptor file
-        with open(self.TestFile('descriptor.bin')) as fd:
+        with open(self.TestFile('descriptor.bin'), 'rb') as fd:
             TestFunctional._MakeInputFile('descriptor.bin', fd.read())
 
         shutil.copytree(self.TestFile('files'),
@@ -128,13 +135,46 @@ class TestFunctional(unittest.TestCase):
 
         TestFunctional._MakeInputFile('compress', COMPRESS_DATA)
 
+        # Travis-CI may have an old lz4
+        self.have_lz4 = True
+        try:
+            tools.Run('lz4', '--no-frame-crc', '-c',
+                      os.path.join(self._indir, 'u-boot.bin'))
+        except:
+            self.have_lz4 = False
+
     @classmethod
     def tearDownClass(self):
         """Remove the temporary input directory and its contents"""
-        if self._indir:
-            shutil.rmtree(self._indir)
+        if self.preserve_indir:
+            print('Preserving input dir: %s' % self._indir)
+        else:
+            if self._indir:
+                shutil.rmtree(self._indir)
         self._indir = None
 
+    @classmethod
+    def setup_test_args(cls, preserve_indir=False, preserve_outdirs=False,
+                        toolpath=None, verbosity=None):
+        """Accept arguments controlling test execution
+
+        Args:
+            preserve_indir: Preserve the shared input directory used by all
+                tests in this class.
+            preserve_outdir: Preserve the output directories used by tests. Each
+                test has its own, so this is normally only useful when running a
+                single test.
+            toolpath: ist of paths to use for tools
+        """
+        cls.preserve_indir = preserve_indir
+        cls.preserve_outdirs = preserve_outdirs
+        cls.toolpath = toolpath
+        cls.verbosity = verbosity
+
+    def _CheckLz4(self):
+        if not self.have_lz4:
+            self.skipTest('lz4 --no-frame-crc not available')
+
     def setUp(self):
         # Enable this to turn on debugging output
         # tout.Init(tout.DEBUG)
@@ -142,7 +182,10 @@ class TestFunctional(unittest.TestCase):
 
     def tearDown(self):
         """Remove the temporary output directory"""
-        tools._FinaliseForTest()
+        if self.preserve_outdirs:
+            print('Preserving output dir: %s' % tools.outdir)
+        else:
+            tools._FinaliseForTest()
 
     @classmethod
     def _ResetDtbs(self):
@@ -164,7 +207,7 @@ class TestFunctional(unittest.TestCase):
                             result.stdout + result.stderr))
         return result
 
-    def _DoBinman(self, *args):
+    def _DoBinman(self, *argv):
         """Run binman using directly (in the same process)
 
         Args:
@@ -172,23 +215,22 @@ class TestFunctional(unittest.TestCase):
         Returns:
             Return value (0 for success)
         """
-        args = list(args)
-        if '-D' in sys.argv:
-            args = args + ['-D']
-        (options, args) = cmdline.ParseArgs(args)
-        options.pager = 'binman-invalid-pager'
-        options.build_dir = self._indir
+        argv = list(argv)
+        args = cmdline.ParseArgs(argv)
+        args.pager = 'binman-invalid-pager'
+        args.build_dir = self._indir
 
         # For testing, you can force an increase in verbosity here
-        # options.verbosity = tout.DEBUG
-        return control.Binman(options, args)
+        # args.verbosity = tout.DEBUG
+        return control.Binman(args)
 
     def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
-                    entry_args=None, images=None, use_real_dtb=False):
+                    entry_args=None, images=None, use_real_dtb=False,
+                    verbosity=None):
         """Run binman with a given test file
 
         Args:
-            fname: Device-tree source filename to use (e.g. 05_simple.dts)
+            fname: Device-tree source filename to use (e.g. 005_simple.dts)
             debug: True to enable debugging output
             map: True to output map files for the images
             update_dtb: Update the offset and size of each entry in the device
@@ -198,17 +240,25 @@ class TestFunctional(unittest.TestCase):
                 value: value of that arg
             images: List of image names to build
         """
-        args = ['-p', '-I', self._indir, '-d', self.TestFile(fname)]
+        args = []
         if debug:
             args.append('-D')
+        if verbosity is not None:
+            args.append('-v%d' % verbosity)
+        elif self.verbosity:
+            args.append('-v%d' % self.verbosity)
+        if self.toolpath:
+            for path in self.toolpath:
+                args += ['--toolpath', path]
+        args += ['build', '-p', '-I', self._indir, '-d', self.TestFile(fname)]
         if map:
             args.append('-m')
         if update_dtb:
-            args.append('-up')
+            args.append('-u')
         if not use_real_dtb:
             args.append('--fake-dtb')
         if entry_args:
-            for arg, value in entry_args.iteritems():
+            for arg, value in entry_args.items():
                 args.append('-a%s=%s' % (arg, value))
         if images:
             for image in images:
@@ -228,14 +278,13 @@ class TestFunctional(unittest.TestCase):
         Returns:
             Contents of device-tree binary
         """
-        if not self._output_setup:
-            tools.PrepareOutputDir(self._indir, True)
-            self._output_setup = True
+        tools.PrepareOutputDir(None)
         dtb = fdt_util.EnsureCompiled(self.TestFile(fname))
-        with open(dtb) as fd:
+        with open(dtb, 'rb') as fd:
             data = fd.read()
             TestFunctional._MakeInputFile(outfile, data)
-            return data
+        tools.FinaliseOutputDir()
+        return data
 
     def _GetDtbContentsForSplTpl(self, dtb_data, name):
         """Create a version of the main DTB for SPL or SPL
@@ -266,7 +315,7 @@ class TestFunctional(unittest.TestCase):
         Raises an assertion failure if binman returns a non-zero exit code.
 
         Args:
-            fname: Device-tree source filename to use (e.g. 05_simple.dts)
+            fname: Device-tree source filename to use (e.g. 005_simple.dts)
             use_real_dtb: True to use the test file as the contents of
                 the u-boot-dtb entry. Normally this is not needed and the
                 test contents (the U_BOOT_DTB_DATA string) can be used.
@@ -286,7 +335,6 @@ class TestFunctional(unittest.TestCase):
         # Use the compiled test file as the u-boot-dtb input
         if use_real_dtb:
             dtb_data = self._SetupDtb(fname)
-            infile = os.path.join(self._indir, 'u-boot.dtb')
 
             # For testing purposes, make a copy of the DT for SPL and TPL. Add
             # a node indicating which it is, so aid verification.
@@ -312,18 +360,29 @@ class TestFunctional(unittest.TestCase):
                     map_data = fd.read()
             else:
                 map_data = None
-            with open(image_fname) as fd:
+            with open(image_fname, 'rb') as fd:
                 return fd.read(), dtb_data, map_data, out_dtb_fname
         finally:
             # Put the test file back
             if reset_dtbs and use_real_dtb:
                 self._ResetDtbs()
 
+    def _DoReadFileRealDtb(self, fname):
+        """Run binman with a real .dtb file and return the resulting data
+
+        Args:
+            fname: DT source filename to use (e.g. 082_fdt_update_all.dts)
+
+        Returns:
+            Resulting image contents
+        """
+        return self._DoReadFileDtb(fname, use_real_dtb=True, update_dtb=True)[0]
+
     def _DoReadFile(self, fname, use_real_dtb=False):
         """Helper function which discards the device-tree binary
 
         Args:
-            fname: Device-tree source filename to use (e.g. 05_simple.dts)
+            fname: Device-tree source filename to use (e.g. 005_simple.dts)
             use_real_dtb: True to use the test file as the contents of
                 the u-boot-dtb entry. Normally this is not needed and the
                 test contents (the U_BOOT_DTB_DATA string) can be used.
@@ -367,6 +426,16 @@ class TestFunctional(unittest.TestCase):
             os.makedirs(pathname)
         return pathname
 
+    @classmethod
+    def _SetupSplElf(self, src_fname='bss_data'):
+        """Set up an ELF file with a '_dt_ucode_base_size' symbol
+
+        Args:
+            Filename of ELF file to use as SPL
+        """
+        with open(self.TestFile(src_fname), 'rb') as fd:
+            TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
+
     @classmethod
     def TestFile(self, fname):
         return os.path.join(self._binman_dir, 'test', fname)
@@ -381,7 +450,7 @@ class TestFunctional(unittest.TestCase):
         for grep in grep_list:
             if grep in target:
                 return
-        self.fail("Error: '%' not found in '%s'" % (grep_list, target))
+        self.fail("Error: '%s' not found in '%s'" % (grep_list, target))
 
     def CheckNoGaps(self, entries):
         """Check that all entries fit together without gaps
@@ -405,16 +474,16 @@ class TestFunctional(unittest.TestCase):
         """
         return struct.unpack('>L', dtb[4:8])[0]
 
-    def _GetPropTree(self, dtb, prop_names):
+    def _GetPropTree(self, dtb, prop_names, prefix='/binman/'):
         def AddNode(node, path):
             if node.name != '/':
                 path += '/' + node.name
+            for prop in node.props.values():
+                if prop.name in prop_names:
+                    prop_path = path + ':' + prop.name
+                    tree[prop_path[len(prefix):]] = fdt_util.fdt32_to_cpu(
+                        prop.value)
             for subnode in node.subnodes:
-                for prop in subnode.props.values():
-                    if prop.name in prop_names:
-                        prop_path = path + '/' + subnode.name + ':' + prop.name
-                        tree[prop_path[len('/binman/'):]] = fdt_util.fdt32_to_cpu(
-                            prop.value)
                 AddNode(subnode, path)
 
         tree = {}
@@ -454,22 +523,22 @@ class TestFunctional(unittest.TestCase):
 
     def testBoard(self):
         """Test that we can run it with a specific board"""
-        self._SetupDtb('05_simple.dts', 'sandbox/u-boot.dtb')
+        self._SetupDtb('005_simple.dts', 'sandbox/u-boot.dtb')
         TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
-        result = self._DoBinman('-b', 'sandbox')
+        result = self._DoBinman('build', '-b', 'sandbox')
         self.assertEqual(0, result)
 
     def testNeedBoard(self):
         """Test that we get an error when no board ius supplied"""
         with self.assertRaises(ValueError) as e:
-            result = self._DoBinman()
+            result = self._DoBinman('build')
         self.assertIn("Must provide a board to process (use -b <board>)",
                 str(e.exception))
 
     def testMissingDt(self):
         """Test that an invalid device-tree file generates an error"""
         with self.assertRaises(Exception) as e:
-            self._RunBinman('-d', 'missing_file')
+            self._RunBinman('build', '-d', 'missing_file')
         # We get one error from libfdt, and a different one from fdtget.
         self.AssertInList(["Couldn't open blob from 'missing_file'",
                            'No such file or directory'], str(e.exception))
@@ -481,52 +550,52 @@ class TestFunctional(unittest.TestCase):
         will come from the device-tree compiler (dtc).
         """
         with self.assertRaises(Exception) as e:
-            self._RunBinman('-d', self.TestFile('01_invalid.dts'))
+            self._RunBinman('build', '-d', self.TestFile('001_invalid.dts'))
         self.assertIn("FATAL ERROR: Unable to parse input tree",
                 str(e.exception))
 
     def testMissingNode(self):
         """Test that a device tree without a 'binman' node generates an error"""
         with self.assertRaises(Exception) as e:
-            self._DoBinman('-d', self.TestFile('02_missing_node.dts'))
+            self._DoBinman('build', '-d', self.TestFile('002_missing_node.dts'))
         self.assertIn("does not have a 'binman' node", str(e.exception))
 
     def testEmpty(self):
         """Test that an empty binman node works OK (i.e. does nothing)"""
-        result = self._RunBinman('-d', self.TestFile('03_empty.dts'))
+        result = self._RunBinman('build', '-d', self.TestFile('003_empty.dts'))
         self.assertEqual(0, len(result.stderr))
         self.assertEqual(0, result.return_code)
 
     def testInvalidEntry(self):
         """Test that an invalid entry is flagged"""
         with self.assertRaises(Exception) as e:
-            result = self._RunBinman('-d',
-                                     self.TestFile('04_invalid_entry.dts'))
+            result = self._RunBinman('build', '-d',
+                                     self.TestFile('004_invalid_entry.dts'))
         self.assertIn("Unknown entry type 'not-a-valid-type' in node "
                 "'/binman/not-a-valid-type'", str(e.exception))
 
     def testSimple(self):
         """Test a simple binman with a single file"""
-        data = self._DoReadFile('05_simple.dts')
+        data = self._DoReadFile('005_simple.dts')
         self.assertEqual(U_BOOT_DATA, data)
 
     def testSimpleDebug(self):
         """Test a simple binman run with debugging enabled"""
-        data = self._DoTestFile('05_simple.dts', debug=True)
+        data = self._DoTestFile('005_simple.dts', debug=True)
 
     def testDual(self):
         """Test that we can handle creating two images
 
         This also tests image padding.
         """
-        retcode = self._DoTestFile('06_dual_image.dts')
+        retcode = self._DoTestFile('006_dual_image.dts')
         self.assertEqual(0, retcode)
 
         image = control.images['image1']
         self.assertEqual(len(U_BOOT_DATA), image._size)
         fname = tools.GetOutputFilename('image1.bin')
         self.assertTrue(os.path.exists(fname))
-        with open(fname) as fd:
+        with open(fname, 'rb') as fd:
             data = fd.read()
             self.assertEqual(U_BOOT_DATA, data)
 
@@ -534,22 +603,22 @@ class TestFunctional(unittest.TestCase):
         self.assertEqual(3 + len(U_BOOT_DATA) + 5, image._size)
         fname = tools.GetOutputFilename('image2.bin')
         self.assertTrue(os.path.exists(fname))
-        with open(fname) as fd:
+        with open(fname, 'rb') as fd:
             data = fd.read()
             self.assertEqual(U_BOOT_DATA, data[3:7])
-            self.assertEqual(chr(0) * 3, data[:3])
-            self.assertEqual(chr(0) * 5, data[7:])
+            self.assertEqual(tools.GetBytes(0, 3), data[:3])
+            self.assertEqual(tools.GetBytes(0, 5), data[7:])
 
     def testBadAlign(self):
         """Test that an invalid alignment value is detected"""
         with self.assertRaises(ValueError) as e:
-            self._DoTestFile('07_bad_align.dts')
+            self._DoTestFile('007_bad_align.dts')
         self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
                       "of two", str(e.exception))
 
     def testPackSimple(self):
         """Test that packing works as expected"""
-        retcode = self._DoTestFile('08_pack.dts')
+        retcode = self._DoTestFile('008_pack.dts')
         self.assertEqual(0, retcode)
         self.assertIn('image', control.images)
         image = control.images['image']
@@ -591,7 +660,7 @@ class TestFunctional(unittest.TestCase):
 
     def testPackExtra(self):
         """Test that extra packing feature works as expected"""
-        retcode = self._DoTestFile('09_pack_extra.dts')
+        retcode = self._DoTestFile('009_pack_extra.dts')
 
         self.assertEqual(0, retcode)
         self.assertIn('image', control.images)
@@ -636,35 +705,35 @@ class TestFunctional(unittest.TestCase):
     def testPackAlignPowerOf2(self):
         """Test that invalid entry alignment is detected"""
         with self.assertRaises(ValueError) as e:
-            self._DoTestFile('10_pack_align_power2.dts')
+            self._DoTestFile('010_pack_align_power2.dts')
         self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
                       "of two", str(e.exception))
 
     def testPackAlignSizePowerOf2(self):
         """Test that invalid entry size alignment is detected"""
         with self.assertRaises(ValueError) as e:
-            self._DoTestFile('11_pack_align_size_power2.dts')
+            self._DoTestFile('011_pack_align_size_power2.dts')
         self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
                       "power of two", str(e.exception))
 
     def testPackInvalidAlign(self):
         """Test detection of an offset that does not match its alignment"""
         with self.assertRaises(ValueError) as e:
-            self._DoTestFile('12_pack_inv_align.dts')
+            self._DoTestFile('012_pack_inv_align.dts')
         self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
                       "align 0x4 (4)", str(e.exception))
 
     def testPackInvalidSizeAlign(self):
         """Test that invalid entry size alignment is detected"""
         with self.assertRaises(ValueError) as e:
-            self._DoTestFile('13_pack_inv_size_align.dts')
+            self._DoTestFile('013_pack_inv_size_align.dts')
         self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
                       "align-size 0x4 (4)", str(e.exception))
 
     def testPackOverlap(self):
         """Test that overlapping regions are detected"""
         with self.assertRaises(ValueError) as e:
-            self._DoTestFile('14_pack_overlap.dts')
+            self._DoTestFile('014_pack_overlap.dts')
         self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
                       "with previous entry '/binman/u-boot' ending at 0x4 (4)",
                       str(e.exception))
@@ -672,20 +741,20 @@ class TestFunctional(unittest.TestCase):
     def testPackEntryOverflow(self):
         """Test that entries that overflow their size are detected"""
         with self.assertRaises(ValueError) as e:
-            self._DoTestFile('15_pack_overflow.dts')
+            self._DoTestFile('015_pack_overflow.dts')
         self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
                       "but entry size is 0x3 (3)", str(e.exception))
 
     def testPackImageOverflow(self):
         """Test that entries which overflow the image size are detected"""
         with self.assertRaises(ValueError) as e:
-            self._DoTestFile('16_pack_image_overflow.dts')
+            self._DoTestFile('016_pack_image_overflow.dts')
         self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section "
                       "size 0x3 (3)", str(e.exception))
 
     def testPackImageSize(self):
         """Test that the image size can be set"""
-        retcode = self._DoTestFile('17_pack_image_size.dts')
+        retcode = self._DoTestFile('017_pack_image_size.dts')
         self.assertEqual(0, retcode)
         self.assertIn('image', control.images)
         image = control.images['image']
@@ -693,7 +762,7 @@ class TestFunctional(unittest.TestCase):
 
     def testPackImageSizeAlign(self):
         """Test that image size alignemnt works as expected"""
-        retcode = self._DoTestFile('18_pack_image_align.dts')
+        retcode = self._DoTestFile('018_pack_image_align.dts')
         self.assertEqual(0, retcode)
         self.assertIn('image', control.images)
         image = control.images['image']
@@ -702,27 +771,27 @@ class TestFunctional(unittest.TestCase):
     def testPackInvalidImageAlign(self):
         """Test that invalid image alignment is detected"""
         with self.assertRaises(ValueError) as e:
-            self._DoTestFile('19_pack_inv_image_align.dts')
+            self._DoTestFile('019_pack_inv_image_align.dts')
         self.assertIn("Section '/binman': Size 0x7 (7) does not match "
                       "align-size 0x8 (8)", str(e.exception))
 
     def testPackAlignPowerOf2(self):
         """Test that invalid image alignment is detected"""
         with self.assertRaises(ValueError) as e:
-            self._DoTestFile('20_pack_inv_image_align_power2.dts')
+            self._DoTestFile('020_pack_inv_image_align_power2.dts')
         self.assertIn("Section '/binman': Alignment size 131 must be a power of "
                       "two", str(e.exception))
 
     def testImagePadByte(self):
         """Test that the image pad byte can be specified"""
-        with open(self.TestFile('bss_data')) as fd:
-            TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
-        data = self._DoReadFile('21_image_pad.dts')
-        self.assertEqual(U_BOOT_SPL_DATA + (chr(0xff) * 1) + U_BOOT_DATA, data)
+        self._SetupSplElf()
+        data = self._DoReadFile('021_image_pad.dts')
+        self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0xff, 1) +
+                         U_BOOT_DATA, data)
 
     def testImageName(self):
         """Test that image files can be named"""
-        retcode = self._DoTestFile('22_image_name.dts')
+        retcode = self._DoTestFile('022_image_name.dts')
         self.assertEqual(0, retcode)
         image = control.images['image1']
         fname = tools.GetOutputFilename('test-name')
@@ -734,80 +803,99 @@ class TestFunctional(unittest.TestCase):
 
     def testBlobFilename(self):
         """Test that generic blobs can be provided by filename"""
-        data = self._DoReadFile('23_blob.dts')
+        data = self._DoReadFile('023_blob.dts')
         self.assertEqual(BLOB_DATA, data)
 
     def testPackSorted(self):
         """Test that entries can be sorted"""
-        data = self._DoReadFile('24_sorted.dts')
-        self.assertEqual(chr(0) * 1 + U_BOOT_SPL_DATA + chr(0) * 2 +
-                         U_BOOT_DATA, data)
+        self._SetupSplElf()
+        data = self._DoReadFile('024_sorted.dts')
+        self.assertEqual(tools.GetBytes(0, 1) + U_BOOT_SPL_DATA +
+                         tools.GetBytes(0, 2) + U_BOOT_DATA, data)
 
     def testPackZeroOffset(self):
         """Test that an entry at offset 0 is not given a new offset"""
         with self.assertRaises(ValueError) as e:
-            self._DoTestFile('25_pack_zero_size.dts')
+            self._DoTestFile('025_pack_zero_size.dts')
         self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
                       "with previous entry '/binman/u-boot' ending at 0x4 (4)",
                       str(e.exception))
 
     def testPackUbootDtb(self):
         """Test that a device tree can be added to U-Boot"""
-        data = self._DoReadFile('26_pack_u_boot_dtb.dts')
+        data = self._DoReadFile('026_pack_u_boot_dtb.dts')
         self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
 
     def testPackX86RomNoSize(self):
         """Test that the end-at-4gb property requires a size property"""
         with self.assertRaises(ValueError) as e:
-            self._DoTestFile('27_pack_4gb_no_size.dts')
+            self._DoTestFile('027_pack_4gb_no_size.dts')
         self.assertIn("Section '/binman': Section size must be provided when "
                       "using end-at-4gb", str(e.exception))
 
+    def test4gbAndSkipAtStartTogether(self):
+        """Test that the end-at-4gb and skip-at-size property can't be used
+        together"""
+        with self.assertRaises(ValueError) as e:
+            self._DoTestFile('80_4gb_and_skip_at_start_together.dts')
+        self.assertIn("Section '/binman': Provide either 'end-at-4gb' or "
+                      "'skip-at-start'", str(e.exception))
+
     def testPackX86RomOutside(self):
         """Test that the end-at-4gb property checks for offset boundaries"""
         with self.assertRaises(ValueError) as e:
-            self._DoTestFile('28_pack_4gb_outside.dts')
+            self._DoTestFile('028_pack_4gb_outside.dts')
         self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
                       "the section starting at 0xffffffe0 (4294967264)",
                       str(e.exception))
 
     def testPackX86Rom(self):
         """Test that a basic x86 ROM can be created"""
-        data = self._DoReadFile('29_x86-rom.dts')
-        self.assertEqual(U_BOOT_DATA + chr(0) * 7 + U_BOOT_SPL_DATA +
-                         chr(0) * 2, data)
+        self._SetupSplElf()
+        data = self._DoReadFile('029_x86-rom.dts')
+        self.assertEqual(U_BOOT_DATA + tools.GetBytes(0, 7) + U_BOOT_SPL_DATA +
+                         tools.GetBytes(0, 2), data)
 
     def testPackX86RomMeNoDesc(self):
         """Test that an invalid Intel descriptor entry is detected"""
-        TestFunctional._MakeInputFile('descriptor.bin', '')
+        TestFunctional._MakeInputFile('descriptor.bin', b'')
         with self.assertRaises(ValueError) as e:
-            self._DoTestFile('31_x86-rom-me.dts')
-        self.assertIn("Node '/binman/intel-descriptor': Cannot find FD "
-                      "signature", str(e.exception))
+            self._DoTestFile('031_x86-rom-me.dts')
+        self.assertIn("Node '/binman/intel-descriptor': Cannot find Intel Flash Descriptor (FD) signature",
+                      str(e.exception))
 
     def testPackX86RomBadDesc(self):
         """Test that the Intel requires a descriptor entry"""
         with self.assertRaises(ValueError) as e:
-            self._DoTestFile('30_x86-rom-me-no-desc.dts')
+            self._DoTestFile('030_x86-rom-me-no-desc.dts')
         self.assertIn("Node '/binman/intel-me': No offset set with "
                       "offset-unset: should another entry provide this correct "
                       "offset?", str(e.exception))
 
     def testPackX86RomMe(self):
         """Test that an x86 ROM with an ME region can be created"""
-        data = self._DoReadFile('31_x86-rom-me.dts')
+        data = self._DoReadFile('031_x86-rom-me.dts')
+        expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
+        if data[:0x1000] != expected_desc:
+            self.fail('Expected descriptor binary at start of image')
         self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
 
     def testPackVga(self):
         """Test that an image with a VGA binary can be created"""
-        data = self._DoReadFile('32_intel-vga.dts')
+        data = self._DoReadFile('032_intel-vga.dts')
         self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
 
     def testPackStart16(self):
         """Test that an image with an x86 start16 region can be created"""
-        data = self._DoReadFile('33_x86-start16.dts')
+        data = self._DoReadFile('033_x86-start16.dts')
         self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
 
+    def testPackPowerpcMpc85xxBootpgResetvec(self):
+        """Test that an image with powerpc-mpc85xx-bootpg-resetvec can be
+        created"""
+        data = self._DoReadFile('81_powerpc_mpc85xx_bootpg_resetvec.dts')
+        self.assertEqual(PPC_MPC85XX_BR_DATA, data[:len(PPC_MPC85XX_BR_DATA)])
+
     def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False):
         """Handle running a test for insertion of microcode
 
@@ -868,10 +956,10 @@ class TestFunctional(unittest.TestCase):
             u-boot.dtb with the microcode removed
             the microcode
         """
-        first, pos_and_size = self._RunMicrocodeTest('34_x86_ucode.dts',
+        first, pos_and_size = self._RunMicrocodeTest('034_x86_ucode.dts',
                                                      U_BOOT_NODTB_DATA)
-        self.assertEqual('nodtb with microcode' + pos_and_size +
-                         ' somewhere in here', first)
+        self.assertEqual(b'nodtb with microcode' + pos_and_size +
+                         b' somewhere in here', first)
 
     def _RunPackUbootSingleMicrocode(self):
         """Test that x86 microcode can be handled correctly
@@ -885,7 +973,7 @@ class TestFunctional(unittest.TestCase):
         # We need the libfdt library to run this test since only that allows
         # finding the offset of a property. This is required by
         # Entry_u_boot_dtb_with_ucode.ObtainContents().
-        data = self._DoReadFile('35_x86_single_ucode.dts', True)
+        data = self._DoReadFile('035_x86_single_ucode.dts', True)
 
         second = data[len(U_BOOT_NODTB_DATA):]
 
@@ -902,8 +990,8 @@ class TestFunctional(unittest.TestCase):
         pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
                                    len(ucode_data))
         first = data[:len(U_BOOT_NODTB_DATA)]
-        self.assertEqual('nodtb with microcode' + pos_and_size +
-                         ' somewhere in here', first)
+        self.assertEqual(b'nodtb with microcode' + pos_and_size +
+                         b' somewhere in here', first)
 
     def testPackUbootSingleMicrocode(self):
         """Test that x86 microcode can be handled correctly with fdt_normal.
@@ -912,27 +1000,27 @@ class TestFunctional(unittest.TestCase):
 
     def testUBootImg(self):
         """Test that u-boot.img can be put in a file"""
-        data = self._DoReadFile('36_u_boot_img.dts')
+        data = self._DoReadFile('036_u_boot_img.dts')
         self.assertEqual(U_BOOT_IMG_DATA, data)
 
     def testNoMicrocode(self):
         """Test that a missing microcode region is detected"""
         with self.assertRaises(ValueError) as e:
-            self._DoReadFile('37_x86_no_ucode.dts', True)
+            self._DoReadFile('037_x86_no_ucode.dts', True)
         self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
                       "node found in ", str(e.exception))
 
     def testMicrocodeWithoutNode(self):
         """Test that a missing u-boot-dtb-with-ucode node is detected"""
         with self.assertRaises(ValueError) as e:
-            self._DoReadFile('38_x86_ucode_missing_node.dts', True)
+            self._DoReadFile('038_x86_ucode_missing_node.dts', True)
         self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
                 "microcode region u-boot-dtb-with-ucode", str(e.exception))
 
     def testMicrocodeWithoutNode2(self):
         """Test that a missing u-boot-ucode node is detected"""
         with self.assertRaises(ValueError) as e:
-            self._DoReadFile('39_x86_ucode_missing_node2.dts', True)
+            self._DoReadFile('039_x86_ucode_missing_node2.dts', True)
         self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
             "microcode region u-boot-ucode", str(e.exception))
 
@@ -940,7 +1028,7 @@ class TestFunctional(unittest.TestCase):
         """Test that a U-Boot binary without the microcode symbol is detected"""
         # ELF file without a '_dt_ucode_base_size' symbol
         try:
-            with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
+            with open(self.TestFile('u_boot_no_ucode_ptr'), 'rb') as fd:
                 TestFunctional._MakeInputFile('u-boot', fd.read())
 
             with self.assertRaises(ValueError) as e:
@@ -950,22 +1038,22 @@ class TestFunctional(unittest.TestCase):
 
         finally:
             # Put the original file back
-            with open(self.TestFile('u_boot_ucode_ptr')) as fd:
+            with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
                 TestFunctional._MakeInputFile('u-boot', fd.read())
 
     def testMicrocodeNotInImage(self):
         """Test that microcode must be placed within the image"""
         with self.assertRaises(ValueError) as e:
-            self._DoReadFile('40_x86_ucode_not_in_image.dts', True)
+            self._DoReadFile('040_x86_ucode_not_in_image.dts', True)
         self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
                 "pointer _dt_ucode_base_size at fffffe14 is outside the "
                 "section ranging from 00000000 to 0000002e", str(e.exception))
 
     def testWithoutMicrocode(self):
         """Test that we can cope with an image without microcode (e.g. qemu)"""
-        with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
+        with open(self.TestFile('u_boot_no_ucode_ptr'), 'rb') as fd:
             TestFunctional._MakeInputFile('u-boot', fd.read())
-        data, dtb, _, _ = self._DoReadFileDtb('44_x86_optional_ucode.dts', True)
+        data, dtb, _, _ = self._DoReadFileDtb('044_x86_optional_ucode.dts', True)
 
         # Now check the device tree has no microcode
         self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
@@ -976,48 +1064,49 @@ class TestFunctional(unittest.TestCase):
 
         used_len = len(U_BOOT_NODTB_DATA) + fdt_len
         third = data[used_len:]
-        self.assertEqual(chr(0) * (0x200 - used_len), third)
+        self.assertEqual(tools.GetBytes(0, 0x200 - used_len), third)
 
     def testUnknownPosSize(self):
         """Test that microcode must be placed within the image"""
         with self.assertRaises(ValueError) as e:
-            self._DoReadFile('41_unknown_pos_size.dts', True)
+            self._DoReadFile('041_unknown_pos_size.dts', True)
         self.assertIn("Section '/binman': Unable to set offset/size for unknown "
                 "entry 'invalid-entry'", str(e.exception))
 
     def testPackFsp(self):
         """Test that an image with a FSP binary can be created"""
-        data = self._DoReadFile('42_intel-fsp.dts')
+        data = self._DoReadFile('042_intel-fsp.dts')
         self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
 
     def testPackCmc(self):
         """Test that an image with a CMC binary can be created"""
-        data = self._DoReadFile('43_intel-cmc.dts')
+        data = self._DoReadFile('043_intel-cmc.dts')
         self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
 
     def testPackVbt(self):
         """Test that an image with a VBT binary can be created"""
-        data = self._DoReadFile('46_intel-vbt.dts')
+        data = self._DoReadFile('046_intel-vbt.dts')
         self.assertEqual(VBT_DATA, data[:len(VBT_DATA)])
 
     def testSplBssPad(self):
         """Test that we can pad SPL's BSS with zeros"""
         # ELF file with a '__bss_size' symbol
-        with open(self.TestFile('bss_data')) as fd:
-            TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
-        data = self._DoReadFile('47_spl_bss_pad.dts')
-        self.assertEqual(U_BOOT_SPL_DATA + (chr(0) * 10) + U_BOOT_DATA, data)
-
-        with open(self.TestFile('u_boot_ucode_ptr')) as fd:
-            TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
+        self._SetupSplElf()
+        data = self._DoReadFile('047_spl_bss_pad.dts')
+        self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0, 10) + U_BOOT_DATA,
+                         data)
+
+    def testSplBssPadMissing(self):
+        """Test that a missing symbol is detected"""
+        self._SetupSplElf('u_boot_ucode_ptr')
         with self.assertRaises(ValueError) as e:
-            data = self._DoReadFile('47_spl_bss_pad.dts')
+            self._DoReadFile('047_spl_bss_pad.dts')
         self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
                       str(e.exception))
 
     def testPackStart16Spl(self):
         """Test that an image with an x86 start16 SPL region can be created"""
-        data = self._DoReadFile('48_x86-start16-spl.dts')
+        data = self._DoReadFile('048_x86-start16-spl.dts')
         self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)])
 
     def _PackUbootSplMicrocode(self, dts, ucode_second=False):
@@ -1034,17 +1123,15 @@ class TestFunctional(unittest.TestCase):
             ucode_second: True if the microsecond entry is second instead of
                 third
         """
-        # ELF file with a '_dt_ucode_base_size' symbol
-        with open(self.TestFile('u_boot_ucode_ptr')) as fd:
-            TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
+        self._SetupSplElf('u_boot_ucode_ptr')
         first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA,
                                                      ucode_second=ucode_second)
-        self.assertEqual('splnodtb with microc' + pos_and_size +
-                         'ter somewhere in here', first)
+        self.assertEqual(b'splnodtb with microc' + pos_and_size +
+                         b'ter somewhere in here', first)
 
     def testPackUbootSplMicrocode(self):
         """Test that x86 microcode can be handled correctly in SPL"""
-        self._PackUbootSplMicrocode('49_x86_ucode_spl.dts')
+        self._PackUbootSplMicrocode('049_x86_ucode_spl.dts')
 
     def testPackUbootSplMicrocodeReorder(self):
         """Test that order doesn't matter for microcode entries
@@ -1053,22 +1140,22 @@ class TestFunctional(unittest.TestCase):
         u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode
         entry, so we reply on binman to try later.
         """
-        self._PackUbootSplMicrocode('58_x86_ucode_spl_needs_retry.dts',
+        self._PackUbootSplMicrocode('058_x86_ucode_spl_needs_retry.dts',
                                     ucode_second=True)
 
     def testPackMrc(self):
         """Test that an image with an MRC binary can be created"""
-        data = self._DoReadFile('50_intel_mrc.dts')
+        data = self._DoReadFile('050_intel_mrc.dts')
         self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
 
     def testSplDtb(self):
         """Test that an image with spl/u-boot-spl.dtb can be created"""
-        data = self._DoReadFile('51_u_boot_spl_dtb.dts')
+        data = self._DoReadFile('051_u_boot_spl_dtb.dts')
         self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
 
     def testSplNoDtb(self):
         """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
-        data = self._DoReadFile('52_u_boot_spl_nodtb.dts')
+        data = self._DoReadFile('052_u_boot_spl_nodtb.dts')
         self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
 
     def testSymbols(self):
@@ -1078,30 +1165,30 @@ class TestFunctional(unittest.TestCase):
         addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
         self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
 
-        with open(self.TestFile('u_boot_binman_syms')) as fd:
-            TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
-        data = self._DoReadFile('53_symbols.dts')
+        self._SetupSplElf('u_boot_binman_syms')
+        data = self._DoReadFile('053_symbols.dts')
         sym_values = struct.pack('<LQL', 0x24 + 0, 0x24 + 24, 0x24 + 20)
-        expected = (sym_values + U_BOOT_SPL_DATA[16:] + chr(0xff) +
-                    U_BOOT_DATA +
-                    sym_values + U_BOOT_SPL_DATA[16:])
+        expected = (sym_values + U_BOOT_SPL_DATA[16:] +
+                    tools.GetBytes(0xff, 1) + U_BOOT_DATA + sym_values +
+                    U_BOOT_SPL_DATA[16:])
         self.assertEqual(expected, data)
 
     def testPackUnitAddress(self):
         """Test that we support multiple binaries with the same name"""
-        data = self._DoReadFile('54_unit_address.dts')
+        data = self._DoReadFile('054_unit_address.dts')
         self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
 
     def testSections(self):
         """Basic test of sections"""
-        data = self._DoReadFile('55_sections.dts')
-        expected = (U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12 +
-                    U_BOOT_DATA + '&' * 4)
+        data = self._DoReadFile('055_sections.dts')
+        expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
+                    U_BOOT_DATA + tools.GetBytes(ord('a'), 12) +
+                    U_BOOT_DATA + tools.GetBytes(ord('&'), 4))
         self.assertEqual(expected, data)
 
     def testMap(self):
         """Tests outputting a map of the images"""
-        _, _, map_data, _ = self._DoReadFileDtb('55_sections.dts', map=True)
+        _, _, map_data, _ = self._DoReadFileDtb('055_sections.dts', map=True)
         self.assertEqual('''ImagePos    Offset      Size  Name
 00000000  00000000  00000028  main-section
 00000000   00000000  00000010  section@0
@@ -1114,7 +1201,7 @@ class TestFunctional(unittest.TestCase):
 
     def testNamePrefix(self):
         """Tests that name prefixes are used"""
-        _, _, map_data, _ = self._DoReadFileDtb('56_name_prefix.dts', map=True)
+        _, _, map_data, _ = self._DoReadFileDtb('056_name_prefix.dts', map=True)
         self.assertEqual('''ImagePos    Offset      Size  Name
 00000000  00000000  00000028  main-section
 00000000   00000000  00000010  section@0
@@ -1126,21 +1213,25 @@ class TestFunctional(unittest.TestCase):
     def testUnknownContents(self):
         """Test that obtaining the contents works as expected"""
         with self.assertRaises(ValueError) as e:
-            self._DoReadFile('57_unknown_contents.dts', True)
+            self._DoReadFile('057_unknown_contents.dts', True)
         self.assertIn("Section '/binman': Internal error: Could not complete "
                 "processing of contents: remaining [<_testing.Entry__testing ",
                 str(e.exception))
 
     def testBadChangeSize(self):
         """Test that trying to change the size of an entry fails"""
-        with self.assertRaises(ValueError) as e:
-            self._DoReadFile('59_change_size.dts', True)
-        self.assertIn("Node '/binman/_testing': Cannot update entry size from "
-                      '2 to 1', str(e.exception))
+        try:
+            state.SetAllowEntryExpansion(False)
+            with self.assertRaises(ValueError) as e:
+                self._DoReadFile('059_change_size.dts', True)
+            self.assertIn("Node '/binman/_testing': Cannot update entry size from 1 to 2",
+                          str(e.exception))
+        finally:
+            state.SetAllowEntryExpansion(True)
 
     def testUpdateFdt(self):
         """Test that we can update the device tree with offset/size info"""
-        _, _, _, out_dtb_fname = self._DoReadFileDtb('60_fdt_update.dts',
+        _, _, _, out_dtb_fname = self._DoReadFileDtb('060_fdt_update.dts',
                                                      update_dtb=True)
         dtb = fdt.Fdt(out_dtb_fname)
         dtb.Scan()
@@ -1170,7 +1261,7 @@ class TestFunctional(unittest.TestCase):
     def testUpdateFdtBad(self):
         """Test that we detect when ProcessFdt never completes"""
         with self.assertRaises(ValueError) as e:
-            self._DoReadFileDtb('61_fdt_update_bad.dts', update_dtb=True)
+            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))
 
@@ -1180,7 +1271,7 @@ class TestFunctional(unittest.TestCase):
             'test-str-arg': 'test1',
             'test-int-arg': '456',
         }
-        self._DoReadFileDtb('62_entry_args.dts', entry_args=entry_args)
+        self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
         self.assertIn('image', control.images)
         entry = control.images['image'].GetEntries()['_testing']
         self.assertEqual('test0', entry.test_str_fdt)
@@ -1193,7 +1284,7 @@ class TestFunctional(unittest.TestCase):
         entry_args = {
             'test-int-arg': '456',
         }
-        self._DoReadFileDtb('63_entry_args_missing.dts', entry_args=entry_args)
+        self._DoReadFileDtb('063_entry_args_missing.dts', entry_args=entry_args)
         entry = control.images['image'].GetEntries()['_testing']
         self.assertEqual('test0', entry.test_str_fdt)
         self.assertEqual(None, entry.test_str_arg)
@@ -1206,14 +1297,15 @@ class TestFunctional(unittest.TestCase):
             'test-int-arg': '456',
         }
         with self.assertRaises(ValueError) as e:
-            self._DoReadFileDtb('64_entry_args_required.dts')
+            self._DoReadFileDtb('064_entry_args_required.dts')
         self.assertIn("Node '/binman/_testing': Missing required "
             'properties/entry args: test-str-arg, test-int-fdt, test-int-arg',
             str(e.exception))
 
     def testEntryArgsInvalidFormat(self):
         """Test that an invalid entry-argument format is detected"""
-        args = ['-d', self.TestFile('64_entry_args_required.dts'), '-ano-value']
+        args = ['build', '-d', self.TestFile('064_entry_args_required.dts'),
+                '-ano-value']
         with self.assertRaises(ValueError) as e:
             self._DoBinman(*args)
         self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
@@ -1224,7 +1316,7 @@ class TestFunctional(unittest.TestCase):
             'test-int-arg': 'abc',
         }
         with self.assertRaises(ValueError) as e:
-            self._DoReadFileDtb('62_entry_args.dts', entry_args=entry_args)
+            self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
         self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
                       "'test-int-arg' (value 'abc') to integer",
             str(e.exception))
@@ -1240,7 +1332,7 @@ class TestFunctional(unittest.TestCase):
             'test-bad-datatype-arg': '12',
         }
         with self.assertRaises(ValueError) as e:
-            self._DoReadFileDtb('65_entry_args_unknown_datatype.dts',
+            self._DoReadFileDtb('065_entry_args_unknown_datatype.dts',
                                 entry_args=entry_args)
         self.assertIn('GetArg() internal error: Unknown data type ',
                       str(e.exception))
@@ -1252,10 +1344,12 @@ class TestFunctional(unittest.TestCase):
             'test-id2': TEXT_DATA2,
             'test-id3': TEXT_DATA3,
         }
-        data, _, _, _ = self._DoReadFileDtb('66_text.dts',
+        data, _, _, _ = self._DoReadFileDtb('066_text.dts',
                                             entry_args=entry_args)
-        expected = (TEXT_DATA + chr(0) * (8 - len(TEXT_DATA)) + TEXT_DATA2 +
-                    TEXT_DATA3 + 'some text')
+        expected = (tools.ToBytes(TEXT_DATA) +
+                    tools.GetBytes(0, 8 - len(TEXT_DATA)) +
+                    tools.ToBytes(TEXT_DATA2) + tools.ToBytes(TEXT_DATA3) +
+                    b'some text' + b'more text')
         self.assertEqual(expected, data)
 
     def testEntryDocs(self):
@@ -1274,53 +1368,54 @@ class TestFunctional(unittest.TestCase):
 
     def testFmap(self):
         """Basic test of generation of a flashrom fmap"""
-        data = self._DoReadFile('67_fmap.dts')
+        data = self._DoReadFile('067_fmap.dts')
         fhdr, fentries = fmap_util.DecodeFmap(data[32:])
-        expected = U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12
+        expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
+                    U_BOOT_DATA + tools.GetBytes(ord('a'), 12))
         self.assertEqual(expected, data[:32])
-        self.assertEqual('__FMAP__', fhdr.signature)
+        self.assertEqual(b'__FMAP__', fhdr.signature)
         self.assertEqual(1, fhdr.ver_major)
         self.assertEqual(0, fhdr.ver_minor)
         self.assertEqual(0, fhdr.base)
         self.assertEqual(16 + 16 +
                          fmap_util.FMAP_HEADER_LEN +
                          fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
-        self.assertEqual('FMAP', fhdr.name)
+        self.assertEqual(b'FMAP', fhdr.name)
         self.assertEqual(3, fhdr.nareas)
         for fentry in fentries:
             self.assertEqual(0, fentry.flags)
 
         self.assertEqual(0, fentries[0].offset)
         self.assertEqual(4, fentries[0].size)
-        self.assertEqual('RO_U_BOOT', fentries[0].name)
+        self.assertEqual(b'RO_U_BOOT', fentries[0].name)
 
         self.assertEqual(16, fentries[1].offset)
         self.assertEqual(4, fentries[1].size)
-        self.assertEqual('RW_U_BOOT', fentries[1].name)
+        self.assertEqual(b'RW_U_BOOT', fentries[1].name)
 
         self.assertEqual(32, fentries[2].offset)
         self.assertEqual(fmap_util.FMAP_HEADER_LEN +
                          fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
-        self.assertEqual('FMAP', fentries[2].name)
+        self.assertEqual(b'FMAP', fentries[2].name)
 
     def testBlobNamedByArg(self):
         """Test we can add a blob with the filename coming from an entry arg"""
         entry_args = {
             'cros-ec-rw-path': 'ecrw.bin',
         }
-        data, _, _, _ = self._DoReadFileDtb('68_blob_named_by_arg.dts',
+        data, _, _, _ = self._DoReadFileDtb('068_blob_named_by_arg.dts',
                                             entry_args=entry_args)
 
     def testFill(self):
         """Test for an fill entry type"""
-        data = self._DoReadFile('69_fill.dts')
-        expected = 8 * chr(0xff) + 8 * chr(0)
+        data = self._DoReadFile('069_fill.dts')
+        expected = tools.GetBytes(0xff, 8) + tools.GetBytes(0, 8)
         self.assertEqual(expected, data)
 
     def testFillNoSize(self):
         """Test for an fill entry type with no size"""
         with self.assertRaises(ValueError) as e:
-            self._DoReadFile('70_fill_no_size.dts')
+            self._DoReadFile('070_fill_no_size.dts')
         self.assertIn("'fill' entry must have a size property",
                       str(e.exception))
 
@@ -1330,7 +1425,7 @@ class TestFunctional(unittest.TestCase):
             fname = pipe_list[0][-1]
             # Append our GBB data to the file, which will happen every time the
             # futility command is called.
-            with open(fname, 'a') as fd:
+            with open(fname, 'ab') as fd:
                 fd.write(GBB_DATA)
             return command.CommandResult()
 
@@ -1341,23 +1436,24 @@ class TestFunctional(unittest.TestCase):
             'keydir': 'devkeys',
             'bmpblk': 'bmpblk.bin',
         }
-        data, _, _, _ = self._DoReadFileDtb('71_gbb.dts', entry_args=entry_args)
+        data, _, _, _ = self._DoReadFileDtb('071_gbb.dts', entry_args=entry_args)
 
         # Since futility
-        expected = GBB_DATA + GBB_DATA + 8 * chr(0) + (0x2180 - 16) * chr(0)
+        expected = (GBB_DATA + GBB_DATA + tools.GetBytes(0, 8) +
+                    tools.GetBytes(0, 0x2180 - 16))
         self.assertEqual(expected, data)
 
     def testGbbTooSmall(self):
         """Test for the Chromium OS Google Binary Block being large enough"""
         with self.assertRaises(ValueError) as e:
-            self._DoReadFileDtb('72_gbb_too_small.dts')
+            self._DoReadFileDtb('072_gbb_too_small.dts')
         self.assertIn("Node '/binman/gbb': GBB is too small",
                       str(e.exception))
 
     def testGbbNoSize(self):
         """Test for the Chromium OS Google Binary Block having a size"""
         with self.assertRaises(ValueError) as e:
-            self._DoReadFileDtb('73_gbb_no_size.dts')
+            self._DoReadFileDtb('073_gbb_no_size.dts')
         self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
                       str(e.exception))
 
@@ -1375,7 +1471,7 @@ class TestFunctional(unittest.TestCase):
         entry_args = {
             'keydir': 'devkeys',
         }
-        data, _, _, _ = self._DoReadFileDtb('74_vblock.dts',
+        data, _, _, _ = self._DoReadFileDtb('074_vblock.dts',
                                             entry_args=entry_args)
         expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
         self.assertEqual(expected, data)
@@ -1383,70 +1479,78 @@ class TestFunctional(unittest.TestCase):
     def testVblockNoContent(self):
         """Test we detect a vblock which has no content to sign"""
         with self.assertRaises(ValueError) as e:
-            self._DoReadFile('75_vblock_no_content.dts')
+            self._DoReadFile('075_vblock_no_content.dts')
         self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
                       'property', str(e.exception))
 
     def testVblockBadPhandle(self):
         """Test that we detect a vblock with an invalid phandle in contents"""
         with self.assertRaises(ValueError) as e:
-            self._DoReadFile('76_vblock_bad_phandle.dts')
+            self._DoReadFile('076_vblock_bad_phandle.dts')
         self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
                       '1000', str(e.exception))
 
     def testVblockBadEntry(self):
         """Test that we detect an entry that points to a non-entry"""
         with self.assertRaises(ValueError) as e:
-            self._DoReadFile('77_vblock_bad_entry.dts')
+            self._DoReadFile('077_vblock_bad_entry.dts')
         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:
+        with open(self.TestFile('bss_data'), 'rb') as fd:
             TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
-        data = self._DoReadFile('78_u_boot_tpl.dts')
+        data = self._DoReadFile('078_u_boot_tpl.dts')
         self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
 
     def testUsesPos(self):
         """Test that the 'pos' property cannot be used anymore"""
         with self.assertRaises(ValueError) as e:
-           data = self._DoReadFile('79_uses_pos.dts')
+           data = self._DoReadFile('079_uses_pos.dts')
         self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
                       "'pos'", str(e.exception))
 
     def testFillZero(self):
         """Test for an fill entry type with a size of 0"""
-        data = self._DoReadFile('80_fill_empty.dts')
-        self.assertEqual(chr(0) * 16, data)
+        data = self._DoReadFile('080_fill_empty.dts')
+        self.assertEqual(tools.GetBytes(0, 16), data)
 
     def testTextMissing(self):
         """Test for a text entry type where there is no text"""
         with self.assertRaises(ValueError) as e:
-            self._DoReadFileDtb('66_text.dts',)
+            self._DoReadFileDtb('066_text.dts',)
         self.assertIn("Node '/binman/text': No value provided for text label "
                       "'test-id'", str(e.exception))
 
     def testPackStart16Tpl(self):
         """Test that an image with an x86 start16 TPL region can be created"""
-        data = self._DoReadFile('81_x86-start16-tpl.dts')
+        data = self._DoReadFile('081_x86-start16-tpl.dts')
         self.assertEqual(X86_START16_TPL_DATA, data[:len(X86_START16_TPL_DATA)])
 
     def testSelectImage(self):
         """Test that we can select which images to build"""
-        with test_util.capture_sys_output() as (stdout, stderr):
-            retcode = self._DoTestFile('06_dual_image.dts', images=['image2'])
-        self.assertEqual(0, retcode)
-        self.assertIn('Skipping images: image1', stdout.getvalue())
+        expected = 'Skipping images: image1'
+
+        # We should only get the expected message in verbose mode
+        for verbosity in (0, 2):
+            with test_util.capture_sys_output() as (stdout, stderr):
+                retcode = self._DoTestFile('006_dual_image.dts',
+                                           verbosity=verbosity,
+                                           images=['image2'])
+            self.assertEqual(0, retcode)
+            if verbosity:
+                self.assertIn(expected, stdout.getvalue())
+            else:
+                self.assertNotIn(expected, stdout.getvalue())
 
-        self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
-        self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
+            self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
+            self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
 
     def testUpdateFdtAll(self):
         """Test that all device trees are updated with offset/size info"""
-        data, _, _, _ = self._DoReadFileDtb('82_fdt_update_all.dts',
-                                            use_real_dtb=True, update_dtb=True)
+        data = self._DoReadFileRealDtb('082_fdt_update_all.dts')
 
         base_expected = {
             'section:image-pos': 0,
@@ -1485,12 +1589,12 @@ class TestFunctional(unittest.TestCase):
     def testUpdateFdtOutput(self):
         """Test that output DTB files are updated"""
         try:
-            data, dtb_data, _, _ = self._DoReadFileDtb('82_fdt_update_all.dts',
+            data, dtb_data, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
                     use_real_dtb=True, update_dtb=True, reset_dtbs=False)
 
             # Unfortunately, compiling a source file always results in a file
             # called source.dtb (see fdt_util.EnsureCompiled()). The test
-            # source file (e.g. test/75_fdt_update_all.dts) thus does not enter
+            # source file (e.g. test/075_fdt_update_all.dts) thus does not enter
             # binman as a file called u-boot.dtb. To fix this, copy the file
             # over to the expected place.
             #tools.WriteFile(os.path.join(self._indir, 'u-boot.dtb'),
@@ -1518,20 +1622,12 @@ class TestFunctional(unittest.TestCase):
             self._ResetDtbs()
 
     def _decompress(self, data):
-        out = os.path.join(self._indir, 'lz4.tmp')
-        with open(out, 'wb') as fd:
-            fd.write(data)
-        return tools.Run('lz4', '-dc', out)
-        '''
-        try:
-            orig = lz4.frame.decompress(data)
-        except AttributeError:
-            orig = lz4.decompress(data)
-        '''
+        return tools.Decompress(data, 'lz4')
 
     def testCompress(self):
         """Test compression of blobs"""
-        data, _, _, out_dtb_fname = self._DoReadFileDtb('83_compress.dts',
+        self._CheckLz4()
+        data, _, _, out_dtb_fname = self._DoReadFileDtb('083_compress.dts',
                                             use_real_dtb=True, update_dtb=True)
         dtb = fdt.Fdt(out_dtb_fname)
         dtb.Scan()
@@ -1547,19 +1643,20 @@ class TestFunctional(unittest.TestCase):
 
     def testFiles(self):
         """Test bringing in multiple files"""
-        data = self._DoReadFile('84_files.dts')
+        data = self._DoReadFile('084_files.dts')
         self.assertEqual(FILES_DATA, data)
 
     def testFilesCompress(self):
         """Test bringing in multiple files and compressing them"""
-        data = self._DoReadFile('85_files_compress.dts')
+        self._CheckLz4()
+        data = self._DoReadFile('085_files_compress.dts')
 
         image = control.images['image']
         entries = image.GetEntries()
         files = entries['files']
         entries = files._section._entries
 
-        orig = ''
+        orig = b''
         for i in range(1, 3):
             key = '%d.dat' % i
             start = entries[key].image_pos
@@ -1572,25 +1669,25 @@ class TestFunctional(unittest.TestCase):
     def testFilesMissing(self):
         """Test missing files"""
         with self.assertRaises(ValueError) as e:
-            data = self._DoReadFile('86_files_none.dts')
+            data = self._DoReadFile('086_files_none.dts')
         self.assertIn("Node '/binman/files': Pattern \'files/*.none\' matched "
                       'no files', str(e.exception))
 
     def testFilesNoPattern(self):
         """Test missing files"""
         with self.assertRaises(ValueError) as e:
-            data = self._DoReadFile('87_files_no_pattern.dts')
+            data = self._DoReadFile('087_files_no_pattern.dts')
         self.assertIn("Node '/binman/files': Missing 'pattern' property",
                       str(e.exception))
 
     def testExpandSize(self):
         """Test an expanding entry"""
-        data, _, map_data, _ = self._DoReadFileDtb('88_expand_size.dts',
+        data, _, map_data, _ = self._DoReadFileDtb('088_expand_size.dts',
                                                    map=True)
-        expect = ('a' * 8 + U_BOOT_DATA +
-                  MRC_DATA + 'b' * 1 + U_BOOT_DATA +
-                  'c' * 8 + U_BOOT_DATA +
-                  'd' * 8)
+        expect = (tools.GetBytes(ord('a'), 8) + U_BOOT_DATA +
+                  MRC_DATA + tools.GetBytes(ord('b'), 1) + U_BOOT_DATA +
+                  tools.GetBytes(ord('c'), 8) + U_BOOT_DATA +
+                  tools.GetBytes(ord('d'), 8))
         self.assertEqual(expect, data)
         self.assertEqual('''ImagePos    Offset      Size  Name
 00000000  00000000  00000028  main-section
@@ -1607,45 +1704,46 @@ class TestFunctional(unittest.TestCase):
 
     def testExpandSizeBad(self):
         """Test an expanding entry which fails to provide contents"""
-        with self.assertRaises(ValueError) as e:
-            self._DoReadFileDtb('89_expand_size_bad.dts', map=True)
+        with test_util.capture_sys_output() as (stdout, stderr):
+            with self.assertRaises(ValueError) as e:
+                self._DoReadFileDtb('089_expand_size_bad.dts', map=True)
         self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
                       'expanding entry', str(e.exception))
 
     def testHash(self):
         """Test hashing of the contents of an entry"""
-        _, _, _, out_dtb_fname = self._DoReadFileDtb('90_hash.dts',
+        _, _, _, out_dtb_fname = self._DoReadFileDtb('090_hash.dts',
                 use_real_dtb=True, update_dtb=True)
         dtb = fdt.Fdt(out_dtb_fname)
         dtb.Scan()
         hash_node = dtb.GetNode('/binman/u-boot/hash').props['value']
         m = hashlib.sha256()
         m.update(U_BOOT_DATA)
-        self.assertEqual(m.digest(), ''.join(hash_node.value))
+        self.assertEqual(m.digest(), b''.join(hash_node.value))
 
     def testHashNoAlgo(self):
         with self.assertRaises(ValueError) as e:
-            self._DoReadFileDtb('91_hash_no_algo.dts', update_dtb=True)
+            self._DoReadFileDtb('091_hash_no_algo.dts', update_dtb=True)
         self.assertIn("Node \'/binman/u-boot\': Missing \'algo\' property for "
                       'hash node', str(e.exception))
 
     def testHashBadAlgo(self):
         with self.assertRaises(ValueError) as e:
-            self._DoReadFileDtb('92_hash_bad_algo.dts', update_dtb=True)
+            self._DoReadFileDtb('092_hash_bad_algo.dts', update_dtb=True)
         self.assertIn("Node '/binman/u-boot': Unknown hash algorithm",
                       str(e.exception))
 
     def testHashSection(self):
         """Test hashing of the contents of an entry"""
-        _, _, _, out_dtb_fname = self._DoReadFileDtb('99_hash_section.dts',
+        _, _, _, out_dtb_fname = self._DoReadFileDtb('099_hash_section.dts',
                 use_real_dtb=True, update_dtb=True)
         dtb = fdt.Fdt(out_dtb_fname)
         dtb.Scan()
         hash_node = dtb.GetNode('/binman/section/hash').props['value']
         m = hashlib.sha256()
         m.update(U_BOOT_DATA)
-        m.update(16 * 'a')
-        self.assertEqual(m.digest(), ''.join(hash_node.value))
+        m.update(tools.GetBytes(ord('a'), 16))
+        self.assertEqual(m.digest(), b''.join(hash_node.value))
 
     def testPackUBootTplMicrocode(self):
         """Test that x86 microcode can be handled correctly in TPL
@@ -1656,18 +1754,18 @@ class TestFunctional(unittest.TestCase):
             u-boot-tpl.dtb with the microcode removed
             the microcode
         """
-        with open(self.TestFile('u_boot_ucode_ptr')) as fd:
+        with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
             TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
-        first, pos_and_size = self._RunMicrocodeTest('93_x86_tpl_ucode.dts',
+        first, pos_and_size = self._RunMicrocodeTest('093_x86_tpl_ucode.dts',
                                                      U_BOOT_TPL_NODTB_DATA)
-        self.assertEqual('tplnodtb with microc' + pos_and_size +
-                         'ter somewhere in here', first)
+        self.assertEqual(b'tplnodtb with microc' + pos_and_size +
+                         b'ter somewhere in here', first)
 
     def testFmapX86(self):
         """Basic test of generation of a flashrom fmap"""
-        data = self._DoReadFile('94_fmap_x86.dts')
+        data = self._DoReadFile('094_fmap_x86.dts')
         fhdr, fentries = fmap_util.DecodeFmap(data[32:])
-        expected = U_BOOT_DATA + MRC_DATA + 'a' * (32 - 7)
+        expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('a'), 32 - 7)
         self.assertEqual(expected, data[:32])
         fhdr, fentries = fmap_util.DecodeFmap(data[32:])
 
@@ -1675,21 +1773,21 @@ class TestFunctional(unittest.TestCase):
 
         self.assertEqual(0, fentries[0].offset)
         self.assertEqual(4, fentries[0].size)
-        self.assertEqual('U_BOOT', fentries[0].name)
+        self.assertEqual(b'U_BOOT', fentries[0].name)
 
         self.assertEqual(4, fentries[1].offset)
         self.assertEqual(3, fentries[1].size)
-        self.assertEqual('INTEL_MRC', fentries[1].name)
+        self.assertEqual(b'INTEL_MRC', fentries[1].name)
 
         self.assertEqual(32, fentries[2].offset)
         self.assertEqual(fmap_util.FMAP_HEADER_LEN +
                          fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
-        self.assertEqual('FMAP', fentries[2].name)
+        self.assertEqual(b'FMAP', fentries[2].name)
 
     def testFmapX86Section(self):
         """Basic test of generation of a flashrom fmap"""
-        data = self._DoReadFile('95_fmap_x86_section.dts')
-        expected = U_BOOT_DATA + MRC_DATA + 'b' * (32 - 7)
+        data = self._DoReadFile('095_fmap_x86_section.dts')
+        expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('b'), 32 - 7)
         self.assertEqual(expected, data[:32])
         fhdr, fentries = fmap_util.DecodeFmap(data[36:])
 
@@ -1697,16 +1795,395 @@ class TestFunctional(unittest.TestCase):
 
         self.assertEqual(0, fentries[0].offset)
         self.assertEqual(4, fentries[0].size)
-        self.assertEqual('U_BOOT', fentries[0].name)
+        self.assertEqual(b'U_BOOT', fentries[0].name)
 
         self.assertEqual(4, fentries[1].offset)
         self.assertEqual(3, fentries[1].size)
-        self.assertEqual('INTEL_MRC', fentries[1].name)
+        self.assertEqual(b'INTEL_MRC', fentries[1].name)
 
         self.assertEqual(36, fentries[2].offset)
         self.assertEqual(fmap_util.FMAP_HEADER_LEN +
                          fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
-        self.assertEqual('FMAP', fentries[2].name)
+        self.assertEqual(b'FMAP', fentries[2].name)
+
+    def testElf(self):
+        """Basic test of ELF entries"""
+        self._SetupSplElf()
+        with open(self.TestFile('bss_data'), 'rb') as fd:
+            TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
+        with open(self.TestFile('bss_data'), 'rb') as fd:
+            TestFunctional._MakeInputFile('-boot', fd.read())
+        data = self._DoReadFile('096_elf.dts')
+
+    def testElfStrip(self):
+        """Basic test of ELF entries"""
+        self._SetupSplElf()
+        with open(self.TestFile('bss_data'), 'rb') as fd:
+            TestFunctional._MakeInputFile('-boot', fd.read())
+        data = self._DoReadFile('097_elf_strip.dts')
+
+    def testPackOverlapMap(self):
+        """Test that overlapping regions are detected"""
+        with test_util.capture_sys_output() as (stdout, stderr):
+            with self.assertRaises(ValueError) as e:
+                self._DoTestFile('014_pack_overlap.dts', map=True)
+        map_fname = tools.GetOutputFilename('image.map')
+        self.assertEqual("Wrote map file '%s' to show errors\n" % map_fname,
+                         stdout.getvalue())
+
+        # We should not get an inmage, but there should be a map file
+        self.assertFalse(os.path.exists(tools.GetOutputFilename('image.bin')))
+        self.assertTrue(os.path.exists(map_fname))
+        map_data = tools.ReadFile(map_fname, binary=False)
+        self.assertEqual('''ImagePos    Offset      Size  Name
+<none>    00000000  00000007  main-section
+<none>     00000000  00000004  u-boot
+<none>     00000003  00000004  u-boot-align
+''', map_data)
+
+    def testPackRefCode(self):
+        """Test that an image with an Intel Reference code binary works"""
+        data = self._DoReadFile('100_intel_refcode.dts')
+        self.assertEqual(REFCODE_DATA, data[:len(REFCODE_DATA)])
+
+    def testSectionOffset(self):
+        """Tests use of a section with an offset"""
+        data, _, map_data, _ = self._DoReadFileDtb('101_sections_offset.dts',
+                                                   map=True)
+        self.assertEqual('''ImagePos    Offset      Size  Name
+00000000  00000000  00000038  main-section
+00000004   00000004  00000010  section@0
+00000004    00000000  00000004  u-boot
+00000018   00000018  00000010  section@1
+00000018    00000000  00000004  u-boot
+0000002c   0000002c  00000004  section@2
+0000002c    00000000  00000004  u-boot
+''', map_data)
+        self.assertEqual(data,
+                         tools.GetBytes(0x26, 4) + U_BOOT_DATA +
+                             tools.GetBytes(0x21, 12) +
+                         tools.GetBytes(0x26, 4) + U_BOOT_DATA +
+                             tools.GetBytes(0x61, 12) +
+                         tools.GetBytes(0x26, 4) + U_BOOT_DATA +
+                             tools.GetBytes(0x26, 8))
+
+    def testCbfsRaw(self):
+        """Test base handling of a Coreboot Filesystem (CBFS)
+
+        The exact contents of the CBFS is verified by similar tests in
+        cbfs_util_test.py. The tests here merely check that the files added to
+        the CBFS can be found in the final image.
+        """
+        data = self._DoReadFile('102_cbfs_raw.dts')
+        size = 0xb0
+
+        cbfs = cbfs_util.CbfsReader(data)
+        self.assertEqual(size, cbfs.rom_size)
+
+        self.assertIn('u-boot-dtb', cbfs.files)
+        cfile = cbfs.files['u-boot-dtb']
+        self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
+
+    def testCbfsArch(self):
+        """Test on non-x86 architecture"""
+        data = self._DoReadFile('103_cbfs_raw_ppc.dts')
+        size = 0x100
+
+        cbfs = cbfs_util.CbfsReader(data)
+        self.assertEqual(size, cbfs.rom_size)
+
+        self.assertIn('u-boot-dtb', cbfs.files)
+        cfile = cbfs.files['u-boot-dtb']
+        self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
+
+    def testCbfsStage(self):
+        """Tests handling of a Coreboot Filesystem (CBFS)"""
+        if not elf.ELF_TOOLS:
+            self.skipTest('Python elftools not available')
+        elf_fname = os.path.join(self._indir, 'cbfs-stage.elf')
+        elf.MakeElf(elf_fname, U_BOOT_DATA, U_BOOT_DTB_DATA)
+        size = 0xb0
+
+        data = self._DoReadFile('104_cbfs_stage.dts')
+        cbfs = cbfs_util.CbfsReader(data)
+        self.assertEqual(size, cbfs.rom_size)
+
+        self.assertIn('u-boot', cbfs.files)
+        cfile = cbfs.files['u-boot']
+        self.assertEqual(U_BOOT_DATA + U_BOOT_DTB_DATA, cfile.data)
+
+    def testCbfsRawCompress(self):
+        """Test handling of compressing raw files"""
+        self._CheckLz4()
+        data = self._DoReadFile('105_cbfs_raw_compress.dts')
+        size = 0x140
+
+        cbfs = cbfs_util.CbfsReader(data)
+        self.assertIn('u-boot', cbfs.files)
+        cfile = cbfs.files['u-boot']
+        self.assertEqual(COMPRESS_DATA, cfile.data)
+
+    def testCbfsBadArch(self):
+        """Test handling of a bad architecture"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFile('106_cbfs_bad_arch.dts')
+        self.assertIn("Invalid architecture 'bad-arch'", str(e.exception))
+
+    def testCbfsNoSize(self):
+        """Test handling of a missing size property"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFile('107_cbfs_no_size.dts')
+        self.assertIn('entry must have a size property', str(e.exception))
+
+    def testCbfsNoCOntents(self):
+        """Test handling of a CBFS entry which does not provide contentsy"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFile('108_cbfs_no_contents.dts')
+        self.assertIn('Could not complete processing of contents',
+                      str(e.exception))
+
+    def testCbfsBadCompress(self):
+        """Test handling of a bad architecture"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFile('109_cbfs_bad_compress.dts')
+        self.assertIn("Invalid compression in 'u-boot': 'invalid-algo'",
+                      str(e.exception))
+
+    def testCbfsNamedEntries(self):
+        """Test handling of named entries"""
+        data = self._DoReadFile('110_cbfs_name.dts')
+
+        cbfs = cbfs_util.CbfsReader(data)
+        self.assertIn('FRED', cbfs.files)
+        cfile1 = cbfs.files['FRED']
+        self.assertEqual(U_BOOT_DATA, cfile1.data)
+
+        self.assertIn('hello', cbfs.files)
+        cfile2 = cbfs.files['hello']
+        self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
+
+    def _SetupIfwi(self, fname):
+        """Set up to run an IFWI test
+
+        Args:
+            fname: Filename of input file to provide (fitimage.bin or ifwi.bin)
+        """
+        self._SetupSplElf()
+
+        # Intel Integrated Firmware Image (IFWI) file
+        with gzip.open(self.TestFile('%s.gz' % fname), 'rb') as fd:
+            data = fd.read()
+        TestFunctional._MakeInputFile(fname,data)
+
+    def _CheckIfwi(self, data):
+        """Check that an image with an IFWI contains the correct output
+
+        Args:
+            data: Conents of output file
+        """
+        expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
+        if data[:0x1000] != expected_desc:
+            self.fail('Expected descriptor binary at start of image')
+
+        # We expect to find the TPL wil in subpart IBBP entry IBBL
+        image_fname = tools.GetOutputFilename('image.bin')
+        tpl_fname = tools.GetOutputFilename('tpl.out')
+        tools.RunIfwiTool(image_fname, tools.CMD_EXTRACT, fname=tpl_fname,
+                          subpart='IBBP', entry_name='IBBL')
+
+        tpl_data = tools.ReadFile(tpl_fname)
+        self.assertEqual(tpl_data[:len(U_BOOT_TPL_DATA)], U_BOOT_TPL_DATA)
+
+    def testPackX86RomIfwi(self):
+        """Test that an x86 ROM with Integrated Firmware Image can be created"""
+        self._SetupIfwi('fitimage.bin')
+        data = self._DoReadFile('111_x86-rom-ifwi.dts')
+        self._CheckIfwi(data)
+
+    def testPackX86RomIfwiNoDesc(self):
+        """Test that an x86 ROM with IFWI can be created from an ifwi.bin file"""
+        self._SetupIfwi('ifwi.bin')
+        data = self._DoReadFile('112_x86-rom-ifwi-nodesc.dts')
+        self._CheckIfwi(data)
+
+    def testPackX86RomIfwiNoData(self):
+        """Test that an x86 ROM with IFWI handles missing data"""
+        self._SetupIfwi('ifwi.bin')
+        with self.assertRaises(ValueError) as e:
+            data = self._DoReadFile('113_x86-rom-ifwi-nodata.dts')
+        self.assertIn('Could not complete processing of contents',
+                      str(e.exception))
+
+    def testCbfsOffset(self):
+        """Test a CBFS with files at particular offsets
+
+        Like all CFBS tests, this is just checking the logic that calls
+        cbfs_util. See cbfs_util_test for fully tests (e.g. test_cbfs_offset()).
+        """
+        data = self._DoReadFile('114_cbfs_offset.dts')
+        size = 0x200
+
+        cbfs = cbfs_util.CbfsReader(data)
+        self.assertEqual(size, cbfs.rom_size)
+
+        self.assertIn('u-boot', cbfs.files)
+        cfile = cbfs.files['u-boot']
+        self.assertEqual(U_BOOT_DATA, cfile.data)
+        self.assertEqual(0x40, cfile.cbfs_offset)
+
+        self.assertIn('u-boot-dtb', cbfs.files)
+        cfile2 = cbfs.files['u-boot-dtb']
+        self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
+        self.assertEqual(0x140, cfile2.cbfs_offset)
+
+    def testFdtmap(self):
+        """Test an FDT map can be inserted in the image"""
+        data = self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
+        fdtmap_data = data[len(U_BOOT_DATA):]
+        magic = fdtmap_data[:8]
+        self.assertEqual('_FDTMAP_', magic)
+        self.assertEqual(tools.GetBytes(0, 8), fdtmap_data[8:16])
+
+        fdt_data = fdtmap_data[16:]
+        dtb = fdt.Fdt.FromData(fdt_data)
+        dtb.Scan()
+        props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'],
+                                  prefix='/')
+        self.assertEqual({
+            'image-pos': 0,
+            'offset': 0,
+            'u-boot:offset': 0,
+            'u-boot:size': len(U_BOOT_DATA),
+            'u-boot:image-pos': 0,
+            'fdtmap:image-pos': 4,
+            'fdtmap:offset': 4,
+            'fdtmap:size': len(fdtmap_data),
+            'size': len(data),
+        }, props)
+
+    def testFdtmapNoMatch(self):
+        """Check handling of an FDT map when the section cannot be found"""
+        self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
+
+        # Mangle the section name, which should cause a mismatch between the
+        # correct FDT path and the one expected by the section
+        image = control.images['image']
+        image._node.path += '-suffix'
+        entries = image.GetEntries()
+        fdtmap = entries['fdtmap']
+        with self.assertRaises(ValueError) as e:
+            fdtmap._GetFdtmap()
+        self.assertIn("Cannot locate node for path '/binman-suffix'",
+                      str(e.exception))
+
+    def testFdtmapHeader(self):
+        """Test an FDT map and image header can be inserted in the image"""
+        data = self.data = self._DoReadFileRealDtb('116_fdtmap_hdr.dts')
+        fdtmap_pos = len(U_BOOT_DATA)
+        fdtmap_data = data[fdtmap_pos:]
+        fdt_data = fdtmap_data[16:]
+        dtb = fdt.Fdt.FromData(fdt_data)
+        fdt_size = dtb.GetFdtObj().totalsize()
+        hdr_data = data[-8:]
+        self.assertEqual('BinM', hdr_data[:4])
+        offset = struct.unpack('<I', hdr_data[4:])[0] & 0xffffffff
+        self.assertEqual(fdtmap_pos - 0x400, offset - (1 << 32))
+
+    def testFdtmapHeaderStart(self):
+        """Test an image header can be inserted at the image start"""
+        data = self.data = self._DoReadFileRealDtb('117_fdtmap_hdr_start.dts')
+        fdtmap_pos = 0x100 + len(U_BOOT_DATA)
+        hdr_data = data[:8]
+        self.assertEqual('BinM', hdr_data[:4])
+        offset = struct.unpack('<I', hdr_data[4:])[0]
+        self.assertEqual(fdtmap_pos, offset)
+
+    def testFdtmapHeaderPos(self):
+        """Test an image header can be inserted at a chosen position"""
+        data = self.data = self._DoReadFileRealDtb('118_fdtmap_hdr_pos.dts')
+        fdtmap_pos = 0x100 + len(U_BOOT_DATA)
+        hdr_data = data[0x80:0x88]
+        self.assertEqual('BinM', hdr_data[:4])
+        offset = struct.unpack('<I', hdr_data[4:])[0]
+        self.assertEqual(fdtmap_pos, offset)
+
+    def testHeaderMissingFdtmap(self):
+        """Test an image header requires an fdtmap"""
+        with self.assertRaises(ValueError) as e:
+            self.data = self._DoReadFileRealDtb('119_fdtmap_hdr_missing.dts')
+        self.assertIn("'image_header' section must have an 'fdtmap' sibling",
+                      str(e.exception))
+
+    def testHeaderNoLocation(self):
+        """Test an image header with a no specified location is detected"""
+        with self.assertRaises(ValueError) as e:
+            self.data = self._DoReadFileRealDtb('120_hdr_no_location.dts')
+        self.assertIn("Invalid location 'None', expected 'start' or 'end'",
+                      str(e.exception))
+
+    def testEntryExpand(self):
+        """Test expanding an entry after it is packed"""
+        data = self._DoReadFile('121_entry_expand.dts')
+        self.assertEqual(b'aa', data[:2])
+        self.assertEqual(U_BOOT_DATA, data[2:2 + len(U_BOOT_DATA)])
+        self.assertEqual(b'aa', data[-2:])
+
+    def testEntryExpandBad(self):
+        """Test expanding an entry after it is packed, twice"""
+        with self.assertRaises(ValueError) as e:
+            self._DoReadFile('122_entry_expand_twice.dts')
+        self.assertIn("Image '/binman': Entries expanded after packing",
+                      str(e.exception))
+
+    def testEntryExpandSection(self):
+        """Test expanding an entry within a section after it is packed"""
+        data = self._DoReadFile('123_entry_expand_section.dts')
+        self.assertEqual(b'aa', data[:2])
+        self.assertEqual(U_BOOT_DATA, data[2:2 + len(U_BOOT_DATA)])
+        self.assertEqual(b'aa', data[-2:])
+
+    def testCompressDtb(self):
+        """Test that compress of device-tree files is supported"""
+        self._CheckLz4()
+        data = self.data = self._DoReadFileRealDtb('124_compress_dtb.dts')
+        self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
+        comp_data = data[len(U_BOOT_DATA):]
+        orig = self._decompress(comp_data)
+        dtb = fdt.Fdt.FromData(orig)
+        dtb.Scan()
+        props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
+        expected = {
+            'u-boot:size': len(U_BOOT_DATA),
+            'u-boot-dtb:uncomp-size': len(orig),
+            'u-boot-dtb:size': len(comp_data),
+            'size': len(data),
+            }
+        self.assertEqual(expected, props)
+
+    def testCbfsUpdateFdt(self):
+        """Test that we can update the device tree with CBFS offset/size info"""
+        self._CheckLz4()
+        data, _, _, out_dtb_fname = self._DoReadFileDtb('125_cbfs_update.dts',
+                                                        update_dtb=True)
+        dtb = fdt.Fdt(out_dtb_fname)
+        dtb.Scan()
+        props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos',
+                                        'uncomp-size'])
+        del props['cbfs/u-boot:size']
+        self.assertEqual({
+            'offset': 0,
+            'size': len(data),
+            'image-pos': 0,
+            'cbfs:offset': 0,
+            'cbfs:size': len(data),
+            'cbfs:image-pos': 0,
+            'cbfs/u-boot:offset': 0x38,
+            'cbfs/u-boot:uncomp-size': len(U_BOOT_DATA),
+            'cbfs/u-boot:image-pos': 0x38,
+            'cbfs/u-boot-dtb:offset': 0xb8,
+            'cbfs/u-boot-dtb:size': len(U_BOOT_DATA),
+            'cbfs/u-boot-dtb:image-pos': 0xb8,
+            }, props)
 
 
 if __name__ == "__main__":