xref: /openbmc/u-boot/tools/binman/ftest.py (revision 3ae192c2a4d52a755031e93fa6cc3a31ba90f29f)
183d290c5STom Rini# SPDX-License-Identifier: GPL-2.0+
2680e3312SSimon Glass# Copyright (c) 2016 Google, Inc
3680e3312SSimon Glass# Written by Simon Glass <sjg@chromium.org>
4680e3312SSimon Glass#
5680e3312SSimon Glass# To run a single test, change to this directory, and:
6680e3312SSimon Glass#
7680e3312SSimon Glass#    python -m unittest func_test.TestFunctional.testHelp
8680e3312SSimon Glass
9e0e5df93SSimon Glassimport hashlib
10680e3312SSimon Glassfrom optparse import OptionParser
11680e3312SSimon Glassimport os
12680e3312SSimon Glassimport shutil
13680e3312SSimon Glassimport struct
14680e3312SSimon Glassimport sys
15680e3312SSimon Glassimport tempfile
16680e3312SSimon Glassimport unittest
17680e3312SSimon Glass
18680e3312SSimon Glassimport binman
19680e3312SSimon Glassimport cmdline
20680e3312SSimon Glassimport command
21680e3312SSimon Glassimport control
2219790632SSimon Glassimport elf
23680e3312SSimon Glassimport fdt
24680e3312SSimon Glassimport fdt_util
2511e36cceSSimon Glassimport fmap_util
26fd8d1f79SSimon Glassimport test_util
27c55a50f5SSimon Glassimport state
28680e3312SSimon Glassimport tools
29680e3312SSimon Glassimport tout
30680e3312SSimon Glass
31680e3312SSimon Glass# Contents of test files, corresponding to different entry types
32680e3312SSimon GlassU_BOOT_DATA           = '1234'
33680e3312SSimon GlassU_BOOT_IMG_DATA       = 'img'
34f689890dSSimon GlassU_BOOT_SPL_DATA       = '56780123456789abcde'
35b8ef5b6bSSimon GlassU_BOOT_TPL_DATA       = 'tpl'
36680e3312SSimon GlassBLOB_DATA             = '89'
37680e3312SSimon GlassME_DATA               = '0abcd'
38680e3312SSimon GlassVGA_DATA              = 'vga'
39680e3312SSimon GlassU_BOOT_DTB_DATA       = 'udtb'
4047419eaeSSimon GlassU_BOOT_SPL_DTB_DATA   = 'spldtb'
41b8ef5b6bSSimon GlassU_BOOT_TPL_DTB_DATA   = 'tpldtb'
42680e3312SSimon GlassX86_START16_DATA      = 'start16'
438772213eSSimon GlassX86_START16_SPL_DATA  = 'start16spl'
4435b384cbSSimon GlassX86_START16_TPL_DATA  = 'start16tpl'
459d368f32SJagdish GediyaPPC_MPC85XX_BR_DATA   = 'ppcmpc85xxbr'
46680e3312SSimon GlassU_BOOT_NODTB_DATA     = 'nodtb with microcode pointer somewhere in here'
476b187df7SSimon GlassU_BOOT_SPL_NODTB_DATA = 'splnodtb with microcode pointer somewhere in here'
48f0253635SSimon GlassU_BOOT_TPL_NODTB_DATA = 'tplnodtb with microcode pointer somewhere in here'
49680e3312SSimon GlassFSP_DATA              = 'fsp'
50680e3312SSimon GlassCMC_DATA              = 'cmc'
51680e3312SSimon GlassVBT_DATA              = 'vbt'
52ca4f4ff7SSimon GlassMRC_DATA              = 'mrc'
53bb74837cSSimon GlassTEXT_DATA             = 'text'
54bb74837cSSimon GlassTEXT_DATA2            = 'text2'
55bb74837cSSimon GlassTEXT_DATA3            = 'text3'
56ec127af0SSimon GlassCROS_EC_RW_DATA       = 'ecrw'
570ef87aa3SSimon GlassGBB_DATA              = 'gbbd'
580ef87aa3SSimon GlassBMPBLK_DATA           = 'bmp'
5924d0d3c3SSimon GlassVBLOCK_DATA           = 'vblk'
600a98b28bSSimon GlassFILES_DATA            = ("sorry I'm late\nOh, don't bother apologising, I'm " +
610a98b28bSSimon Glass                         "sorry you're alive\n")
6283d73c2fSSimon GlassCOMPRESS_DATA         = 'data to compress'
63*3ae192c2SSimon GlassREFCODE_DATA          = 'refcode'
64ec127af0SSimon Glass
65680e3312SSimon Glass
66680e3312SSimon Glassclass TestFunctional(unittest.TestCase):
67680e3312SSimon Glass    """Functional tests for binman
68680e3312SSimon Glass
69680e3312SSimon Glass    Most of these use a sample .dts file to build an image and then check
70680e3312SSimon Glass    that it looks correct. The sample files are in the test/ subdirectory
71680e3312SSimon Glass    and are numbered.
72680e3312SSimon Glass
73680e3312SSimon Glass    For each entry type a very small test file is created using fixed
74680e3312SSimon Glass    string contents. This makes it easy to test that things look right, and
75680e3312SSimon Glass    debug problems.
76680e3312SSimon Glass
77680e3312SSimon Glass    In some cases a 'real' file must be used - these are also supplied in
78680e3312SSimon Glass    the test/ diurectory.
79680e3312SSimon Glass    """
80680e3312SSimon Glass    @classmethod
81680e3312SSimon Glass    def setUpClass(self):
824d5994f9SSimon Glass        global entry
834d5994f9SSimon Glass        import entry
844d5994f9SSimon Glass
85680e3312SSimon Glass        # Handle the case where argv[0] is 'python'
86680e3312SSimon Glass        self._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
87680e3312SSimon Glass        self._binman_pathname = os.path.join(self._binman_dir, 'binman')
88680e3312SSimon Glass
89680e3312SSimon Glass        # Create a temporary directory for input files
90680e3312SSimon Glass        self._indir = tempfile.mkdtemp(prefix='binmant.')
91680e3312SSimon Glass
92680e3312SSimon Glass        # Create some test files
93680e3312SSimon Glass        TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
94680e3312SSimon Glass        TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
95680e3312SSimon Glass        TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
96b8ef5b6bSSimon Glass        TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
97680e3312SSimon Glass        TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
98680e3312SSimon Glass        TestFunctional._MakeInputFile('me.bin', ME_DATA)
99680e3312SSimon Glass        TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
100b8ef5b6bSSimon Glass        self._ResetDtbs()
101680e3312SSimon Glass        TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
1029d368f32SJagdish Gediya        TestFunctional._MakeInputFile('u-boot-br.bin', PPC_MPC85XX_BR_DATA)
1038772213eSSimon Glass        TestFunctional._MakeInputFile('spl/u-boot-x86-16bit-spl.bin',
1048772213eSSimon Glass                                      X86_START16_SPL_DATA)
10535b384cbSSimon Glass        TestFunctional._MakeInputFile('tpl/u-boot-x86-16bit-tpl.bin',
10635b384cbSSimon Glass                                      X86_START16_TPL_DATA)
107680e3312SSimon Glass        TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
1086b187df7SSimon Glass        TestFunctional._MakeInputFile('spl/u-boot-spl-nodtb.bin',
1096b187df7SSimon Glass                                      U_BOOT_SPL_NODTB_DATA)
110f0253635SSimon Glass        TestFunctional._MakeInputFile('tpl/u-boot-tpl-nodtb.bin',
111f0253635SSimon Glass                                      U_BOOT_TPL_NODTB_DATA)
112680e3312SSimon Glass        TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
113680e3312SSimon Glass        TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
114680e3312SSimon Glass        TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
115ca4f4ff7SSimon Glass        TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
116ec127af0SSimon Glass        TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
1170ef87aa3SSimon Glass        TestFunctional._MakeInputDir('devkeys')
1180ef87aa3SSimon Glass        TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
119*3ae192c2SSimon Glass        TestFunctional._MakeInputFile('refcode.bin', REFCODE_DATA)
120680e3312SSimon Glass
121680e3312SSimon Glass        # ELF file with a '_dt_ucode_base_size' symbol
122680e3312SSimon Glass        with open(self.TestFile('u_boot_ucode_ptr')) as fd:
123680e3312SSimon Glass            TestFunctional._MakeInputFile('u-boot', fd.read())
124680e3312SSimon Glass
125680e3312SSimon Glass        # Intel flash descriptor file
126680e3312SSimon Glass        with open(self.TestFile('descriptor.bin')) as fd:
127680e3312SSimon Glass            TestFunctional._MakeInputFile('descriptor.bin', fd.read())
128680e3312SSimon Glass
1290a98b28bSSimon Glass        shutil.copytree(self.TestFile('files'),
1300a98b28bSSimon Glass                        os.path.join(self._indir, 'files'))
1310a98b28bSSimon Glass
13283d73c2fSSimon Glass        TestFunctional._MakeInputFile('compress', COMPRESS_DATA)
13383d73c2fSSimon Glass
134680e3312SSimon Glass    @classmethod
135680e3312SSimon Glass    def tearDownClass(self):
136680e3312SSimon Glass        """Remove the temporary input directory and its contents"""
137680e3312SSimon Glass        if self._indir:
138680e3312SSimon Glass            shutil.rmtree(self._indir)
139680e3312SSimon Glass        self._indir = None
140680e3312SSimon Glass
141680e3312SSimon Glass    def setUp(self):
142680e3312SSimon Glass        # Enable this to turn on debugging output
143680e3312SSimon Glass        # tout.Init(tout.DEBUG)
144680e3312SSimon Glass        command.test_result = None
145680e3312SSimon Glass
146680e3312SSimon Glass    def tearDown(self):
147680e3312SSimon Glass        """Remove the temporary output directory"""
148680e3312SSimon Glass        tools._FinaliseForTest()
149680e3312SSimon Glass
150b8ef5b6bSSimon Glass    @classmethod
151b8ef5b6bSSimon Glass    def _ResetDtbs(self):
152b8ef5b6bSSimon Glass        TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
153b8ef5b6bSSimon Glass        TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
154b8ef5b6bSSimon Glass        TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
155b8ef5b6bSSimon Glass
156680e3312SSimon Glass    def _RunBinman(self, *args, **kwargs):
157680e3312SSimon Glass        """Run binman using the command line
158680e3312SSimon Glass
159680e3312SSimon Glass        Args:
160680e3312SSimon Glass            Arguments to pass, as a list of strings
161680e3312SSimon Glass            kwargs: Arguments to pass to Command.RunPipe()
162680e3312SSimon Glass        """
163680e3312SSimon Glass        result = command.RunPipe([[self._binman_pathname] + list(args)],
164680e3312SSimon Glass                capture=True, capture_stderr=True, raise_on_error=False)
165680e3312SSimon Glass        if result.return_code and kwargs.get('raise_on_error', True):
166680e3312SSimon Glass            raise Exception("Error running '%s': %s" % (' '.join(args),
167680e3312SSimon Glass                            result.stdout + result.stderr))
168680e3312SSimon Glass        return result
169680e3312SSimon Glass
170680e3312SSimon Glass    def _DoBinman(self, *args):
171680e3312SSimon Glass        """Run binman using directly (in the same process)
172680e3312SSimon Glass
173680e3312SSimon Glass        Args:
174680e3312SSimon Glass            Arguments to pass, as a list of strings
175680e3312SSimon Glass        Returns:
176680e3312SSimon Glass            Return value (0 for success)
177680e3312SSimon Glass        """
1787fe9173bSSimon Glass        args = list(args)
1797fe9173bSSimon Glass        if '-D' in sys.argv:
1807fe9173bSSimon Glass            args = args + ['-D']
1817fe9173bSSimon Glass        (options, args) = cmdline.ParseArgs(args)
182680e3312SSimon Glass        options.pager = 'binman-invalid-pager'
183680e3312SSimon Glass        options.build_dir = self._indir
184680e3312SSimon Glass
185680e3312SSimon Glass        # For testing, you can force an increase in verbosity here
186680e3312SSimon Glass        # options.verbosity = tout.DEBUG
187680e3312SSimon Glass        return control.Binman(options, args)
188680e3312SSimon Glass
18953af22a9SSimon Glass    def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
19093d17413SSimon Glass                    entry_args=None, images=None, use_real_dtb=False):
191680e3312SSimon Glass        """Run binman with a given test file
192680e3312SSimon Glass
193680e3312SSimon Glass        Args:
194741f2d62SSimon Glass            fname: Device-tree source filename to use (e.g. 005_simple.dts)
1957ae5f315SSimon Glass            debug: True to enable debugging output
1963b0c3821SSimon Glass            map: True to output map files for the images
1973ab9598dSSimon Glass            update_dtb: Update the offset and size of each entry in the device
19816b8d6b7SSimon Glass                tree before packing it into the image
1990bfa7b09SSimon Glass            entry_args: Dict of entry args to supply to binman
2000bfa7b09SSimon Glass                key: arg name
2010bfa7b09SSimon Glass                value: value of that arg
2020bfa7b09SSimon Glass            images: List of image names to build
203680e3312SSimon Glass        """
2047fe9173bSSimon Glass        args = ['-p', '-I', self._indir, '-d', self.TestFile(fname)]
2057fe9173bSSimon Glass        if debug:
2067fe9173bSSimon Glass            args.append('-D')
2073b0c3821SSimon Glass        if map:
2083b0c3821SSimon Glass            args.append('-m')
20916b8d6b7SSimon Glass        if update_dtb:
21016b8d6b7SSimon Glass            args.append('-up')
21193d17413SSimon Glass        if not use_real_dtb:
21293d17413SSimon Glass            args.append('--fake-dtb')
21353af22a9SSimon Glass        if entry_args:
21453af22a9SSimon Glass            for arg, value in entry_args.iteritems():
21553af22a9SSimon Glass                args.append('-a%s=%s' % (arg, value))
2160bfa7b09SSimon Glass        if images:
2170bfa7b09SSimon Glass            for image in images:
2180bfa7b09SSimon Glass                args += ['-i', image]
2197fe9173bSSimon Glass        return self._DoBinman(*args)
220680e3312SSimon Glass
221680e3312SSimon Glass    def _SetupDtb(self, fname, outfile='u-boot.dtb'):
222680e3312SSimon Glass        """Set up a new test device-tree file
223680e3312SSimon Glass
224680e3312SSimon Glass        The given file is compiled and set up as the device tree to be used
225680e3312SSimon Glass        for ths test.
226680e3312SSimon Glass
227680e3312SSimon Glass        Args:
228680e3312SSimon Glass            fname: Filename of .dts file to read
2297ae5f315SSimon Glass            outfile: Output filename for compiled device-tree binary
230680e3312SSimon Glass
231680e3312SSimon Glass        Returns:
2327ae5f315SSimon Glass            Contents of device-tree binary
233680e3312SSimon Glass        """
234e0e6275fSSimon Glass        tools.PrepareOutputDir(None)
235680e3312SSimon Glass        dtb = fdt_util.EnsureCompiled(self.TestFile(fname))
236680e3312SSimon Glass        with open(dtb) as fd:
237680e3312SSimon Glass            data = fd.read()
238680e3312SSimon Glass            TestFunctional._MakeInputFile(outfile, data)
239e0e6275fSSimon Glass        tools.FinaliseOutputDir()
240680e3312SSimon Glass        return data
241680e3312SSimon Glass
2426ed45ba0SSimon Glass    def _GetDtbContentsForSplTpl(self, dtb_data, name):
2436ed45ba0SSimon Glass        """Create a version of the main DTB for SPL or SPL
2446ed45ba0SSimon Glass
2456ed45ba0SSimon Glass        For testing we don't actually have different versions of the DTB. With
2466ed45ba0SSimon Glass        U-Boot we normally run fdtgrep to remove unwanted nodes, but for tests
2476ed45ba0SSimon Glass        we don't normally have any unwanted nodes.
2486ed45ba0SSimon Glass
2496ed45ba0SSimon Glass        We still want the DTBs for SPL and TPL to be different though, since
2506ed45ba0SSimon Glass        otherwise it is confusing to know which one we are looking at. So add
2516ed45ba0SSimon Glass        an 'spl' or 'tpl' property to the top-level node.
2526ed45ba0SSimon Glass        """
2536ed45ba0SSimon Glass        dtb = fdt.Fdt.FromData(dtb_data)
2546ed45ba0SSimon Glass        dtb.Scan()
2556ed45ba0SSimon Glass        dtb.GetNode('/binman').AddZeroProp(name)
2566ed45ba0SSimon Glass        dtb.Sync(auto_resize=True)
2576ed45ba0SSimon Glass        dtb.Pack()
2586ed45ba0SSimon Glass        return dtb.GetContents()
2596ed45ba0SSimon Glass
26016b8d6b7SSimon Glass    def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
2616ed45ba0SSimon Glass                       update_dtb=False, entry_args=None, reset_dtbs=True):
262680e3312SSimon Glass        """Run binman and return the resulting image
263680e3312SSimon Glass
264680e3312SSimon Glass        This runs binman with a given test file and then reads the resulting
265680e3312SSimon Glass        output file. It is a shortcut function since most tests need to do
266680e3312SSimon Glass        these steps.
267680e3312SSimon Glass
268680e3312SSimon Glass        Raises an assertion failure if binman returns a non-zero exit code.
269680e3312SSimon Glass
270680e3312SSimon Glass        Args:
271741f2d62SSimon Glass            fname: Device-tree source filename to use (e.g. 005_simple.dts)
272680e3312SSimon Glass            use_real_dtb: True to use the test file as the contents of
273680e3312SSimon Glass                the u-boot-dtb entry. Normally this is not needed and the
274680e3312SSimon Glass                test contents (the U_BOOT_DTB_DATA string) can be used.
275680e3312SSimon Glass                But in some test we need the real contents.
2763b0c3821SSimon Glass            map: True to output map files for the images
2773ab9598dSSimon Glass            update_dtb: Update the offset and size of each entry in the device
27816b8d6b7SSimon Glass                tree before packing it into the image
279680e3312SSimon Glass
280680e3312SSimon Glass        Returns:
281680e3312SSimon Glass            Tuple:
282680e3312SSimon Glass                Resulting image contents
283680e3312SSimon Glass                Device tree contents
2843b0c3821SSimon Glass                Map data showing contents of image (or None if none)
285ea6922e3SSimon Glass                Output device tree binary filename ('u-boot.dtb' path)
286680e3312SSimon Glass        """
287680e3312SSimon Glass        dtb_data = None
288680e3312SSimon Glass        # Use the compiled test file as the u-boot-dtb input
289680e3312SSimon Glass        if use_real_dtb:
290680e3312SSimon Glass            dtb_data = self._SetupDtb(fname)
2916ed45ba0SSimon Glass            infile = os.path.join(self._indir, 'u-boot.dtb')
2926ed45ba0SSimon Glass
2936ed45ba0SSimon Glass            # For testing purposes, make a copy of the DT for SPL and TPL. Add
2946ed45ba0SSimon Glass            # a node indicating which it is, so aid verification.
2956ed45ba0SSimon Glass            for name in ['spl', 'tpl']:
2966ed45ba0SSimon Glass                dtb_fname = '%s/u-boot-%s.dtb' % (name, name)
2976ed45ba0SSimon Glass                outfile = os.path.join(self._indir, dtb_fname)
2986ed45ba0SSimon Glass                TestFunctional._MakeInputFile(dtb_fname,
2996ed45ba0SSimon Glass                        self._GetDtbContentsForSplTpl(dtb_data, name))
300680e3312SSimon Glass
301680e3312SSimon Glass        try:
30253af22a9SSimon Glass            retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
3036ed45ba0SSimon Glass                    entry_args=entry_args, use_real_dtb=use_real_dtb)
304680e3312SSimon Glass            self.assertEqual(0, retcode)
3056ed45ba0SSimon Glass            out_dtb_fname = tools.GetOutputFilename('u-boot.dtb.out')
306680e3312SSimon Glass
307680e3312SSimon Glass            # Find the (only) image, read it and return its contents
308680e3312SSimon Glass            image = control.images['image']
30916b8d6b7SSimon Glass            image_fname = tools.GetOutputFilename('image.bin')
31016b8d6b7SSimon Glass            self.assertTrue(os.path.exists(image_fname))
3113b0c3821SSimon Glass            if map:
3123b0c3821SSimon Glass                map_fname = tools.GetOutputFilename('image.map')
3133b0c3821SSimon Glass                with open(map_fname) as fd:
3143b0c3821SSimon Glass                    map_data = fd.read()
3153b0c3821SSimon Glass            else:
3163b0c3821SSimon Glass                map_data = None
31716b8d6b7SSimon Glass            with open(image_fname) as fd:
31816b8d6b7SSimon Glass                return fd.read(), dtb_data, map_data, out_dtb_fname
319680e3312SSimon Glass        finally:
320680e3312SSimon Glass            # Put the test file back
3216ed45ba0SSimon Glass            if reset_dtbs and use_real_dtb:
322b8ef5b6bSSimon Glass                self._ResetDtbs()
323680e3312SSimon Glass
324680e3312SSimon Glass    def _DoReadFile(self, fname, use_real_dtb=False):
3257ae5f315SSimon Glass        """Helper function which discards the device-tree binary
3267ae5f315SSimon Glass
3277ae5f315SSimon Glass        Args:
328741f2d62SSimon Glass            fname: Device-tree source filename to use (e.g. 005_simple.dts)
3297ae5f315SSimon Glass            use_real_dtb: True to use the test file as the contents of
3307ae5f315SSimon Glass                the u-boot-dtb entry. Normally this is not needed and the
3317ae5f315SSimon Glass                test contents (the U_BOOT_DTB_DATA string) can be used.
3327ae5f315SSimon Glass                But in some test we need the real contents.
333ea6922e3SSimon Glass
334ea6922e3SSimon Glass        Returns:
335ea6922e3SSimon Glass            Resulting image contents
3367ae5f315SSimon Glass        """
337680e3312SSimon Glass        return self._DoReadFileDtb(fname, use_real_dtb)[0]
338680e3312SSimon Glass
339680e3312SSimon Glass    @classmethod
340680e3312SSimon Glass    def _MakeInputFile(self, fname, contents):
341680e3312SSimon Glass        """Create a new test input file, creating directories as needed
342680e3312SSimon Glass
343680e3312SSimon Glass        Args:
3443ab9598dSSimon Glass            fname: Filename to create
345680e3312SSimon Glass            contents: File contents to write in to the file
346680e3312SSimon Glass        Returns:
347680e3312SSimon Glass            Full pathname of file created
348680e3312SSimon Glass        """
349680e3312SSimon Glass        pathname = os.path.join(self._indir, fname)
350680e3312SSimon Glass        dirname = os.path.dirname(pathname)
351680e3312SSimon Glass        if dirname and not os.path.exists(dirname):
352680e3312SSimon Glass            os.makedirs(dirname)
353680e3312SSimon Glass        with open(pathname, 'wb') as fd:
354680e3312SSimon Glass            fd.write(contents)
355680e3312SSimon Glass        return pathname
356680e3312SSimon Glass
357680e3312SSimon Glass    @classmethod
3580ef87aa3SSimon Glass    def _MakeInputDir(self, dirname):
3590ef87aa3SSimon Glass        """Create a new test input directory, creating directories as needed
3600ef87aa3SSimon Glass
3610ef87aa3SSimon Glass        Args:
3620ef87aa3SSimon Glass            dirname: Directory name to create
3630ef87aa3SSimon Glass
3640ef87aa3SSimon Glass        Returns:
3650ef87aa3SSimon Glass            Full pathname of directory created
3660ef87aa3SSimon Glass        """
3670ef87aa3SSimon Glass        pathname = os.path.join(self._indir, dirname)
3680ef87aa3SSimon Glass        if not os.path.exists(pathname):
3690ef87aa3SSimon Glass            os.makedirs(pathname)
3700ef87aa3SSimon Glass        return pathname
3710ef87aa3SSimon Glass
3720ef87aa3SSimon Glass    @classmethod
37311ae93eeSSimon Glass    def _SetupSplElf(self, src_fname='bss_data'):
37411ae93eeSSimon Glass        """Set up an ELF file with a '_dt_ucode_base_size' symbol
37511ae93eeSSimon Glass
37611ae93eeSSimon Glass        Args:
37711ae93eeSSimon Glass            Filename of ELF file to use as SPL
37811ae93eeSSimon Glass        """
37911ae93eeSSimon Glass        with open(self.TestFile(src_fname)) as fd:
38011ae93eeSSimon Glass            TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
38111ae93eeSSimon Glass
38211ae93eeSSimon Glass    @classmethod
383680e3312SSimon Glass    def TestFile(self, fname):
384680e3312SSimon Glass        return os.path.join(self._binman_dir, 'test', fname)
385680e3312SSimon Glass
386680e3312SSimon Glass    def AssertInList(self, grep_list, target):
387680e3312SSimon Glass        """Assert that at least one of a list of things is in a target
388680e3312SSimon Glass
389680e3312SSimon Glass        Args:
390680e3312SSimon Glass            grep_list: List of strings to check
391680e3312SSimon Glass            target: Target string
392680e3312SSimon Glass        """
393680e3312SSimon Glass        for grep in grep_list:
394680e3312SSimon Glass            if grep in target:
395680e3312SSimon Glass                return
396680e3312SSimon Glass        self.fail("Error: '%' not found in '%s'" % (grep_list, target))
397680e3312SSimon Glass
398680e3312SSimon Glass    def CheckNoGaps(self, entries):
399680e3312SSimon Glass        """Check that all entries fit together without gaps
400680e3312SSimon Glass
401680e3312SSimon Glass        Args:
402680e3312SSimon Glass            entries: List of entries to check
403680e3312SSimon Glass        """
4043ab9598dSSimon Glass        offset = 0
405680e3312SSimon Glass        for entry in entries.values():
4063ab9598dSSimon Glass            self.assertEqual(offset, entry.offset)
4073ab9598dSSimon Glass            offset += entry.size
408680e3312SSimon Glass
409680e3312SSimon Glass    def GetFdtLen(self, dtb):
4107ae5f315SSimon Glass        """Get the totalsize field from a device-tree binary
411680e3312SSimon Glass
412680e3312SSimon Glass        Args:
4137ae5f315SSimon Glass            dtb: Device-tree binary contents
414680e3312SSimon Glass
415680e3312SSimon Glass        Returns:
4167ae5f315SSimon Glass            Total size of device-tree binary, from the header
417680e3312SSimon Glass        """
418680e3312SSimon Glass        return struct.unpack('>L', dtb[4:8])[0]
419680e3312SSimon Glass
420cee02e6fSSimon Glass    def _GetPropTree(self, dtb, prop_names):
42116b8d6b7SSimon Glass        def AddNode(node, path):
42216b8d6b7SSimon Glass            if node.name != '/':
42316b8d6b7SSimon Glass                path += '/' + node.name
42416b8d6b7SSimon Glass            for subnode in node.subnodes:
42516b8d6b7SSimon Glass                for prop in subnode.props.values():
426cee02e6fSSimon Glass                    if prop.name in prop_names:
42716b8d6b7SSimon Glass                        prop_path = path + '/' + subnode.name + ':' + prop.name
42816b8d6b7SSimon Glass                        tree[prop_path[len('/binman/'):]] = fdt_util.fdt32_to_cpu(
42916b8d6b7SSimon Glass                            prop.value)
43016b8d6b7SSimon Glass                AddNode(subnode, path)
43116b8d6b7SSimon Glass
43216b8d6b7SSimon Glass        tree = {}
43316b8d6b7SSimon Glass        AddNode(dtb.GetRoot(), '')
43416b8d6b7SSimon Glass        return tree
43516b8d6b7SSimon Glass
436680e3312SSimon Glass    def testRun(self):
437680e3312SSimon Glass        """Test a basic run with valid args"""
438680e3312SSimon Glass        result = self._RunBinman('-h')
439680e3312SSimon Glass
440680e3312SSimon Glass    def testFullHelp(self):
441680e3312SSimon Glass        """Test that the full help is displayed with -H"""
442680e3312SSimon Glass        result = self._RunBinman('-H')
443680e3312SSimon Glass        help_file = os.path.join(self._binman_dir, 'README')
4443759df0cSTom Rini        # Remove possible extraneous strings
4453759df0cSTom Rini        extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
4463759df0cSTom Rini        gothelp = result.stdout.replace(extra, '')
4473759df0cSTom Rini        self.assertEqual(len(gothelp), os.path.getsize(help_file))
448680e3312SSimon Glass        self.assertEqual(0, len(result.stderr))
449680e3312SSimon Glass        self.assertEqual(0, result.return_code)
450680e3312SSimon Glass
451680e3312SSimon Glass    def testFullHelpInternal(self):
452680e3312SSimon Glass        """Test that the full help is displayed with -H"""
453680e3312SSimon Glass        try:
454680e3312SSimon Glass            command.test_result = command.CommandResult()
455680e3312SSimon Glass            result = self._DoBinman('-H')
456680e3312SSimon Glass            help_file = os.path.join(self._binman_dir, 'README')
457680e3312SSimon Glass        finally:
458680e3312SSimon Glass            command.test_result = None
459680e3312SSimon Glass
460680e3312SSimon Glass    def testHelp(self):
461680e3312SSimon Glass        """Test that the basic help is displayed with -h"""
462680e3312SSimon Glass        result = self._RunBinman('-h')
463680e3312SSimon Glass        self.assertTrue(len(result.stdout) > 200)
464680e3312SSimon Glass        self.assertEqual(0, len(result.stderr))
465680e3312SSimon Glass        self.assertEqual(0, result.return_code)
466680e3312SSimon Glass
467680e3312SSimon Glass    def testBoard(self):
468680e3312SSimon Glass        """Test that we can run it with a specific board"""
469741f2d62SSimon Glass        self._SetupDtb('005_simple.dts', 'sandbox/u-boot.dtb')
470680e3312SSimon Glass        TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
471680e3312SSimon Glass        result = self._DoBinman('-b', 'sandbox')
472680e3312SSimon Glass        self.assertEqual(0, result)
473680e3312SSimon Glass
474680e3312SSimon Glass    def testNeedBoard(self):
475680e3312SSimon Glass        """Test that we get an error when no board ius supplied"""
476680e3312SSimon Glass        with self.assertRaises(ValueError) as e:
477680e3312SSimon Glass            result = self._DoBinman()
478680e3312SSimon Glass        self.assertIn("Must provide a board to process (use -b <board>)",
479680e3312SSimon Glass                str(e.exception))
480680e3312SSimon Glass
481680e3312SSimon Glass    def testMissingDt(self):
4827ae5f315SSimon Glass        """Test that an invalid device-tree file generates an error"""
483680e3312SSimon Glass        with self.assertRaises(Exception) as e:
484680e3312SSimon Glass            self._RunBinman('-d', 'missing_file')
485680e3312SSimon Glass        # We get one error from libfdt, and a different one from fdtget.
486680e3312SSimon Glass        self.AssertInList(["Couldn't open blob from 'missing_file'",
487680e3312SSimon Glass                           'No such file or directory'], str(e.exception))
488680e3312SSimon Glass
489680e3312SSimon Glass    def testBrokenDt(self):
4907ae5f315SSimon Glass        """Test that an invalid device-tree source file generates an error
491680e3312SSimon Glass
492680e3312SSimon Glass        Since this is a source file it should be compiled and the error
493680e3312SSimon Glass        will come from the device-tree compiler (dtc).
494680e3312SSimon Glass        """
495680e3312SSimon Glass        with self.assertRaises(Exception) as e:
496741f2d62SSimon Glass            self._RunBinman('-d', self.TestFile('001_invalid.dts'))
497680e3312SSimon Glass        self.assertIn("FATAL ERROR: Unable to parse input tree",
498680e3312SSimon Glass                str(e.exception))
499680e3312SSimon Glass
500680e3312SSimon Glass    def testMissingNode(self):
501680e3312SSimon Glass        """Test that a device tree without a 'binman' node generates an error"""
502680e3312SSimon Glass        with self.assertRaises(Exception) as e:
503741f2d62SSimon Glass            self._DoBinman('-d', self.TestFile('002_missing_node.dts'))
504680e3312SSimon Glass        self.assertIn("does not have a 'binman' node", str(e.exception))
505680e3312SSimon Glass
506680e3312SSimon Glass    def testEmpty(self):
507680e3312SSimon Glass        """Test that an empty binman node works OK (i.e. does nothing)"""
508741f2d62SSimon Glass        result = self._RunBinman('-d', self.TestFile('003_empty.dts'))
509680e3312SSimon Glass        self.assertEqual(0, len(result.stderr))
510680e3312SSimon Glass        self.assertEqual(0, result.return_code)
511680e3312SSimon Glass
512680e3312SSimon Glass    def testInvalidEntry(self):
513680e3312SSimon Glass        """Test that an invalid entry is flagged"""
514680e3312SSimon Glass        with self.assertRaises(Exception) as e:
515680e3312SSimon Glass            result = self._RunBinman('-d',
516741f2d62SSimon Glass                                     self.TestFile('004_invalid_entry.dts'))
517680e3312SSimon Glass        self.assertIn("Unknown entry type 'not-a-valid-type' in node "
518680e3312SSimon Glass                "'/binman/not-a-valid-type'", str(e.exception))
519680e3312SSimon Glass
520680e3312SSimon Glass    def testSimple(self):
521680e3312SSimon Glass        """Test a simple binman with a single file"""
522741f2d62SSimon Glass        data = self._DoReadFile('005_simple.dts')
523680e3312SSimon Glass        self.assertEqual(U_BOOT_DATA, data)
524680e3312SSimon Glass
5257fe9173bSSimon Glass    def testSimpleDebug(self):
5267fe9173bSSimon Glass        """Test a simple binman run with debugging enabled"""
527741f2d62SSimon Glass        data = self._DoTestFile('005_simple.dts', debug=True)
5287fe9173bSSimon Glass
529680e3312SSimon Glass    def testDual(self):
530680e3312SSimon Glass        """Test that we can handle creating two images
531680e3312SSimon Glass
532680e3312SSimon Glass        This also tests image padding.
533680e3312SSimon Glass        """
534741f2d62SSimon Glass        retcode = self._DoTestFile('006_dual_image.dts')
535680e3312SSimon Glass        self.assertEqual(0, retcode)
536680e3312SSimon Glass
537680e3312SSimon Glass        image = control.images['image1']
538680e3312SSimon Glass        self.assertEqual(len(U_BOOT_DATA), image._size)
539680e3312SSimon Glass        fname = tools.GetOutputFilename('image1.bin')
540680e3312SSimon Glass        self.assertTrue(os.path.exists(fname))
541680e3312SSimon Glass        with open(fname) as fd:
542680e3312SSimon Glass            data = fd.read()
543680e3312SSimon Glass            self.assertEqual(U_BOOT_DATA, data)
544680e3312SSimon Glass
545680e3312SSimon Glass        image = control.images['image2']
546680e3312SSimon Glass        self.assertEqual(3 + len(U_BOOT_DATA) + 5, image._size)
547680e3312SSimon Glass        fname = tools.GetOutputFilename('image2.bin')
548680e3312SSimon Glass        self.assertTrue(os.path.exists(fname))
549680e3312SSimon Glass        with open(fname) as fd:
550680e3312SSimon Glass            data = fd.read()
551680e3312SSimon Glass            self.assertEqual(U_BOOT_DATA, data[3:7])
552680e3312SSimon Glass            self.assertEqual(chr(0) * 3, data[:3])
553680e3312SSimon Glass            self.assertEqual(chr(0) * 5, data[7:])
554680e3312SSimon Glass
555680e3312SSimon Glass    def testBadAlign(self):
556680e3312SSimon Glass        """Test that an invalid alignment value is detected"""
557680e3312SSimon Glass        with self.assertRaises(ValueError) as e:
558741f2d62SSimon Glass            self._DoTestFile('007_bad_align.dts')
559680e3312SSimon Glass        self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
560680e3312SSimon Glass                      "of two", str(e.exception))
561680e3312SSimon Glass
562680e3312SSimon Glass    def testPackSimple(self):
563680e3312SSimon Glass        """Test that packing works as expected"""
564741f2d62SSimon Glass        retcode = self._DoTestFile('008_pack.dts')
565680e3312SSimon Glass        self.assertEqual(0, retcode)
566680e3312SSimon Glass        self.assertIn('image', control.images)
567680e3312SSimon Glass        image = control.images['image']
5688f1da50cSSimon Glass        entries = image.GetEntries()
569680e3312SSimon Glass        self.assertEqual(5, len(entries))
570680e3312SSimon Glass
571680e3312SSimon Glass        # First u-boot
572680e3312SSimon Glass        self.assertIn('u-boot', entries)
573680e3312SSimon Glass        entry = entries['u-boot']
5743ab9598dSSimon Glass        self.assertEqual(0, entry.offset)
575680e3312SSimon Glass        self.assertEqual(len(U_BOOT_DATA), entry.size)
576680e3312SSimon Glass
577680e3312SSimon Glass        # Second u-boot, aligned to 16-byte boundary
578680e3312SSimon Glass        self.assertIn('u-boot-align', entries)
579680e3312SSimon Glass        entry = entries['u-boot-align']
5803ab9598dSSimon Glass        self.assertEqual(16, entry.offset)
581680e3312SSimon Glass        self.assertEqual(len(U_BOOT_DATA), entry.size)
582680e3312SSimon Glass
583680e3312SSimon Glass        # Third u-boot, size 23 bytes
584680e3312SSimon Glass        self.assertIn('u-boot-size', entries)
585680e3312SSimon Glass        entry = entries['u-boot-size']
5863ab9598dSSimon Glass        self.assertEqual(20, entry.offset)
587680e3312SSimon Glass        self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
588680e3312SSimon Glass        self.assertEqual(23, entry.size)
589680e3312SSimon Glass
590680e3312SSimon Glass        # Fourth u-boot, placed immediate after the above
591680e3312SSimon Glass        self.assertIn('u-boot-next', entries)
592680e3312SSimon Glass        entry = entries['u-boot-next']
5933ab9598dSSimon Glass        self.assertEqual(43, entry.offset)
594680e3312SSimon Glass        self.assertEqual(len(U_BOOT_DATA), entry.size)
595680e3312SSimon Glass
5963ab9598dSSimon Glass        # Fifth u-boot, placed at a fixed offset
597680e3312SSimon Glass        self.assertIn('u-boot-fixed', entries)
598680e3312SSimon Glass        entry = entries['u-boot-fixed']
5993ab9598dSSimon Glass        self.assertEqual(61, entry.offset)
600680e3312SSimon Glass        self.assertEqual(len(U_BOOT_DATA), entry.size)
601680e3312SSimon Glass
602680e3312SSimon Glass        self.assertEqual(65, image._size)
603680e3312SSimon Glass
604680e3312SSimon Glass    def testPackExtra(self):
605680e3312SSimon Glass        """Test that extra packing feature works as expected"""
606741f2d62SSimon Glass        retcode = self._DoTestFile('009_pack_extra.dts')
607680e3312SSimon Glass
608680e3312SSimon Glass        self.assertEqual(0, retcode)
609680e3312SSimon Glass        self.assertIn('image', control.images)
610680e3312SSimon Glass        image = control.images['image']
6118f1da50cSSimon Glass        entries = image.GetEntries()
612680e3312SSimon Glass        self.assertEqual(5, len(entries))
613680e3312SSimon Glass
614680e3312SSimon Glass        # First u-boot with padding before and after
615680e3312SSimon Glass        self.assertIn('u-boot', entries)
616680e3312SSimon Glass        entry = entries['u-boot']
6173ab9598dSSimon Glass        self.assertEqual(0, entry.offset)
618680e3312SSimon Glass        self.assertEqual(3, entry.pad_before)
619680e3312SSimon Glass        self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
620680e3312SSimon Glass
621680e3312SSimon Glass        # Second u-boot has an aligned size, but it has no effect
622680e3312SSimon Glass        self.assertIn('u-boot-align-size-nop', entries)
623680e3312SSimon Glass        entry = entries['u-boot-align-size-nop']
6243ab9598dSSimon Glass        self.assertEqual(12, entry.offset)
625680e3312SSimon Glass        self.assertEqual(4, entry.size)
626680e3312SSimon Glass
627680e3312SSimon Glass        # Third u-boot has an aligned size too
628680e3312SSimon Glass        self.assertIn('u-boot-align-size', entries)
629680e3312SSimon Glass        entry = entries['u-boot-align-size']
6303ab9598dSSimon Glass        self.assertEqual(16, entry.offset)
631680e3312SSimon Glass        self.assertEqual(32, entry.size)
632680e3312SSimon Glass
633680e3312SSimon Glass        # Fourth u-boot has an aligned end
634680e3312SSimon Glass        self.assertIn('u-boot-align-end', entries)
635680e3312SSimon Glass        entry = entries['u-boot-align-end']
6363ab9598dSSimon Glass        self.assertEqual(48, entry.offset)
637680e3312SSimon Glass        self.assertEqual(16, entry.size)
638680e3312SSimon Glass
639680e3312SSimon Glass        # Fifth u-boot immediately afterwards
640680e3312SSimon Glass        self.assertIn('u-boot-align-both', entries)
641680e3312SSimon Glass        entry = entries['u-boot-align-both']
6423ab9598dSSimon Glass        self.assertEqual(64, entry.offset)
643680e3312SSimon Glass        self.assertEqual(64, entry.size)
644680e3312SSimon Glass
645680e3312SSimon Glass        self.CheckNoGaps(entries)
646680e3312SSimon Glass        self.assertEqual(128, image._size)
647680e3312SSimon Glass
648680e3312SSimon Glass    def testPackAlignPowerOf2(self):
649680e3312SSimon Glass        """Test that invalid entry alignment is detected"""
650680e3312SSimon Glass        with self.assertRaises(ValueError) as e:
651741f2d62SSimon Glass            self._DoTestFile('010_pack_align_power2.dts')
652680e3312SSimon Glass        self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
653680e3312SSimon Glass                      "of two", str(e.exception))
654680e3312SSimon Glass
655680e3312SSimon Glass    def testPackAlignSizePowerOf2(self):
656680e3312SSimon Glass        """Test that invalid entry size alignment is detected"""
657680e3312SSimon Glass        with self.assertRaises(ValueError) as e:
658741f2d62SSimon Glass            self._DoTestFile('011_pack_align_size_power2.dts')
659680e3312SSimon Glass        self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
660680e3312SSimon Glass                      "power of two", str(e.exception))
661680e3312SSimon Glass
662680e3312SSimon Glass    def testPackInvalidAlign(self):
6633ab9598dSSimon Glass        """Test detection of an offset that does not match its alignment"""
664680e3312SSimon Glass        with self.assertRaises(ValueError) as e:
665741f2d62SSimon Glass            self._DoTestFile('012_pack_inv_align.dts')
6663ab9598dSSimon Glass        self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
667680e3312SSimon Glass                      "align 0x4 (4)", str(e.exception))
668680e3312SSimon Glass
669680e3312SSimon Glass    def testPackInvalidSizeAlign(self):
670680e3312SSimon Glass        """Test that invalid entry size alignment is detected"""
671680e3312SSimon Glass        with self.assertRaises(ValueError) as e:
672741f2d62SSimon Glass            self._DoTestFile('013_pack_inv_size_align.dts')
673680e3312SSimon Glass        self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
674680e3312SSimon Glass                      "align-size 0x4 (4)", str(e.exception))
675680e3312SSimon Glass
676680e3312SSimon Glass    def testPackOverlap(self):
677680e3312SSimon Glass        """Test that overlapping regions are detected"""
678680e3312SSimon Glass        with self.assertRaises(ValueError) as e:
679741f2d62SSimon Glass            self._DoTestFile('014_pack_overlap.dts')
6803ab9598dSSimon Glass        self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
681680e3312SSimon Glass                      "with previous entry '/binman/u-boot' ending at 0x4 (4)",
682680e3312SSimon Glass                      str(e.exception))
683680e3312SSimon Glass
684680e3312SSimon Glass    def testPackEntryOverflow(self):
685680e3312SSimon Glass        """Test that entries that overflow their size are detected"""
686680e3312SSimon Glass        with self.assertRaises(ValueError) as e:
687741f2d62SSimon Glass            self._DoTestFile('015_pack_overflow.dts')
688680e3312SSimon Glass        self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
689680e3312SSimon Glass                      "but entry size is 0x3 (3)", str(e.exception))
690680e3312SSimon Glass
691680e3312SSimon Glass    def testPackImageOverflow(self):
692680e3312SSimon Glass        """Test that entries which overflow the image size are detected"""
693680e3312SSimon Glass        with self.assertRaises(ValueError) as e:
694741f2d62SSimon Glass            self._DoTestFile('016_pack_image_overflow.dts')
6958f1da50cSSimon Glass        self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section "
696680e3312SSimon Glass                      "size 0x3 (3)", str(e.exception))
697680e3312SSimon Glass
698680e3312SSimon Glass    def testPackImageSize(self):
699680e3312SSimon Glass        """Test that the image size can be set"""
700741f2d62SSimon Glass        retcode = self._DoTestFile('017_pack_image_size.dts')
701680e3312SSimon Glass        self.assertEqual(0, retcode)
702680e3312SSimon Glass        self.assertIn('image', control.images)
703680e3312SSimon Glass        image = control.images['image']
704680e3312SSimon Glass        self.assertEqual(7, image._size)
705680e3312SSimon Glass
706680e3312SSimon Glass    def testPackImageSizeAlign(self):
707680e3312SSimon Glass        """Test that image size alignemnt works as expected"""
708741f2d62SSimon Glass        retcode = self._DoTestFile('018_pack_image_align.dts')
709680e3312SSimon Glass        self.assertEqual(0, retcode)
710680e3312SSimon Glass        self.assertIn('image', control.images)
711680e3312SSimon Glass        image = control.images['image']
712680e3312SSimon Glass        self.assertEqual(16, image._size)
713680e3312SSimon Glass
714680e3312SSimon Glass    def testPackInvalidImageAlign(self):
715680e3312SSimon Glass        """Test that invalid image alignment is detected"""
716680e3312SSimon Glass        with self.assertRaises(ValueError) as e:
717741f2d62SSimon Glass            self._DoTestFile('019_pack_inv_image_align.dts')
7188f1da50cSSimon Glass        self.assertIn("Section '/binman': Size 0x7 (7) does not match "
719680e3312SSimon Glass                      "align-size 0x8 (8)", str(e.exception))
720680e3312SSimon Glass
721680e3312SSimon Glass    def testPackAlignPowerOf2(self):
722680e3312SSimon Glass        """Test that invalid image alignment is detected"""
723680e3312SSimon Glass        with self.assertRaises(ValueError) as e:
724741f2d62SSimon Glass            self._DoTestFile('020_pack_inv_image_align_power2.dts')
7258f1da50cSSimon Glass        self.assertIn("Section '/binman': Alignment size 131 must be a power of "
726680e3312SSimon Glass                      "two", str(e.exception))
727680e3312SSimon Glass
728680e3312SSimon Glass    def testImagePadByte(self):
729680e3312SSimon Glass        """Test that the image pad byte can be specified"""
73011ae93eeSSimon Glass        self._SetupSplElf()
731741f2d62SSimon Glass        data = self._DoReadFile('021_image_pad.dts')
732f689890dSSimon Glass        self.assertEqual(U_BOOT_SPL_DATA + (chr(0xff) * 1) + U_BOOT_DATA, data)
733680e3312SSimon Glass
734680e3312SSimon Glass    def testImageName(self):
735680e3312SSimon Glass        """Test that image files can be named"""
736741f2d62SSimon Glass        retcode = self._DoTestFile('022_image_name.dts')
737680e3312SSimon Glass        self.assertEqual(0, retcode)
738680e3312SSimon Glass        image = control.images['image1']
739680e3312SSimon Glass        fname = tools.GetOutputFilename('test-name')
740680e3312SSimon Glass        self.assertTrue(os.path.exists(fname))
741680e3312SSimon Glass
742680e3312SSimon Glass        image = control.images['image2']
743680e3312SSimon Glass        fname = tools.GetOutputFilename('test-name.xx')
744680e3312SSimon Glass        self.assertTrue(os.path.exists(fname))
745680e3312SSimon Glass
746680e3312SSimon Glass    def testBlobFilename(self):
747680e3312SSimon Glass        """Test that generic blobs can be provided by filename"""
748741f2d62SSimon Glass        data = self._DoReadFile('023_blob.dts')
749680e3312SSimon Glass        self.assertEqual(BLOB_DATA, data)
750680e3312SSimon Glass
751680e3312SSimon Glass    def testPackSorted(self):
752680e3312SSimon Glass        """Test that entries can be sorted"""
75311ae93eeSSimon Glass        self._SetupSplElf()
754741f2d62SSimon Glass        data = self._DoReadFile('024_sorted.dts')
755f689890dSSimon Glass        self.assertEqual(chr(0) * 1 + U_BOOT_SPL_DATA + chr(0) * 2 +
756680e3312SSimon Glass                         U_BOOT_DATA, data)
757680e3312SSimon Glass
7583ab9598dSSimon Glass    def testPackZeroOffset(self):
7593ab9598dSSimon Glass        """Test that an entry at offset 0 is not given a new offset"""
760680e3312SSimon Glass        with self.assertRaises(ValueError) as e:
761741f2d62SSimon Glass            self._DoTestFile('025_pack_zero_size.dts')
7623ab9598dSSimon Glass        self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
763680e3312SSimon Glass                      "with previous entry '/binman/u-boot' ending at 0x4 (4)",
764680e3312SSimon Glass                      str(e.exception))
765680e3312SSimon Glass
766680e3312SSimon Glass    def testPackUbootDtb(self):
767680e3312SSimon Glass        """Test that a device tree can be added to U-Boot"""
768741f2d62SSimon Glass        data = self._DoReadFile('026_pack_u_boot_dtb.dts')
769680e3312SSimon Glass        self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
770680e3312SSimon Glass
771680e3312SSimon Glass    def testPackX86RomNoSize(self):
772680e3312SSimon Glass        """Test that the end-at-4gb property requires a size property"""
773680e3312SSimon Glass        with self.assertRaises(ValueError) as e:
774741f2d62SSimon Glass            self._DoTestFile('027_pack_4gb_no_size.dts')
7758f1da50cSSimon Glass        self.assertIn("Section '/binman': Section size must be provided when "
776680e3312SSimon Glass                      "using end-at-4gb", str(e.exception))
777680e3312SSimon Glass
77894b57db0SJagdish Gediya    def test4gbAndSkipAtStartTogether(self):
77994b57db0SJagdish Gediya        """Test that the end-at-4gb and skip-at-size property can't be used
78094b57db0SJagdish Gediya        together"""
78194b57db0SJagdish Gediya        with self.assertRaises(ValueError) as e:
78294b57db0SJagdish Gediya            self._DoTestFile('80_4gb_and_skip_at_start_together.dts')
78394b57db0SJagdish Gediya        self.assertIn("Section '/binman': Provide either 'end-at-4gb' or "
78494b57db0SJagdish Gediya                      "'skip-at-start'", str(e.exception))
78594b57db0SJagdish Gediya
786680e3312SSimon Glass    def testPackX86RomOutside(self):
7873ab9598dSSimon Glass        """Test that the end-at-4gb property checks for offset boundaries"""
788680e3312SSimon Glass        with self.assertRaises(ValueError) as e:
789741f2d62SSimon Glass            self._DoTestFile('028_pack_4gb_outside.dts')
7903ab9598dSSimon Glass        self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
7918f1da50cSSimon Glass                      "the section starting at 0xffffffe0 (4294967264)",
792680e3312SSimon Glass                      str(e.exception))
793680e3312SSimon Glass
794680e3312SSimon Glass    def testPackX86Rom(self):
795680e3312SSimon Glass        """Test that a basic x86 ROM can be created"""
79611ae93eeSSimon Glass        self._SetupSplElf()
797741f2d62SSimon Glass        data = self._DoReadFile('029_x86-rom.dts')
798f689890dSSimon Glass        self.assertEqual(U_BOOT_DATA + chr(0) * 7 + U_BOOT_SPL_DATA +
799f689890dSSimon Glass                         chr(0) * 2, data)
800680e3312SSimon Glass
801680e3312SSimon Glass    def testPackX86RomMeNoDesc(self):
802680e3312SSimon Glass        """Test that an invalid Intel descriptor entry is detected"""
803680e3312SSimon Glass        TestFunctional._MakeInputFile('descriptor.bin', '')
804680e3312SSimon Glass        with self.assertRaises(ValueError) as e:
805741f2d62SSimon Glass            self._DoTestFile('031_x86-rom-me.dts')
806680e3312SSimon Glass        self.assertIn("Node '/binman/intel-descriptor': Cannot find FD "
807680e3312SSimon Glass                      "signature", str(e.exception))
808680e3312SSimon Glass
809680e3312SSimon Glass    def testPackX86RomBadDesc(self):
810680e3312SSimon Glass        """Test that the Intel requires a descriptor entry"""
811680e3312SSimon Glass        with self.assertRaises(ValueError) as e:
812741f2d62SSimon Glass            self._DoTestFile('030_x86-rom-me-no-desc.dts')
8133ab9598dSSimon Glass        self.assertIn("Node '/binman/intel-me': No offset set with "
8143ab9598dSSimon Glass                      "offset-unset: should another entry provide this correct "
8153ab9598dSSimon Glass                      "offset?", str(e.exception))
816680e3312SSimon Glass
817680e3312SSimon Glass    def testPackX86RomMe(self):
818680e3312SSimon Glass        """Test that an x86 ROM with an ME region can be created"""
819741f2d62SSimon Glass        data = self._DoReadFile('031_x86-rom-me.dts')
820680e3312SSimon Glass        self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
821680e3312SSimon Glass
822680e3312SSimon Glass    def testPackVga(self):
823680e3312SSimon Glass        """Test that an image with a VGA binary can be created"""
824741f2d62SSimon Glass        data = self._DoReadFile('032_intel-vga.dts')
825680e3312SSimon Glass        self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
826680e3312SSimon Glass
827680e3312SSimon Glass    def testPackStart16(self):
828680e3312SSimon Glass        """Test that an image with an x86 start16 region can be created"""
829741f2d62SSimon Glass        data = self._DoReadFile('033_x86-start16.dts')
830680e3312SSimon Glass        self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
831680e3312SSimon Glass
8329d368f32SJagdish Gediya    def testPackPowerpcMpc85xxBootpgResetvec(self):
8339d368f32SJagdish Gediya        """Test that an image with powerpc-mpc85xx-bootpg-resetvec can be
8349d368f32SJagdish Gediya        created"""
8359d368f32SJagdish Gediya        data = self._DoReadFile('81_powerpc_mpc85xx_bootpg_resetvec.dts')
8369d368f32SJagdish Gediya        self.assertEqual(PPC_MPC85XX_BR_DATA, data[:len(PPC_MPC85XX_BR_DATA)])
8379d368f32SJagdish Gediya
838736bb0aeSSimon Glass    def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False):
839adc57011SSimon Glass        """Handle running a test for insertion of microcode
840adc57011SSimon Glass
841adc57011SSimon Glass        Args:
842adc57011SSimon Glass            dts_fname: Name of test .dts file
843adc57011SSimon Glass            nodtb_data: Data that we expect in the first section
844736bb0aeSSimon Glass            ucode_second: True if the microsecond entry is second instead of
845736bb0aeSSimon Glass                third
846adc57011SSimon Glass
847adc57011SSimon Glass        Returns:
848adc57011SSimon Glass            Tuple:
849adc57011SSimon Glass                Contents of first region (U-Boot or SPL)
8503ab9598dSSimon Glass                Offset and size components of microcode pointer, as inserted
851adc57011SSimon Glass                    in the above (two 4-byte words)
852adc57011SSimon Glass        """
8536b187df7SSimon Glass        data = self._DoReadFile(dts_fname, True)
854680e3312SSimon Glass
855680e3312SSimon Glass        # Now check the device tree has no microcode
856736bb0aeSSimon Glass        if ucode_second:
857736bb0aeSSimon Glass            ucode_content = data[len(nodtb_data):]
858736bb0aeSSimon Glass            ucode_pos = len(nodtb_data)
859736bb0aeSSimon Glass            dtb_with_ucode = ucode_content[16:]
860736bb0aeSSimon Glass            fdt_len = self.GetFdtLen(dtb_with_ucode)
861736bb0aeSSimon Glass        else:
862adc57011SSimon Glass            dtb_with_ucode = data[len(nodtb_data):]
863adc57011SSimon Glass            fdt_len = self.GetFdtLen(dtb_with_ucode)
864adc57011SSimon Glass            ucode_content = dtb_with_ucode[fdt_len:]
865adc57011SSimon Glass            ucode_pos = len(nodtb_data) + fdt_len
866680e3312SSimon Glass        fname = tools.GetOutputFilename('test.dtb')
867680e3312SSimon Glass        with open(fname, 'wb') as fd:
868adc57011SSimon Glass            fd.write(dtb_with_ucode)
869680e3312SSimon Glass        dtb = fdt.FdtScan(fname)
870680e3312SSimon Glass        ucode = dtb.GetNode('/microcode')
871680e3312SSimon Glass        self.assertTrue(ucode)
872680e3312SSimon Glass        for node in ucode.subnodes:
873680e3312SSimon Glass            self.assertFalse(node.props.get('data'))
874680e3312SSimon Glass
875680e3312SSimon Glass        # Check that the microcode appears immediately after the Fdt
876680e3312SSimon Glass        # This matches the concatenation of the data properties in
8778772213eSSimon Glass        # the /microcode/update@xxx nodes in 34_x86_ucode.dts.
878680e3312SSimon Glass        ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
879680e3312SSimon Glass                                 0x78235609)
880adc57011SSimon Glass        self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
881680e3312SSimon Glass
882680e3312SSimon Glass        # Check that the microcode pointer was inserted. It should match the
8833ab9598dSSimon Glass        # expected offset and size
884680e3312SSimon Glass        pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
885680e3312SSimon Glass                                   len(ucode_data))
886736bb0aeSSimon Glass        u_boot = data[:len(nodtb_data)]
887736bb0aeSSimon Glass        return u_boot, pos_and_size
8886b187df7SSimon Glass
8896b187df7SSimon Glass    def testPackUbootMicrocode(self):
8906b187df7SSimon Glass        """Test that x86 microcode can be handled correctly
8916b187df7SSimon Glass
8926b187df7SSimon Glass        We expect to see the following in the image, in order:
8936b187df7SSimon Glass            u-boot-nodtb.bin with a microcode pointer inserted at the correct
8946b187df7SSimon Glass                place
8956b187df7SSimon Glass            u-boot.dtb with the microcode removed
8966b187df7SSimon Glass            the microcode
8976b187df7SSimon Glass        """
898741f2d62SSimon Glass        first, pos_and_size = self._RunMicrocodeTest('034_x86_ucode.dts',
8996b187df7SSimon Glass                                                     U_BOOT_NODTB_DATA)
900680e3312SSimon Glass        self.assertEqual('nodtb with microcode' + pos_and_size +
901680e3312SSimon Glass                         ' somewhere in here', first)
902680e3312SSimon Glass
903680e3312SSimon Glass    def _RunPackUbootSingleMicrocode(self):
904680e3312SSimon Glass        """Test that x86 microcode can be handled correctly
905680e3312SSimon Glass
906680e3312SSimon Glass        We expect to see the following in the image, in order:
907680e3312SSimon Glass            u-boot-nodtb.bin with a microcode pointer inserted at the correct
908680e3312SSimon Glass                place
909680e3312SSimon Glass            u-boot.dtb with the microcode
910680e3312SSimon Glass            an empty microcode region
911680e3312SSimon Glass        """
912680e3312SSimon Glass        # We need the libfdt library to run this test since only that allows
913680e3312SSimon Glass        # finding the offset of a property. This is required by
914680e3312SSimon Glass        # Entry_u_boot_dtb_with_ucode.ObtainContents().
915741f2d62SSimon Glass        data = self._DoReadFile('035_x86_single_ucode.dts', True)
916680e3312SSimon Glass
917680e3312SSimon Glass        second = data[len(U_BOOT_NODTB_DATA):]
918680e3312SSimon Glass
919680e3312SSimon Glass        fdt_len = self.GetFdtLen(second)
920680e3312SSimon Glass        third = second[fdt_len:]
921680e3312SSimon Glass        second = second[:fdt_len]
922680e3312SSimon Glass
923680e3312SSimon Glass        ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
924680e3312SSimon Glass        self.assertIn(ucode_data, second)
925680e3312SSimon Glass        ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
926680e3312SSimon Glass
927680e3312SSimon Glass        # Check that the microcode pointer was inserted. It should match the
9283ab9598dSSimon Glass        # expected offset and size
929680e3312SSimon Glass        pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
930680e3312SSimon Glass                                   len(ucode_data))
931680e3312SSimon Glass        first = data[:len(U_BOOT_NODTB_DATA)]
932680e3312SSimon Glass        self.assertEqual('nodtb with microcode' + pos_and_size +
933680e3312SSimon Glass                         ' somewhere in here', first)
934680e3312SSimon Glass
935680e3312SSimon Glass    def testPackUbootSingleMicrocode(self):
936680e3312SSimon Glass        """Test that x86 microcode can be handled correctly with fdt_normal.
937680e3312SSimon Glass        """
938680e3312SSimon Glass        self._RunPackUbootSingleMicrocode()
939680e3312SSimon Glass
940680e3312SSimon Glass    def testUBootImg(self):
941680e3312SSimon Glass        """Test that u-boot.img can be put in a file"""
942741f2d62SSimon Glass        data = self._DoReadFile('036_u_boot_img.dts')
943680e3312SSimon Glass        self.assertEqual(U_BOOT_IMG_DATA, data)
944680e3312SSimon Glass
945680e3312SSimon Glass    def testNoMicrocode(self):
946680e3312SSimon Glass        """Test that a missing microcode region is detected"""
947680e3312SSimon Glass        with self.assertRaises(ValueError) as e:
948741f2d62SSimon Glass            self._DoReadFile('037_x86_no_ucode.dts', True)
949680e3312SSimon Glass        self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
950680e3312SSimon Glass                      "node found in ", str(e.exception))
951680e3312SSimon Glass
952680e3312SSimon Glass    def testMicrocodeWithoutNode(self):
953680e3312SSimon Glass        """Test that a missing u-boot-dtb-with-ucode node is detected"""
954680e3312SSimon Glass        with self.assertRaises(ValueError) as e:
955741f2d62SSimon Glass            self._DoReadFile('038_x86_ucode_missing_node.dts', True)
956680e3312SSimon Glass        self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
957680e3312SSimon Glass                "microcode region u-boot-dtb-with-ucode", str(e.exception))
958680e3312SSimon Glass
959680e3312SSimon Glass    def testMicrocodeWithoutNode2(self):
960680e3312SSimon Glass        """Test that a missing u-boot-ucode node is detected"""
961680e3312SSimon Glass        with self.assertRaises(ValueError) as e:
962741f2d62SSimon Glass            self._DoReadFile('039_x86_ucode_missing_node2.dts', True)
963680e3312SSimon Glass        self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
964680e3312SSimon Glass            "microcode region u-boot-ucode", str(e.exception))
965680e3312SSimon Glass
966680e3312SSimon Glass    def testMicrocodeWithoutPtrInElf(self):
967680e3312SSimon Glass        """Test that a U-Boot binary without the microcode symbol is detected"""
968680e3312SSimon Glass        # ELF file without a '_dt_ucode_base_size' symbol
969680e3312SSimon Glass        try:
970680e3312SSimon Glass            with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
971680e3312SSimon Glass                TestFunctional._MakeInputFile('u-boot', fd.read())
972680e3312SSimon Glass
973680e3312SSimon Glass            with self.assertRaises(ValueError) as e:
974680e3312SSimon Glass                self._RunPackUbootSingleMicrocode()
975680e3312SSimon Glass            self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
976680e3312SSimon Glass                    "_dt_ucode_base_size symbol in u-boot", str(e.exception))
977680e3312SSimon Glass
978680e3312SSimon Glass        finally:
979680e3312SSimon Glass            # Put the original file back
980680e3312SSimon Glass            with open(self.TestFile('u_boot_ucode_ptr')) as fd:
981680e3312SSimon Glass                TestFunctional._MakeInputFile('u-boot', fd.read())
982680e3312SSimon Glass
983680e3312SSimon Glass    def testMicrocodeNotInImage(self):
984680e3312SSimon Glass        """Test that microcode must be placed within the image"""
985680e3312SSimon Glass        with self.assertRaises(ValueError) as e:
986741f2d62SSimon Glass            self._DoReadFile('040_x86_ucode_not_in_image.dts', True)
987680e3312SSimon Glass        self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
988680e3312SSimon Glass                "pointer _dt_ucode_base_size at fffffe14 is outside the "
98925ac0e61SSimon Glass                "section ranging from 00000000 to 0000002e", str(e.exception))
990680e3312SSimon Glass
991680e3312SSimon Glass    def testWithoutMicrocode(self):
992680e3312SSimon Glass        """Test that we can cope with an image without microcode (e.g. qemu)"""
993680e3312SSimon Glass        with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
994680e3312SSimon Glass            TestFunctional._MakeInputFile('u-boot', fd.read())
995741f2d62SSimon Glass        data, dtb, _, _ = self._DoReadFileDtb('044_x86_optional_ucode.dts', True)
996680e3312SSimon Glass
997680e3312SSimon Glass        # Now check the device tree has no microcode
998680e3312SSimon Glass        self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
999680e3312SSimon Glass        second = data[len(U_BOOT_NODTB_DATA):]
1000680e3312SSimon Glass
1001680e3312SSimon Glass        fdt_len = self.GetFdtLen(second)
1002680e3312SSimon Glass        self.assertEqual(dtb, second[:fdt_len])
1003680e3312SSimon Glass
1004680e3312SSimon Glass        used_len = len(U_BOOT_NODTB_DATA) + fdt_len
1005680e3312SSimon Glass        third = data[used_len:]
1006680e3312SSimon Glass        self.assertEqual(chr(0) * (0x200 - used_len), third)
1007680e3312SSimon Glass
1008680e3312SSimon Glass    def testUnknownPosSize(self):
1009680e3312SSimon Glass        """Test that microcode must be placed within the image"""
1010680e3312SSimon Glass        with self.assertRaises(ValueError) as e:
1011741f2d62SSimon Glass            self._DoReadFile('041_unknown_pos_size.dts', True)
10123ab9598dSSimon Glass        self.assertIn("Section '/binman': Unable to set offset/size for unknown "
1013680e3312SSimon Glass                "entry 'invalid-entry'", str(e.exception))
1014680e3312SSimon Glass
1015680e3312SSimon Glass    def testPackFsp(self):
1016680e3312SSimon Glass        """Test that an image with a FSP binary can be created"""
1017741f2d62SSimon Glass        data = self._DoReadFile('042_intel-fsp.dts')
1018680e3312SSimon Glass        self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
1019680e3312SSimon Glass
1020680e3312SSimon Glass    def testPackCmc(self):
1021680e3312SSimon Glass        """Test that an image with a CMC binary can be created"""
1022741f2d62SSimon Glass        data = self._DoReadFile('043_intel-cmc.dts')
1023680e3312SSimon Glass        self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
1024680e3312SSimon Glass
1025680e3312SSimon Glass    def testPackVbt(self):
1026680e3312SSimon Glass        """Test that an image with a VBT binary can be created"""
1027741f2d62SSimon Glass        data = self._DoReadFile('046_intel-vbt.dts')
1028680e3312SSimon Glass        self.assertEqual(VBT_DATA, data[:len(VBT_DATA)])
10299fc60b49SSimon Glass
103056509843SSimon Glass    def testSplBssPad(self):
103156509843SSimon Glass        """Test that we can pad SPL's BSS with zeros"""
10326b187df7SSimon Glass        # ELF file with a '__bss_size' symbol
103311ae93eeSSimon Glass        self._SetupSplElf()
1034741f2d62SSimon Glass        data = self._DoReadFile('047_spl_bss_pad.dts')
103556509843SSimon Glass        self.assertEqual(U_BOOT_SPL_DATA + (chr(0) * 10) + U_BOOT_DATA, data)
103656509843SSimon Glass
103786af511dSSimon Glass    def testSplBssPadMissing(self):
103886af511dSSimon Glass        """Test that a missing symbol is detected"""
103911ae93eeSSimon Glass        self._SetupSplElf('u_boot_ucode_ptr')
1040b50e5611SSimon Glass        with self.assertRaises(ValueError) as e:
1041741f2d62SSimon Glass            self._DoReadFile('047_spl_bss_pad.dts')
1042b50e5611SSimon Glass        self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
1043b50e5611SSimon Glass                      str(e.exception))
1044b50e5611SSimon Glass
10458772213eSSimon Glass    def testPackStart16Spl(self):
104635b384cbSSimon Glass        """Test that an image with an x86 start16 SPL region can be created"""
1047741f2d62SSimon Glass        data = self._DoReadFile('048_x86-start16-spl.dts')
10488772213eSSimon Glass        self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)])
10498772213eSSimon Glass
1050736bb0aeSSimon Glass    def _PackUbootSplMicrocode(self, dts, ucode_second=False):
1051736bb0aeSSimon Glass        """Helper function for microcode tests
10526b187df7SSimon Glass
10536b187df7SSimon Glass        We expect to see the following in the image, in order:
10546b187df7SSimon Glass            u-boot-spl-nodtb.bin with a microcode pointer inserted at the
10556b187df7SSimon Glass                correct place
10566b187df7SSimon Glass            u-boot.dtb with the microcode removed
10576b187df7SSimon Glass            the microcode
1058736bb0aeSSimon Glass
1059736bb0aeSSimon Glass        Args:
1060736bb0aeSSimon Glass            dts: Device tree file to use for test
1061736bb0aeSSimon Glass            ucode_second: True if the microsecond entry is second instead of
1062736bb0aeSSimon Glass                third
10636b187df7SSimon Glass        """
106411ae93eeSSimon Glass        self._SetupSplElf('u_boot_ucode_ptr')
1065736bb0aeSSimon Glass        first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA,
1066736bb0aeSSimon Glass                                                     ucode_second=ucode_second)
10676b187df7SSimon Glass        self.assertEqual('splnodtb with microc' + pos_and_size +
10686b187df7SSimon Glass                         'ter somewhere in here', first)
10696b187df7SSimon Glass
1070736bb0aeSSimon Glass    def testPackUbootSplMicrocode(self):
1071736bb0aeSSimon Glass        """Test that x86 microcode can be handled correctly in SPL"""
1072741f2d62SSimon Glass        self._PackUbootSplMicrocode('049_x86_ucode_spl.dts')
1073736bb0aeSSimon Glass
1074736bb0aeSSimon Glass    def testPackUbootSplMicrocodeReorder(self):
1075736bb0aeSSimon Glass        """Test that order doesn't matter for microcode entries
1076736bb0aeSSimon Glass
1077736bb0aeSSimon Glass        This is the same as testPackUbootSplMicrocode but when we process the
1078736bb0aeSSimon Glass        u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode
1079736bb0aeSSimon Glass        entry, so we reply on binman to try later.
1080736bb0aeSSimon Glass        """
1081741f2d62SSimon Glass        self._PackUbootSplMicrocode('058_x86_ucode_spl_needs_retry.dts',
1082736bb0aeSSimon Glass                                    ucode_second=True)
1083736bb0aeSSimon Glass
1084ca4f4ff7SSimon Glass    def testPackMrc(self):
1085ca4f4ff7SSimon Glass        """Test that an image with an MRC binary can be created"""
1086741f2d62SSimon Glass        data = self._DoReadFile('050_intel_mrc.dts')
1087ca4f4ff7SSimon Glass        self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
1088ca4f4ff7SSimon Glass
108947419eaeSSimon Glass    def testSplDtb(self):
109047419eaeSSimon Glass        """Test that an image with spl/u-boot-spl.dtb can be created"""
1091741f2d62SSimon Glass        data = self._DoReadFile('051_u_boot_spl_dtb.dts')
109247419eaeSSimon Glass        self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
109347419eaeSSimon Glass
10944e6fdbefSSimon Glass    def testSplNoDtb(self):
10954e6fdbefSSimon Glass        """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
1096741f2d62SSimon Glass        data = self._DoReadFile('052_u_boot_spl_nodtb.dts')
10974e6fdbefSSimon Glass        self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
10984e6fdbefSSimon Glass
109919790632SSimon Glass    def testSymbols(self):
110019790632SSimon Glass        """Test binman can assign symbols embedded in U-Boot"""
110119790632SSimon Glass        elf_fname = self.TestFile('u_boot_binman_syms')
110219790632SSimon Glass        syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
110319790632SSimon Glass        addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
11043ab9598dSSimon Glass        self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
110519790632SSimon Glass
110611ae93eeSSimon Glass        self._SetupSplElf('u_boot_binman_syms')
1107741f2d62SSimon Glass        data = self._DoReadFile('053_symbols.dts')
110819790632SSimon Glass        sym_values = struct.pack('<LQL', 0x24 + 0, 0x24 + 24, 0x24 + 20)
110919790632SSimon Glass        expected = (sym_values + U_BOOT_SPL_DATA[16:] + chr(0xff) +
111019790632SSimon Glass                    U_BOOT_DATA +
111119790632SSimon Glass                    sym_values + U_BOOT_SPL_DATA[16:])
111219790632SSimon Glass        self.assertEqual(expected, data)
111319790632SSimon Glass
1114dd57c13bSSimon Glass    def testPackUnitAddress(self):
1115dd57c13bSSimon Glass        """Test that we support multiple binaries with the same name"""
1116741f2d62SSimon Glass        data = self._DoReadFile('054_unit_address.dts')
1117dd57c13bSSimon Glass        self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
1118dd57c13bSSimon Glass
11191854695bSSimon Glass    def testSections(self):
11201854695bSSimon Glass        """Basic test of sections"""
1121741f2d62SSimon Glass        data = self._DoReadFile('055_sections.dts')
11228122f396SSimon Glass        expected = (U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12 +
11238122f396SSimon Glass                    U_BOOT_DATA + '&' * 4)
11241854695bSSimon Glass        self.assertEqual(expected, data)
11259fc60b49SSimon Glass
11263b0c3821SSimon Glass    def testMap(self):
11273b0c3821SSimon Glass        """Tests outputting a map of the images"""
1128741f2d62SSimon Glass        _, _, map_data, _ = self._DoReadFileDtb('055_sections.dts', map=True)
11291be70d20SSimon Glass        self.assertEqual('''ImagePos    Offset      Size  Name
11301be70d20SSimon Glass00000000  00000000  00000028  main-section
11311be70d20SSimon Glass00000000   00000000  00000010  section@0
11321be70d20SSimon Glass00000000    00000000  00000004  u-boot
11331be70d20SSimon Glass00000010   00000010  00000010  section@1
11341be70d20SSimon Glass00000010    00000000  00000004  u-boot
11351be70d20SSimon Glass00000020   00000020  00000004  section@2
11361be70d20SSimon Glass00000020    00000000  00000004  u-boot
11373b0c3821SSimon Glass''', map_data)
11383b0c3821SSimon Glass
1139c8d48efbSSimon Glass    def testNamePrefix(self):
1140c8d48efbSSimon Glass        """Tests that name prefixes are used"""
1141741f2d62SSimon Glass        _, _, map_data, _ = self._DoReadFileDtb('056_name_prefix.dts', map=True)
11421be70d20SSimon Glass        self.assertEqual('''ImagePos    Offset      Size  Name
11431be70d20SSimon Glass00000000  00000000  00000028  main-section
11441be70d20SSimon Glass00000000   00000000  00000010  section@0
11451be70d20SSimon Glass00000000    00000000  00000004  ro-u-boot
11461be70d20SSimon Glass00000010   00000010  00000010  section@1
11471be70d20SSimon Glass00000010    00000000  00000004  rw-u-boot
1148c8d48efbSSimon Glass''', map_data)
1149c8d48efbSSimon Glass
1150736bb0aeSSimon Glass    def testUnknownContents(self):
1151736bb0aeSSimon Glass        """Test that obtaining the contents works as expected"""
1152736bb0aeSSimon Glass        with self.assertRaises(ValueError) as e:
1153741f2d62SSimon Glass            self._DoReadFile('057_unknown_contents.dts', True)
1154736bb0aeSSimon Glass        self.assertIn("Section '/binman': Internal error: Could not complete "
1155736bb0aeSSimon Glass                "processing of contents: remaining [<_testing.Entry__testing ",
1156736bb0aeSSimon Glass                str(e.exception))
1157736bb0aeSSimon Glass
11585c890238SSimon Glass    def testBadChangeSize(self):
11595c890238SSimon Glass        """Test that trying to change the size of an entry fails"""
11605c890238SSimon Glass        with self.assertRaises(ValueError) as e:
1161741f2d62SSimon Glass            self._DoReadFile('059_change_size.dts', True)
11625c890238SSimon Glass        self.assertIn("Node '/binman/_testing': Cannot update entry size from "
11635c890238SSimon Glass                      '2 to 1', str(e.exception))
11645c890238SSimon Glass
116516b8d6b7SSimon Glass    def testUpdateFdt(self):
11663ab9598dSSimon Glass        """Test that we can update the device tree with offset/size info"""
1167741f2d62SSimon Glass        _, _, _, out_dtb_fname = self._DoReadFileDtb('060_fdt_update.dts',
116816b8d6b7SSimon Glass                                                     update_dtb=True)
1169cee02e6fSSimon Glass        dtb = fdt.Fdt(out_dtb_fname)
1170cee02e6fSSimon Glass        dtb.Scan()
1171cee02e6fSSimon Glass        props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'])
117216b8d6b7SSimon Glass        self.assertEqual({
1173dbf6be9fSSimon Glass            'image-pos': 0,
11748122f396SSimon Glass            'offset': 0,
11753ab9598dSSimon Glass            '_testing:offset': 32,
117616b8d6b7SSimon Glass            '_testing:size': 1,
1177dbf6be9fSSimon Glass            '_testing:image-pos': 32,
11783ab9598dSSimon Glass            'section@0/u-boot:offset': 0,
117916b8d6b7SSimon Glass            'section@0/u-boot:size': len(U_BOOT_DATA),
1180dbf6be9fSSimon Glass            'section@0/u-boot:image-pos': 0,
11813ab9598dSSimon Glass            'section@0:offset': 0,
118216b8d6b7SSimon Glass            'section@0:size': 16,
1183dbf6be9fSSimon Glass            'section@0:image-pos': 0,
118416b8d6b7SSimon Glass
11853ab9598dSSimon Glass            'section@1/u-boot:offset': 0,
118616b8d6b7SSimon Glass            'section@1/u-boot:size': len(U_BOOT_DATA),
1187dbf6be9fSSimon Glass            'section@1/u-boot:image-pos': 16,
11883ab9598dSSimon Glass            'section@1:offset': 16,
118916b8d6b7SSimon Glass            'section@1:size': 16,
1190dbf6be9fSSimon Glass            'section@1:image-pos': 16,
119116b8d6b7SSimon Glass            'size': 40
119216b8d6b7SSimon Glass        }, props)
119316b8d6b7SSimon Glass
119416b8d6b7SSimon Glass    def testUpdateFdtBad(self):
119516b8d6b7SSimon Glass        """Test that we detect when ProcessFdt never completes"""
119616b8d6b7SSimon Glass        with self.assertRaises(ValueError) as e:
1197741f2d62SSimon Glass            self._DoReadFileDtb('061_fdt_update_bad.dts', update_dtb=True)
119816b8d6b7SSimon Glass        self.assertIn('Could not complete processing of Fdt: remaining '
119916b8d6b7SSimon Glass                      '[<_testing.Entry__testing', str(e.exception))
12005c890238SSimon Glass
120153af22a9SSimon Glass    def testEntryArgs(self):
120253af22a9SSimon Glass        """Test passing arguments to entries from the command line"""
120353af22a9SSimon Glass        entry_args = {
120453af22a9SSimon Glass            'test-str-arg': 'test1',
120553af22a9SSimon Glass            'test-int-arg': '456',
120653af22a9SSimon Glass        }
1207741f2d62SSimon Glass        self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
120853af22a9SSimon Glass        self.assertIn('image', control.images)
120953af22a9SSimon Glass        entry = control.images['image'].GetEntries()['_testing']
121053af22a9SSimon Glass        self.assertEqual('test0', entry.test_str_fdt)
121153af22a9SSimon Glass        self.assertEqual('test1', entry.test_str_arg)
121253af22a9SSimon Glass        self.assertEqual(123, entry.test_int_fdt)
121353af22a9SSimon Glass        self.assertEqual(456, entry.test_int_arg)
121453af22a9SSimon Glass
121553af22a9SSimon Glass    def testEntryArgsMissing(self):
121653af22a9SSimon Glass        """Test missing arguments and properties"""
121753af22a9SSimon Glass        entry_args = {
121853af22a9SSimon Glass            'test-int-arg': '456',
121953af22a9SSimon Glass        }
1220741f2d62SSimon Glass        self._DoReadFileDtb('063_entry_args_missing.dts', entry_args=entry_args)
122153af22a9SSimon Glass        entry = control.images['image'].GetEntries()['_testing']
122253af22a9SSimon Glass        self.assertEqual('test0', entry.test_str_fdt)
122353af22a9SSimon Glass        self.assertEqual(None, entry.test_str_arg)
122453af22a9SSimon Glass        self.assertEqual(None, entry.test_int_fdt)
122553af22a9SSimon Glass        self.assertEqual(456, entry.test_int_arg)
122653af22a9SSimon Glass
122753af22a9SSimon Glass    def testEntryArgsRequired(self):
122853af22a9SSimon Glass        """Test missing arguments and properties"""
122953af22a9SSimon Glass        entry_args = {
123053af22a9SSimon Glass            'test-int-arg': '456',
123153af22a9SSimon Glass        }
123253af22a9SSimon Glass        with self.assertRaises(ValueError) as e:
1233741f2d62SSimon Glass            self._DoReadFileDtb('064_entry_args_required.dts')
123453af22a9SSimon Glass        self.assertIn("Node '/binman/_testing': Missing required "
123553af22a9SSimon Glass            'properties/entry args: test-str-arg, test-int-fdt, test-int-arg',
123653af22a9SSimon Glass            str(e.exception))
123753af22a9SSimon Glass
123853af22a9SSimon Glass    def testEntryArgsInvalidFormat(self):
123953af22a9SSimon Glass        """Test that an invalid entry-argument format is detected"""
1240741f2d62SSimon Glass        args = ['-d', self.TestFile('064_entry_args_required.dts'), '-ano-value']
124153af22a9SSimon Glass        with self.assertRaises(ValueError) as e:
124253af22a9SSimon Glass            self._DoBinman(*args)
124353af22a9SSimon Glass        self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
124453af22a9SSimon Glass
124553af22a9SSimon Glass    def testEntryArgsInvalidInteger(self):
124653af22a9SSimon Glass        """Test that an invalid entry-argument integer is detected"""
124753af22a9SSimon Glass        entry_args = {
124853af22a9SSimon Glass            'test-int-arg': 'abc',
124953af22a9SSimon Glass        }
125053af22a9SSimon Glass        with self.assertRaises(ValueError) as e:
1251741f2d62SSimon Glass            self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
125253af22a9SSimon Glass        self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
125353af22a9SSimon Glass                      "'test-int-arg' (value 'abc') to integer",
125453af22a9SSimon Glass            str(e.exception))
125553af22a9SSimon Glass
125653af22a9SSimon Glass    def testEntryArgsInvalidDatatype(self):
125753af22a9SSimon Glass        """Test that an invalid entry-argument datatype is detected
125853af22a9SSimon Glass
125953af22a9SSimon Glass        This test could be written in entry_test.py except that it needs
126053af22a9SSimon Glass        access to control.entry_args, which seems more than that module should
126153af22a9SSimon Glass        be able to see.
126253af22a9SSimon Glass        """
126353af22a9SSimon Glass        entry_args = {
126453af22a9SSimon Glass            'test-bad-datatype-arg': '12',
126553af22a9SSimon Glass        }
126653af22a9SSimon Glass        with self.assertRaises(ValueError) as e:
1267741f2d62SSimon Glass            self._DoReadFileDtb('065_entry_args_unknown_datatype.dts',
126853af22a9SSimon Glass                                entry_args=entry_args)
126953af22a9SSimon Glass        self.assertIn('GetArg() internal error: Unknown data type ',
127053af22a9SSimon Glass                      str(e.exception))
127153af22a9SSimon Glass
1272bb74837cSSimon Glass    def testText(self):
1273bb74837cSSimon Glass        """Test for a text entry type"""
1274bb74837cSSimon Glass        entry_args = {
1275bb74837cSSimon Glass            'test-id': TEXT_DATA,
1276bb74837cSSimon Glass            'test-id2': TEXT_DATA2,
1277bb74837cSSimon Glass            'test-id3': TEXT_DATA3,
1278bb74837cSSimon Glass        }
1279741f2d62SSimon Glass        data, _, _, _ = self._DoReadFileDtb('066_text.dts',
1280bb74837cSSimon Glass                                            entry_args=entry_args)
1281bb74837cSSimon Glass        expected = (TEXT_DATA + chr(0) * (8 - len(TEXT_DATA)) + TEXT_DATA2 +
1282bb74837cSSimon Glass                    TEXT_DATA3 + 'some text')
1283bb74837cSSimon Glass        self.assertEqual(expected, data)
1284bb74837cSSimon Glass
1285fd8d1f79SSimon Glass    def testEntryDocs(self):
1286fd8d1f79SSimon Glass        """Test for creation of entry documentation"""
1287fd8d1f79SSimon Glass        with test_util.capture_sys_output() as (stdout, stderr):
1288fd8d1f79SSimon Glass            control.WriteEntryDocs(binman.GetEntryModules())
1289fd8d1f79SSimon Glass        self.assertTrue(len(stdout.getvalue()) > 0)
1290fd8d1f79SSimon Glass
1291fd8d1f79SSimon Glass    def testEntryDocsMissing(self):
1292fd8d1f79SSimon Glass        """Test handling of missing entry documentation"""
1293fd8d1f79SSimon Glass        with self.assertRaises(ValueError) as e:
1294fd8d1f79SSimon Glass            with test_util.capture_sys_output() as (stdout, stderr):
1295fd8d1f79SSimon Glass                control.WriteEntryDocs(binman.GetEntryModules(), 'u_boot')
1296fd8d1f79SSimon Glass        self.assertIn('Documentation is missing for modules: u_boot',
1297fd8d1f79SSimon Glass                      str(e.exception))
1298fd8d1f79SSimon Glass
129911e36cceSSimon Glass    def testFmap(self):
130011e36cceSSimon Glass        """Basic test of generation of a flashrom fmap"""
1301741f2d62SSimon Glass        data = self._DoReadFile('067_fmap.dts')
130211e36cceSSimon Glass        fhdr, fentries = fmap_util.DecodeFmap(data[32:])
130311e36cceSSimon Glass        expected = U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12
130411e36cceSSimon Glass        self.assertEqual(expected, data[:32])
130511e36cceSSimon Glass        self.assertEqual('__FMAP__', fhdr.signature)
130611e36cceSSimon Glass        self.assertEqual(1, fhdr.ver_major)
130711e36cceSSimon Glass        self.assertEqual(0, fhdr.ver_minor)
130811e36cceSSimon Glass        self.assertEqual(0, fhdr.base)
130911e36cceSSimon Glass        self.assertEqual(16 + 16 +
131011e36cceSSimon Glass                         fmap_util.FMAP_HEADER_LEN +
131111e36cceSSimon Glass                         fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
131211e36cceSSimon Glass        self.assertEqual('FMAP', fhdr.name)
131311e36cceSSimon Glass        self.assertEqual(3, fhdr.nareas)
131411e36cceSSimon Glass        for fentry in fentries:
131511e36cceSSimon Glass            self.assertEqual(0, fentry.flags)
131611e36cceSSimon Glass
131711e36cceSSimon Glass        self.assertEqual(0, fentries[0].offset)
131811e36cceSSimon Glass        self.assertEqual(4, fentries[0].size)
131911e36cceSSimon Glass        self.assertEqual('RO_U_BOOT', fentries[0].name)
132011e36cceSSimon Glass
132111e36cceSSimon Glass        self.assertEqual(16, fentries[1].offset)
132211e36cceSSimon Glass        self.assertEqual(4, fentries[1].size)
132311e36cceSSimon Glass        self.assertEqual('RW_U_BOOT', fentries[1].name)
132411e36cceSSimon Glass
132511e36cceSSimon Glass        self.assertEqual(32, fentries[2].offset)
132611e36cceSSimon Glass        self.assertEqual(fmap_util.FMAP_HEADER_LEN +
132711e36cceSSimon Glass                         fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
132811e36cceSSimon Glass        self.assertEqual('FMAP', fentries[2].name)
132911e36cceSSimon Glass
1330ec127af0SSimon Glass    def testBlobNamedByArg(self):
1331ec127af0SSimon Glass        """Test we can add a blob with the filename coming from an entry arg"""
1332ec127af0SSimon Glass        entry_args = {
1333ec127af0SSimon Glass            'cros-ec-rw-path': 'ecrw.bin',
1334ec127af0SSimon Glass        }
1335741f2d62SSimon Glass        data, _, _, _ = self._DoReadFileDtb('068_blob_named_by_arg.dts',
1336ec127af0SSimon Glass                                            entry_args=entry_args)
1337ec127af0SSimon Glass
13383af8e49cSSimon Glass    def testFill(self):
13393af8e49cSSimon Glass        """Test for an fill entry type"""
1340741f2d62SSimon Glass        data = self._DoReadFile('069_fill.dts')
13413af8e49cSSimon Glass        expected = 8 * chr(0xff) + 8 * chr(0)
13423af8e49cSSimon Glass        self.assertEqual(expected, data)
13433af8e49cSSimon Glass
13443af8e49cSSimon Glass    def testFillNoSize(self):
13453af8e49cSSimon Glass        """Test for an fill entry type with no size"""
13463af8e49cSSimon Glass        with self.assertRaises(ValueError) as e:
1347741f2d62SSimon Glass            self._DoReadFile('070_fill_no_size.dts')
13483af8e49cSSimon Glass        self.assertIn("'fill' entry must have a size property",
13493af8e49cSSimon Glass                      str(e.exception))
13503af8e49cSSimon Glass
13510ef87aa3SSimon Glass    def _HandleGbbCommand(self, pipe_list):
13520ef87aa3SSimon Glass        """Fake calls to the futility utility"""
13530ef87aa3SSimon Glass        if pipe_list[0][0] == 'futility':
13540ef87aa3SSimon Glass            fname = pipe_list[0][-1]
13550ef87aa3SSimon Glass            # Append our GBB data to the file, which will happen every time the
13560ef87aa3SSimon Glass            # futility command is called.
13570ef87aa3SSimon Glass            with open(fname, 'a') as fd:
13580ef87aa3SSimon Glass                fd.write(GBB_DATA)
13590ef87aa3SSimon Glass            return command.CommandResult()
13600ef87aa3SSimon Glass
13610ef87aa3SSimon Glass    def testGbb(self):
13620ef87aa3SSimon Glass        """Test for the Chromium OS Google Binary Block"""
13630ef87aa3SSimon Glass        command.test_result = self._HandleGbbCommand
13640ef87aa3SSimon Glass        entry_args = {
13650ef87aa3SSimon Glass            'keydir': 'devkeys',
13660ef87aa3SSimon Glass            'bmpblk': 'bmpblk.bin',
13670ef87aa3SSimon Glass        }
1368741f2d62SSimon Glass        data, _, _, _ = self._DoReadFileDtb('071_gbb.dts', entry_args=entry_args)
13690ef87aa3SSimon Glass
13700ef87aa3SSimon Glass        # Since futility
13710ef87aa3SSimon Glass        expected = GBB_DATA + GBB_DATA + 8 * chr(0) + (0x2180 - 16) * chr(0)
13720ef87aa3SSimon Glass        self.assertEqual(expected, data)
13730ef87aa3SSimon Glass
13740ef87aa3SSimon Glass    def testGbbTooSmall(self):
13750ef87aa3SSimon Glass        """Test for the Chromium OS Google Binary Block being large enough"""
13760ef87aa3SSimon Glass        with self.assertRaises(ValueError) as e:
1377741f2d62SSimon Glass            self._DoReadFileDtb('072_gbb_too_small.dts')
13780ef87aa3SSimon Glass        self.assertIn("Node '/binman/gbb': GBB is too small",
13790ef87aa3SSimon Glass                      str(e.exception))
13800ef87aa3SSimon Glass
13810ef87aa3SSimon Glass    def testGbbNoSize(self):
13820ef87aa3SSimon Glass        """Test for the Chromium OS Google Binary Block having a size"""
13830ef87aa3SSimon Glass        with self.assertRaises(ValueError) as e:
1384741f2d62SSimon Glass            self._DoReadFileDtb('073_gbb_no_size.dts')
13850ef87aa3SSimon Glass        self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
13860ef87aa3SSimon Glass                      str(e.exception))
13870ef87aa3SSimon Glass
138824d0d3c3SSimon Glass    def _HandleVblockCommand(self, pipe_list):
138924d0d3c3SSimon Glass        """Fake calls to the futility utility"""
139024d0d3c3SSimon Glass        if pipe_list[0][0] == 'futility':
139124d0d3c3SSimon Glass            fname = pipe_list[0][3]
1392a326b495SSimon Glass            with open(fname, 'wb') as fd:
139324d0d3c3SSimon Glass                fd.write(VBLOCK_DATA)
139424d0d3c3SSimon Glass            return command.CommandResult()
139524d0d3c3SSimon Glass
139624d0d3c3SSimon Glass    def testVblock(self):
139724d0d3c3SSimon Glass        """Test for the Chromium OS Verified Boot Block"""
139824d0d3c3SSimon Glass        command.test_result = self._HandleVblockCommand
139924d0d3c3SSimon Glass        entry_args = {
140024d0d3c3SSimon Glass            'keydir': 'devkeys',
140124d0d3c3SSimon Glass        }
1402741f2d62SSimon Glass        data, _, _, _ = self._DoReadFileDtb('074_vblock.dts',
140324d0d3c3SSimon Glass                                            entry_args=entry_args)
140424d0d3c3SSimon Glass        expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
140524d0d3c3SSimon Glass        self.assertEqual(expected, data)
140624d0d3c3SSimon Glass
140724d0d3c3SSimon Glass    def testVblockNoContent(self):
140824d0d3c3SSimon Glass        """Test we detect a vblock which has no content to sign"""
140924d0d3c3SSimon Glass        with self.assertRaises(ValueError) as e:
1410741f2d62SSimon Glass            self._DoReadFile('075_vblock_no_content.dts')
141124d0d3c3SSimon Glass        self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
141224d0d3c3SSimon Glass                      'property', str(e.exception))
141324d0d3c3SSimon Glass
141424d0d3c3SSimon Glass    def testVblockBadPhandle(self):
141524d0d3c3SSimon Glass        """Test that we detect a vblock with an invalid phandle in contents"""
141624d0d3c3SSimon Glass        with self.assertRaises(ValueError) as e:
1417741f2d62SSimon Glass            self._DoReadFile('076_vblock_bad_phandle.dts')
141824d0d3c3SSimon Glass        self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
141924d0d3c3SSimon Glass                      '1000', str(e.exception))
142024d0d3c3SSimon Glass
142124d0d3c3SSimon Glass    def testVblockBadEntry(self):
142224d0d3c3SSimon Glass        """Test that we detect an entry that points to a non-entry"""
142324d0d3c3SSimon Glass        with self.assertRaises(ValueError) as e:
1424741f2d62SSimon Glass            self._DoReadFile('077_vblock_bad_entry.dts')
142524d0d3c3SSimon Glass        self.assertIn("Node '/binman/vblock': Cannot find entry for node "
142624d0d3c3SSimon Glass                      "'other'", str(e.exception))
142724d0d3c3SSimon Glass
1428b8ef5b6bSSimon Glass    def testTpl(self):
1429b8ef5b6bSSimon Glass        """Test that an image with TPL and ots device tree can be created"""
1430b8ef5b6bSSimon Glass        # ELF file with a '__bss_size' symbol
1431b8ef5b6bSSimon Glass        with open(self.TestFile('bss_data')) as fd:
1432b8ef5b6bSSimon Glass            TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1433741f2d62SSimon Glass        data = self._DoReadFile('078_u_boot_tpl.dts')
1434b8ef5b6bSSimon Glass        self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
1435b8ef5b6bSSimon Glass
143615a587c9SSimon Glass    def testUsesPos(self):
143715a587c9SSimon Glass        """Test that the 'pos' property cannot be used anymore"""
143815a587c9SSimon Glass        with self.assertRaises(ValueError) as e:
1439741f2d62SSimon Glass           data = self._DoReadFile('079_uses_pos.dts')
144015a587c9SSimon Glass        self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
144115a587c9SSimon Glass                      "'pos'", str(e.exception))
144215a587c9SSimon Glass
1443d178eab8SSimon Glass    def testFillZero(self):
1444d178eab8SSimon Glass        """Test for an fill entry type with a size of 0"""
1445741f2d62SSimon Glass        data = self._DoReadFile('080_fill_empty.dts')
1446d178eab8SSimon Glass        self.assertEqual(chr(0) * 16, data)
1447d178eab8SSimon Glass
14480b489364SSimon Glass    def testTextMissing(self):
14490b489364SSimon Glass        """Test for a text entry type where there is no text"""
14500b489364SSimon Glass        with self.assertRaises(ValueError) as e:
1451741f2d62SSimon Glass            self._DoReadFileDtb('066_text.dts',)
14520b489364SSimon Glass        self.assertIn("Node '/binman/text': No value provided for text label "
14530b489364SSimon Glass                      "'test-id'", str(e.exception))
14540b489364SSimon Glass
145535b384cbSSimon Glass    def testPackStart16Tpl(self):
145635b384cbSSimon Glass        """Test that an image with an x86 start16 TPL region can be created"""
1457741f2d62SSimon Glass        data = self._DoReadFile('081_x86-start16-tpl.dts')
145835b384cbSSimon Glass        self.assertEqual(X86_START16_TPL_DATA, data[:len(X86_START16_TPL_DATA)])
145935b384cbSSimon Glass
14600bfa7b09SSimon Glass    def testSelectImage(self):
14610bfa7b09SSimon Glass        """Test that we can select which images to build"""
14620bfa7b09SSimon Glass        with test_util.capture_sys_output() as (stdout, stderr):
1463741f2d62SSimon Glass            retcode = self._DoTestFile('006_dual_image.dts', images=['image2'])
14640bfa7b09SSimon Glass        self.assertEqual(0, retcode)
14650bfa7b09SSimon Glass        self.assertIn('Skipping images: image1', stdout.getvalue())
14660bfa7b09SSimon Glass
14670bfa7b09SSimon Glass        self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
14680bfa7b09SSimon Glass        self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
14690bfa7b09SSimon Glass
14706ed45ba0SSimon Glass    def testUpdateFdtAll(self):
14716ed45ba0SSimon Glass        """Test that all device trees are updated with offset/size info"""
1472741f2d62SSimon Glass        data, _, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
14736ed45ba0SSimon Glass                                            use_real_dtb=True, update_dtb=True)
14746ed45ba0SSimon Glass
14756ed45ba0SSimon Glass        base_expected = {
14766ed45ba0SSimon Glass            'section:image-pos': 0,
14776ed45ba0SSimon Glass            'u-boot-tpl-dtb:size': 513,
14786ed45ba0SSimon Glass            'u-boot-spl-dtb:size': 513,
14796ed45ba0SSimon Glass            'u-boot-spl-dtb:offset': 493,
14806ed45ba0SSimon Glass            'image-pos': 0,
14816ed45ba0SSimon Glass            'section/u-boot-dtb:image-pos': 0,
14826ed45ba0SSimon Glass            'u-boot-spl-dtb:image-pos': 493,
14836ed45ba0SSimon Glass            'section/u-boot-dtb:size': 493,
14846ed45ba0SSimon Glass            'u-boot-tpl-dtb:image-pos': 1006,
14856ed45ba0SSimon Glass            'section/u-boot-dtb:offset': 0,
14866ed45ba0SSimon Glass            'section:size': 493,
14876ed45ba0SSimon Glass            'offset': 0,
14886ed45ba0SSimon Glass            'section:offset': 0,
14896ed45ba0SSimon Glass            'u-boot-tpl-dtb:offset': 1006,
14906ed45ba0SSimon Glass            'size': 1519
14916ed45ba0SSimon Glass        }
14926ed45ba0SSimon Glass
14936ed45ba0SSimon Glass        # We expect three device-tree files in the output, one after the other.
14946ed45ba0SSimon Glass        # Read them in sequence. We look for an 'spl' property in the SPL tree,
14956ed45ba0SSimon Glass        # and 'tpl' in the TPL tree, to make sure they are distinct from the
14966ed45ba0SSimon Glass        # main U-Boot tree. All three should have the same postions and offset.
14976ed45ba0SSimon Glass        start = 0
14986ed45ba0SSimon Glass        for item in ['', 'spl', 'tpl']:
14996ed45ba0SSimon Glass            dtb = fdt.Fdt.FromData(data[start:])
15006ed45ba0SSimon Glass            dtb.Scan()
15016ed45ba0SSimon Glass            props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos',
15026ed45ba0SSimon Glass                                            'spl', 'tpl'])
15036ed45ba0SSimon Glass            expected = dict(base_expected)
15046ed45ba0SSimon Glass            if item:
15056ed45ba0SSimon Glass                expected[item] = 0
15066ed45ba0SSimon Glass            self.assertEqual(expected, props)
15076ed45ba0SSimon Glass            start += dtb._fdt_obj.totalsize()
15086ed45ba0SSimon Glass
15096ed45ba0SSimon Glass    def testUpdateFdtOutput(self):
15106ed45ba0SSimon Glass        """Test that output DTB files are updated"""
15116ed45ba0SSimon Glass        try:
1512741f2d62SSimon Glass            data, dtb_data, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
15136ed45ba0SSimon Glass                    use_real_dtb=True, update_dtb=True, reset_dtbs=False)
15146ed45ba0SSimon Glass
15156ed45ba0SSimon Glass            # Unfortunately, compiling a source file always results in a file
15166ed45ba0SSimon Glass            # called source.dtb (see fdt_util.EnsureCompiled()). The test
1517741f2d62SSimon Glass            # source file (e.g. test/075_fdt_update_all.dts) thus does not enter
15186ed45ba0SSimon Glass            # binman as a file called u-boot.dtb. To fix this, copy the file
15196ed45ba0SSimon Glass            # over to the expected place.
15206ed45ba0SSimon Glass            #tools.WriteFile(os.path.join(self._indir, 'u-boot.dtb'),
15216ed45ba0SSimon Glass                    #tools.ReadFile(tools.GetOutputFilename('source.dtb')))
15226ed45ba0SSimon Glass            start = 0
15236ed45ba0SSimon Glass            for fname in ['u-boot.dtb.out', 'spl/u-boot-spl.dtb.out',
15246ed45ba0SSimon Glass                          'tpl/u-boot-tpl.dtb.out']:
15256ed45ba0SSimon Glass                dtb = fdt.Fdt.FromData(data[start:])
15266ed45ba0SSimon Glass                size = dtb._fdt_obj.totalsize()
15276ed45ba0SSimon Glass                pathname = tools.GetOutputFilename(os.path.split(fname)[1])
15286ed45ba0SSimon Glass                outdata = tools.ReadFile(pathname)
15296ed45ba0SSimon Glass                name = os.path.split(fname)[0]
15306ed45ba0SSimon Glass
15316ed45ba0SSimon Glass                if name:
15326ed45ba0SSimon Glass                    orig_indata = self._GetDtbContentsForSplTpl(dtb_data, name)
15336ed45ba0SSimon Glass                else:
15346ed45ba0SSimon Glass                    orig_indata = dtb_data
15356ed45ba0SSimon Glass                self.assertNotEqual(outdata, orig_indata,
15366ed45ba0SSimon Glass                        "Expected output file '%s' be updated" % pathname)
15376ed45ba0SSimon Glass                self.assertEqual(outdata, data[start:start + size],
15386ed45ba0SSimon Glass                        "Expected output file '%s' to match output image" %
15396ed45ba0SSimon Glass                        pathname)
15406ed45ba0SSimon Glass                start += size
15416ed45ba0SSimon Glass        finally:
15426ed45ba0SSimon Glass            self._ResetDtbs()
15436ed45ba0SSimon Glass
154483d73c2fSSimon Glass    def _decompress(self, data):
154583d73c2fSSimon Glass        out = os.path.join(self._indir, 'lz4.tmp')
154683d73c2fSSimon Glass        with open(out, 'wb') as fd:
154783d73c2fSSimon Glass            fd.write(data)
154883d73c2fSSimon Glass        return tools.Run('lz4', '-dc', out)
154983d73c2fSSimon Glass        '''
155083d73c2fSSimon Glass        try:
155183d73c2fSSimon Glass            orig = lz4.frame.decompress(data)
155283d73c2fSSimon Glass        except AttributeError:
155383d73c2fSSimon Glass            orig = lz4.decompress(data)
155483d73c2fSSimon Glass        '''
155583d73c2fSSimon Glass
155683d73c2fSSimon Glass    def testCompress(self):
155783d73c2fSSimon Glass        """Test compression of blobs"""
1558741f2d62SSimon Glass        data, _, _, out_dtb_fname = self._DoReadFileDtb('083_compress.dts',
155983d73c2fSSimon Glass                                            use_real_dtb=True, update_dtb=True)
156083d73c2fSSimon Glass        dtb = fdt.Fdt(out_dtb_fname)
156183d73c2fSSimon Glass        dtb.Scan()
156283d73c2fSSimon Glass        props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
156383d73c2fSSimon Glass        orig = self._decompress(data)
156483d73c2fSSimon Glass        self.assertEquals(COMPRESS_DATA, orig)
156583d73c2fSSimon Glass        expected = {
156683d73c2fSSimon Glass            'blob:uncomp-size': len(COMPRESS_DATA),
156783d73c2fSSimon Glass            'blob:size': len(data),
156883d73c2fSSimon Glass            'size': len(data),
156983d73c2fSSimon Glass            }
157083d73c2fSSimon Glass        self.assertEqual(expected, props)
157183d73c2fSSimon Glass
15720a98b28bSSimon Glass    def testFiles(self):
15730a98b28bSSimon Glass        """Test bringing in multiple files"""
1574741f2d62SSimon Glass        data = self._DoReadFile('084_files.dts')
15750a98b28bSSimon Glass        self.assertEqual(FILES_DATA, data)
15760a98b28bSSimon Glass
15770a98b28bSSimon Glass    def testFilesCompress(self):
15780a98b28bSSimon Glass        """Test bringing in multiple files and compressing them"""
1579741f2d62SSimon Glass        data = self._DoReadFile('085_files_compress.dts')
15800a98b28bSSimon Glass
15810a98b28bSSimon Glass        image = control.images['image']
15820a98b28bSSimon Glass        entries = image.GetEntries()
15830a98b28bSSimon Glass        files = entries['files']
15840a98b28bSSimon Glass        entries = files._section._entries
15850a98b28bSSimon Glass
15860a98b28bSSimon Glass        orig = ''
15870a98b28bSSimon Glass        for i in range(1, 3):
15880a98b28bSSimon Glass            key = '%d.dat' % i
15890a98b28bSSimon Glass            start = entries[key].image_pos
15900a98b28bSSimon Glass            len = entries[key].size
15910a98b28bSSimon Glass            chunk = data[start:start + len]
15920a98b28bSSimon Glass            orig += self._decompress(chunk)
15930a98b28bSSimon Glass
15940a98b28bSSimon Glass        self.assertEqual(FILES_DATA, orig)
15950a98b28bSSimon Glass
15960a98b28bSSimon Glass    def testFilesMissing(self):
15970a98b28bSSimon Glass        """Test missing files"""
15980a98b28bSSimon Glass        with self.assertRaises(ValueError) as e:
1599741f2d62SSimon Glass            data = self._DoReadFile('086_files_none.dts')
16000a98b28bSSimon Glass        self.assertIn("Node '/binman/files': Pattern \'files/*.none\' matched "
16010a98b28bSSimon Glass                      'no files', str(e.exception))
16020a98b28bSSimon Glass
16030a98b28bSSimon Glass    def testFilesNoPattern(self):
16040a98b28bSSimon Glass        """Test missing files"""
16050a98b28bSSimon Glass        with self.assertRaises(ValueError) as e:
1606741f2d62SSimon Glass            data = self._DoReadFile('087_files_no_pattern.dts')
16070a98b28bSSimon Glass        self.assertIn("Node '/binman/files': Missing 'pattern' property",
16080a98b28bSSimon Glass                      str(e.exception))
16090a98b28bSSimon Glass
1610ba64a0bbSSimon Glass    def testExpandSize(self):
1611ba64a0bbSSimon Glass        """Test an expanding entry"""
1612741f2d62SSimon Glass        data, _, map_data, _ = self._DoReadFileDtb('088_expand_size.dts',
1613ba64a0bbSSimon Glass                                                   map=True)
1614ba64a0bbSSimon Glass        expect = ('a' * 8 + U_BOOT_DATA +
1615ba64a0bbSSimon Glass                  MRC_DATA + 'b' * 1 + U_BOOT_DATA +
1616ba64a0bbSSimon Glass                  'c' * 8 + U_BOOT_DATA +
1617ba64a0bbSSimon Glass                  'd' * 8)
1618ba64a0bbSSimon Glass        self.assertEqual(expect, data)
1619ba64a0bbSSimon Glass        self.assertEqual('''ImagePos    Offset      Size  Name
1620ba64a0bbSSimon Glass00000000  00000000  00000028  main-section
1621ba64a0bbSSimon Glass00000000   00000000  00000008  fill
1622ba64a0bbSSimon Glass00000008   00000008  00000004  u-boot
1623ba64a0bbSSimon Glass0000000c   0000000c  00000004  section
1624ba64a0bbSSimon Glass0000000c    00000000  00000003  intel-mrc
1625ba64a0bbSSimon Glass00000010   00000010  00000004  u-boot2
1626ba64a0bbSSimon Glass00000014   00000014  0000000c  section2
1627ba64a0bbSSimon Glass00000014    00000000  00000008  fill
1628ba64a0bbSSimon Glass0000001c    00000008  00000004  u-boot
1629ba64a0bbSSimon Glass00000020   00000020  00000008  fill2
1630ba64a0bbSSimon Glass''', map_data)
1631ba64a0bbSSimon Glass
1632ba64a0bbSSimon Glass    def testExpandSizeBad(self):
1633ba64a0bbSSimon Glass        """Test an expanding entry which fails to provide contents"""
1634163ed6c3SSimon Glass        with test_util.capture_sys_output() as (stdout, stderr):
1635ba64a0bbSSimon Glass            with self.assertRaises(ValueError) as e:
1636741f2d62SSimon Glass                self._DoReadFileDtb('089_expand_size_bad.dts', map=True)
1637ba64a0bbSSimon Glass        self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
1638ba64a0bbSSimon Glass                      'expanding entry', str(e.exception))
1639ba64a0bbSSimon Glass
1640e0e5df93SSimon Glass    def testHash(self):
1641e0e5df93SSimon Glass        """Test hashing of the contents of an entry"""
1642741f2d62SSimon Glass        _, _, _, out_dtb_fname = self._DoReadFileDtb('090_hash.dts',
1643e0e5df93SSimon Glass                use_real_dtb=True, update_dtb=True)
1644e0e5df93SSimon Glass        dtb = fdt.Fdt(out_dtb_fname)
1645e0e5df93SSimon Glass        dtb.Scan()
1646e0e5df93SSimon Glass        hash_node = dtb.GetNode('/binman/u-boot/hash').props['value']
1647e0e5df93SSimon Glass        m = hashlib.sha256()
1648e0e5df93SSimon Glass        m.update(U_BOOT_DATA)
1649e0e5df93SSimon Glass        self.assertEqual(m.digest(), ''.join(hash_node.value))
1650e0e5df93SSimon Glass
1651e0e5df93SSimon Glass    def testHashNoAlgo(self):
1652e0e5df93SSimon Glass        with self.assertRaises(ValueError) as e:
1653741f2d62SSimon Glass            self._DoReadFileDtb('091_hash_no_algo.dts', update_dtb=True)
1654e0e5df93SSimon Glass        self.assertIn("Node \'/binman/u-boot\': Missing \'algo\' property for "
1655e0e5df93SSimon Glass                      'hash node', str(e.exception))
1656e0e5df93SSimon Glass
1657e0e5df93SSimon Glass    def testHashBadAlgo(self):
1658e0e5df93SSimon Glass        with self.assertRaises(ValueError) as e:
1659741f2d62SSimon Glass            self._DoReadFileDtb('092_hash_bad_algo.dts', update_dtb=True)
1660e0e5df93SSimon Glass        self.assertIn("Node '/binman/u-boot': Unknown hash algorithm",
1661e0e5df93SSimon Glass                      str(e.exception))
1662e0e5df93SSimon Glass
1663e0e5df93SSimon Glass    def testHashSection(self):
1664e0e5df93SSimon Glass        """Test hashing of the contents of an entry"""
1665741f2d62SSimon Glass        _, _, _, out_dtb_fname = self._DoReadFileDtb('099_hash_section.dts',
1666e0e5df93SSimon Glass                use_real_dtb=True, update_dtb=True)
1667e0e5df93SSimon Glass        dtb = fdt.Fdt(out_dtb_fname)
1668e0e5df93SSimon Glass        dtb.Scan()
1669e0e5df93SSimon Glass        hash_node = dtb.GetNode('/binman/section/hash').props['value']
1670e0e5df93SSimon Glass        m = hashlib.sha256()
1671e0e5df93SSimon Glass        m.update(U_BOOT_DATA)
1672e0e5df93SSimon Glass        m.update(16 * 'a')
1673e0e5df93SSimon Glass        self.assertEqual(m.digest(), ''.join(hash_node.value))
1674e0e5df93SSimon Glass
1675f0253635SSimon Glass    def testPackUBootTplMicrocode(self):
1676f0253635SSimon Glass        """Test that x86 microcode can be handled correctly in TPL
1677f0253635SSimon Glass
1678f0253635SSimon Glass        We expect to see the following in the image, in order:
1679f0253635SSimon Glass            u-boot-tpl-nodtb.bin with a microcode pointer inserted at the correct
1680f0253635SSimon Glass                place
1681f0253635SSimon Glass            u-boot-tpl.dtb with the microcode removed
1682f0253635SSimon Glass            the microcode
1683f0253635SSimon Glass        """
1684f0253635SSimon Glass        with open(self.TestFile('u_boot_ucode_ptr')) as fd:
1685f0253635SSimon Glass            TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1686741f2d62SSimon Glass        first, pos_and_size = self._RunMicrocodeTest('093_x86_tpl_ucode.dts',
1687f0253635SSimon Glass                                                     U_BOOT_TPL_NODTB_DATA)
1688f0253635SSimon Glass        self.assertEqual('tplnodtb with microc' + pos_and_size +
1689f0253635SSimon Glass                         'ter somewhere in here', first)
1690f0253635SSimon Glass
1691f8f8df6eSSimon Glass    def testFmapX86(self):
1692f8f8df6eSSimon Glass        """Basic test of generation of a flashrom fmap"""
1693741f2d62SSimon Glass        data = self._DoReadFile('094_fmap_x86.dts')
1694f8f8df6eSSimon Glass        fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1695f8f8df6eSSimon Glass        expected = U_BOOT_DATA + MRC_DATA + 'a' * (32 - 7)
1696f8f8df6eSSimon Glass        self.assertEqual(expected, data[:32])
1697f8f8df6eSSimon Glass        fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1698f8f8df6eSSimon Glass
1699f8f8df6eSSimon Glass        self.assertEqual(0x100, fhdr.image_size)
1700f8f8df6eSSimon Glass
1701f8f8df6eSSimon Glass        self.assertEqual(0, fentries[0].offset)
1702f8f8df6eSSimon Glass        self.assertEqual(4, fentries[0].size)
1703f8f8df6eSSimon Glass        self.assertEqual('U_BOOT', fentries[0].name)
1704f8f8df6eSSimon Glass
1705f8f8df6eSSimon Glass        self.assertEqual(4, fentries[1].offset)
1706f8f8df6eSSimon Glass        self.assertEqual(3, fentries[1].size)
1707f8f8df6eSSimon Glass        self.assertEqual('INTEL_MRC', fentries[1].name)
1708f8f8df6eSSimon Glass
1709f8f8df6eSSimon Glass        self.assertEqual(32, fentries[2].offset)
1710f8f8df6eSSimon Glass        self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1711f8f8df6eSSimon Glass                         fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1712f8f8df6eSSimon Glass        self.assertEqual('FMAP', fentries[2].name)
1713f8f8df6eSSimon Glass
1714f8f8df6eSSimon Glass    def testFmapX86Section(self):
1715f8f8df6eSSimon Glass        """Basic test of generation of a flashrom fmap"""
1716741f2d62SSimon Glass        data = self._DoReadFile('095_fmap_x86_section.dts')
1717f8f8df6eSSimon Glass        expected = U_BOOT_DATA + MRC_DATA + 'b' * (32 - 7)
1718f8f8df6eSSimon Glass        self.assertEqual(expected, data[:32])
1719f8f8df6eSSimon Glass        fhdr, fentries = fmap_util.DecodeFmap(data[36:])
1720f8f8df6eSSimon Glass
1721f8f8df6eSSimon Glass        self.assertEqual(0x100, fhdr.image_size)
1722f8f8df6eSSimon Glass
1723f8f8df6eSSimon Glass        self.assertEqual(0, fentries[0].offset)
1724f8f8df6eSSimon Glass        self.assertEqual(4, fentries[0].size)
1725f8f8df6eSSimon Glass        self.assertEqual('U_BOOT', fentries[0].name)
1726f8f8df6eSSimon Glass
1727f8f8df6eSSimon Glass        self.assertEqual(4, fentries[1].offset)
1728f8f8df6eSSimon Glass        self.assertEqual(3, fentries[1].size)
1729f8f8df6eSSimon Glass        self.assertEqual('INTEL_MRC', fentries[1].name)
1730f8f8df6eSSimon Glass
1731f8f8df6eSSimon Glass        self.assertEqual(36, fentries[2].offset)
1732f8f8df6eSSimon Glass        self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1733f8f8df6eSSimon Glass                         fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1734f8f8df6eSSimon Glass        self.assertEqual('FMAP', fentries[2].name)
1735f8f8df6eSSimon Glass
1736fe1ae3ecSSimon Glass    def testElf(self):
1737fe1ae3ecSSimon Glass        """Basic test of ELF entries"""
173811ae93eeSSimon Glass        self._SetupSplElf()
1739fe1ae3ecSSimon Glass        with open(self.TestFile('bss_data')) as fd:
1740fe1ae3ecSSimon Glass            TestFunctional._MakeInputFile('-boot', fd.read())
1741741f2d62SSimon Glass        data = self._DoReadFile('096_elf.dts')
1742fe1ae3ecSSimon Glass
1743fe1ae3ecSSimon Glass    def testElfStripg(self):
1744fe1ae3ecSSimon Glass        """Basic test of ELF entries"""
174511ae93eeSSimon Glass        self._SetupSplElf()
1746fe1ae3ecSSimon Glass        with open(self.TestFile('bss_data')) as fd:
1747fe1ae3ecSSimon Glass            TestFunctional._MakeInputFile('-boot', fd.read())
1748741f2d62SSimon Glass        data = self._DoReadFile('097_elf_strip.dts')
1749fe1ae3ecSSimon Glass
1750163ed6c3SSimon Glass    def testPackOverlapMap(self):
1751163ed6c3SSimon Glass        """Test that overlapping regions are detected"""
1752163ed6c3SSimon Glass        with test_util.capture_sys_output() as (stdout, stderr):
1753163ed6c3SSimon Glass            with self.assertRaises(ValueError) as e:
1754741f2d62SSimon Glass                self._DoTestFile('014_pack_overlap.dts', map=True)
1755163ed6c3SSimon Glass        map_fname = tools.GetOutputFilename('image.map')
1756163ed6c3SSimon Glass        self.assertEqual("Wrote map file '%s' to show errors\n" % map_fname,
1757163ed6c3SSimon Glass                         stdout.getvalue())
1758163ed6c3SSimon Glass
1759163ed6c3SSimon Glass        # We should not get an inmage, but there should be a map file
1760163ed6c3SSimon Glass        self.assertFalse(os.path.exists(tools.GetOutputFilename('image.bin')))
1761163ed6c3SSimon Glass        self.assertTrue(os.path.exists(map_fname))
1762163ed6c3SSimon Glass        map_data = tools.ReadFile(map_fname)
1763163ed6c3SSimon Glass        self.assertEqual('''ImagePos    Offset      Size  Name
1764163ed6c3SSimon Glass<none>    00000000  00000007  main-section
1765163ed6c3SSimon Glass<none>     00000000  00000004  u-boot
1766163ed6c3SSimon Glass<none>     00000003  00000004  u-boot-align
1767163ed6c3SSimon Glass''', map_data)
1768163ed6c3SSimon Glass
1769*3ae192c2SSimon Glass    def testPacRefCode(self):
1770*3ae192c2SSimon Glass        """Test that an image with an Intel Reference code binary works"""
1771*3ae192c2SSimon Glass        data = self._DoReadFile('100_intel_refcode.dts')
1772*3ae192c2SSimon Glass        self.assertEqual(REFCODE_DATA, data[:len(REFCODE_DATA)])
1773*3ae192c2SSimon Glass
177453af22a9SSimon Glass
17759fc60b49SSimon Glassif __name__ == "__main__":
17769fc60b49SSimon Glass    unittest.main()
1777