xref: /rk3399_rockchip-uboot/tools/binman/func_test.py (revision dd31be21bf8117df054f9ad072784bfc4df9e76f)
14f44304bSSimon Glass#
24f44304bSSimon Glass# Copyright (c) 2016 Google, Inc
34f44304bSSimon Glass# Written by Simon Glass <sjg@chromium.org>
44f44304bSSimon Glass#
54f44304bSSimon Glass# SPDX-License-Identifier:      GPL-2.0+
64f44304bSSimon Glass#
74f44304bSSimon Glass# To run a single test, change to this directory, and:
84f44304bSSimon Glass#
94f44304bSSimon Glass#    python -m unittest func_test.TestFunctional.testHelp
104f44304bSSimon Glass
114f44304bSSimon Glassfrom optparse import OptionParser
124f44304bSSimon Glassimport os
134f44304bSSimon Glassimport shutil
144f44304bSSimon Glassimport struct
154f44304bSSimon Glassimport sys
164f44304bSSimon Glassimport tempfile
174f44304bSSimon Glassimport unittest
184f44304bSSimon Glass
194f44304bSSimon Glassimport binman
204f44304bSSimon Glassimport cmdline
214f44304bSSimon Glassimport command
224f44304bSSimon Glassimport control
234f44304bSSimon Glassimport entry
24*99ed4a2eSSimon Glassimport fdt
254f44304bSSimon Glassimport fdt_util
264f44304bSSimon Glassimport tools
274f44304bSSimon Glassimport tout
284f44304bSSimon Glass
294f44304bSSimon Glass# Contents of test files, corresponding to different entry types
304f44304bSSimon GlassU_BOOT_DATA         = '1234'
314f44304bSSimon GlassU_BOOT_IMG_DATA     = 'img'
324f44304bSSimon GlassU_BOOT_SPL_DATA     = '567'
334f44304bSSimon GlassBLOB_DATA           = '89'
344f44304bSSimon GlassME_DATA             = '0abcd'
354f44304bSSimon GlassVGA_DATA            = 'vga'
364f44304bSSimon GlassU_BOOT_DTB_DATA     = 'udtb'
374f44304bSSimon GlassX86_START16_DATA    = 'start16'
384f44304bSSimon GlassU_BOOT_NODTB_DATA   = 'nodtb with microcode pointer somewhere in here'
39da229090SSimon GlassFSP_DATA            = 'fsp'
40da229090SSimon GlassCMC_DATA            = 'cmc'
414f44304bSSimon Glass
424f44304bSSimon Glassclass TestFunctional(unittest.TestCase):
434f44304bSSimon Glass    """Functional tests for binman
444f44304bSSimon Glass
454f44304bSSimon Glass    Most of these use a sample .dts file to build an image and then check
464f44304bSSimon Glass    that it looks correct. The sample files are in the test/ subdirectory
474f44304bSSimon Glass    and are numbered.
484f44304bSSimon Glass
494f44304bSSimon Glass    For each entry type a very small test file is created using fixed
504f44304bSSimon Glass    string contents. This makes it easy to test that things look right, and
514f44304bSSimon Glass    debug problems.
524f44304bSSimon Glass
534f44304bSSimon Glass    In some cases a 'real' file must be used - these are also supplied in
544f44304bSSimon Glass    the test/ diurectory.
554f44304bSSimon Glass    """
564f44304bSSimon Glass    @classmethod
574f44304bSSimon Glass    def setUpClass(self):
584f44304bSSimon Glass        # Handle the case where argv[0] is 'python'
594f44304bSSimon Glass        self._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
604f44304bSSimon Glass        self._binman_pathname = os.path.join(self._binman_dir, 'binman')
614f44304bSSimon Glass
624f44304bSSimon Glass        # Create a temporary directory for input files
634f44304bSSimon Glass        self._indir = tempfile.mkdtemp(prefix='binmant.')
644f44304bSSimon Glass
654f44304bSSimon Glass        # Create some test files
664f44304bSSimon Glass        TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
674f44304bSSimon Glass        TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
684f44304bSSimon Glass        TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
694f44304bSSimon Glass        TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
70e0ff8551SSimon Glass        TestFunctional._MakeInputFile('me.bin', ME_DATA)
71e0ff8551SSimon Glass        TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
724f44304bSSimon Glass        TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
73e0ff8551SSimon Glass        TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
744f44304bSSimon Glass        TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
75da229090SSimon Glass        TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
76da229090SSimon Glass        TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
774f44304bSSimon Glass        self._output_setup = False
784f44304bSSimon Glass
79e0ff8551SSimon Glass        # ELF file with a '_dt_ucode_base_size' symbol
80e0ff8551SSimon Glass        with open(self.TestFile('u_boot_ucode_ptr')) as fd:
81e0ff8551SSimon Glass            TestFunctional._MakeInputFile('u-boot', fd.read())
82e0ff8551SSimon Glass
83e0ff8551SSimon Glass        # Intel flash descriptor file
84e0ff8551SSimon Glass        with open(self.TestFile('descriptor.bin')) as fd:
85e0ff8551SSimon Glass            TestFunctional._MakeInputFile('descriptor.bin', fd.read())
86e0ff8551SSimon Glass
874f44304bSSimon Glass    @classmethod
884f44304bSSimon Glass    def tearDownClass(self):
894f44304bSSimon Glass        """Remove the temporary input directory and its contents"""
904f44304bSSimon Glass        if self._indir:
914f44304bSSimon Glass            shutil.rmtree(self._indir)
924f44304bSSimon Glass        self._indir = None
934f44304bSSimon Glass
944f44304bSSimon Glass    def setUp(self):
954f44304bSSimon Glass        # Enable this to turn on debugging output
964f44304bSSimon Glass        # tout.Init(tout.DEBUG)
974f44304bSSimon Glass        command.test_result = None
984f44304bSSimon Glass
994f44304bSSimon Glass    def tearDown(self):
1004f44304bSSimon Glass        """Remove the temporary output directory"""
1014f44304bSSimon Glass        tools._FinaliseForTest()
1024f44304bSSimon Glass
1034f44304bSSimon Glass    def _RunBinman(self, *args, **kwargs):
1044f44304bSSimon Glass        """Run binman using the command line
1054f44304bSSimon Glass
1064f44304bSSimon Glass        Args:
1074f44304bSSimon Glass            Arguments to pass, as a list of strings
1084f44304bSSimon Glass            kwargs: Arguments to pass to Command.RunPipe()
1094f44304bSSimon Glass        """
1104f44304bSSimon Glass        result = command.RunPipe([[self._binman_pathname] + list(args)],
1114f44304bSSimon Glass                capture=True, capture_stderr=True, raise_on_error=False)
1124f44304bSSimon Glass        if result.return_code and kwargs.get('raise_on_error', True):
1134f44304bSSimon Glass            raise Exception("Error running '%s': %s" % (' '.join(args),
1144f44304bSSimon Glass                            result.stdout + result.stderr))
1154f44304bSSimon Glass        return result
1164f44304bSSimon Glass
1174f44304bSSimon Glass    def _DoBinman(self, *args):
1184f44304bSSimon Glass        """Run binman using directly (in the same process)
1194f44304bSSimon Glass
1204f44304bSSimon Glass        Args:
1214f44304bSSimon Glass            Arguments to pass, as a list of strings
1224f44304bSSimon Glass        Returns:
1234f44304bSSimon Glass            Return value (0 for success)
1244f44304bSSimon Glass        """
1254f44304bSSimon Glass        (options, args) = cmdline.ParseArgs(list(args))
1264f44304bSSimon Glass        options.pager = 'binman-invalid-pager'
1274f44304bSSimon Glass        options.build_dir = self._indir
1284f44304bSSimon Glass
1294f44304bSSimon Glass        # For testing, you can force an increase in verbosity here
1304f44304bSSimon Glass        # options.verbosity = tout.DEBUG
1314f44304bSSimon Glass        return control.Binman(options, args)
1324f44304bSSimon Glass
1334f44304bSSimon Glass    def _DoTestFile(self, fname):
1344f44304bSSimon Glass        """Run binman with a given test file
1354f44304bSSimon Glass
1364f44304bSSimon Glass        Args:
1374f44304bSSimon Glass            fname: Device tree source filename to use (e.g. 05_simple.dts)
1384f44304bSSimon Glass        """
1394f44304bSSimon Glass        return self._DoBinman('-p', '-I', self._indir,
1404f44304bSSimon Glass                              '-d', self.TestFile(fname))
1414f44304bSSimon Glass
1424f44304bSSimon Glass    def _SetupDtb(self, fname, outfile='u-boot.dtb'):
143e0ff8551SSimon Glass        """Set up a new test device-tree file
144e0ff8551SSimon Glass
145e0ff8551SSimon Glass        The given file is compiled and set up as the device tree to be used
146e0ff8551SSimon Glass        for ths test.
147e0ff8551SSimon Glass
148e0ff8551SSimon Glass        Args:
149e0ff8551SSimon Glass            fname: Filename of .dts file to read
150e0ff8551SSimon Glass            outfile: Output filename for compiled device tree binary
151e0ff8551SSimon Glass
152e0ff8551SSimon Glass        Returns:
153e0ff8551SSimon Glass            Contents of device tree binary
154e0ff8551SSimon Glass        """
1554f44304bSSimon Glass        if not self._output_setup:
1564f44304bSSimon Glass            tools.PrepareOutputDir(self._indir, True)
1574f44304bSSimon Glass            self._output_setup = True
1584f44304bSSimon Glass        dtb = fdt_util.EnsureCompiled(self.TestFile(fname))
1594f44304bSSimon Glass        with open(dtb) as fd:
1604f44304bSSimon Glass            data = fd.read()
1614f44304bSSimon Glass            TestFunctional._MakeInputFile(outfile, data)
162e0ff8551SSimon Glass            return data
1634f44304bSSimon Glass
164e0ff8551SSimon Glass    def _DoReadFileDtb(self, fname, use_real_dtb=False):
1654f44304bSSimon Glass        """Run binman and return the resulting image
1664f44304bSSimon Glass
1674f44304bSSimon Glass        This runs binman with a given test file and then reads the resulting
1684f44304bSSimon Glass        output file. It is a shortcut function since most tests need to do
1694f44304bSSimon Glass        these steps.
1704f44304bSSimon Glass
1714f44304bSSimon Glass        Raises an assertion failure if binman returns a non-zero exit code.
1724f44304bSSimon Glass
1734f44304bSSimon Glass        Args:
1744f44304bSSimon Glass            fname: Device tree source filename to use (e.g. 05_simple.dts)
1754f44304bSSimon Glass            use_real_dtb: True to use the test file as the contents of
1764f44304bSSimon Glass                the u-boot-dtb entry. Normally this is not needed and the
1774f44304bSSimon Glass                test contents (the U_BOOT_DTB_DATA string) can be used.
1784f44304bSSimon Glass                But in some test we need the real contents.
179e0ff8551SSimon Glass
180e0ff8551SSimon Glass        Returns:
181e0ff8551SSimon Glass            Tuple:
182e0ff8551SSimon Glass                Resulting image contents
183e0ff8551SSimon Glass                Device tree contents
1844f44304bSSimon Glass        """
185e0ff8551SSimon Glass        dtb_data = None
1864f44304bSSimon Glass        # Use the compiled test file as the u-boot-dtb input
1874f44304bSSimon Glass        if use_real_dtb:
188e0ff8551SSimon Glass            dtb_data = self._SetupDtb(fname)
1894f44304bSSimon Glass
1904f44304bSSimon Glass        try:
1914f44304bSSimon Glass            retcode = self._DoTestFile(fname)
1924f44304bSSimon Glass            self.assertEqual(0, retcode)
1934f44304bSSimon Glass
1944f44304bSSimon Glass            # Find the (only) image, read it and return its contents
1954f44304bSSimon Glass            image = control.images['image']
1964f44304bSSimon Glass            fname = tools.GetOutputFilename('image.bin')
1974f44304bSSimon Glass            self.assertTrue(os.path.exists(fname))
1984f44304bSSimon Glass            with open(fname) as fd:
199e0ff8551SSimon Glass                return fd.read(), dtb_data
2004f44304bSSimon Glass        finally:
2014f44304bSSimon Glass            # Put the test file back
2024f44304bSSimon Glass            if use_real_dtb:
2034f44304bSSimon Glass                TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
2044f44304bSSimon Glass
205e0ff8551SSimon Glass    def _DoReadFile(self, fname, use_real_dtb=False):
206e0ff8551SSimon Glass        """Helper function which discards the device-tree binary"""
207e0ff8551SSimon Glass        return self._DoReadFileDtb(fname, use_real_dtb)[0]
208e0ff8551SSimon Glass
2094f44304bSSimon Glass    @classmethod
2104f44304bSSimon Glass    def _MakeInputFile(self, fname, contents):
2114f44304bSSimon Glass        """Create a new test input file, creating directories as needed
2124f44304bSSimon Glass
2134f44304bSSimon Glass        Args:
2144f44304bSSimon Glass            fname: Filenaem to create
2154f44304bSSimon Glass            contents: File contents to write in to the file
2164f44304bSSimon Glass        Returns:
2174f44304bSSimon Glass            Full pathname of file created
2184f44304bSSimon Glass        """
2194f44304bSSimon Glass        pathname = os.path.join(self._indir, fname)
2204f44304bSSimon Glass        dirname = os.path.dirname(pathname)
2214f44304bSSimon Glass        if dirname and not os.path.exists(dirname):
2224f44304bSSimon Glass            os.makedirs(dirname)
2234f44304bSSimon Glass        with open(pathname, 'wb') as fd:
2244f44304bSSimon Glass            fd.write(contents)
2254f44304bSSimon Glass        return pathname
2264f44304bSSimon Glass
2274f44304bSSimon Glass    @classmethod
2284f44304bSSimon Glass    def TestFile(self, fname):
2294f44304bSSimon Glass        return os.path.join(self._binman_dir, 'test', fname)
2304f44304bSSimon Glass
2314f44304bSSimon Glass    def AssertInList(self, grep_list, target):
2324f44304bSSimon Glass        """Assert that at least one of a list of things is in a target
2334f44304bSSimon Glass
2344f44304bSSimon Glass        Args:
2354f44304bSSimon Glass            grep_list: List of strings to check
2364f44304bSSimon Glass            target: Target string
2374f44304bSSimon Glass        """
2384f44304bSSimon Glass        for grep in grep_list:
2394f44304bSSimon Glass            if grep in target:
2404f44304bSSimon Glass                return
2414f44304bSSimon Glass        self.fail("Error: '%' not found in '%s'" % (grep_list, target))
2424f44304bSSimon Glass
2434f44304bSSimon Glass    def CheckNoGaps(self, entries):
2444f44304bSSimon Glass        """Check that all entries fit together without gaps
2454f44304bSSimon Glass
2464f44304bSSimon Glass        Args:
2474f44304bSSimon Glass            entries: List of entries to check
2484f44304bSSimon Glass        """
2494f44304bSSimon Glass        pos = 0
2504f44304bSSimon Glass        for entry in entries.values():
2514f44304bSSimon Glass            self.assertEqual(pos, entry.pos)
2524f44304bSSimon Glass            pos += entry.size
2534f44304bSSimon Glass
254e0ff8551SSimon Glass    def GetFdtLen(self, dtb):
255e0ff8551SSimon Glass        """Get the totalsize field from a device tree binary
256e0ff8551SSimon Glass
257e0ff8551SSimon Glass        Args:
258e0ff8551SSimon Glass            dtb: Device tree binary contents
259e0ff8551SSimon Glass
260e0ff8551SSimon Glass        Returns:
261e0ff8551SSimon Glass            Total size of device tree binary, from the header
262e0ff8551SSimon Glass        """
263e0ff8551SSimon Glass        return struct.unpack('>L', dtb[4:8])[0]
264e0ff8551SSimon Glass
2654f44304bSSimon Glass    def testRun(self):
2664f44304bSSimon Glass        """Test a basic run with valid args"""
2674f44304bSSimon Glass        result = self._RunBinman('-h')
2684f44304bSSimon Glass
2694f44304bSSimon Glass    def testFullHelp(self):
2704f44304bSSimon Glass        """Test that the full help is displayed with -H"""
2714f44304bSSimon Glass        result = self._RunBinman('-H')
2724f44304bSSimon Glass        help_file = os.path.join(self._binman_dir, 'README')
2734f44304bSSimon Glass        self.assertEqual(len(result.stdout), os.path.getsize(help_file))
2744f44304bSSimon Glass        self.assertEqual(0, len(result.stderr))
2754f44304bSSimon Glass        self.assertEqual(0, result.return_code)
2764f44304bSSimon Glass
2774f44304bSSimon Glass    def testFullHelpInternal(self):
2784f44304bSSimon Glass        """Test that the full help is displayed with -H"""
2794f44304bSSimon Glass        try:
2804f44304bSSimon Glass            command.test_result = command.CommandResult()
2814f44304bSSimon Glass            result = self._DoBinman('-H')
2824f44304bSSimon Glass            help_file = os.path.join(self._binman_dir, 'README')
2834f44304bSSimon Glass        finally:
2844f44304bSSimon Glass            command.test_result = None
2854f44304bSSimon Glass
2864f44304bSSimon Glass    def testHelp(self):
2874f44304bSSimon Glass        """Test that the basic help is displayed with -h"""
2884f44304bSSimon Glass        result = self._RunBinman('-h')
2894f44304bSSimon Glass        self.assertTrue(len(result.stdout) > 200)
2904f44304bSSimon Glass        self.assertEqual(0, len(result.stderr))
2914f44304bSSimon Glass        self.assertEqual(0, result.return_code)
2924f44304bSSimon Glass
2934f44304bSSimon Glass    # Not yet available.
2944f44304bSSimon Glass    def testBoard(self):
2954f44304bSSimon Glass        """Test that we can run it with a specific board"""
2964f44304bSSimon Glass        self._SetupDtb('05_simple.dts', 'sandbox/u-boot.dtb')
2974f44304bSSimon Glass        TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
2984f44304bSSimon Glass        result = self._DoBinman('-b', 'sandbox')
2994f44304bSSimon Glass        self.assertEqual(0, result)
3004f44304bSSimon Glass
3014f44304bSSimon Glass    def testNeedBoard(self):
3024f44304bSSimon Glass        """Test that we get an error when no board ius supplied"""
3034f44304bSSimon Glass        with self.assertRaises(ValueError) as e:
3044f44304bSSimon Glass            result = self._DoBinman()
3054f44304bSSimon Glass        self.assertIn("Must provide a board to process (use -b <board>)",
3064f44304bSSimon Glass                str(e.exception))
3074f44304bSSimon Glass
3084f44304bSSimon Glass    def testMissingDt(self):
3094f44304bSSimon Glass        """Test that an invalid device tree file generates an error"""
3104f44304bSSimon Glass        with self.assertRaises(Exception) as e:
3114f44304bSSimon Glass            self._RunBinman('-d', 'missing_file')
3124f44304bSSimon Glass        # We get one error from libfdt, and a different one from fdtget.
3134f44304bSSimon Glass        self.AssertInList(["Couldn't open blob from 'missing_file'",
3144f44304bSSimon Glass                           'No such file or directory'], str(e.exception))
3154f44304bSSimon Glass
3164f44304bSSimon Glass    def testBrokenDt(self):
3174f44304bSSimon Glass        """Test that an invalid device tree source file generates an error
3184f44304bSSimon Glass
3194f44304bSSimon Glass        Since this is a source file it should be compiled and the error
3204f44304bSSimon Glass        will come from the device-tree compiler (dtc).
3214f44304bSSimon Glass        """
3224f44304bSSimon Glass        with self.assertRaises(Exception) as e:
3234f44304bSSimon Glass            self._RunBinman('-d', self.TestFile('01_invalid.dts'))
3244f44304bSSimon Glass        self.assertIn("FATAL ERROR: Unable to parse input tree",
3254f44304bSSimon Glass                str(e.exception))
3264f44304bSSimon Glass
3274f44304bSSimon Glass    def testMissingNode(self):
3284f44304bSSimon Glass        """Test that a device tree without a 'binman' node generates an error"""
3294f44304bSSimon Glass        with self.assertRaises(Exception) as e:
3304f44304bSSimon Glass            self._DoBinman('-d', self.TestFile('02_missing_node.dts'))
3314f44304bSSimon Glass        self.assertIn("does not have a 'binman' node", str(e.exception))
3324f44304bSSimon Glass
3334f44304bSSimon Glass    def testEmpty(self):
3344f44304bSSimon Glass        """Test that an empty binman node works OK (i.e. does nothing)"""
3354f44304bSSimon Glass        result = self._RunBinman('-d', self.TestFile('03_empty.dts'))
3364f44304bSSimon Glass        self.assertEqual(0, len(result.stderr))
3374f44304bSSimon Glass        self.assertEqual(0, result.return_code)
3384f44304bSSimon Glass
3394f44304bSSimon Glass    def testInvalidEntry(self):
3404f44304bSSimon Glass        """Test that an invalid entry is flagged"""
3414f44304bSSimon Glass        with self.assertRaises(Exception) as e:
3424f44304bSSimon Glass            result = self._RunBinman('-d',
3434f44304bSSimon Glass                                     self.TestFile('04_invalid_entry.dts'))
3444f44304bSSimon Glass        #print e.exception
3454f44304bSSimon Glass        self.assertIn("Unknown entry type 'not-a-valid-type' in node "
3464f44304bSSimon Glass                "'/binman/not-a-valid-type'", str(e.exception))
3474f44304bSSimon Glass
3484f44304bSSimon Glass    def testSimple(self):
3494f44304bSSimon Glass        """Test a simple binman with a single file"""
3504f44304bSSimon Glass        data = self._DoReadFile('05_simple.dts')
3514f44304bSSimon Glass        self.assertEqual(U_BOOT_DATA, data)
3524f44304bSSimon Glass
3534f44304bSSimon Glass    def testDual(self):
3544f44304bSSimon Glass        """Test that we can handle creating two images
3554f44304bSSimon Glass
3564f44304bSSimon Glass        This also tests image padding.
3574f44304bSSimon Glass        """
3584f44304bSSimon Glass        retcode = self._DoTestFile('06_dual_image.dts')
3594f44304bSSimon Glass        self.assertEqual(0, retcode)
3604f44304bSSimon Glass
3614f44304bSSimon Glass        image = control.images['image1']
3624f44304bSSimon Glass        self.assertEqual(len(U_BOOT_DATA), image._size)
3634f44304bSSimon Glass        fname = tools.GetOutputFilename('image1.bin')
3644f44304bSSimon Glass        self.assertTrue(os.path.exists(fname))
3654f44304bSSimon Glass        with open(fname) as fd:
3664f44304bSSimon Glass            data = fd.read()
3674f44304bSSimon Glass            self.assertEqual(U_BOOT_DATA, data)
3684f44304bSSimon Glass
3694f44304bSSimon Glass        image = control.images['image2']
3704f44304bSSimon Glass        self.assertEqual(3 + len(U_BOOT_DATA) + 5, image._size)
3714f44304bSSimon Glass        fname = tools.GetOutputFilename('image2.bin')
3724f44304bSSimon Glass        self.assertTrue(os.path.exists(fname))
3734f44304bSSimon Glass        with open(fname) as fd:
3744f44304bSSimon Glass            data = fd.read()
3754f44304bSSimon Glass            self.assertEqual(U_BOOT_DATA, data[3:7])
3764f44304bSSimon Glass            self.assertEqual(chr(0) * 3, data[:3])
3774f44304bSSimon Glass            self.assertEqual(chr(0) * 5, data[7:])
3784f44304bSSimon Glass
3794f44304bSSimon Glass    def testBadAlign(self):
3804f44304bSSimon Glass        """Test that an invalid alignment value is detected"""
3814f44304bSSimon Glass        with self.assertRaises(ValueError) as e:
3824f44304bSSimon Glass            self._DoTestFile('07_bad_align.dts')
3834f44304bSSimon Glass        self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
3844f44304bSSimon Glass                      "of two", str(e.exception))
3854f44304bSSimon Glass
3864f44304bSSimon Glass    def testPackSimple(self):
3874f44304bSSimon Glass        """Test that packing works as expected"""
3884f44304bSSimon Glass        retcode = self._DoTestFile('08_pack.dts')
3894f44304bSSimon Glass        self.assertEqual(0, retcode)
3904f44304bSSimon Glass        self.assertIn('image', control.images)
3914f44304bSSimon Glass        image = control.images['image']
3924f44304bSSimon Glass        entries = image._entries
3934f44304bSSimon Glass        self.assertEqual(5, len(entries))
3944f44304bSSimon Glass
3954f44304bSSimon Glass        # First u-boot
3964f44304bSSimon Glass        self.assertIn('u-boot', entries)
3974f44304bSSimon Glass        entry = entries['u-boot']
3984f44304bSSimon Glass        self.assertEqual(0, entry.pos)
3994f44304bSSimon Glass        self.assertEqual(len(U_BOOT_DATA), entry.size)
4004f44304bSSimon Glass
4014f44304bSSimon Glass        # Second u-boot, aligned to 16-byte boundary
4024f44304bSSimon Glass        self.assertIn('u-boot-align', entries)
4034f44304bSSimon Glass        entry = entries['u-boot-align']
4044f44304bSSimon Glass        self.assertEqual(16, entry.pos)
4054f44304bSSimon Glass        self.assertEqual(len(U_BOOT_DATA), entry.size)
4064f44304bSSimon Glass
4074f44304bSSimon Glass        # Third u-boot, size 23 bytes
4084f44304bSSimon Glass        self.assertIn('u-boot-size', entries)
4094f44304bSSimon Glass        entry = entries['u-boot-size']
4104f44304bSSimon Glass        self.assertEqual(20, entry.pos)
4114f44304bSSimon Glass        self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
4124f44304bSSimon Glass        self.assertEqual(23, entry.size)
4134f44304bSSimon Glass
4144f44304bSSimon Glass        # Fourth u-boot, placed immediate after the above
4154f44304bSSimon Glass        self.assertIn('u-boot-next', entries)
4164f44304bSSimon Glass        entry = entries['u-boot-next']
4174f44304bSSimon Glass        self.assertEqual(43, entry.pos)
4184f44304bSSimon Glass        self.assertEqual(len(U_BOOT_DATA), entry.size)
4194f44304bSSimon Glass
4204f44304bSSimon Glass        # Fifth u-boot, placed at a fixed position
4214f44304bSSimon Glass        self.assertIn('u-boot-fixed', entries)
4224f44304bSSimon Glass        entry = entries['u-boot-fixed']
4234f44304bSSimon Glass        self.assertEqual(61, entry.pos)
4244f44304bSSimon Glass        self.assertEqual(len(U_BOOT_DATA), entry.size)
4254f44304bSSimon Glass
4264f44304bSSimon Glass        self.assertEqual(65, image._size)
4274f44304bSSimon Glass
4284f44304bSSimon Glass    def testPackExtra(self):
4294f44304bSSimon Glass        """Test that extra packing feature works as expected"""
4304f44304bSSimon Glass        retcode = self._DoTestFile('09_pack_extra.dts')
4314f44304bSSimon Glass
4324f44304bSSimon Glass        self.assertEqual(0, retcode)
4334f44304bSSimon Glass        self.assertIn('image', control.images)
4344f44304bSSimon Glass        image = control.images['image']
4354f44304bSSimon Glass        entries = image._entries
4364f44304bSSimon Glass        self.assertEqual(5, len(entries))
4374f44304bSSimon Glass
4384f44304bSSimon Glass        # First u-boot with padding before and after
4394f44304bSSimon Glass        self.assertIn('u-boot', entries)
4404f44304bSSimon Glass        entry = entries['u-boot']
4414f44304bSSimon Glass        self.assertEqual(0, entry.pos)
4424f44304bSSimon Glass        self.assertEqual(3, entry.pad_before)
4434f44304bSSimon Glass        self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
4444f44304bSSimon Glass
4454f44304bSSimon Glass        # Second u-boot has an aligned size, but it has no effect
4464f44304bSSimon Glass        self.assertIn('u-boot-align-size-nop', entries)
4474f44304bSSimon Glass        entry = entries['u-boot-align-size-nop']
4484f44304bSSimon Glass        self.assertEqual(12, entry.pos)
4494f44304bSSimon Glass        self.assertEqual(4, entry.size)
4504f44304bSSimon Glass
4514f44304bSSimon Glass        # Third u-boot has an aligned size too
4524f44304bSSimon Glass        self.assertIn('u-boot-align-size', entries)
4534f44304bSSimon Glass        entry = entries['u-boot-align-size']
4544f44304bSSimon Glass        self.assertEqual(16, entry.pos)
4554f44304bSSimon Glass        self.assertEqual(32, entry.size)
4564f44304bSSimon Glass
4574f44304bSSimon Glass        # Fourth u-boot has an aligned end
4584f44304bSSimon Glass        self.assertIn('u-boot-align-end', entries)
4594f44304bSSimon Glass        entry = entries['u-boot-align-end']
4604f44304bSSimon Glass        self.assertEqual(48, entry.pos)
4614f44304bSSimon Glass        self.assertEqual(16, entry.size)
4624f44304bSSimon Glass
4634f44304bSSimon Glass        # Fifth u-boot immediately afterwards
4644f44304bSSimon Glass        self.assertIn('u-boot-align-both', entries)
4654f44304bSSimon Glass        entry = entries['u-boot-align-both']
4664f44304bSSimon Glass        self.assertEqual(64, entry.pos)
4674f44304bSSimon Glass        self.assertEqual(64, entry.size)
4684f44304bSSimon Glass
4694f44304bSSimon Glass        self.CheckNoGaps(entries)
4704f44304bSSimon Glass        self.assertEqual(128, image._size)
4714f44304bSSimon Glass
4724f44304bSSimon Glass    def testPackAlignPowerOf2(self):
4734f44304bSSimon Glass        """Test that invalid entry alignment is detected"""
4744f44304bSSimon Glass        with self.assertRaises(ValueError) as e:
4754f44304bSSimon Glass            self._DoTestFile('10_pack_align_power2.dts')
4764f44304bSSimon Glass        self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
4774f44304bSSimon Glass                      "of two", str(e.exception))
4784f44304bSSimon Glass
4794f44304bSSimon Glass    def testPackAlignSizePowerOf2(self):
4804f44304bSSimon Glass        """Test that invalid entry size alignment is detected"""
4814f44304bSSimon Glass        with self.assertRaises(ValueError) as e:
4824f44304bSSimon Glass            self._DoTestFile('11_pack_align_size_power2.dts')
4834f44304bSSimon Glass        self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
4844f44304bSSimon Glass                      "power of two", str(e.exception))
4854f44304bSSimon Glass
4864f44304bSSimon Glass    def testPackInvalidAlign(self):
4874f44304bSSimon Glass        """Test detection of an position that does not match its alignment"""
4884f44304bSSimon Glass        with self.assertRaises(ValueError) as e:
4894f44304bSSimon Glass            self._DoTestFile('12_pack_inv_align.dts')
4904f44304bSSimon Glass        self.assertIn("Node '/binman/u-boot': Position 0x5 (5) does not match "
4914f44304bSSimon Glass                      "align 0x4 (4)", str(e.exception))
4924f44304bSSimon Glass
4934f44304bSSimon Glass    def testPackInvalidSizeAlign(self):
4944f44304bSSimon Glass        """Test that invalid entry size alignment is detected"""
4954f44304bSSimon Glass        with self.assertRaises(ValueError) as e:
4964f44304bSSimon Glass            self._DoTestFile('13_pack_inv_size_align.dts')
4974f44304bSSimon Glass        self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
4984f44304bSSimon Glass                      "align-size 0x4 (4)", str(e.exception))
4994f44304bSSimon Glass
5004f44304bSSimon Glass    def testPackOverlap(self):
5014f44304bSSimon Glass        """Test that overlapping regions are detected"""
5024f44304bSSimon Glass        with self.assertRaises(ValueError) as e:
5034f44304bSSimon Glass            self._DoTestFile('14_pack_overlap.dts')
5044f44304bSSimon Glass        self.assertIn("Node '/binman/u-boot-align': Position 0x3 (3) overlaps "
5054f44304bSSimon Glass                      "with previous entry '/binman/u-boot' ending at 0x4 (4)",
5064f44304bSSimon Glass                      str(e.exception))
5074f44304bSSimon Glass
5084f44304bSSimon Glass    def testPackEntryOverflow(self):
5094f44304bSSimon Glass        """Test that entries that overflow their size are detected"""
5104f44304bSSimon Glass        with self.assertRaises(ValueError) as e:
5114f44304bSSimon Glass            self._DoTestFile('15_pack_overflow.dts')
5124f44304bSSimon Glass        self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
5134f44304bSSimon Glass                      "but entry size is 0x3 (3)", str(e.exception))
5144f44304bSSimon Glass
5154f44304bSSimon Glass    def testPackImageOverflow(self):
5164f44304bSSimon Glass        """Test that entries which overflow the image size are detected"""
5174f44304bSSimon Glass        with self.assertRaises(ValueError) as e:
5184f44304bSSimon Glass            self._DoTestFile('16_pack_image_overflow.dts')
5194f44304bSSimon Glass        self.assertIn("Image '/binman': contents size 0x4 (4) exceeds image "
5204f44304bSSimon Glass                      "size 0x3 (3)", str(e.exception))
5214f44304bSSimon Glass
5224f44304bSSimon Glass    def testPackImageSize(self):
5234f44304bSSimon Glass        """Test that the image size can be set"""
5244f44304bSSimon Glass        retcode = self._DoTestFile('17_pack_image_size.dts')
5254f44304bSSimon Glass        self.assertEqual(0, retcode)
5264f44304bSSimon Glass        self.assertIn('image', control.images)
5274f44304bSSimon Glass        image = control.images['image']
5284f44304bSSimon Glass        self.assertEqual(7, image._size)
5294f44304bSSimon Glass
5304f44304bSSimon Glass    def testPackImageSizeAlign(self):
5314f44304bSSimon Glass        """Test that image size alignemnt works as expected"""
5324f44304bSSimon Glass        retcode = self._DoTestFile('18_pack_image_align.dts')
5334f44304bSSimon Glass        self.assertEqual(0, retcode)
5344f44304bSSimon Glass        self.assertIn('image', control.images)
5354f44304bSSimon Glass        image = control.images['image']
5364f44304bSSimon Glass        self.assertEqual(16, image._size)
5374f44304bSSimon Glass
5384f44304bSSimon Glass    def testPackInvalidImageAlign(self):
5394f44304bSSimon Glass        """Test that invalid image alignment is detected"""
5404f44304bSSimon Glass        with self.assertRaises(ValueError) as e:
5414f44304bSSimon Glass            self._DoTestFile('19_pack_inv_image_align.dts')
5424f44304bSSimon Glass        self.assertIn("Image '/binman': Size 0x7 (7) does not match "
5434f44304bSSimon Glass                      "align-size 0x8 (8)", str(e.exception))
5444f44304bSSimon Glass
5454f44304bSSimon Glass    def testPackAlignPowerOf2(self):
5464f44304bSSimon Glass        """Test that invalid image alignment is detected"""
5474f44304bSSimon Glass        with self.assertRaises(ValueError) as e:
5484f44304bSSimon Glass            self._DoTestFile('20_pack_inv_image_align_power2.dts')
5494f44304bSSimon Glass        self.assertIn("Image '/binman': Alignment size 131 must be a power of "
5504f44304bSSimon Glass                      "two", str(e.exception))
5514f44304bSSimon Glass
5524f44304bSSimon Glass    def testImagePadByte(self):
5534f44304bSSimon Glass        """Test that the image pad byte can be specified"""
5544f44304bSSimon Glass        data = self._DoReadFile('21_image_pad.dts')
5554f44304bSSimon Glass        self.assertEqual(U_BOOT_SPL_DATA + (chr(0xff) * 9) + U_BOOT_DATA, data)
5564f44304bSSimon Glass
5574f44304bSSimon Glass    def testImageName(self):
5584f44304bSSimon Glass        """Test that image files can be named"""
5594f44304bSSimon Glass        retcode = self._DoTestFile('22_image_name.dts')
5604f44304bSSimon Glass        self.assertEqual(0, retcode)
5614f44304bSSimon Glass        image = control.images['image1']
5624f44304bSSimon Glass        fname = tools.GetOutputFilename('test-name')
5634f44304bSSimon Glass        self.assertTrue(os.path.exists(fname))
5644f44304bSSimon Glass
5654f44304bSSimon Glass        image = control.images['image2']
5664f44304bSSimon Glass        fname = tools.GetOutputFilename('test-name.xx')
5674f44304bSSimon Glass        self.assertTrue(os.path.exists(fname))
5684f44304bSSimon Glass
5694f44304bSSimon Glass    def testBlobFilename(self):
5704f44304bSSimon Glass        """Test that generic blobs can be provided by filename"""
5714f44304bSSimon Glass        data = self._DoReadFile('23_blob.dts')
5724f44304bSSimon Glass        self.assertEqual(BLOB_DATA, data)
5734f44304bSSimon Glass
5744f44304bSSimon Glass    def testPackSorted(self):
5754f44304bSSimon Glass        """Test that entries can be sorted"""
5764f44304bSSimon Glass        data = self._DoReadFile('24_sorted.dts')
5774f44304bSSimon Glass        self.assertEqual(chr(0) * 5 + U_BOOT_SPL_DATA + chr(0) * 2 +
5784f44304bSSimon Glass                         U_BOOT_DATA, data)
5794f44304bSSimon Glass
5804f44304bSSimon Glass    def testPackZeroPosition(self):
5814f44304bSSimon Glass        """Test that an entry at position 0 is not given a new position"""
5824f44304bSSimon Glass        with self.assertRaises(ValueError) as e:
5834f44304bSSimon Glass            self._DoTestFile('25_pack_zero_size.dts')
5844f44304bSSimon Glass        self.assertIn("Node '/binman/u-boot-spl': Position 0x0 (0) overlaps "
5854f44304bSSimon Glass                      "with previous entry '/binman/u-boot' ending at 0x4 (4)",
5864f44304bSSimon Glass                      str(e.exception))
5874f44304bSSimon Glass
5884f44304bSSimon Glass    def testPackUbootDtb(self):
5894f44304bSSimon Glass        """Test that a device tree can be added to U-Boot"""
5904f44304bSSimon Glass        data = self._DoReadFile('26_pack_u_boot_dtb.dts')
5914f44304bSSimon Glass        self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
592e0ff8551SSimon Glass
593e0ff8551SSimon Glass    def testPackX86RomNoSize(self):
594e0ff8551SSimon Glass        """Test that the end-at-4gb property requires a size property"""
595e0ff8551SSimon Glass        with self.assertRaises(ValueError) as e:
596e0ff8551SSimon Glass            self._DoTestFile('27_pack_4gb_no_size.dts')
597e0ff8551SSimon Glass        self.assertIn("Image '/binman': Image size must be provided when "
598e0ff8551SSimon Glass                      "using end-at-4gb", str(e.exception))
599e0ff8551SSimon Glass
600e0ff8551SSimon Glass    def testPackX86RomOutside(self):
601e0ff8551SSimon Glass        """Test that the end-at-4gb property checks for position boundaries"""
602e0ff8551SSimon Glass        with self.assertRaises(ValueError) as e:
603e0ff8551SSimon Glass            self._DoTestFile('28_pack_4gb_outside.dts')
604e0ff8551SSimon Glass        self.assertIn("Node '/binman/u-boot': Position 0x0 (0) is outside "
605e0ff8551SSimon Glass                      "the image starting at 0xfffffff0 (4294967280)",
606e0ff8551SSimon Glass                      str(e.exception))
607e0ff8551SSimon Glass
608e0ff8551SSimon Glass    def testPackX86Rom(self):
609e0ff8551SSimon Glass        """Test that a basic x86 ROM can be created"""
610e0ff8551SSimon Glass        data = self._DoReadFile('29_x86-rom.dts')
611e0ff8551SSimon Glass        self.assertEqual(U_BOOT_DATA + chr(0) * 3 + U_BOOT_SPL_DATA +
612e0ff8551SSimon Glass                         chr(0) * 6, data)
613e0ff8551SSimon Glass
614e0ff8551SSimon Glass    def testPackX86RomMeNoDesc(self):
615e0ff8551SSimon Glass        """Test that an invalid Intel descriptor entry is detected"""
616e0ff8551SSimon Glass        TestFunctional._MakeInputFile('descriptor.bin', '')
617e0ff8551SSimon Glass        with self.assertRaises(ValueError) as e:
618e0ff8551SSimon Glass            self._DoTestFile('31_x86-rom-me.dts')
619e0ff8551SSimon Glass        self.assertIn("Node '/binman/intel-descriptor': Cannot find FD "
620e0ff8551SSimon Glass                      "signature", str(e.exception))
621e0ff8551SSimon Glass
622e0ff8551SSimon Glass    def testPackX86RomBadDesc(self):
623e0ff8551SSimon Glass        """Test that the Intel requires a descriptor entry"""
624e0ff8551SSimon Glass        with self.assertRaises(ValueError) as e:
625e0ff8551SSimon Glass            self._DoTestFile('30_x86-rom-me-no-desc.dts')
626e0ff8551SSimon Glass        self.assertIn("Node '/binman/intel-me': No position set with "
627e0ff8551SSimon Glass                      "pos-unset: should another entry provide this correct "
628e0ff8551SSimon Glass                      "position?", str(e.exception))
629e0ff8551SSimon Glass
630e0ff8551SSimon Glass    def testPackX86RomMe(self):
631e0ff8551SSimon Glass        """Test that an x86 ROM with an ME region can be created"""
632e0ff8551SSimon Glass        data = self._DoReadFile('31_x86-rom-me.dts')
633e0ff8551SSimon Glass        self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
634e0ff8551SSimon Glass
635e0ff8551SSimon Glass    def testPackVga(self):
636e0ff8551SSimon Glass        """Test that an image with a VGA binary can be created"""
637e0ff8551SSimon Glass        data = self._DoReadFile('32_intel-vga.dts')
638e0ff8551SSimon Glass        self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
639e0ff8551SSimon Glass
640e0ff8551SSimon Glass    def testPackStart16(self):
641e0ff8551SSimon Glass        """Test that an image with an x86 start16 region can be created"""
642e0ff8551SSimon Glass        data = self._DoReadFile('33_x86-start16.dts')
643e0ff8551SSimon Glass        self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
644e0ff8551SSimon Glass
645e0ff8551SSimon Glass    def testPackUbootMicrocode(self):
646e0ff8551SSimon Glass        """Test that x86 microcode can be handled correctly
647e0ff8551SSimon Glass
648e0ff8551SSimon Glass        We expect to see the following in the image, in order:
649e0ff8551SSimon Glass            u-boot-nodtb.bin with a microcode pointer inserted at the correct
650e0ff8551SSimon Glass                place
651e0ff8551SSimon Glass            u-boot.dtb with the microcode removed
652e0ff8551SSimon Glass            the microcode
653e0ff8551SSimon Glass        """
654e0ff8551SSimon Glass        data = self._DoReadFile('34_x86_ucode.dts', True)
655e0ff8551SSimon Glass
656e0ff8551SSimon Glass        # Now check the device tree has no microcode
657e0ff8551SSimon Glass        second = data[len(U_BOOT_NODTB_DATA):]
658e0ff8551SSimon Glass        fname = tools.GetOutputFilename('test.dtb')
659e0ff8551SSimon Glass        with open(fname, 'wb') as fd:
660e0ff8551SSimon Glass            fd.write(second)
661ec3f378aSSimon Glass        dtb = fdt.FdtScan(fname)
662ec3f378aSSimon Glass        ucode = dtb.GetNode('/microcode')
663e0ff8551SSimon Glass        self.assertTrue(ucode)
664e0ff8551SSimon Glass        for node in ucode.subnodes:
665e0ff8551SSimon Glass            self.assertFalse(node.props.get('data'))
666e0ff8551SSimon Glass
667e0ff8551SSimon Glass        fdt_len = self.GetFdtLen(second)
668e0ff8551SSimon Glass        third = second[fdt_len:]
669e0ff8551SSimon Glass
670e0ff8551SSimon Glass        # Check that the microcode appears immediately after the Fdt
671e0ff8551SSimon Glass        # This matches the concatenation of the data properties in
672e0ff8551SSimon Glass        # the /microcode/update@xxx nodes in x86_ucode.dts.
673e0ff8551SSimon Glass        ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
674e0ff8551SSimon Glass                                 0x78235609)
675e0ff8551SSimon Glass        self.assertEqual(ucode_data, third[:len(ucode_data)])
676e0ff8551SSimon Glass        ucode_pos = len(U_BOOT_NODTB_DATA) + fdt_len
677e0ff8551SSimon Glass
678e0ff8551SSimon Glass        # Check that the microcode pointer was inserted. It should match the
679e0ff8551SSimon Glass        # expected position and size
680e0ff8551SSimon Glass        pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
681e0ff8551SSimon Glass                                   len(ucode_data))
682e0ff8551SSimon Glass        first = data[:len(U_BOOT_NODTB_DATA)]
683e0ff8551SSimon Glass        self.assertEqual('nodtb with microcode' + pos_and_size +
684e0ff8551SSimon Glass                         ' somewhere in here', first)
685e0ff8551SSimon Glass
686160a7664SSimon Glass    def _RunPackUbootSingleMicrocode(self):
687e0ff8551SSimon Glass        """Test that x86 microcode can be handled correctly
688e0ff8551SSimon Glass
689e0ff8551SSimon Glass        We expect to see the following in the image, in order:
690e0ff8551SSimon Glass            u-boot-nodtb.bin with a microcode pointer inserted at the correct
691e0ff8551SSimon Glass                place
692e0ff8551SSimon Glass            u-boot.dtb with the microcode
693e0ff8551SSimon Glass            an empty microcode region
694e0ff8551SSimon Glass        """
695e0ff8551SSimon Glass        # We need the libfdt library to run this test since only that allows
696e0ff8551SSimon Glass        # finding the offset of a property. This is required by
697e0ff8551SSimon Glass        # Entry_u_boot_dtb_with_ucode.ObtainContents().
698e0ff8551SSimon Glass        data = self._DoReadFile('35_x86_single_ucode.dts', True)
699e0ff8551SSimon Glass
700e0ff8551SSimon Glass        second = data[len(U_BOOT_NODTB_DATA):]
701e0ff8551SSimon Glass
702e0ff8551SSimon Glass        fdt_len = self.GetFdtLen(second)
703e0ff8551SSimon Glass        third = second[fdt_len:]
704e0ff8551SSimon Glass        second = second[:fdt_len]
705e0ff8551SSimon Glass
706e0ff8551SSimon Glass        ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
707e0ff8551SSimon Glass        self.assertIn(ucode_data, second)
708e0ff8551SSimon Glass        ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
709e0ff8551SSimon Glass
710e0ff8551SSimon Glass        # Check that the microcode pointer was inserted. It should match the
711e0ff8551SSimon Glass        # expected position and size
712e0ff8551SSimon Glass        pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
713e0ff8551SSimon Glass                                   len(ucode_data))
714e0ff8551SSimon Glass        first = data[:len(U_BOOT_NODTB_DATA)]
715e0ff8551SSimon Glass        self.assertEqual('nodtb with microcode' + pos_and_size +
716e0ff8551SSimon Glass                         ' somewhere in here', first)
717c49deb83SSimon Glass
71875db0860SSimon Glass    def testPackUbootSingleMicrocode(self):
71975db0860SSimon Glass        """Test that x86 microcode can be handled correctly with fdt_normal.
72075db0860SSimon Glass        """
721160a7664SSimon Glass        self._RunPackUbootSingleMicrocode()
72275db0860SSimon Glass
723c49deb83SSimon Glass    def testUBootImg(self):
724c49deb83SSimon Glass        """Test that u-boot.img can be put in a file"""
725c49deb83SSimon Glass        data = self._DoReadFile('36_u_boot_img.dts')
726c49deb83SSimon Glass        self.assertEqual(U_BOOT_IMG_DATA, data)
72775db0860SSimon Glass
72875db0860SSimon Glass    def testNoMicrocode(self):
72975db0860SSimon Glass        """Test that a missing microcode region is detected"""
73075db0860SSimon Glass        with self.assertRaises(ValueError) as e:
73175db0860SSimon Glass            self._DoReadFile('37_x86_no_ucode.dts', True)
73275db0860SSimon Glass        self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
73375db0860SSimon Glass                      "node found in ", str(e.exception))
73475db0860SSimon Glass
73575db0860SSimon Glass    def testMicrocodeWithoutNode(self):
73675db0860SSimon Glass        """Test that a missing u-boot-dtb-with-ucode node is detected"""
73775db0860SSimon Glass        with self.assertRaises(ValueError) as e:
73875db0860SSimon Glass            self._DoReadFile('38_x86_ucode_missing_node.dts', True)
73975db0860SSimon Glass        self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
74075db0860SSimon Glass                "microcode region u-boot-dtb-with-ucode", str(e.exception))
74175db0860SSimon Glass
74275db0860SSimon Glass    def testMicrocodeWithoutNode2(self):
74375db0860SSimon Glass        """Test that a missing u-boot-ucode node is detected"""
74475db0860SSimon Glass        with self.assertRaises(ValueError) as e:
74575db0860SSimon Glass            self._DoReadFile('39_x86_ucode_missing_node2.dts', True)
74675db0860SSimon Glass        self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
74775db0860SSimon Glass            "microcode region u-boot-ucode", str(e.exception))
74875db0860SSimon Glass
74975db0860SSimon Glass    def testMicrocodeWithoutPtrInElf(self):
75075db0860SSimon Glass        """Test that a U-Boot binary without the microcode symbol is detected"""
75175db0860SSimon Glass        # ELF file without a '_dt_ucode_base_size' symbol
75275db0860SSimon Glass        try:
75375db0860SSimon Glass            with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
75475db0860SSimon Glass                TestFunctional._MakeInputFile('u-boot', fd.read())
75575db0860SSimon Glass
75675db0860SSimon Glass            with self.assertRaises(ValueError) as e:
757160a7664SSimon Glass                self._RunPackUbootSingleMicrocode()
75875db0860SSimon Glass            self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
75975db0860SSimon Glass                    "_dt_ucode_base_size symbol in u-boot", str(e.exception))
76075db0860SSimon Glass
76175db0860SSimon Glass        finally:
76275db0860SSimon Glass            # Put the original file back
76375db0860SSimon Glass            with open(self.TestFile('u_boot_ucode_ptr')) as fd:
76475db0860SSimon Glass                TestFunctional._MakeInputFile('u-boot', fd.read())
76575db0860SSimon Glass
76675db0860SSimon Glass    def testMicrocodeNotInImage(self):
76775db0860SSimon Glass        """Test that microcode must be placed within the image"""
76875db0860SSimon Glass        with self.assertRaises(ValueError) as e:
76975db0860SSimon Glass            self._DoReadFile('40_x86_ucode_not_in_image.dts', True)
77075db0860SSimon Glass        self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
77175db0860SSimon Glass                "pointer _dt_ucode_base_size at fffffe14 is outside the "
77275db0860SSimon Glass                "image ranging from 00000000 to 0000002e", str(e.exception))
77375db0860SSimon Glass
77475db0860SSimon Glass    def testWithoutMicrocode(self):
77575db0860SSimon Glass        """Test that we can cope with an image without microcode (e.g. qemu)"""
77675db0860SSimon Glass        with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
77775db0860SSimon Glass            TestFunctional._MakeInputFile('u-boot', fd.read())
77875db0860SSimon Glass        data, dtb = self._DoReadFileDtb('44_x86_optional_ucode.dts', True)
77975db0860SSimon Glass
78075db0860SSimon Glass        # Now check the device tree has no microcode
78175db0860SSimon Glass        self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
78275db0860SSimon Glass        second = data[len(U_BOOT_NODTB_DATA):]
78375db0860SSimon Glass
78475db0860SSimon Glass        fdt_len = self.GetFdtLen(second)
78575db0860SSimon Glass        self.assertEqual(dtb, second[:fdt_len])
78675db0860SSimon Glass
78775db0860SSimon Glass        used_len = len(U_BOOT_NODTB_DATA) + fdt_len
78875db0860SSimon Glass        third = data[used_len:]
78975db0860SSimon Glass        self.assertEqual(chr(0) * (0x200 - used_len), third)
79075db0860SSimon Glass
79175db0860SSimon Glass    def testUnknownPosSize(self):
79275db0860SSimon Glass        """Test that microcode must be placed within the image"""
79375db0860SSimon Glass        with self.assertRaises(ValueError) as e:
79475db0860SSimon Glass            self._DoReadFile('41_unknown_pos_size.dts', True)
79575db0860SSimon Glass        self.assertIn("Image '/binman': Unable to set pos/size for unknown "
79675db0860SSimon Glass                "entry 'invalid-entry'", str(e.exception))
797da229090SSimon Glass
798da229090SSimon Glass    def testPackFsp(self):
799da229090SSimon Glass        """Test that an image with a FSP binary can be created"""
800da229090SSimon Glass        data = self._DoReadFile('42_intel-fsp.dts')
801da229090SSimon Glass        self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
802da229090SSimon Glass
803da229090SSimon Glass    def testPackCmc(self):
804da229090SSimon Glass        """Test that an image with a FSP binary can be created"""
805da229090SSimon Glass        data = self._DoReadFile('43_intel-cmc.dts')
806da229090SSimon Glass        self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
807