e1fc9e8e9e8f19c82338042ade2d9c45ca6d2f75
[oweals/u-boot.git] / tools / binman / ftest.py
1 # SPDX-License-Identifier: GPL-2.0+
2 # Copyright (c) 2016 Google, Inc
3 # Written by Simon Glass <sjg@chromium.org>
4 #
5 # To run a single test, change to this directory, and:
6 #
7 #    python -m unittest func_test.TestFunctional.testHelp
8
9 import hashlib
10 from optparse import OptionParser
11 import os
12 import shutil
13 import struct
14 import sys
15 import tempfile
16 import unittest
17
18 import binman
19 import cmdline
20 import command
21 import control
22 import elf
23 import fdt
24 import fdt_util
25 import fmap_util
26 import test_util
27 import state
28 import tools
29 import tout
30
31 # Contents of test files, corresponding to different entry types
32 U_BOOT_DATA           = '1234'
33 U_BOOT_IMG_DATA       = 'img'
34 U_BOOT_SPL_DATA       = '56780123456789abcde'
35 U_BOOT_TPL_DATA       = 'tpl'
36 BLOB_DATA             = '89'
37 ME_DATA               = '0abcd'
38 VGA_DATA              = 'vga'
39 U_BOOT_DTB_DATA       = 'udtb'
40 U_BOOT_SPL_DTB_DATA   = 'spldtb'
41 U_BOOT_TPL_DTB_DATA   = 'tpldtb'
42 X86_START16_DATA      = 'start16'
43 X86_START16_SPL_DATA  = 'start16spl'
44 X86_START16_TPL_DATA  = 'start16tpl'
45 PPC_MPC85XX_BR_DATA   = 'ppcmpc85xxbr'
46 U_BOOT_NODTB_DATA     = 'nodtb with microcode pointer somewhere in here'
47 U_BOOT_SPL_NODTB_DATA = 'splnodtb with microcode pointer somewhere in here'
48 U_BOOT_TPL_NODTB_DATA = 'tplnodtb with microcode pointer somewhere in here'
49 FSP_DATA              = 'fsp'
50 CMC_DATA              = 'cmc'
51 VBT_DATA              = 'vbt'
52 MRC_DATA              = 'mrc'
53 TEXT_DATA             = 'text'
54 TEXT_DATA2            = 'text2'
55 TEXT_DATA3            = 'text3'
56 CROS_EC_RW_DATA       = 'ecrw'
57 GBB_DATA              = 'gbbd'
58 BMPBLK_DATA           = 'bmp'
59 VBLOCK_DATA           = 'vblk'
60 FILES_DATA            = ("sorry I'm late\nOh, don't bother apologising, I'm " +
61                          "sorry you're alive\n")
62 COMPRESS_DATA         = 'data to compress'
63 REFCODE_DATA          = 'refcode'
64
65
66 class TestFunctional(unittest.TestCase):
67     """Functional tests for binman
68
69     Most of these use a sample .dts file to build an image and then check
70     that it looks correct. The sample files are in the test/ subdirectory
71     and are numbered.
72
73     For each entry type a very small test file is created using fixed
74     string contents. This makes it easy to test that things look right, and
75     debug problems.
76
77     In some cases a 'real' file must be used - these are also supplied in
78     the test/ diurectory.
79     """
80     @classmethod
81     def setUpClass(self):
82         global entry
83         import entry
84
85         # Handle the case where argv[0] is 'python'
86         self._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
87         self._binman_pathname = os.path.join(self._binman_dir, 'binman')
88
89         # Create a temporary directory for input files
90         self._indir = tempfile.mkdtemp(prefix='binmant.')
91
92         # Create some test files
93         TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
94         TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
95         TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
96         TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
97         TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
98         TestFunctional._MakeInputFile('me.bin', ME_DATA)
99         TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
100         self._ResetDtbs()
101         TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
102         TestFunctional._MakeInputFile('u-boot-br.bin', PPC_MPC85XX_BR_DATA)
103         TestFunctional._MakeInputFile('spl/u-boot-x86-16bit-spl.bin',
104                                       X86_START16_SPL_DATA)
105         TestFunctional._MakeInputFile('tpl/u-boot-x86-16bit-tpl.bin',
106                                       X86_START16_TPL_DATA)
107         TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
108         TestFunctional._MakeInputFile('spl/u-boot-spl-nodtb.bin',
109                                       U_BOOT_SPL_NODTB_DATA)
110         TestFunctional._MakeInputFile('tpl/u-boot-tpl-nodtb.bin',
111                                       U_BOOT_TPL_NODTB_DATA)
112         TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
113         TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
114         TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
115         TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
116         TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
117         TestFunctional._MakeInputDir('devkeys')
118         TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
119         TestFunctional._MakeInputFile('refcode.bin', REFCODE_DATA)
120
121         # ELF file with a '_dt_ucode_base_size' symbol
122         with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
123             TestFunctional._MakeInputFile('u-boot', fd.read())
124
125         # Intel flash descriptor file
126         with open(self.TestFile('descriptor.bin'), 'rb') as fd:
127             TestFunctional._MakeInputFile('descriptor.bin', fd.read())
128
129         shutil.copytree(self.TestFile('files'),
130                         os.path.join(self._indir, 'files'))
131
132         TestFunctional._MakeInputFile('compress', COMPRESS_DATA)
133
134     @classmethod
135     def tearDownClass(self):
136         """Remove the temporary input directory and its contents"""
137         if self._indir:
138             shutil.rmtree(self._indir)
139         self._indir = None
140
141     def setUp(self):
142         # Enable this to turn on debugging output
143         # tout.Init(tout.DEBUG)
144         command.test_result = None
145
146     def tearDown(self):
147         """Remove the temporary output directory"""
148         tools._FinaliseForTest()
149
150     @classmethod
151     def _ResetDtbs(self):
152         TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
153         TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
154         TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
155
156     def _RunBinman(self, *args, **kwargs):
157         """Run binman using the command line
158
159         Args:
160             Arguments to pass, as a list of strings
161             kwargs: Arguments to pass to Command.RunPipe()
162         """
163         result = command.RunPipe([[self._binman_pathname] + list(args)],
164                 capture=True, capture_stderr=True, raise_on_error=False)
165         if result.return_code and kwargs.get('raise_on_error', True):
166             raise Exception("Error running '%s': %s" % (' '.join(args),
167                             result.stdout + result.stderr))
168         return result
169
170     def _DoBinman(self, *args):
171         """Run binman using directly (in the same process)
172
173         Args:
174             Arguments to pass, as a list of strings
175         Returns:
176             Return value (0 for success)
177         """
178         args = list(args)
179         if '-D' in sys.argv:
180             args = args + ['-D']
181         (options, args) = cmdline.ParseArgs(args)
182         options.pager = 'binman-invalid-pager'
183         options.build_dir = self._indir
184
185         # For testing, you can force an increase in verbosity here
186         # options.verbosity = tout.DEBUG
187         return control.Binman(options, args)
188
189     def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
190                     entry_args=None, images=None, use_real_dtb=False,
191                     verbosity=None):
192         """Run binman with a given test file
193
194         Args:
195             fname: Device-tree source filename to use (e.g. 005_simple.dts)
196             debug: True to enable debugging output
197             map: True to output map files for the images
198             update_dtb: Update the offset and size of each entry in the device
199                 tree before packing it into the image
200             entry_args: Dict of entry args to supply to binman
201                 key: arg name
202                 value: value of that arg
203             images: List of image names to build
204         """
205         args = ['-p', '-I', self._indir, '-d', self.TestFile(fname)]
206         if debug:
207             args.append('-D')
208         if map:
209             args.append('-m')
210         if update_dtb:
211             args.append('-up')
212         if not use_real_dtb:
213             args.append('--fake-dtb')
214         if verbosity is not None:
215             args.append('-v%d' % verbosity)
216         if entry_args:
217             for arg, value in entry_args.items():
218                 args.append('-a%s=%s' % (arg, value))
219         if images:
220             for image in images:
221                 args += ['-i', image]
222         return self._DoBinman(*args)
223
224     def _SetupDtb(self, fname, outfile='u-boot.dtb'):
225         """Set up a new test device-tree file
226
227         The given file is compiled and set up as the device tree to be used
228         for ths test.
229
230         Args:
231             fname: Filename of .dts file to read
232             outfile: Output filename for compiled device-tree binary
233
234         Returns:
235             Contents of device-tree binary
236         """
237         tools.PrepareOutputDir(None)
238         dtb = fdt_util.EnsureCompiled(self.TestFile(fname))
239         with open(dtb, 'rb') as fd:
240             data = fd.read()
241             TestFunctional._MakeInputFile(outfile, data)
242         tools.FinaliseOutputDir()
243         return data
244
245     def _GetDtbContentsForSplTpl(self, dtb_data, name):
246         """Create a version of the main DTB for SPL or SPL
247
248         For testing we don't actually have different versions of the DTB. With
249         U-Boot we normally run fdtgrep to remove unwanted nodes, but for tests
250         we don't normally have any unwanted nodes.
251
252         We still want the DTBs for SPL and TPL to be different though, since
253         otherwise it is confusing to know which one we are looking at. So add
254         an 'spl' or 'tpl' property to the top-level node.
255         """
256         dtb = fdt.Fdt.FromData(dtb_data)
257         dtb.Scan()
258         dtb.GetNode('/binman').AddZeroProp(name)
259         dtb.Sync(auto_resize=True)
260         dtb.Pack()
261         return dtb.GetContents()
262
263     def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
264                        update_dtb=False, entry_args=None, reset_dtbs=True):
265         """Run binman and return the resulting image
266
267         This runs binman with a given test file and then reads the resulting
268         output file. It is a shortcut function since most tests need to do
269         these steps.
270
271         Raises an assertion failure if binman returns a non-zero exit code.
272
273         Args:
274             fname: Device-tree source filename to use (e.g. 005_simple.dts)
275             use_real_dtb: True to use the test file as the contents of
276                 the u-boot-dtb entry. Normally this is not needed and the
277                 test contents (the U_BOOT_DTB_DATA string) can be used.
278                 But in some test we need the real contents.
279             map: True to output map files for the images
280             update_dtb: Update the offset and size of each entry in the device
281                 tree before packing it into the image
282
283         Returns:
284             Tuple:
285                 Resulting image contents
286                 Device tree contents
287                 Map data showing contents of image (or None if none)
288                 Output device tree binary filename ('u-boot.dtb' path)
289         """
290         dtb_data = None
291         # Use the compiled test file as the u-boot-dtb input
292         if use_real_dtb:
293             dtb_data = self._SetupDtb(fname)
294
295             # For testing purposes, make a copy of the DT for SPL and TPL. Add
296             # a node indicating which it is, so aid verification.
297             for name in ['spl', 'tpl']:
298                 dtb_fname = '%s/u-boot-%s.dtb' % (name, name)
299                 outfile = os.path.join(self._indir, dtb_fname)
300                 TestFunctional._MakeInputFile(dtb_fname,
301                         self._GetDtbContentsForSplTpl(dtb_data, name))
302
303         try:
304             retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
305                     entry_args=entry_args, use_real_dtb=use_real_dtb)
306             self.assertEqual(0, retcode)
307             out_dtb_fname = tools.GetOutputFilename('u-boot.dtb.out')
308
309             # Find the (only) image, read it and return its contents
310             image = control.images['image']
311             image_fname = tools.GetOutputFilename('image.bin')
312             self.assertTrue(os.path.exists(image_fname))
313             if map:
314                 map_fname = tools.GetOutputFilename('image.map')
315                 with open(map_fname) as fd:
316                     map_data = fd.read()
317             else:
318                 map_data = None
319             with open(image_fname, 'rb') as fd:
320                 return fd.read(), dtb_data, map_data, out_dtb_fname
321         finally:
322             # Put the test file back
323             if reset_dtbs and use_real_dtb:
324                 self._ResetDtbs()
325
326     def _DoReadFile(self, fname, use_real_dtb=False):
327         """Helper function which discards the device-tree binary
328
329         Args:
330             fname: Device-tree source filename to use (e.g. 005_simple.dts)
331             use_real_dtb: True to use the test file as the contents of
332                 the u-boot-dtb entry. Normally this is not needed and the
333                 test contents (the U_BOOT_DTB_DATA string) can be used.
334                 But in some test we need the real contents.
335
336         Returns:
337             Resulting image contents
338         """
339         return self._DoReadFileDtb(fname, use_real_dtb)[0]
340
341     @classmethod
342     def _MakeInputFile(self, fname, contents):
343         """Create a new test input file, creating directories as needed
344
345         Args:
346             fname: Filename to create
347             contents: File contents to write in to the file
348         Returns:
349             Full pathname of file created
350         """
351         pathname = os.path.join(self._indir, fname)
352         dirname = os.path.dirname(pathname)
353         if dirname and not os.path.exists(dirname):
354             os.makedirs(dirname)
355         with open(pathname, 'wb') as fd:
356             fd.write(contents)
357         return pathname
358
359     @classmethod
360     def _MakeInputDir(self, dirname):
361         """Create a new test input directory, creating directories as needed
362
363         Args:
364             dirname: Directory name to create
365
366         Returns:
367             Full pathname of directory created
368         """
369         pathname = os.path.join(self._indir, dirname)
370         if not os.path.exists(pathname):
371             os.makedirs(pathname)
372         return pathname
373
374     @classmethod
375     def _SetupSplElf(self, src_fname='bss_data'):
376         """Set up an ELF file with a '_dt_ucode_base_size' symbol
377
378         Args:
379             Filename of ELF file to use as SPL
380         """
381         with open(self.TestFile(src_fname), 'rb') as fd:
382             TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
383
384     @classmethod
385     def TestFile(self, fname):
386         return os.path.join(self._binman_dir, 'test', fname)
387
388     def AssertInList(self, grep_list, target):
389         """Assert that at least one of a list of things is in a target
390
391         Args:
392             grep_list: List of strings to check
393             target: Target string
394         """
395         for grep in grep_list:
396             if grep in target:
397                 return
398         self.fail("Error: '%' not found in '%s'" % (grep_list, target))
399
400     def CheckNoGaps(self, entries):
401         """Check that all entries fit together without gaps
402
403         Args:
404             entries: List of entries to check
405         """
406         offset = 0
407         for entry in entries.values():
408             self.assertEqual(offset, entry.offset)
409             offset += entry.size
410
411     def GetFdtLen(self, dtb):
412         """Get the totalsize field from a device-tree binary
413
414         Args:
415             dtb: Device-tree binary contents
416
417         Returns:
418             Total size of device-tree binary, from the header
419         """
420         return struct.unpack('>L', dtb[4:8])[0]
421
422     def _GetPropTree(self, dtb, prop_names):
423         def AddNode(node, path):
424             if node.name != '/':
425                 path += '/' + node.name
426             for subnode in node.subnodes:
427                 for prop in subnode.props.values():
428                     if prop.name in prop_names:
429                         prop_path = path + '/' + subnode.name + ':' + prop.name
430                         tree[prop_path[len('/binman/'):]] = fdt_util.fdt32_to_cpu(
431                             prop.value)
432                 AddNode(subnode, path)
433
434         tree = {}
435         AddNode(dtb.GetRoot(), '')
436         return tree
437
438     def testRun(self):
439         """Test a basic run with valid args"""
440         result = self._RunBinman('-h')
441
442     def testFullHelp(self):
443         """Test that the full help is displayed with -H"""
444         result = self._RunBinman('-H')
445         help_file = os.path.join(self._binman_dir, 'README')
446         # Remove possible extraneous strings
447         extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
448         gothelp = result.stdout.replace(extra, '')
449         self.assertEqual(len(gothelp), os.path.getsize(help_file))
450         self.assertEqual(0, len(result.stderr))
451         self.assertEqual(0, result.return_code)
452
453     def testFullHelpInternal(self):
454         """Test that the full help is displayed with -H"""
455         try:
456             command.test_result = command.CommandResult()
457             result = self._DoBinman('-H')
458             help_file = os.path.join(self._binman_dir, 'README')
459         finally:
460             command.test_result = None
461
462     def testHelp(self):
463         """Test that the basic help is displayed with -h"""
464         result = self._RunBinman('-h')
465         self.assertTrue(len(result.stdout) > 200)
466         self.assertEqual(0, len(result.stderr))
467         self.assertEqual(0, result.return_code)
468
469     def testBoard(self):
470         """Test that we can run it with a specific board"""
471         self._SetupDtb('005_simple.dts', 'sandbox/u-boot.dtb')
472         TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
473         result = self._DoBinman('-b', 'sandbox')
474         self.assertEqual(0, result)
475
476     def testNeedBoard(self):
477         """Test that we get an error when no board ius supplied"""
478         with self.assertRaises(ValueError) as e:
479             result = self._DoBinman()
480         self.assertIn("Must provide a board to process (use -b <board>)",
481                 str(e.exception))
482
483     def testMissingDt(self):
484         """Test that an invalid device-tree file generates an error"""
485         with self.assertRaises(Exception) as e:
486             self._RunBinman('-d', 'missing_file')
487         # We get one error from libfdt, and a different one from fdtget.
488         self.AssertInList(["Couldn't open blob from 'missing_file'",
489                            'No such file or directory'], str(e.exception))
490
491     def testBrokenDt(self):
492         """Test that an invalid device-tree source file generates an error
493
494         Since this is a source file it should be compiled and the error
495         will come from the device-tree compiler (dtc).
496         """
497         with self.assertRaises(Exception) as e:
498             self._RunBinman('-d', self.TestFile('001_invalid.dts'))
499         self.assertIn("FATAL ERROR: Unable to parse input tree",
500                 str(e.exception))
501
502     def testMissingNode(self):
503         """Test that a device tree without a 'binman' node generates an error"""
504         with self.assertRaises(Exception) as e:
505             self._DoBinman('-d', self.TestFile('002_missing_node.dts'))
506         self.assertIn("does not have a 'binman' node", str(e.exception))
507
508     def testEmpty(self):
509         """Test that an empty binman node works OK (i.e. does nothing)"""
510         result = self._RunBinman('-d', self.TestFile('003_empty.dts'))
511         self.assertEqual(0, len(result.stderr))
512         self.assertEqual(0, result.return_code)
513
514     def testInvalidEntry(self):
515         """Test that an invalid entry is flagged"""
516         with self.assertRaises(Exception) as e:
517             result = self._RunBinman('-d',
518                                      self.TestFile('004_invalid_entry.dts'))
519         self.assertIn("Unknown entry type 'not-a-valid-type' in node "
520                 "'/binman/not-a-valid-type'", str(e.exception))
521
522     def testSimple(self):
523         """Test a simple binman with a single file"""
524         data = self._DoReadFile('005_simple.dts')
525         self.assertEqual(U_BOOT_DATA, data)
526
527     def testSimpleDebug(self):
528         """Test a simple binman run with debugging enabled"""
529         data = self._DoTestFile('005_simple.dts', debug=True)
530
531     def testDual(self):
532         """Test that we can handle creating two images
533
534         This also tests image padding.
535         """
536         retcode = self._DoTestFile('006_dual_image.dts')
537         self.assertEqual(0, retcode)
538
539         image = control.images['image1']
540         self.assertEqual(len(U_BOOT_DATA), image._size)
541         fname = tools.GetOutputFilename('image1.bin')
542         self.assertTrue(os.path.exists(fname))
543         with open(fname, 'rb') as fd:
544             data = fd.read()
545             self.assertEqual(U_BOOT_DATA, data)
546
547         image = control.images['image2']
548         self.assertEqual(3 + len(U_BOOT_DATA) + 5, image._size)
549         fname = tools.GetOutputFilename('image2.bin')
550         self.assertTrue(os.path.exists(fname))
551         with open(fname, 'rb') as fd:
552             data = fd.read()
553             self.assertEqual(U_BOOT_DATA, data[3:7])
554             self.assertEqual(chr(0) * 3, data[:3])
555             self.assertEqual(chr(0) * 5, data[7:])
556
557     def testBadAlign(self):
558         """Test that an invalid alignment value is detected"""
559         with self.assertRaises(ValueError) as e:
560             self._DoTestFile('007_bad_align.dts')
561         self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
562                       "of two", str(e.exception))
563
564     def testPackSimple(self):
565         """Test that packing works as expected"""
566         retcode = self._DoTestFile('008_pack.dts')
567         self.assertEqual(0, retcode)
568         self.assertIn('image', control.images)
569         image = control.images['image']
570         entries = image.GetEntries()
571         self.assertEqual(5, len(entries))
572
573         # First u-boot
574         self.assertIn('u-boot', entries)
575         entry = entries['u-boot']
576         self.assertEqual(0, entry.offset)
577         self.assertEqual(len(U_BOOT_DATA), entry.size)
578
579         # Second u-boot, aligned to 16-byte boundary
580         self.assertIn('u-boot-align', entries)
581         entry = entries['u-boot-align']
582         self.assertEqual(16, entry.offset)
583         self.assertEqual(len(U_BOOT_DATA), entry.size)
584
585         # Third u-boot, size 23 bytes
586         self.assertIn('u-boot-size', entries)
587         entry = entries['u-boot-size']
588         self.assertEqual(20, entry.offset)
589         self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
590         self.assertEqual(23, entry.size)
591
592         # Fourth u-boot, placed immediate after the above
593         self.assertIn('u-boot-next', entries)
594         entry = entries['u-boot-next']
595         self.assertEqual(43, entry.offset)
596         self.assertEqual(len(U_BOOT_DATA), entry.size)
597
598         # Fifth u-boot, placed at a fixed offset
599         self.assertIn('u-boot-fixed', entries)
600         entry = entries['u-boot-fixed']
601         self.assertEqual(61, entry.offset)
602         self.assertEqual(len(U_BOOT_DATA), entry.size)
603
604         self.assertEqual(65, image._size)
605
606     def testPackExtra(self):
607         """Test that extra packing feature works as expected"""
608         retcode = self._DoTestFile('009_pack_extra.dts')
609
610         self.assertEqual(0, retcode)
611         self.assertIn('image', control.images)
612         image = control.images['image']
613         entries = image.GetEntries()
614         self.assertEqual(5, len(entries))
615
616         # First u-boot with padding before and after
617         self.assertIn('u-boot', entries)
618         entry = entries['u-boot']
619         self.assertEqual(0, entry.offset)
620         self.assertEqual(3, entry.pad_before)
621         self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
622
623         # Second u-boot has an aligned size, but it has no effect
624         self.assertIn('u-boot-align-size-nop', entries)
625         entry = entries['u-boot-align-size-nop']
626         self.assertEqual(12, entry.offset)
627         self.assertEqual(4, entry.size)
628
629         # Third u-boot has an aligned size too
630         self.assertIn('u-boot-align-size', entries)
631         entry = entries['u-boot-align-size']
632         self.assertEqual(16, entry.offset)
633         self.assertEqual(32, entry.size)
634
635         # Fourth u-boot has an aligned end
636         self.assertIn('u-boot-align-end', entries)
637         entry = entries['u-boot-align-end']
638         self.assertEqual(48, entry.offset)
639         self.assertEqual(16, entry.size)
640
641         # Fifth u-boot immediately afterwards
642         self.assertIn('u-boot-align-both', entries)
643         entry = entries['u-boot-align-both']
644         self.assertEqual(64, entry.offset)
645         self.assertEqual(64, entry.size)
646
647         self.CheckNoGaps(entries)
648         self.assertEqual(128, image._size)
649
650     def testPackAlignPowerOf2(self):
651         """Test that invalid entry alignment is detected"""
652         with self.assertRaises(ValueError) as e:
653             self._DoTestFile('010_pack_align_power2.dts')
654         self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
655                       "of two", str(e.exception))
656
657     def testPackAlignSizePowerOf2(self):
658         """Test that invalid entry size alignment is detected"""
659         with self.assertRaises(ValueError) as e:
660             self._DoTestFile('011_pack_align_size_power2.dts')
661         self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
662                       "power of two", str(e.exception))
663
664     def testPackInvalidAlign(self):
665         """Test detection of an offset that does not match its alignment"""
666         with self.assertRaises(ValueError) as e:
667             self._DoTestFile('012_pack_inv_align.dts')
668         self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
669                       "align 0x4 (4)", str(e.exception))
670
671     def testPackInvalidSizeAlign(self):
672         """Test that invalid entry size alignment is detected"""
673         with self.assertRaises(ValueError) as e:
674             self._DoTestFile('013_pack_inv_size_align.dts')
675         self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
676                       "align-size 0x4 (4)", str(e.exception))
677
678     def testPackOverlap(self):
679         """Test that overlapping regions are detected"""
680         with self.assertRaises(ValueError) as e:
681             self._DoTestFile('014_pack_overlap.dts')
682         self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
683                       "with previous entry '/binman/u-boot' ending at 0x4 (4)",
684                       str(e.exception))
685
686     def testPackEntryOverflow(self):
687         """Test that entries that overflow their size are detected"""
688         with self.assertRaises(ValueError) as e:
689             self._DoTestFile('015_pack_overflow.dts')
690         self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
691                       "but entry size is 0x3 (3)", str(e.exception))
692
693     def testPackImageOverflow(self):
694         """Test that entries which overflow the image size are detected"""
695         with self.assertRaises(ValueError) as e:
696             self._DoTestFile('016_pack_image_overflow.dts')
697         self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section "
698                       "size 0x3 (3)", str(e.exception))
699
700     def testPackImageSize(self):
701         """Test that the image size can be set"""
702         retcode = self._DoTestFile('017_pack_image_size.dts')
703         self.assertEqual(0, retcode)
704         self.assertIn('image', control.images)
705         image = control.images['image']
706         self.assertEqual(7, image._size)
707
708     def testPackImageSizeAlign(self):
709         """Test that image size alignemnt works as expected"""
710         retcode = self._DoTestFile('018_pack_image_align.dts')
711         self.assertEqual(0, retcode)
712         self.assertIn('image', control.images)
713         image = control.images['image']
714         self.assertEqual(16, image._size)
715
716     def testPackInvalidImageAlign(self):
717         """Test that invalid image alignment is detected"""
718         with self.assertRaises(ValueError) as e:
719             self._DoTestFile('019_pack_inv_image_align.dts')
720         self.assertIn("Section '/binman': Size 0x7 (7) does not match "
721                       "align-size 0x8 (8)", str(e.exception))
722
723     def testPackAlignPowerOf2(self):
724         """Test that invalid image alignment is detected"""
725         with self.assertRaises(ValueError) as e:
726             self._DoTestFile('020_pack_inv_image_align_power2.dts')
727         self.assertIn("Section '/binman': Alignment size 131 must be a power of "
728                       "two", str(e.exception))
729
730     def testImagePadByte(self):
731         """Test that the image pad byte can be specified"""
732         self._SetupSplElf()
733         data = self._DoReadFile('021_image_pad.dts')
734         self.assertEqual(U_BOOT_SPL_DATA + (chr(0xff) * 1) + U_BOOT_DATA, data)
735
736     def testImageName(self):
737         """Test that image files can be named"""
738         retcode = self._DoTestFile('022_image_name.dts')
739         self.assertEqual(0, retcode)
740         image = control.images['image1']
741         fname = tools.GetOutputFilename('test-name')
742         self.assertTrue(os.path.exists(fname))
743
744         image = control.images['image2']
745         fname = tools.GetOutputFilename('test-name.xx')
746         self.assertTrue(os.path.exists(fname))
747
748     def testBlobFilename(self):
749         """Test that generic blobs can be provided by filename"""
750         data = self._DoReadFile('023_blob.dts')
751         self.assertEqual(BLOB_DATA, data)
752
753     def testPackSorted(self):
754         """Test that entries can be sorted"""
755         self._SetupSplElf()
756         data = self._DoReadFile('024_sorted.dts')
757         self.assertEqual(chr(0) * 1 + U_BOOT_SPL_DATA + chr(0) * 2 +
758                          U_BOOT_DATA, data)
759
760     def testPackZeroOffset(self):
761         """Test that an entry at offset 0 is not given a new offset"""
762         with self.assertRaises(ValueError) as e:
763             self._DoTestFile('025_pack_zero_size.dts')
764         self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
765                       "with previous entry '/binman/u-boot' ending at 0x4 (4)",
766                       str(e.exception))
767
768     def testPackUbootDtb(self):
769         """Test that a device tree can be added to U-Boot"""
770         data = self._DoReadFile('026_pack_u_boot_dtb.dts')
771         self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
772
773     def testPackX86RomNoSize(self):
774         """Test that the end-at-4gb property requires a size property"""
775         with self.assertRaises(ValueError) as e:
776             self._DoTestFile('027_pack_4gb_no_size.dts')
777         self.assertIn("Section '/binman': Section size must be provided when "
778                       "using end-at-4gb", str(e.exception))
779
780     def test4gbAndSkipAtStartTogether(self):
781         """Test that the end-at-4gb and skip-at-size property can't be used
782         together"""
783         with self.assertRaises(ValueError) as e:
784             self._DoTestFile('80_4gb_and_skip_at_start_together.dts')
785         self.assertIn("Section '/binman': Provide either 'end-at-4gb' or "
786                       "'skip-at-start'", str(e.exception))
787
788     def testPackX86RomOutside(self):
789         """Test that the end-at-4gb property checks for offset boundaries"""
790         with self.assertRaises(ValueError) as e:
791             self._DoTestFile('028_pack_4gb_outside.dts')
792         self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
793                       "the section starting at 0xffffffe0 (4294967264)",
794                       str(e.exception))
795
796     def testPackX86Rom(self):
797         """Test that a basic x86 ROM can be created"""
798         self._SetupSplElf()
799         data = self._DoReadFile('029_x86-rom.dts')
800         self.assertEqual(U_BOOT_DATA + chr(0) * 7 + U_BOOT_SPL_DATA +
801                          chr(0) * 2, data)
802
803     def testPackX86RomMeNoDesc(self):
804         """Test that an invalid Intel descriptor entry is detected"""
805         TestFunctional._MakeInputFile('descriptor.bin', '')
806         with self.assertRaises(ValueError) as e:
807             self._DoTestFile('031_x86-rom-me.dts')
808         self.assertIn("Node '/binman/intel-descriptor': Cannot find FD "
809                       "signature", str(e.exception))
810
811     def testPackX86RomBadDesc(self):
812         """Test that the Intel requires a descriptor entry"""
813         with self.assertRaises(ValueError) as e:
814             self._DoTestFile('030_x86-rom-me-no-desc.dts')
815         self.assertIn("Node '/binman/intel-me': No offset set with "
816                       "offset-unset: should another entry provide this correct "
817                       "offset?", str(e.exception))
818
819     def testPackX86RomMe(self):
820         """Test that an x86 ROM with an ME region can be created"""
821         data = self._DoReadFile('031_x86-rom-me.dts')
822         self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
823
824     def testPackVga(self):
825         """Test that an image with a VGA binary can be created"""
826         data = self._DoReadFile('032_intel-vga.dts')
827         self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
828
829     def testPackStart16(self):
830         """Test that an image with an x86 start16 region can be created"""
831         data = self._DoReadFile('033_x86-start16.dts')
832         self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
833
834     def testPackPowerpcMpc85xxBootpgResetvec(self):
835         """Test that an image with powerpc-mpc85xx-bootpg-resetvec can be
836         created"""
837         data = self._DoReadFile('81_powerpc_mpc85xx_bootpg_resetvec.dts')
838         self.assertEqual(PPC_MPC85XX_BR_DATA, data[:len(PPC_MPC85XX_BR_DATA)])
839
840     def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False):
841         """Handle running a test for insertion of microcode
842
843         Args:
844             dts_fname: Name of test .dts file
845             nodtb_data: Data that we expect in the first section
846             ucode_second: True if the microsecond entry is second instead of
847                 third
848
849         Returns:
850             Tuple:
851                 Contents of first region (U-Boot or SPL)
852                 Offset and size components of microcode pointer, as inserted
853                     in the above (two 4-byte words)
854         """
855         data = self._DoReadFile(dts_fname, True)
856
857         # Now check the device tree has no microcode
858         if ucode_second:
859             ucode_content = data[len(nodtb_data):]
860             ucode_pos = len(nodtb_data)
861             dtb_with_ucode = ucode_content[16:]
862             fdt_len = self.GetFdtLen(dtb_with_ucode)
863         else:
864             dtb_with_ucode = data[len(nodtb_data):]
865             fdt_len = self.GetFdtLen(dtb_with_ucode)
866             ucode_content = dtb_with_ucode[fdt_len:]
867             ucode_pos = len(nodtb_data) + fdt_len
868         fname = tools.GetOutputFilename('test.dtb')
869         with open(fname, 'wb') as fd:
870             fd.write(dtb_with_ucode)
871         dtb = fdt.FdtScan(fname)
872         ucode = dtb.GetNode('/microcode')
873         self.assertTrue(ucode)
874         for node in ucode.subnodes:
875             self.assertFalse(node.props.get('data'))
876
877         # Check that the microcode appears immediately after the Fdt
878         # This matches the concatenation of the data properties in
879         # the /microcode/update@xxx nodes in 34_x86_ucode.dts.
880         ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
881                                  0x78235609)
882         self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
883
884         # Check that the microcode pointer was inserted. It should match the
885         # expected offset and size
886         pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
887                                    len(ucode_data))
888         u_boot = data[:len(nodtb_data)]
889         return u_boot, pos_and_size
890
891     def testPackUbootMicrocode(self):
892         """Test that x86 microcode can be handled correctly
893
894         We expect to see the following in the image, in order:
895             u-boot-nodtb.bin with a microcode pointer inserted at the correct
896                 place
897             u-boot.dtb with the microcode removed
898             the microcode
899         """
900         first, pos_and_size = self._RunMicrocodeTest('034_x86_ucode.dts',
901                                                      U_BOOT_NODTB_DATA)
902         self.assertEqual('nodtb with microcode' + pos_and_size +
903                          ' somewhere in here', first)
904
905     def _RunPackUbootSingleMicrocode(self):
906         """Test that x86 microcode can be handled correctly
907
908         We expect to see the following in the image, in order:
909             u-boot-nodtb.bin with a microcode pointer inserted at the correct
910                 place
911             u-boot.dtb with the microcode
912             an empty microcode region
913         """
914         # We need the libfdt library to run this test since only that allows
915         # finding the offset of a property. This is required by
916         # Entry_u_boot_dtb_with_ucode.ObtainContents().
917         data = self._DoReadFile('035_x86_single_ucode.dts', True)
918
919         second = data[len(U_BOOT_NODTB_DATA):]
920
921         fdt_len = self.GetFdtLen(second)
922         third = second[fdt_len:]
923         second = second[:fdt_len]
924
925         ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
926         self.assertIn(ucode_data, second)
927         ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
928
929         # Check that the microcode pointer was inserted. It should match the
930         # expected offset and size
931         pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
932                                    len(ucode_data))
933         first = data[:len(U_BOOT_NODTB_DATA)]
934         self.assertEqual('nodtb with microcode' + pos_and_size +
935                          ' somewhere in here', first)
936
937     def testPackUbootSingleMicrocode(self):
938         """Test that x86 microcode can be handled correctly with fdt_normal.
939         """
940         self._RunPackUbootSingleMicrocode()
941
942     def testUBootImg(self):
943         """Test that u-boot.img can be put in a file"""
944         data = self._DoReadFile('036_u_boot_img.dts')
945         self.assertEqual(U_BOOT_IMG_DATA, data)
946
947     def testNoMicrocode(self):
948         """Test that a missing microcode region is detected"""
949         with self.assertRaises(ValueError) as e:
950             self._DoReadFile('037_x86_no_ucode.dts', True)
951         self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
952                       "node found in ", str(e.exception))
953
954     def testMicrocodeWithoutNode(self):
955         """Test that a missing u-boot-dtb-with-ucode node is detected"""
956         with self.assertRaises(ValueError) as e:
957             self._DoReadFile('038_x86_ucode_missing_node.dts', True)
958         self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
959                 "microcode region u-boot-dtb-with-ucode", str(e.exception))
960
961     def testMicrocodeWithoutNode2(self):
962         """Test that a missing u-boot-ucode node is detected"""
963         with self.assertRaises(ValueError) as e:
964             self._DoReadFile('039_x86_ucode_missing_node2.dts', True)
965         self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
966             "microcode region u-boot-ucode", str(e.exception))
967
968     def testMicrocodeWithoutPtrInElf(self):
969         """Test that a U-Boot binary without the microcode symbol is detected"""
970         # ELF file without a '_dt_ucode_base_size' symbol
971         try:
972             with open(self.TestFile('u_boot_no_ucode_ptr'), 'rb') as fd:
973                 TestFunctional._MakeInputFile('u-boot', fd.read())
974
975             with self.assertRaises(ValueError) as e:
976                 self._RunPackUbootSingleMicrocode()
977             self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
978                     "_dt_ucode_base_size symbol in u-boot", str(e.exception))
979
980         finally:
981             # Put the original file back
982             with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
983                 TestFunctional._MakeInputFile('u-boot', fd.read())
984
985     def testMicrocodeNotInImage(self):
986         """Test that microcode must be placed within the image"""
987         with self.assertRaises(ValueError) as e:
988             self._DoReadFile('040_x86_ucode_not_in_image.dts', True)
989         self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
990                 "pointer _dt_ucode_base_size at fffffe14 is outside the "
991                 "section ranging from 00000000 to 0000002e", str(e.exception))
992
993     def testWithoutMicrocode(self):
994         """Test that we can cope with an image without microcode (e.g. qemu)"""
995         with open(self.TestFile('u_boot_no_ucode_ptr'), 'rb') as fd:
996             TestFunctional._MakeInputFile('u-boot', fd.read())
997         data, dtb, _, _ = self._DoReadFileDtb('044_x86_optional_ucode.dts', True)
998
999         # Now check the device tree has no microcode
1000         self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
1001         second = data[len(U_BOOT_NODTB_DATA):]
1002
1003         fdt_len = self.GetFdtLen(second)
1004         self.assertEqual(dtb, second[:fdt_len])
1005
1006         used_len = len(U_BOOT_NODTB_DATA) + fdt_len
1007         third = data[used_len:]
1008         self.assertEqual(chr(0) * (0x200 - used_len), third)
1009
1010     def testUnknownPosSize(self):
1011         """Test that microcode must be placed within the image"""
1012         with self.assertRaises(ValueError) as e:
1013             self._DoReadFile('041_unknown_pos_size.dts', True)
1014         self.assertIn("Section '/binman': Unable to set offset/size for unknown "
1015                 "entry 'invalid-entry'", str(e.exception))
1016
1017     def testPackFsp(self):
1018         """Test that an image with a FSP binary can be created"""
1019         data = self._DoReadFile('042_intel-fsp.dts')
1020         self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
1021
1022     def testPackCmc(self):
1023         """Test that an image with a CMC binary can be created"""
1024         data = self._DoReadFile('043_intel-cmc.dts')
1025         self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
1026
1027     def testPackVbt(self):
1028         """Test that an image with a VBT binary can be created"""
1029         data = self._DoReadFile('046_intel-vbt.dts')
1030         self.assertEqual(VBT_DATA, data[:len(VBT_DATA)])
1031
1032     def testSplBssPad(self):
1033         """Test that we can pad SPL's BSS with zeros"""
1034         # ELF file with a '__bss_size' symbol
1035         self._SetupSplElf()
1036         data = self._DoReadFile('047_spl_bss_pad.dts')
1037         self.assertEqual(U_BOOT_SPL_DATA + (chr(0) * 10) + U_BOOT_DATA, data)
1038
1039     def testSplBssPadMissing(self):
1040         """Test that a missing symbol is detected"""
1041         self._SetupSplElf('u_boot_ucode_ptr')
1042         with self.assertRaises(ValueError) as e:
1043             self._DoReadFile('047_spl_bss_pad.dts')
1044         self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
1045                       str(e.exception))
1046
1047     def testPackStart16Spl(self):
1048         """Test that an image with an x86 start16 SPL region can be created"""
1049         data = self._DoReadFile('048_x86-start16-spl.dts')
1050         self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)])
1051
1052     def _PackUbootSplMicrocode(self, dts, ucode_second=False):
1053         """Helper function for microcode tests
1054
1055         We expect to see the following in the image, in order:
1056             u-boot-spl-nodtb.bin with a microcode pointer inserted at the
1057                 correct place
1058             u-boot.dtb with the microcode removed
1059             the microcode
1060
1061         Args:
1062             dts: Device tree file to use for test
1063             ucode_second: True if the microsecond entry is second instead of
1064                 third
1065         """
1066         self._SetupSplElf('u_boot_ucode_ptr')
1067         first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA,
1068                                                      ucode_second=ucode_second)
1069         self.assertEqual('splnodtb with microc' + pos_and_size +
1070                          'ter somewhere in here', first)
1071
1072     def testPackUbootSplMicrocode(self):
1073         """Test that x86 microcode can be handled correctly in SPL"""
1074         self._PackUbootSplMicrocode('049_x86_ucode_spl.dts')
1075
1076     def testPackUbootSplMicrocodeReorder(self):
1077         """Test that order doesn't matter for microcode entries
1078
1079         This is the same as testPackUbootSplMicrocode but when we process the
1080         u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode
1081         entry, so we reply on binman to try later.
1082         """
1083         self._PackUbootSplMicrocode('058_x86_ucode_spl_needs_retry.dts',
1084                                     ucode_second=True)
1085
1086     def testPackMrc(self):
1087         """Test that an image with an MRC binary can be created"""
1088         data = self._DoReadFile('050_intel_mrc.dts')
1089         self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
1090
1091     def testSplDtb(self):
1092         """Test that an image with spl/u-boot-spl.dtb can be created"""
1093         data = self._DoReadFile('051_u_boot_spl_dtb.dts')
1094         self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
1095
1096     def testSplNoDtb(self):
1097         """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
1098         data = self._DoReadFile('052_u_boot_spl_nodtb.dts')
1099         self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
1100
1101     def testSymbols(self):
1102         """Test binman can assign symbols embedded in U-Boot"""
1103         elf_fname = self.TestFile('u_boot_binman_syms')
1104         syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
1105         addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
1106         self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
1107
1108         self._SetupSplElf('u_boot_binman_syms')
1109         data = self._DoReadFile('053_symbols.dts')
1110         sym_values = struct.pack('<LQL', 0x24 + 0, 0x24 + 24, 0x24 + 20)
1111         expected = (sym_values + U_BOOT_SPL_DATA[16:] + chr(0xff) +
1112                     U_BOOT_DATA +
1113                     sym_values + U_BOOT_SPL_DATA[16:])
1114         self.assertEqual(expected, data)
1115
1116     def testPackUnitAddress(self):
1117         """Test that we support multiple binaries with the same name"""
1118         data = self._DoReadFile('054_unit_address.dts')
1119         self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
1120
1121     def testSections(self):
1122         """Basic test of sections"""
1123         data = self._DoReadFile('055_sections.dts')
1124         expected = (U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12 +
1125                     U_BOOT_DATA + '&' * 4)
1126         self.assertEqual(expected, data)
1127
1128     def testMap(self):
1129         """Tests outputting a map of the images"""
1130         _, _, map_data, _ = self._DoReadFileDtb('055_sections.dts', map=True)
1131         self.assertEqual('''ImagePos    Offset      Size  Name
1132 00000000  00000000  00000028  main-section
1133 00000000   00000000  00000010  section@0
1134 00000000    00000000  00000004  u-boot
1135 00000010   00000010  00000010  section@1
1136 00000010    00000000  00000004  u-boot
1137 00000020   00000020  00000004  section@2
1138 00000020    00000000  00000004  u-boot
1139 ''', map_data)
1140
1141     def testNamePrefix(self):
1142         """Tests that name prefixes are used"""
1143         _, _, map_data, _ = self._DoReadFileDtb('056_name_prefix.dts', map=True)
1144         self.assertEqual('''ImagePos    Offset      Size  Name
1145 00000000  00000000  00000028  main-section
1146 00000000   00000000  00000010  section@0
1147 00000000    00000000  00000004  ro-u-boot
1148 00000010   00000010  00000010  section@1
1149 00000010    00000000  00000004  rw-u-boot
1150 ''', map_data)
1151
1152     def testUnknownContents(self):
1153         """Test that obtaining the contents works as expected"""
1154         with self.assertRaises(ValueError) as e:
1155             self._DoReadFile('057_unknown_contents.dts', True)
1156         self.assertIn("Section '/binman': Internal error: Could not complete "
1157                 "processing of contents: remaining [<_testing.Entry__testing ",
1158                 str(e.exception))
1159
1160     def testBadChangeSize(self):
1161         """Test that trying to change the size of an entry fails"""
1162         with self.assertRaises(ValueError) as e:
1163             self._DoReadFile('059_change_size.dts', True)
1164         self.assertIn("Node '/binman/_testing': Cannot update entry size from "
1165                       '2 to 1', str(e.exception))
1166
1167     def testUpdateFdt(self):
1168         """Test that we can update the device tree with offset/size info"""
1169         _, _, _, out_dtb_fname = self._DoReadFileDtb('060_fdt_update.dts',
1170                                                      update_dtb=True)
1171         dtb = fdt.Fdt(out_dtb_fname)
1172         dtb.Scan()
1173         props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'])
1174         self.assertEqual({
1175             'image-pos': 0,
1176             'offset': 0,
1177             '_testing:offset': 32,
1178             '_testing:size': 1,
1179             '_testing:image-pos': 32,
1180             'section@0/u-boot:offset': 0,
1181             'section@0/u-boot:size': len(U_BOOT_DATA),
1182             'section@0/u-boot:image-pos': 0,
1183             'section@0:offset': 0,
1184             'section@0:size': 16,
1185             'section@0:image-pos': 0,
1186
1187             'section@1/u-boot:offset': 0,
1188             'section@1/u-boot:size': len(U_BOOT_DATA),
1189             'section@1/u-boot:image-pos': 16,
1190             'section@1:offset': 16,
1191             'section@1:size': 16,
1192             'section@1:image-pos': 16,
1193             'size': 40
1194         }, props)
1195
1196     def testUpdateFdtBad(self):
1197         """Test that we detect when ProcessFdt never completes"""
1198         with self.assertRaises(ValueError) as e:
1199             self._DoReadFileDtb('061_fdt_update_bad.dts', update_dtb=True)
1200         self.assertIn('Could not complete processing of Fdt: remaining '
1201                       '[<_testing.Entry__testing', str(e.exception))
1202
1203     def testEntryArgs(self):
1204         """Test passing arguments to entries from the command line"""
1205         entry_args = {
1206             'test-str-arg': 'test1',
1207             'test-int-arg': '456',
1208         }
1209         self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
1210         self.assertIn('image', control.images)
1211         entry = control.images['image'].GetEntries()['_testing']
1212         self.assertEqual('test0', entry.test_str_fdt)
1213         self.assertEqual('test1', entry.test_str_arg)
1214         self.assertEqual(123, entry.test_int_fdt)
1215         self.assertEqual(456, entry.test_int_arg)
1216
1217     def testEntryArgsMissing(self):
1218         """Test missing arguments and properties"""
1219         entry_args = {
1220             'test-int-arg': '456',
1221         }
1222         self._DoReadFileDtb('063_entry_args_missing.dts', entry_args=entry_args)
1223         entry = control.images['image'].GetEntries()['_testing']
1224         self.assertEqual('test0', entry.test_str_fdt)
1225         self.assertEqual(None, entry.test_str_arg)
1226         self.assertEqual(None, entry.test_int_fdt)
1227         self.assertEqual(456, entry.test_int_arg)
1228
1229     def testEntryArgsRequired(self):
1230         """Test missing arguments and properties"""
1231         entry_args = {
1232             'test-int-arg': '456',
1233         }
1234         with self.assertRaises(ValueError) as e:
1235             self._DoReadFileDtb('064_entry_args_required.dts')
1236         self.assertIn("Node '/binman/_testing': Missing required "
1237             'properties/entry args: test-str-arg, test-int-fdt, test-int-arg',
1238             str(e.exception))
1239
1240     def testEntryArgsInvalidFormat(self):
1241         """Test that an invalid entry-argument format is detected"""
1242         args = ['-d', self.TestFile('064_entry_args_required.dts'), '-ano-value']
1243         with self.assertRaises(ValueError) as e:
1244             self._DoBinman(*args)
1245         self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
1246
1247     def testEntryArgsInvalidInteger(self):
1248         """Test that an invalid entry-argument integer is detected"""
1249         entry_args = {
1250             'test-int-arg': 'abc',
1251         }
1252         with self.assertRaises(ValueError) as e:
1253             self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
1254         self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
1255                       "'test-int-arg' (value 'abc') to integer",
1256             str(e.exception))
1257
1258     def testEntryArgsInvalidDatatype(self):
1259         """Test that an invalid entry-argument datatype is detected
1260
1261         This test could be written in entry_test.py except that it needs
1262         access to control.entry_args, which seems more than that module should
1263         be able to see.
1264         """
1265         entry_args = {
1266             'test-bad-datatype-arg': '12',
1267         }
1268         with self.assertRaises(ValueError) as e:
1269             self._DoReadFileDtb('065_entry_args_unknown_datatype.dts',
1270                                 entry_args=entry_args)
1271         self.assertIn('GetArg() internal error: Unknown data type ',
1272                       str(e.exception))
1273
1274     def testText(self):
1275         """Test for a text entry type"""
1276         entry_args = {
1277             'test-id': TEXT_DATA,
1278             'test-id2': TEXT_DATA2,
1279             'test-id3': TEXT_DATA3,
1280         }
1281         data, _, _, _ = self._DoReadFileDtb('066_text.dts',
1282                                             entry_args=entry_args)
1283         expected = (TEXT_DATA + chr(0) * (8 - len(TEXT_DATA)) + TEXT_DATA2 +
1284                     TEXT_DATA3 + 'some text')
1285         self.assertEqual(expected, data)
1286
1287     def testEntryDocs(self):
1288         """Test for creation of entry documentation"""
1289         with test_util.capture_sys_output() as (stdout, stderr):
1290             control.WriteEntryDocs(binman.GetEntryModules())
1291         self.assertTrue(len(stdout.getvalue()) > 0)
1292
1293     def testEntryDocsMissing(self):
1294         """Test handling of missing entry documentation"""
1295         with self.assertRaises(ValueError) as e:
1296             with test_util.capture_sys_output() as (stdout, stderr):
1297                 control.WriteEntryDocs(binman.GetEntryModules(), 'u_boot')
1298         self.assertIn('Documentation is missing for modules: u_boot',
1299                       str(e.exception))
1300
1301     def testFmap(self):
1302         """Basic test of generation of a flashrom fmap"""
1303         data = self._DoReadFile('067_fmap.dts')
1304         fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1305         expected = U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12
1306         self.assertEqual(expected, data[:32])
1307         self.assertEqual('__FMAP__', fhdr.signature)
1308         self.assertEqual(1, fhdr.ver_major)
1309         self.assertEqual(0, fhdr.ver_minor)
1310         self.assertEqual(0, fhdr.base)
1311         self.assertEqual(16 + 16 +
1312                          fmap_util.FMAP_HEADER_LEN +
1313                          fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
1314         self.assertEqual('FMAP', fhdr.name)
1315         self.assertEqual(3, fhdr.nareas)
1316         for fentry in fentries:
1317             self.assertEqual(0, fentry.flags)
1318
1319         self.assertEqual(0, fentries[0].offset)
1320         self.assertEqual(4, fentries[0].size)
1321         self.assertEqual('RO_U_BOOT', fentries[0].name)
1322
1323         self.assertEqual(16, fentries[1].offset)
1324         self.assertEqual(4, fentries[1].size)
1325         self.assertEqual('RW_U_BOOT', fentries[1].name)
1326
1327         self.assertEqual(32, fentries[2].offset)
1328         self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1329                          fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1330         self.assertEqual('FMAP', fentries[2].name)
1331
1332     def testBlobNamedByArg(self):
1333         """Test we can add a blob with the filename coming from an entry arg"""
1334         entry_args = {
1335             'cros-ec-rw-path': 'ecrw.bin',
1336         }
1337         data, _, _, _ = self._DoReadFileDtb('068_blob_named_by_arg.dts',
1338                                             entry_args=entry_args)
1339
1340     def testFill(self):
1341         """Test for an fill entry type"""
1342         data = self._DoReadFile('069_fill.dts')
1343         expected = 8 * chr(0xff) + 8 * chr(0)
1344         self.assertEqual(expected, data)
1345
1346     def testFillNoSize(self):
1347         """Test for an fill entry type with no size"""
1348         with self.assertRaises(ValueError) as e:
1349             self._DoReadFile('070_fill_no_size.dts')
1350         self.assertIn("'fill' entry must have a size property",
1351                       str(e.exception))
1352
1353     def _HandleGbbCommand(self, pipe_list):
1354         """Fake calls to the futility utility"""
1355         if pipe_list[0][0] == 'futility':
1356             fname = pipe_list[0][-1]
1357             # Append our GBB data to the file, which will happen every time the
1358             # futility command is called.
1359             with open(fname, 'ab') as fd:
1360                 fd.write(GBB_DATA)
1361             return command.CommandResult()
1362
1363     def testGbb(self):
1364         """Test for the Chromium OS Google Binary Block"""
1365         command.test_result = self._HandleGbbCommand
1366         entry_args = {
1367             'keydir': 'devkeys',
1368             'bmpblk': 'bmpblk.bin',
1369         }
1370         data, _, _, _ = self._DoReadFileDtb('071_gbb.dts', entry_args=entry_args)
1371
1372         # Since futility
1373         expected = GBB_DATA + GBB_DATA + 8 * chr(0) + (0x2180 - 16) * chr(0)
1374         self.assertEqual(expected, data)
1375
1376     def testGbbTooSmall(self):
1377         """Test for the Chromium OS Google Binary Block being large enough"""
1378         with self.assertRaises(ValueError) as e:
1379             self._DoReadFileDtb('072_gbb_too_small.dts')
1380         self.assertIn("Node '/binman/gbb': GBB is too small",
1381                       str(e.exception))
1382
1383     def testGbbNoSize(self):
1384         """Test for the Chromium OS Google Binary Block having a size"""
1385         with self.assertRaises(ValueError) as e:
1386             self._DoReadFileDtb('073_gbb_no_size.dts')
1387         self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
1388                       str(e.exception))
1389
1390     def _HandleVblockCommand(self, pipe_list):
1391         """Fake calls to the futility utility"""
1392         if pipe_list[0][0] == 'futility':
1393             fname = pipe_list[0][3]
1394             with open(fname, 'wb') as fd:
1395                 fd.write(VBLOCK_DATA)
1396             return command.CommandResult()
1397
1398     def testVblock(self):
1399         """Test for the Chromium OS Verified Boot Block"""
1400         command.test_result = self._HandleVblockCommand
1401         entry_args = {
1402             'keydir': 'devkeys',
1403         }
1404         data, _, _, _ = self._DoReadFileDtb('074_vblock.dts',
1405                                             entry_args=entry_args)
1406         expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
1407         self.assertEqual(expected, data)
1408
1409     def testVblockNoContent(self):
1410         """Test we detect a vblock which has no content to sign"""
1411         with self.assertRaises(ValueError) as e:
1412             self._DoReadFile('075_vblock_no_content.dts')
1413         self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
1414                       'property', str(e.exception))
1415
1416     def testVblockBadPhandle(self):
1417         """Test that we detect a vblock with an invalid phandle in contents"""
1418         with self.assertRaises(ValueError) as e:
1419             self._DoReadFile('076_vblock_bad_phandle.dts')
1420         self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
1421                       '1000', str(e.exception))
1422
1423     def testVblockBadEntry(self):
1424         """Test that we detect an entry that points to a non-entry"""
1425         with self.assertRaises(ValueError) as e:
1426             self._DoReadFile('077_vblock_bad_entry.dts')
1427         self.assertIn("Node '/binman/vblock': Cannot find entry for node "
1428                       "'other'", str(e.exception))
1429
1430     def testTpl(self):
1431         """Test that an image with TPL and ots device tree can be created"""
1432         # ELF file with a '__bss_size' symbol
1433         with open(self.TestFile('bss_data'), 'rb') as fd:
1434             TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1435         data = self._DoReadFile('078_u_boot_tpl.dts')
1436         self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
1437
1438     def testUsesPos(self):
1439         """Test that the 'pos' property cannot be used anymore"""
1440         with self.assertRaises(ValueError) as e:
1441            data = self._DoReadFile('079_uses_pos.dts')
1442         self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
1443                       "'pos'", str(e.exception))
1444
1445     def testFillZero(self):
1446         """Test for an fill entry type with a size of 0"""
1447         data = self._DoReadFile('080_fill_empty.dts')
1448         self.assertEqual(chr(0) * 16, data)
1449
1450     def testTextMissing(self):
1451         """Test for a text entry type where there is no text"""
1452         with self.assertRaises(ValueError) as e:
1453             self._DoReadFileDtb('066_text.dts',)
1454         self.assertIn("Node '/binman/text': No value provided for text label "
1455                       "'test-id'", str(e.exception))
1456
1457     def testPackStart16Tpl(self):
1458         """Test that an image with an x86 start16 TPL region can be created"""
1459         data = self._DoReadFile('081_x86-start16-tpl.dts')
1460         self.assertEqual(X86_START16_TPL_DATA, data[:len(X86_START16_TPL_DATA)])
1461
1462     def testSelectImage(self):
1463         """Test that we can select which images to build"""
1464         expected = 'Skipping images: image1'
1465
1466         # We should only get the expected message in verbose mode
1467         for verbosity in (None, 2):
1468             with test_util.capture_sys_output() as (stdout, stderr):
1469                 retcode = self._DoTestFile('006_dual_image.dts',
1470                                            verbosity=verbosity,
1471                                            images=['image2'])
1472             self.assertEqual(0, retcode)
1473             if verbosity:
1474                 self.assertIn(expected, stdout.getvalue())
1475             else:
1476                 self.assertNotIn(expected, stdout.getvalue())
1477
1478             self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
1479             self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
1480
1481     def testUpdateFdtAll(self):
1482         """Test that all device trees are updated with offset/size info"""
1483         data, _, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
1484                                             use_real_dtb=True, update_dtb=True)
1485
1486         base_expected = {
1487             'section:image-pos': 0,
1488             'u-boot-tpl-dtb:size': 513,
1489             'u-boot-spl-dtb:size': 513,
1490             'u-boot-spl-dtb:offset': 493,
1491             'image-pos': 0,
1492             'section/u-boot-dtb:image-pos': 0,
1493             'u-boot-spl-dtb:image-pos': 493,
1494             'section/u-boot-dtb:size': 493,
1495             'u-boot-tpl-dtb:image-pos': 1006,
1496             'section/u-boot-dtb:offset': 0,
1497             'section:size': 493,
1498             'offset': 0,
1499             'section:offset': 0,
1500             'u-boot-tpl-dtb:offset': 1006,
1501             'size': 1519
1502         }
1503
1504         # We expect three device-tree files in the output, one after the other.
1505         # Read them in sequence. We look for an 'spl' property in the SPL tree,
1506         # and 'tpl' in the TPL tree, to make sure they are distinct from the
1507         # main U-Boot tree. All three should have the same postions and offset.
1508         start = 0
1509         for item in ['', 'spl', 'tpl']:
1510             dtb = fdt.Fdt.FromData(data[start:])
1511             dtb.Scan()
1512             props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos',
1513                                             'spl', 'tpl'])
1514             expected = dict(base_expected)
1515             if item:
1516                 expected[item] = 0
1517             self.assertEqual(expected, props)
1518             start += dtb._fdt_obj.totalsize()
1519
1520     def testUpdateFdtOutput(self):
1521         """Test that output DTB files are updated"""
1522         try:
1523             data, dtb_data, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
1524                     use_real_dtb=True, update_dtb=True, reset_dtbs=False)
1525
1526             # Unfortunately, compiling a source file always results in a file
1527             # called source.dtb (see fdt_util.EnsureCompiled()). The test
1528             # source file (e.g. test/075_fdt_update_all.dts) thus does not enter
1529             # binman as a file called u-boot.dtb. To fix this, copy the file
1530             # over to the expected place.
1531             #tools.WriteFile(os.path.join(self._indir, 'u-boot.dtb'),
1532                     #tools.ReadFile(tools.GetOutputFilename('source.dtb')))
1533             start = 0
1534             for fname in ['u-boot.dtb.out', 'spl/u-boot-spl.dtb.out',
1535                           'tpl/u-boot-tpl.dtb.out']:
1536                 dtb = fdt.Fdt.FromData(data[start:])
1537                 size = dtb._fdt_obj.totalsize()
1538                 pathname = tools.GetOutputFilename(os.path.split(fname)[1])
1539                 outdata = tools.ReadFile(pathname)
1540                 name = os.path.split(fname)[0]
1541
1542                 if name:
1543                     orig_indata = self._GetDtbContentsForSplTpl(dtb_data, name)
1544                 else:
1545                     orig_indata = dtb_data
1546                 self.assertNotEqual(outdata, orig_indata,
1547                         "Expected output file '%s' be updated" % pathname)
1548                 self.assertEqual(outdata, data[start:start + size],
1549                         "Expected output file '%s' to match output image" %
1550                         pathname)
1551                 start += size
1552         finally:
1553             self._ResetDtbs()
1554
1555     def _decompress(self, data):
1556         out = os.path.join(self._indir, 'lz4.tmp')
1557         with open(out, 'wb') as fd:
1558             fd.write(data)
1559         return tools.Run('lz4', '-dc', out, binary=True)
1560         '''
1561         try:
1562             orig = lz4.frame.decompress(data)
1563         except AttributeError:
1564             orig = lz4.decompress(data)
1565         '''
1566
1567     def testCompress(self):
1568         """Test compression of blobs"""
1569         data, _, _, out_dtb_fname = self._DoReadFileDtb('083_compress.dts',
1570                                             use_real_dtb=True, update_dtb=True)
1571         dtb = fdt.Fdt(out_dtb_fname)
1572         dtb.Scan()
1573         props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
1574         orig = self._decompress(data)
1575         self.assertEquals(COMPRESS_DATA, orig)
1576         expected = {
1577             'blob:uncomp-size': len(COMPRESS_DATA),
1578             'blob:size': len(data),
1579             'size': len(data),
1580             }
1581         self.assertEqual(expected, props)
1582
1583     def testFiles(self):
1584         """Test bringing in multiple files"""
1585         data = self._DoReadFile('084_files.dts')
1586         self.assertEqual(FILES_DATA, data)
1587
1588     def testFilesCompress(self):
1589         """Test bringing in multiple files and compressing them"""
1590         data = self._DoReadFile('085_files_compress.dts')
1591
1592         image = control.images['image']
1593         entries = image.GetEntries()
1594         files = entries['files']
1595         entries = files._section._entries
1596
1597         orig = ''
1598         for i in range(1, 3):
1599             key = '%d.dat' % i
1600             start = entries[key].image_pos
1601             len = entries[key].size
1602             chunk = data[start:start + len]
1603             orig += self._decompress(chunk)
1604
1605         self.assertEqual(FILES_DATA, orig)
1606
1607     def testFilesMissing(self):
1608         """Test missing files"""
1609         with self.assertRaises(ValueError) as e:
1610             data = self._DoReadFile('086_files_none.dts')
1611         self.assertIn("Node '/binman/files': Pattern \'files/*.none\' matched "
1612                       'no files', str(e.exception))
1613
1614     def testFilesNoPattern(self):
1615         """Test missing files"""
1616         with self.assertRaises(ValueError) as e:
1617             data = self._DoReadFile('087_files_no_pattern.dts')
1618         self.assertIn("Node '/binman/files': Missing 'pattern' property",
1619                       str(e.exception))
1620
1621     def testExpandSize(self):
1622         """Test an expanding entry"""
1623         data, _, map_data, _ = self._DoReadFileDtb('088_expand_size.dts',
1624                                                    map=True)
1625         expect = ('a' * 8 + U_BOOT_DATA +
1626                   MRC_DATA + 'b' * 1 + U_BOOT_DATA +
1627                   'c' * 8 + U_BOOT_DATA +
1628                   'd' * 8)
1629         self.assertEqual(expect, data)
1630         self.assertEqual('''ImagePos    Offset      Size  Name
1631 00000000  00000000  00000028  main-section
1632 00000000   00000000  00000008  fill
1633 00000008   00000008  00000004  u-boot
1634 0000000c   0000000c  00000004  section
1635 0000000c    00000000  00000003  intel-mrc
1636 00000010   00000010  00000004  u-boot2
1637 00000014   00000014  0000000c  section2
1638 00000014    00000000  00000008  fill
1639 0000001c    00000008  00000004  u-boot
1640 00000020   00000020  00000008  fill2
1641 ''', map_data)
1642
1643     def testExpandSizeBad(self):
1644         """Test an expanding entry which fails to provide contents"""
1645         with test_util.capture_sys_output() as (stdout, stderr):
1646             with self.assertRaises(ValueError) as e:
1647                 self._DoReadFileDtb('089_expand_size_bad.dts', map=True)
1648         self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
1649                       'expanding entry', str(e.exception))
1650
1651     def testHash(self):
1652         """Test hashing of the contents of an entry"""
1653         _, _, _, out_dtb_fname = self._DoReadFileDtb('090_hash.dts',
1654                 use_real_dtb=True, update_dtb=True)
1655         dtb = fdt.Fdt(out_dtb_fname)
1656         dtb.Scan()
1657         hash_node = dtb.GetNode('/binman/u-boot/hash').props['value']
1658         m = hashlib.sha256()
1659         m.update(U_BOOT_DATA)
1660         self.assertEqual(m.digest(), ''.join(hash_node.value))
1661
1662     def testHashNoAlgo(self):
1663         with self.assertRaises(ValueError) as e:
1664             self._DoReadFileDtb('091_hash_no_algo.dts', update_dtb=True)
1665         self.assertIn("Node \'/binman/u-boot\': Missing \'algo\' property for "
1666                       'hash node', str(e.exception))
1667
1668     def testHashBadAlgo(self):
1669         with self.assertRaises(ValueError) as e:
1670             self._DoReadFileDtb('092_hash_bad_algo.dts', update_dtb=True)
1671         self.assertIn("Node '/binman/u-boot': Unknown hash algorithm",
1672                       str(e.exception))
1673
1674     def testHashSection(self):
1675         """Test hashing of the contents of an entry"""
1676         _, _, _, out_dtb_fname = self._DoReadFileDtb('099_hash_section.dts',
1677                 use_real_dtb=True, update_dtb=True)
1678         dtb = fdt.Fdt(out_dtb_fname)
1679         dtb.Scan()
1680         hash_node = dtb.GetNode('/binman/section/hash').props['value']
1681         m = hashlib.sha256()
1682         m.update(U_BOOT_DATA)
1683         m.update(16 * 'a')
1684         self.assertEqual(m.digest(), ''.join(hash_node.value))
1685
1686     def testPackUBootTplMicrocode(self):
1687         """Test that x86 microcode can be handled correctly in TPL
1688
1689         We expect to see the following in the image, in order:
1690             u-boot-tpl-nodtb.bin with a microcode pointer inserted at the correct
1691                 place
1692             u-boot-tpl.dtb with the microcode removed
1693             the microcode
1694         """
1695         with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
1696             TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1697         first, pos_and_size = self._RunMicrocodeTest('093_x86_tpl_ucode.dts',
1698                                                      U_BOOT_TPL_NODTB_DATA)
1699         self.assertEqual('tplnodtb with microc' + pos_and_size +
1700                          'ter somewhere in here', first)
1701
1702     def testFmapX86(self):
1703         """Basic test of generation of a flashrom fmap"""
1704         data = self._DoReadFile('094_fmap_x86.dts')
1705         fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1706         expected = U_BOOT_DATA + MRC_DATA + 'a' * (32 - 7)
1707         self.assertEqual(expected, data[:32])
1708         fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1709
1710         self.assertEqual(0x100, fhdr.image_size)
1711
1712         self.assertEqual(0, fentries[0].offset)
1713         self.assertEqual(4, fentries[0].size)
1714         self.assertEqual('U_BOOT', fentries[0].name)
1715
1716         self.assertEqual(4, fentries[1].offset)
1717         self.assertEqual(3, fentries[1].size)
1718         self.assertEqual('INTEL_MRC', fentries[1].name)
1719
1720         self.assertEqual(32, fentries[2].offset)
1721         self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1722                          fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1723         self.assertEqual('FMAP', fentries[2].name)
1724
1725     def testFmapX86Section(self):
1726         """Basic test of generation of a flashrom fmap"""
1727         data = self._DoReadFile('095_fmap_x86_section.dts')
1728         expected = U_BOOT_DATA + MRC_DATA + 'b' * (32 - 7)
1729         self.assertEqual(expected, data[:32])
1730         fhdr, fentries = fmap_util.DecodeFmap(data[36:])
1731
1732         self.assertEqual(0x100, fhdr.image_size)
1733
1734         self.assertEqual(0, fentries[0].offset)
1735         self.assertEqual(4, fentries[0].size)
1736         self.assertEqual('U_BOOT', fentries[0].name)
1737
1738         self.assertEqual(4, fentries[1].offset)
1739         self.assertEqual(3, fentries[1].size)
1740         self.assertEqual('INTEL_MRC', fentries[1].name)
1741
1742         self.assertEqual(36, fentries[2].offset)
1743         self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1744                          fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1745         self.assertEqual('FMAP', fentries[2].name)
1746
1747     def testElf(self):
1748         """Basic test of ELF entries"""
1749         self._SetupSplElf()
1750         with open(self.TestFile('bss_data'), 'rb') as fd:
1751             TestFunctional._MakeInputFile('-boot', fd.read())
1752         data = self._DoReadFile('096_elf.dts')
1753
1754     def testElfStripg(self):
1755         """Basic test of ELF entries"""
1756         self._SetupSplElf()
1757         with open(self.TestFile('bss_data'), 'rb') as fd:
1758             TestFunctional._MakeInputFile('-boot', fd.read())
1759         data = self._DoReadFile('097_elf_strip.dts')
1760
1761     def testPackOverlapMap(self):
1762         """Test that overlapping regions are detected"""
1763         with test_util.capture_sys_output() as (stdout, stderr):
1764             with self.assertRaises(ValueError) as e:
1765                 self._DoTestFile('014_pack_overlap.dts', map=True)
1766         map_fname = tools.GetOutputFilename('image.map')
1767         self.assertEqual("Wrote map file '%s' to show errors\n" % map_fname,
1768                          stdout.getvalue())
1769
1770         # We should not get an inmage, but there should be a map file
1771         self.assertFalse(os.path.exists(tools.GetOutputFilename('image.bin')))
1772         self.assertTrue(os.path.exists(map_fname))
1773         map_data = tools.ReadFile(map_fname)
1774         self.assertEqual('''ImagePos    Offset      Size  Name
1775 <none>    00000000  00000007  main-section
1776 <none>     00000000  00000004  u-boot
1777 <none>     00000003  00000004  u-boot-align
1778 ''', map_data)
1779
1780     def testPacRefCode(self):
1781         """Test that an image with an Intel Reference code binary works"""
1782         data = self._DoReadFile('100_intel_refcode.dts')
1783         self.assertEqual(REFCODE_DATA, data[:len(REFCODE_DATA)])
1784
1785     def testSectionOffset(self):
1786         """Tests use of a section with an offset"""
1787         data, _, map_data, _ = self._DoReadFileDtb('101_sections_offset.dts',
1788                                                    map=True)
1789         self.assertEqual('''ImagePos    Offset      Size  Name
1790 00000000  00000000  00000038  main-section
1791 00000004   00000004  00000010  section@0
1792 00000004    00000000  00000004  u-boot
1793 00000018   00000018  00000010  section@1
1794 00000018    00000000  00000004  u-boot
1795 0000002c   0000002c  00000004  section@2
1796 0000002c    00000000  00000004  u-boot
1797 ''', map_data)
1798         self.assertEqual(data,
1799                          4 * chr(0x26) + U_BOOT_DATA + 12 * chr(0x21) +
1800                          4 * chr(0x26) + U_BOOT_DATA + 12 * chr(0x61) +
1801                          4 * chr(0x26) + U_BOOT_DATA + 8 * chr(0x26))
1802
1803
1804 if __name__ == "__main__":
1805     unittest.main()