1 # SPDX-License-Identifier: GPL-2.0+
2 # Copyright (c) 2016 Google, Inc
3 # Written by Simon Glass <sjg@chromium.org>
5 # To run a single test, change to this directory, and:
7 # python -m unittest func_test.TestFunctional.testHelp
9 from __future__ import print_function
12 from optparse import OptionParser
35 # Contents of test files, corresponding to different entry types
37 U_BOOT_IMG_DATA = b'img'
38 U_BOOT_SPL_DATA = b'56780123456789abcde'
39 U_BOOT_TPL_DATA = b'tpl'
43 U_BOOT_DTB_DATA = b'udtb'
44 U_BOOT_SPL_DTB_DATA = b'spldtb'
45 U_BOOT_TPL_DTB_DATA = b'tpldtb'
46 X86_START16_DATA = b'start16'
47 X86_START16_SPL_DATA = b'start16spl'
48 X86_START16_TPL_DATA = b'start16tpl'
49 PPC_MPC85XX_BR_DATA = b'ppcmpc85xxbr'
50 U_BOOT_NODTB_DATA = b'nodtb with microcode pointer somewhere in here'
51 U_BOOT_SPL_NODTB_DATA = b'splnodtb with microcode pointer somewhere in here'
52 U_BOOT_TPL_NODTB_DATA = b'tplnodtb with microcode pointer somewhere in here'
60 CROS_EC_RW_DATA = b'ecrw'
64 FILES_DATA = (b"sorry I'm late\nOh, don't bother apologising, I'm " +
65 b"sorry you're alive\n")
66 COMPRESS_DATA = b'compress xxxxxxxxxxxxxxxxxxxxxx data'
67 REFCODE_DATA = b'refcode'
70 class TestFunctional(unittest.TestCase):
71 """Functional tests for binman
73 Most of these use a sample .dts file to build an image and then check
74 that it looks correct. The sample files are in the test/ subdirectory
77 For each entry type a very small test file is created using fixed
78 string contents. This makes it easy to test that things look right, and
81 In some cases a 'real' file must be used - these are also supplied in
89 # Handle the case where argv[0] is 'python'
90 self._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
91 self._binman_pathname = os.path.join(self._binman_dir, 'binman')
93 # Create a temporary directory for input files
94 self._indir = tempfile.mkdtemp(prefix='binmant.')
96 # Create some test files
97 TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
98 TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
99 TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
100 TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
101 TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
102 TestFunctional._MakeInputFile('me.bin', ME_DATA)
103 TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
105 TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
106 TestFunctional._MakeInputFile('u-boot-br.bin', PPC_MPC85XX_BR_DATA)
107 TestFunctional._MakeInputFile('spl/u-boot-x86-16bit-spl.bin',
108 X86_START16_SPL_DATA)
109 TestFunctional._MakeInputFile('tpl/u-boot-x86-16bit-tpl.bin',
110 X86_START16_TPL_DATA)
111 TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
112 TestFunctional._MakeInputFile('spl/u-boot-spl-nodtb.bin',
113 U_BOOT_SPL_NODTB_DATA)
114 TestFunctional._MakeInputFile('tpl/u-boot-tpl-nodtb.bin',
115 U_BOOT_TPL_NODTB_DATA)
116 TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
117 TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
118 TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
119 TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
120 TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
121 TestFunctional._MakeInputDir('devkeys')
122 TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
123 TestFunctional._MakeInputFile('refcode.bin', REFCODE_DATA)
125 # ELF file with a '_dt_ucode_base_size' symbol
126 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
127 TestFunctional._MakeInputFile('u-boot', fd.read())
129 # Intel flash descriptor file
130 with open(self.TestFile('descriptor.bin'), 'rb') as fd:
131 TestFunctional._MakeInputFile('descriptor.bin', fd.read())
133 shutil.copytree(self.TestFile('files'),
134 os.path.join(self._indir, 'files'))
136 TestFunctional._MakeInputFile('compress', COMPRESS_DATA)
138 # Travis-CI may have an old lz4
141 tools.Run('lz4', '--no-frame-crc', '-c',
142 os.path.join(self._indir, 'u-boot.bin'))
144 self.have_lz4 = False
147 def tearDownClass(self):
148 """Remove the temporary input directory and its contents"""
149 if self.preserve_indir:
150 print('Preserving input dir: %s' % self._indir)
153 shutil.rmtree(self._indir)
157 def setup_test_args(cls, preserve_indir=False, preserve_outdirs=False,
158 toolpath=None, verbosity=None):
159 """Accept arguments controlling test execution
162 preserve_indir: Preserve the shared input directory used by all
164 preserve_outdir: Preserve the output directories used by tests. Each
165 test has its own, so this is normally only useful when running a
167 toolpath: ist of paths to use for tools
169 cls.preserve_indir = preserve_indir
170 cls.preserve_outdirs = preserve_outdirs
171 cls.toolpath = toolpath
172 cls.verbosity = verbosity
175 if not self.have_lz4:
176 self.skipTest('lz4 --no-frame-crc not available')
179 # Enable this to turn on debugging output
180 # tout.Init(tout.DEBUG)
181 command.test_result = None
184 """Remove the temporary output directory"""
185 if self.preserve_outdirs:
186 print('Preserving output dir: %s' % tools.outdir)
188 tools._FinaliseForTest()
191 def _ResetDtbs(self):
192 TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
193 TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
194 TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
196 def _RunBinman(self, *args, **kwargs):
197 """Run binman using the command line
200 Arguments to pass, as a list of strings
201 kwargs: Arguments to pass to Command.RunPipe()
203 result = command.RunPipe([[self._binman_pathname] + list(args)],
204 capture=True, capture_stderr=True, raise_on_error=False)
205 if result.return_code and kwargs.get('raise_on_error', True):
206 raise Exception("Error running '%s': %s" % (' '.join(args),
207 result.stdout + result.stderr))
210 def _DoBinman(self, *argv):
211 """Run binman using directly (in the same process)
214 Arguments to pass, as a list of strings
216 Return value (0 for success)
219 args = cmdline.ParseArgs(argv)
220 args.pager = 'binman-invalid-pager'
221 args.build_dir = self._indir
223 # For testing, you can force an increase in verbosity here
224 # args.verbosity = tout.DEBUG
225 return control.Binman(args)
227 def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
228 entry_args=None, images=None, use_real_dtb=False,
230 """Run binman with a given test file
233 fname: Device-tree source filename to use (e.g. 005_simple.dts)
234 debug: True to enable debugging output
235 map: True to output map files for the images
236 update_dtb: Update the offset and size of each entry in the device
237 tree before packing it into the image
238 entry_args: Dict of entry args to supply to binman
240 value: value of that arg
241 images: List of image names to build
246 if verbosity is not None:
247 args.append('-v%d' % verbosity)
249 args.append('-v%d' % self.verbosity)
251 for path in self.toolpath:
252 args += ['--toolpath', path]
253 args += ['build', '-p', '-I', self._indir, '-d', self.TestFile(fname)]
259 args.append('--fake-dtb')
261 for arg, value in entry_args.items():
262 args.append('-a%s=%s' % (arg, value))
265 args += ['-i', image]
266 return self._DoBinman(*args)
268 def _SetupDtb(self, fname, outfile='u-boot.dtb'):
269 """Set up a new test device-tree file
271 The given file is compiled and set up as the device tree to be used
275 fname: Filename of .dts file to read
276 outfile: Output filename for compiled device-tree binary
279 Contents of device-tree binary
281 tools.PrepareOutputDir(None)
282 dtb = fdt_util.EnsureCompiled(self.TestFile(fname))
283 with open(dtb, 'rb') as fd:
285 TestFunctional._MakeInputFile(outfile, data)
286 tools.FinaliseOutputDir()
289 def _GetDtbContentsForSplTpl(self, dtb_data, name):
290 """Create a version of the main DTB for SPL or SPL
292 For testing we don't actually have different versions of the DTB. With
293 U-Boot we normally run fdtgrep to remove unwanted nodes, but for tests
294 we don't normally have any unwanted nodes.
296 We still want the DTBs for SPL and TPL to be different though, since
297 otherwise it is confusing to know which one we are looking at. So add
298 an 'spl' or 'tpl' property to the top-level node.
300 dtb = fdt.Fdt.FromData(dtb_data)
302 dtb.GetNode('/binman').AddZeroProp(name)
303 dtb.Sync(auto_resize=True)
305 return dtb.GetContents()
307 def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
308 update_dtb=False, entry_args=None, reset_dtbs=True):
309 """Run binman and return the resulting image
311 This runs binman with a given test file and then reads the resulting
312 output file. It is a shortcut function since most tests need to do
315 Raises an assertion failure if binman returns a non-zero exit code.
318 fname: Device-tree source filename to use (e.g. 005_simple.dts)
319 use_real_dtb: True to use the test file as the contents of
320 the u-boot-dtb entry. Normally this is not needed and the
321 test contents (the U_BOOT_DTB_DATA string) can be used.
322 But in some test we need the real contents.
323 map: True to output map files for the images
324 update_dtb: Update the offset and size of each entry in the device
325 tree before packing it into the image
329 Resulting image contents
331 Map data showing contents of image (or None if none)
332 Output device tree binary filename ('u-boot.dtb' path)
335 # Use the compiled test file as the u-boot-dtb input
337 dtb_data = self._SetupDtb(fname)
339 # For testing purposes, make a copy of the DT for SPL and TPL. Add
340 # a node indicating which it is, so aid verification.
341 for name in ['spl', 'tpl']:
342 dtb_fname = '%s/u-boot-%s.dtb' % (name, name)
343 outfile = os.path.join(self._indir, dtb_fname)
344 TestFunctional._MakeInputFile(dtb_fname,
345 self._GetDtbContentsForSplTpl(dtb_data, name))
348 retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
349 entry_args=entry_args, use_real_dtb=use_real_dtb)
350 self.assertEqual(0, retcode)
351 out_dtb_fname = tools.GetOutputFilename('u-boot.dtb.out')
353 # Find the (only) image, read it and return its contents
354 image = control.images['image']
355 image_fname = tools.GetOutputFilename('image.bin')
356 self.assertTrue(os.path.exists(image_fname))
358 map_fname = tools.GetOutputFilename('image.map')
359 with open(map_fname) as fd:
363 with open(image_fname, 'rb') as fd:
364 return fd.read(), dtb_data, map_data, out_dtb_fname
366 # Put the test file back
367 if reset_dtbs and use_real_dtb:
370 def _DoReadFileRealDtb(self, fname):
371 """Run binman with a real .dtb file and return the resulting data
374 fname: DT source filename to use (e.g. 082_fdt_update_all.dts)
377 Resulting image contents
379 return self._DoReadFileDtb(fname, use_real_dtb=True, update_dtb=True)[0]
381 def _DoReadFile(self, fname, use_real_dtb=False):
382 """Helper function which discards the device-tree binary
385 fname: Device-tree source filename to use (e.g. 005_simple.dts)
386 use_real_dtb: True to use the test file as the contents of
387 the u-boot-dtb entry. Normally this is not needed and the
388 test contents (the U_BOOT_DTB_DATA string) can be used.
389 But in some test we need the real contents.
392 Resulting image contents
394 return self._DoReadFileDtb(fname, use_real_dtb)[0]
397 def _MakeInputFile(self, fname, contents):
398 """Create a new test input file, creating directories as needed
401 fname: Filename to create
402 contents: File contents to write in to the file
404 Full pathname of file created
406 pathname = os.path.join(self._indir, fname)
407 dirname = os.path.dirname(pathname)
408 if dirname and not os.path.exists(dirname):
410 with open(pathname, 'wb') as fd:
415 def _MakeInputDir(self, dirname):
416 """Create a new test input directory, creating directories as needed
419 dirname: Directory name to create
422 Full pathname of directory created
424 pathname = os.path.join(self._indir, dirname)
425 if not os.path.exists(pathname):
426 os.makedirs(pathname)
430 def _SetupSplElf(self, src_fname='bss_data'):
431 """Set up an ELF file with a '_dt_ucode_base_size' symbol
434 Filename of ELF file to use as SPL
436 with open(self.TestFile(src_fname), 'rb') as fd:
437 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
440 def TestFile(self, fname):
441 return os.path.join(self._binman_dir, 'test', fname)
443 def AssertInList(self, grep_list, target):
444 """Assert that at least one of a list of things is in a target
447 grep_list: List of strings to check
448 target: Target string
450 for grep in grep_list:
453 self.fail("Error: '%s' not found in '%s'" % (grep_list, target))
455 def CheckNoGaps(self, entries):
456 """Check that all entries fit together without gaps
459 entries: List of entries to check
462 for entry in entries.values():
463 self.assertEqual(offset, entry.offset)
466 def GetFdtLen(self, dtb):
467 """Get the totalsize field from a device-tree binary
470 dtb: Device-tree binary contents
473 Total size of device-tree binary, from the header
475 return struct.unpack('>L', dtb[4:8])[0]
477 def _GetPropTree(self, dtb, prop_names, prefix='/binman/'):
478 def AddNode(node, path):
480 path += '/' + node.name
481 for prop in node.props.values():
482 if prop.name in prop_names:
483 prop_path = path + ':' + prop.name
484 tree[prop_path[len(prefix):]] = fdt_util.fdt32_to_cpu(
486 for subnode in node.subnodes:
487 AddNode(subnode, path)
490 AddNode(dtb.GetRoot(), '')
494 """Test a basic run with valid args"""
495 result = self._RunBinman('-h')
497 def testFullHelp(self):
498 """Test that the full help is displayed with -H"""
499 result = self._RunBinman('-H')
500 help_file = os.path.join(self._binman_dir, 'README')
501 # Remove possible extraneous strings
502 extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
503 gothelp = result.stdout.replace(extra, '')
504 self.assertEqual(len(gothelp), os.path.getsize(help_file))
505 self.assertEqual(0, len(result.stderr))
506 self.assertEqual(0, result.return_code)
508 def testFullHelpInternal(self):
509 """Test that the full help is displayed with -H"""
511 command.test_result = command.CommandResult()
512 result = self._DoBinman('-H')
513 help_file = os.path.join(self._binman_dir, 'README')
515 command.test_result = None
518 """Test that the basic help is displayed with -h"""
519 result = self._RunBinman('-h')
520 self.assertTrue(len(result.stdout) > 200)
521 self.assertEqual(0, len(result.stderr))
522 self.assertEqual(0, result.return_code)
525 """Test that we can run it with a specific board"""
526 self._SetupDtb('005_simple.dts', 'sandbox/u-boot.dtb')
527 TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
528 result = self._DoBinman('build', '-b', 'sandbox')
529 self.assertEqual(0, result)
531 def testNeedBoard(self):
532 """Test that we get an error when no board ius supplied"""
533 with self.assertRaises(ValueError) as e:
534 result = self._DoBinman('build')
535 self.assertIn("Must provide a board to process (use -b <board>)",
538 def testMissingDt(self):
539 """Test that an invalid device-tree file generates an error"""
540 with self.assertRaises(Exception) as e:
541 self._RunBinman('build', '-d', 'missing_file')
542 # We get one error from libfdt, and a different one from fdtget.
543 self.AssertInList(["Couldn't open blob from 'missing_file'",
544 'No such file or directory'], str(e.exception))
546 def testBrokenDt(self):
547 """Test that an invalid device-tree source file generates an error
549 Since this is a source file it should be compiled and the error
550 will come from the device-tree compiler (dtc).
552 with self.assertRaises(Exception) as e:
553 self._RunBinman('build', '-d', self.TestFile('001_invalid.dts'))
554 self.assertIn("FATAL ERROR: Unable to parse input tree",
557 def testMissingNode(self):
558 """Test that a device tree without a 'binman' node generates an error"""
559 with self.assertRaises(Exception) as e:
560 self._DoBinman('build', '-d', self.TestFile('002_missing_node.dts'))
561 self.assertIn("does not have a 'binman' node", str(e.exception))
564 """Test that an empty binman node works OK (i.e. does nothing)"""
565 result = self._RunBinman('build', '-d', self.TestFile('003_empty.dts'))
566 self.assertEqual(0, len(result.stderr))
567 self.assertEqual(0, result.return_code)
569 def testInvalidEntry(self):
570 """Test that an invalid entry is flagged"""
571 with self.assertRaises(Exception) as e:
572 result = self._RunBinman('build', '-d',
573 self.TestFile('004_invalid_entry.dts'))
574 self.assertIn("Unknown entry type 'not-a-valid-type' in node "
575 "'/binman/not-a-valid-type'", str(e.exception))
577 def testSimple(self):
578 """Test a simple binman with a single file"""
579 data = self._DoReadFile('005_simple.dts')
580 self.assertEqual(U_BOOT_DATA, data)
582 def testSimpleDebug(self):
583 """Test a simple binman run with debugging enabled"""
584 data = self._DoTestFile('005_simple.dts', debug=True)
587 """Test that we can handle creating two images
589 This also tests image padding.
591 retcode = self._DoTestFile('006_dual_image.dts')
592 self.assertEqual(0, retcode)
594 image = control.images['image1']
595 self.assertEqual(len(U_BOOT_DATA), image._size)
596 fname = tools.GetOutputFilename('image1.bin')
597 self.assertTrue(os.path.exists(fname))
598 with open(fname, 'rb') as fd:
600 self.assertEqual(U_BOOT_DATA, data)
602 image = control.images['image2']
603 self.assertEqual(3 + len(U_BOOT_DATA) + 5, image._size)
604 fname = tools.GetOutputFilename('image2.bin')
605 self.assertTrue(os.path.exists(fname))
606 with open(fname, 'rb') as fd:
608 self.assertEqual(U_BOOT_DATA, data[3:7])
609 self.assertEqual(tools.GetBytes(0, 3), data[:3])
610 self.assertEqual(tools.GetBytes(0, 5), data[7:])
612 def testBadAlign(self):
613 """Test that an invalid alignment value is detected"""
614 with self.assertRaises(ValueError) as e:
615 self._DoTestFile('007_bad_align.dts')
616 self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
617 "of two", str(e.exception))
619 def testPackSimple(self):
620 """Test that packing works as expected"""
621 retcode = self._DoTestFile('008_pack.dts')
622 self.assertEqual(0, retcode)
623 self.assertIn('image', control.images)
624 image = control.images['image']
625 entries = image.GetEntries()
626 self.assertEqual(5, len(entries))
629 self.assertIn('u-boot', entries)
630 entry = entries['u-boot']
631 self.assertEqual(0, entry.offset)
632 self.assertEqual(len(U_BOOT_DATA), entry.size)
634 # Second u-boot, aligned to 16-byte boundary
635 self.assertIn('u-boot-align', entries)
636 entry = entries['u-boot-align']
637 self.assertEqual(16, entry.offset)
638 self.assertEqual(len(U_BOOT_DATA), entry.size)
640 # Third u-boot, size 23 bytes
641 self.assertIn('u-boot-size', entries)
642 entry = entries['u-boot-size']
643 self.assertEqual(20, entry.offset)
644 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
645 self.assertEqual(23, entry.size)
647 # Fourth u-boot, placed immediate after the above
648 self.assertIn('u-boot-next', entries)
649 entry = entries['u-boot-next']
650 self.assertEqual(43, entry.offset)
651 self.assertEqual(len(U_BOOT_DATA), entry.size)
653 # Fifth u-boot, placed at a fixed offset
654 self.assertIn('u-boot-fixed', entries)
655 entry = entries['u-boot-fixed']
656 self.assertEqual(61, entry.offset)
657 self.assertEqual(len(U_BOOT_DATA), entry.size)
659 self.assertEqual(65, image._size)
661 def testPackExtra(self):
662 """Test that extra packing feature works as expected"""
663 retcode = self._DoTestFile('009_pack_extra.dts')
665 self.assertEqual(0, retcode)
666 self.assertIn('image', control.images)
667 image = control.images['image']
668 entries = image.GetEntries()
669 self.assertEqual(5, len(entries))
671 # First u-boot with padding before and after
672 self.assertIn('u-boot', entries)
673 entry = entries['u-boot']
674 self.assertEqual(0, entry.offset)
675 self.assertEqual(3, entry.pad_before)
676 self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
678 # Second u-boot has an aligned size, but it has no effect
679 self.assertIn('u-boot-align-size-nop', entries)
680 entry = entries['u-boot-align-size-nop']
681 self.assertEqual(12, entry.offset)
682 self.assertEqual(4, entry.size)
684 # Third u-boot has an aligned size too
685 self.assertIn('u-boot-align-size', entries)
686 entry = entries['u-boot-align-size']
687 self.assertEqual(16, entry.offset)
688 self.assertEqual(32, entry.size)
690 # Fourth u-boot has an aligned end
691 self.assertIn('u-boot-align-end', entries)
692 entry = entries['u-boot-align-end']
693 self.assertEqual(48, entry.offset)
694 self.assertEqual(16, entry.size)
696 # Fifth u-boot immediately afterwards
697 self.assertIn('u-boot-align-both', entries)
698 entry = entries['u-boot-align-both']
699 self.assertEqual(64, entry.offset)
700 self.assertEqual(64, entry.size)
702 self.CheckNoGaps(entries)
703 self.assertEqual(128, image._size)
705 def testPackAlignPowerOf2(self):
706 """Test that invalid entry alignment is detected"""
707 with self.assertRaises(ValueError) as e:
708 self._DoTestFile('010_pack_align_power2.dts')
709 self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
710 "of two", str(e.exception))
712 def testPackAlignSizePowerOf2(self):
713 """Test that invalid entry size alignment is detected"""
714 with self.assertRaises(ValueError) as e:
715 self._DoTestFile('011_pack_align_size_power2.dts')
716 self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
717 "power of two", str(e.exception))
719 def testPackInvalidAlign(self):
720 """Test detection of an offset that does not match its alignment"""
721 with self.assertRaises(ValueError) as e:
722 self._DoTestFile('012_pack_inv_align.dts')
723 self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
724 "align 0x4 (4)", str(e.exception))
726 def testPackInvalidSizeAlign(self):
727 """Test that invalid entry size alignment is detected"""
728 with self.assertRaises(ValueError) as e:
729 self._DoTestFile('013_pack_inv_size_align.dts')
730 self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
731 "align-size 0x4 (4)", str(e.exception))
733 def testPackOverlap(self):
734 """Test that overlapping regions are detected"""
735 with self.assertRaises(ValueError) as e:
736 self._DoTestFile('014_pack_overlap.dts')
737 self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
738 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
741 def testPackEntryOverflow(self):
742 """Test that entries that overflow their size are detected"""
743 with self.assertRaises(ValueError) as e:
744 self._DoTestFile('015_pack_overflow.dts')
745 self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
746 "but entry size is 0x3 (3)", str(e.exception))
748 def testPackImageOverflow(self):
749 """Test that entries which overflow the image size are detected"""
750 with self.assertRaises(ValueError) as e:
751 self._DoTestFile('016_pack_image_overflow.dts')
752 self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section "
753 "size 0x3 (3)", str(e.exception))
755 def testPackImageSize(self):
756 """Test that the image size can be set"""
757 retcode = self._DoTestFile('017_pack_image_size.dts')
758 self.assertEqual(0, retcode)
759 self.assertIn('image', control.images)
760 image = control.images['image']
761 self.assertEqual(7, image._size)
763 def testPackImageSizeAlign(self):
764 """Test that image size alignemnt works as expected"""
765 retcode = self._DoTestFile('018_pack_image_align.dts')
766 self.assertEqual(0, retcode)
767 self.assertIn('image', control.images)
768 image = control.images['image']
769 self.assertEqual(16, image._size)
771 def testPackInvalidImageAlign(self):
772 """Test that invalid image alignment is detected"""
773 with self.assertRaises(ValueError) as e:
774 self._DoTestFile('019_pack_inv_image_align.dts')
775 self.assertIn("Section '/binman': Size 0x7 (7) does not match "
776 "align-size 0x8 (8)", str(e.exception))
778 def testPackAlignPowerOf2(self):
779 """Test that invalid image alignment is detected"""
780 with self.assertRaises(ValueError) as e:
781 self._DoTestFile('020_pack_inv_image_align_power2.dts')
782 self.assertIn("Section '/binman': Alignment size 131 must be a power of "
783 "two", str(e.exception))
785 def testImagePadByte(self):
786 """Test that the image pad byte can be specified"""
788 data = self._DoReadFile('021_image_pad.dts')
789 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0xff, 1) +
792 def testImageName(self):
793 """Test that image files can be named"""
794 retcode = self._DoTestFile('022_image_name.dts')
795 self.assertEqual(0, retcode)
796 image = control.images['image1']
797 fname = tools.GetOutputFilename('test-name')
798 self.assertTrue(os.path.exists(fname))
800 image = control.images['image2']
801 fname = tools.GetOutputFilename('test-name.xx')
802 self.assertTrue(os.path.exists(fname))
804 def testBlobFilename(self):
805 """Test that generic blobs can be provided by filename"""
806 data = self._DoReadFile('023_blob.dts')
807 self.assertEqual(BLOB_DATA, data)
809 def testPackSorted(self):
810 """Test that entries can be sorted"""
812 data = self._DoReadFile('024_sorted.dts')
813 self.assertEqual(tools.GetBytes(0, 1) + U_BOOT_SPL_DATA +
814 tools.GetBytes(0, 2) + U_BOOT_DATA, data)
816 def testPackZeroOffset(self):
817 """Test that an entry at offset 0 is not given a new offset"""
818 with self.assertRaises(ValueError) as e:
819 self._DoTestFile('025_pack_zero_size.dts')
820 self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
821 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
824 def testPackUbootDtb(self):
825 """Test that a device tree can be added to U-Boot"""
826 data = self._DoReadFile('026_pack_u_boot_dtb.dts')
827 self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
829 def testPackX86RomNoSize(self):
830 """Test that the end-at-4gb property requires a size property"""
831 with self.assertRaises(ValueError) as e:
832 self._DoTestFile('027_pack_4gb_no_size.dts')
833 self.assertIn("Section '/binman': Section size must be provided when "
834 "using end-at-4gb", str(e.exception))
836 def test4gbAndSkipAtStartTogether(self):
837 """Test that the end-at-4gb and skip-at-size property can't be used
839 with self.assertRaises(ValueError) as e:
840 self._DoTestFile('80_4gb_and_skip_at_start_together.dts')
841 self.assertIn("Section '/binman': Provide either 'end-at-4gb' or "
842 "'skip-at-start'", str(e.exception))
844 def testPackX86RomOutside(self):
845 """Test that the end-at-4gb property checks for offset boundaries"""
846 with self.assertRaises(ValueError) as e:
847 self._DoTestFile('028_pack_4gb_outside.dts')
848 self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
849 "the section starting at 0xffffffe0 (4294967264)",
852 def testPackX86Rom(self):
853 """Test that a basic x86 ROM can be created"""
855 data = self._DoReadFile('029_x86-rom.dts')
856 self.assertEqual(U_BOOT_DATA + tools.GetBytes(0, 7) + U_BOOT_SPL_DATA +
857 tools.GetBytes(0, 2), data)
859 def testPackX86RomMeNoDesc(self):
860 """Test that an invalid Intel descriptor entry is detected"""
861 TestFunctional._MakeInputFile('descriptor.bin', b'')
862 with self.assertRaises(ValueError) as e:
863 self._DoTestFile('031_x86-rom-me.dts')
864 self.assertIn("Node '/binman/intel-descriptor': Cannot find Intel Flash Descriptor (FD) signature",
867 def testPackX86RomBadDesc(self):
868 """Test that the Intel requires a descriptor entry"""
869 with self.assertRaises(ValueError) as e:
870 self._DoTestFile('030_x86-rom-me-no-desc.dts')
871 self.assertIn("Node '/binman/intel-me': No offset set with "
872 "offset-unset: should another entry provide this correct "
873 "offset?", str(e.exception))
875 def testPackX86RomMe(self):
876 """Test that an x86 ROM with an ME region can be created"""
877 data = self._DoReadFile('031_x86-rom-me.dts')
878 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
879 if data[:0x1000] != expected_desc:
880 self.fail('Expected descriptor binary at start of image')
881 self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
883 def testPackVga(self):
884 """Test that an image with a VGA binary can be created"""
885 data = self._DoReadFile('032_intel-vga.dts')
886 self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
888 def testPackStart16(self):
889 """Test that an image with an x86 start16 region can be created"""
890 data = self._DoReadFile('033_x86-start16.dts')
891 self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
893 def testPackPowerpcMpc85xxBootpgResetvec(self):
894 """Test that an image with powerpc-mpc85xx-bootpg-resetvec can be
896 data = self._DoReadFile('81_powerpc_mpc85xx_bootpg_resetvec.dts')
897 self.assertEqual(PPC_MPC85XX_BR_DATA, data[:len(PPC_MPC85XX_BR_DATA)])
899 def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False):
900 """Handle running a test for insertion of microcode
903 dts_fname: Name of test .dts file
904 nodtb_data: Data that we expect in the first section
905 ucode_second: True if the microsecond entry is second instead of
910 Contents of first region (U-Boot or SPL)
911 Offset and size components of microcode pointer, as inserted
912 in the above (two 4-byte words)
914 data = self._DoReadFile(dts_fname, True)
916 # Now check the device tree has no microcode
918 ucode_content = data[len(nodtb_data):]
919 ucode_pos = len(nodtb_data)
920 dtb_with_ucode = ucode_content[16:]
921 fdt_len = self.GetFdtLen(dtb_with_ucode)
923 dtb_with_ucode = data[len(nodtb_data):]
924 fdt_len = self.GetFdtLen(dtb_with_ucode)
925 ucode_content = dtb_with_ucode[fdt_len:]
926 ucode_pos = len(nodtb_data) + fdt_len
927 fname = tools.GetOutputFilename('test.dtb')
928 with open(fname, 'wb') as fd:
929 fd.write(dtb_with_ucode)
930 dtb = fdt.FdtScan(fname)
931 ucode = dtb.GetNode('/microcode')
932 self.assertTrue(ucode)
933 for node in ucode.subnodes:
934 self.assertFalse(node.props.get('data'))
936 # Check that the microcode appears immediately after the Fdt
937 # This matches the concatenation of the data properties in
938 # the /microcode/update@xxx nodes in 34_x86_ucode.dts.
939 ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
941 self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
943 # Check that the microcode pointer was inserted. It should match the
944 # expected offset and size
945 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
947 u_boot = data[:len(nodtb_data)]
948 return u_boot, pos_and_size
950 def testPackUbootMicrocode(self):
951 """Test that x86 microcode can be handled correctly
953 We expect to see the following in the image, in order:
954 u-boot-nodtb.bin with a microcode pointer inserted at the correct
956 u-boot.dtb with the microcode removed
959 first, pos_and_size = self._RunMicrocodeTest('034_x86_ucode.dts',
961 self.assertEqual(b'nodtb with microcode' + pos_and_size +
962 b' somewhere in here', first)
964 def _RunPackUbootSingleMicrocode(self):
965 """Test that x86 microcode can be handled correctly
967 We expect to see the following in the image, in order:
968 u-boot-nodtb.bin with a microcode pointer inserted at the correct
970 u-boot.dtb with the microcode
971 an empty microcode region
973 # We need the libfdt library to run this test since only that allows
974 # finding the offset of a property. This is required by
975 # Entry_u_boot_dtb_with_ucode.ObtainContents().
976 data = self._DoReadFile('035_x86_single_ucode.dts', True)
978 second = data[len(U_BOOT_NODTB_DATA):]
980 fdt_len = self.GetFdtLen(second)
981 third = second[fdt_len:]
982 second = second[:fdt_len]
984 ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
985 self.assertIn(ucode_data, second)
986 ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
988 # Check that the microcode pointer was inserted. It should match the
989 # expected offset and size
990 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
992 first = data[:len(U_BOOT_NODTB_DATA)]
993 self.assertEqual(b'nodtb with microcode' + pos_and_size +
994 b' somewhere in here', first)
996 def testPackUbootSingleMicrocode(self):
997 """Test that x86 microcode can be handled correctly with fdt_normal.
999 self._RunPackUbootSingleMicrocode()
1001 def testUBootImg(self):
1002 """Test that u-boot.img can be put in a file"""
1003 data = self._DoReadFile('036_u_boot_img.dts')
1004 self.assertEqual(U_BOOT_IMG_DATA, data)
1006 def testNoMicrocode(self):
1007 """Test that a missing microcode region is detected"""
1008 with self.assertRaises(ValueError) as e:
1009 self._DoReadFile('037_x86_no_ucode.dts', True)
1010 self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
1011 "node found in ", str(e.exception))
1013 def testMicrocodeWithoutNode(self):
1014 """Test that a missing u-boot-dtb-with-ucode node is detected"""
1015 with self.assertRaises(ValueError) as e:
1016 self._DoReadFile('038_x86_ucode_missing_node.dts', True)
1017 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1018 "microcode region u-boot-dtb-with-ucode", str(e.exception))
1020 def testMicrocodeWithoutNode2(self):
1021 """Test that a missing u-boot-ucode node is detected"""
1022 with self.assertRaises(ValueError) as e:
1023 self._DoReadFile('039_x86_ucode_missing_node2.dts', True)
1024 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1025 "microcode region u-boot-ucode", str(e.exception))
1027 def testMicrocodeWithoutPtrInElf(self):
1028 """Test that a U-Boot binary without the microcode symbol is detected"""
1029 # ELF file without a '_dt_ucode_base_size' symbol
1031 with open(self.TestFile('u_boot_no_ucode_ptr'), 'rb') as fd:
1032 TestFunctional._MakeInputFile('u-boot', fd.read())
1034 with self.assertRaises(ValueError) as e:
1035 self._RunPackUbootSingleMicrocode()
1036 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
1037 "_dt_ucode_base_size symbol in u-boot", str(e.exception))
1040 # Put the original file back
1041 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
1042 TestFunctional._MakeInputFile('u-boot', fd.read())
1044 def testMicrocodeNotInImage(self):
1045 """Test that microcode must be placed within the image"""
1046 with self.assertRaises(ValueError) as e:
1047 self._DoReadFile('040_x86_ucode_not_in_image.dts', True)
1048 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
1049 "pointer _dt_ucode_base_size at fffffe14 is outside the "
1050 "section ranging from 00000000 to 0000002e", str(e.exception))
1052 def testWithoutMicrocode(self):
1053 """Test that we can cope with an image without microcode (e.g. qemu)"""
1054 with open(self.TestFile('u_boot_no_ucode_ptr'), 'rb') as fd:
1055 TestFunctional._MakeInputFile('u-boot', fd.read())
1056 data, dtb, _, _ = self._DoReadFileDtb('044_x86_optional_ucode.dts', True)
1058 # Now check the device tree has no microcode
1059 self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
1060 second = data[len(U_BOOT_NODTB_DATA):]
1062 fdt_len = self.GetFdtLen(second)
1063 self.assertEqual(dtb, second[:fdt_len])
1065 used_len = len(U_BOOT_NODTB_DATA) + fdt_len
1066 third = data[used_len:]
1067 self.assertEqual(tools.GetBytes(0, 0x200 - used_len), third)
1069 def testUnknownPosSize(self):
1070 """Test that microcode must be placed within the image"""
1071 with self.assertRaises(ValueError) as e:
1072 self._DoReadFile('041_unknown_pos_size.dts', True)
1073 self.assertIn("Section '/binman': Unable to set offset/size for unknown "
1074 "entry 'invalid-entry'", str(e.exception))
1076 def testPackFsp(self):
1077 """Test that an image with a FSP binary can be created"""
1078 data = self._DoReadFile('042_intel-fsp.dts')
1079 self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
1081 def testPackCmc(self):
1082 """Test that an image with a CMC binary can be created"""
1083 data = self._DoReadFile('043_intel-cmc.dts')
1084 self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
1086 def testPackVbt(self):
1087 """Test that an image with a VBT binary can be created"""
1088 data = self._DoReadFile('046_intel-vbt.dts')
1089 self.assertEqual(VBT_DATA, data[:len(VBT_DATA)])
1091 def testSplBssPad(self):
1092 """Test that we can pad SPL's BSS with zeros"""
1093 # ELF file with a '__bss_size' symbol
1095 data = self._DoReadFile('047_spl_bss_pad.dts')
1096 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0, 10) + U_BOOT_DATA,
1099 def testSplBssPadMissing(self):
1100 """Test that a missing symbol is detected"""
1101 self._SetupSplElf('u_boot_ucode_ptr')
1102 with self.assertRaises(ValueError) as e:
1103 self._DoReadFile('047_spl_bss_pad.dts')
1104 self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
1107 def testPackStart16Spl(self):
1108 """Test that an image with an x86 start16 SPL region can be created"""
1109 data = self._DoReadFile('048_x86-start16-spl.dts')
1110 self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)])
1112 def _PackUbootSplMicrocode(self, dts, ucode_second=False):
1113 """Helper function for microcode tests
1115 We expect to see the following in the image, in order:
1116 u-boot-spl-nodtb.bin with a microcode pointer inserted at the
1118 u-boot.dtb with the microcode removed
1122 dts: Device tree file to use for test
1123 ucode_second: True if the microsecond entry is second instead of
1126 self._SetupSplElf('u_boot_ucode_ptr')
1127 first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA,
1128 ucode_second=ucode_second)
1129 self.assertEqual(b'splnodtb with microc' + pos_and_size +
1130 b'ter somewhere in here', first)
1132 def testPackUbootSplMicrocode(self):
1133 """Test that x86 microcode can be handled correctly in SPL"""
1134 self._PackUbootSplMicrocode('049_x86_ucode_spl.dts')
1136 def testPackUbootSplMicrocodeReorder(self):
1137 """Test that order doesn't matter for microcode entries
1139 This is the same as testPackUbootSplMicrocode but when we process the
1140 u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode
1141 entry, so we reply on binman to try later.
1143 self._PackUbootSplMicrocode('058_x86_ucode_spl_needs_retry.dts',
1146 def testPackMrc(self):
1147 """Test that an image with an MRC binary can be created"""
1148 data = self._DoReadFile('050_intel_mrc.dts')
1149 self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
1151 def testSplDtb(self):
1152 """Test that an image with spl/u-boot-spl.dtb can be created"""
1153 data = self._DoReadFile('051_u_boot_spl_dtb.dts')
1154 self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
1156 def testSplNoDtb(self):
1157 """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
1158 data = self._DoReadFile('052_u_boot_spl_nodtb.dts')
1159 self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
1161 def testSymbols(self):
1162 """Test binman can assign symbols embedded in U-Boot"""
1163 elf_fname = self.TestFile('u_boot_binman_syms')
1164 syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
1165 addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
1166 self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
1168 self._SetupSplElf('u_boot_binman_syms')
1169 data = self._DoReadFile('053_symbols.dts')
1170 sym_values = struct.pack('<LQL', 0x24 + 0, 0x24 + 24, 0x24 + 20)
1171 expected = (sym_values + U_BOOT_SPL_DATA[16:] +
1172 tools.GetBytes(0xff, 1) + U_BOOT_DATA + sym_values +
1173 U_BOOT_SPL_DATA[16:])
1174 self.assertEqual(expected, data)
1176 def testPackUnitAddress(self):
1177 """Test that we support multiple binaries with the same name"""
1178 data = self._DoReadFile('054_unit_address.dts')
1179 self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
1181 def testSections(self):
1182 """Basic test of sections"""
1183 data = self._DoReadFile('055_sections.dts')
1184 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1185 U_BOOT_DATA + tools.GetBytes(ord('a'), 12) +
1186 U_BOOT_DATA + tools.GetBytes(ord('&'), 4))
1187 self.assertEqual(expected, data)
1190 """Tests outputting a map of the images"""
1191 _, _, map_data, _ = self._DoReadFileDtb('055_sections.dts', map=True)
1192 self.assertEqual('''ImagePos Offset Size Name
1193 00000000 00000000 00000028 main-section
1194 00000000 00000000 00000010 section@0
1195 00000000 00000000 00000004 u-boot
1196 00000010 00000010 00000010 section@1
1197 00000010 00000000 00000004 u-boot
1198 00000020 00000020 00000004 section@2
1199 00000020 00000000 00000004 u-boot
1202 def testNamePrefix(self):
1203 """Tests that name prefixes are used"""
1204 _, _, map_data, _ = self._DoReadFileDtb('056_name_prefix.dts', map=True)
1205 self.assertEqual('''ImagePos Offset Size Name
1206 00000000 00000000 00000028 main-section
1207 00000000 00000000 00000010 section@0
1208 00000000 00000000 00000004 ro-u-boot
1209 00000010 00000010 00000010 section@1
1210 00000010 00000000 00000004 rw-u-boot
1213 def testUnknownContents(self):
1214 """Test that obtaining the contents works as expected"""
1215 with self.assertRaises(ValueError) as e:
1216 self._DoReadFile('057_unknown_contents.dts', True)
1217 self.assertIn("Section '/binman': Internal error: Could not complete "
1218 "processing of contents: remaining [<_testing.Entry__testing ",
1221 def testBadChangeSize(self):
1222 """Test that trying to change the size of an entry fails"""
1224 state.SetAllowEntryExpansion(False)
1225 with self.assertRaises(ValueError) as e:
1226 self._DoReadFile('059_change_size.dts', True)
1227 self.assertIn("Node '/binman/_testing': Cannot update entry size from 1 to 2",
1230 state.SetAllowEntryExpansion(True)
1232 def testUpdateFdt(self):
1233 """Test that we can update the device tree with offset/size info"""
1234 _, _, _, out_dtb_fname = self._DoReadFileDtb('060_fdt_update.dts',
1236 dtb = fdt.Fdt(out_dtb_fname)
1238 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'])
1242 '_testing:offset': 32,
1244 '_testing:image-pos': 32,
1245 'section@0/u-boot:offset': 0,
1246 'section@0/u-boot:size': len(U_BOOT_DATA),
1247 'section@0/u-boot:image-pos': 0,
1248 'section@0:offset': 0,
1249 'section@0:size': 16,
1250 'section@0:image-pos': 0,
1252 'section@1/u-boot:offset': 0,
1253 'section@1/u-boot:size': len(U_BOOT_DATA),
1254 'section@1/u-boot:image-pos': 16,
1255 'section@1:offset': 16,
1256 'section@1:size': 16,
1257 'section@1:image-pos': 16,
1261 def testUpdateFdtBad(self):
1262 """Test that we detect when ProcessFdt never completes"""
1263 with self.assertRaises(ValueError) as e:
1264 self._DoReadFileDtb('061_fdt_update_bad.dts', update_dtb=True)
1265 self.assertIn('Could not complete processing of Fdt: remaining '
1266 '[<_testing.Entry__testing', str(e.exception))
1268 def testEntryArgs(self):
1269 """Test passing arguments to entries from the command line"""
1271 'test-str-arg': 'test1',
1272 'test-int-arg': '456',
1274 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
1275 self.assertIn('image', control.images)
1276 entry = control.images['image'].GetEntries()['_testing']
1277 self.assertEqual('test0', entry.test_str_fdt)
1278 self.assertEqual('test1', entry.test_str_arg)
1279 self.assertEqual(123, entry.test_int_fdt)
1280 self.assertEqual(456, entry.test_int_arg)
1282 def testEntryArgsMissing(self):
1283 """Test missing arguments and properties"""
1285 'test-int-arg': '456',
1287 self._DoReadFileDtb('063_entry_args_missing.dts', entry_args=entry_args)
1288 entry = control.images['image'].GetEntries()['_testing']
1289 self.assertEqual('test0', entry.test_str_fdt)
1290 self.assertEqual(None, entry.test_str_arg)
1291 self.assertEqual(None, entry.test_int_fdt)
1292 self.assertEqual(456, entry.test_int_arg)
1294 def testEntryArgsRequired(self):
1295 """Test missing arguments and properties"""
1297 'test-int-arg': '456',
1299 with self.assertRaises(ValueError) as e:
1300 self._DoReadFileDtb('064_entry_args_required.dts')
1301 self.assertIn("Node '/binman/_testing': Missing required "
1302 'properties/entry args: test-str-arg, test-int-fdt, test-int-arg',
1305 def testEntryArgsInvalidFormat(self):
1306 """Test that an invalid entry-argument format is detected"""
1307 args = ['build', '-d', self.TestFile('064_entry_args_required.dts'),
1309 with self.assertRaises(ValueError) as e:
1310 self._DoBinman(*args)
1311 self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
1313 def testEntryArgsInvalidInteger(self):
1314 """Test that an invalid entry-argument integer is detected"""
1316 'test-int-arg': 'abc',
1318 with self.assertRaises(ValueError) as e:
1319 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
1320 self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
1321 "'test-int-arg' (value 'abc') to integer",
1324 def testEntryArgsInvalidDatatype(self):
1325 """Test that an invalid entry-argument datatype is detected
1327 This test could be written in entry_test.py except that it needs
1328 access to control.entry_args, which seems more than that module should
1332 'test-bad-datatype-arg': '12',
1334 with self.assertRaises(ValueError) as e:
1335 self._DoReadFileDtb('065_entry_args_unknown_datatype.dts',
1336 entry_args=entry_args)
1337 self.assertIn('GetArg() internal error: Unknown data type ',
1341 """Test for a text entry type"""
1343 'test-id': TEXT_DATA,
1344 'test-id2': TEXT_DATA2,
1345 'test-id3': TEXT_DATA3,
1347 data, _, _, _ = self._DoReadFileDtb('066_text.dts',
1348 entry_args=entry_args)
1349 expected = (tools.ToBytes(TEXT_DATA) +
1350 tools.GetBytes(0, 8 - len(TEXT_DATA)) +
1351 tools.ToBytes(TEXT_DATA2) + tools.ToBytes(TEXT_DATA3) +
1352 b'some text' + b'more text')
1353 self.assertEqual(expected, data)
1355 def testEntryDocs(self):
1356 """Test for creation of entry documentation"""
1357 with test_util.capture_sys_output() as (stdout, stderr):
1358 control.WriteEntryDocs(binman.GetEntryModules())
1359 self.assertTrue(len(stdout.getvalue()) > 0)
1361 def testEntryDocsMissing(self):
1362 """Test handling of missing entry documentation"""
1363 with self.assertRaises(ValueError) as e:
1364 with test_util.capture_sys_output() as (stdout, stderr):
1365 control.WriteEntryDocs(binman.GetEntryModules(), 'u_boot')
1366 self.assertIn('Documentation is missing for modules: u_boot',
1370 """Basic test of generation of a flashrom fmap"""
1371 data = self._DoReadFile('067_fmap.dts')
1372 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1373 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1374 U_BOOT_DATA + tools.GetBytes(ord('a'), 12))
1375 self.assertEqual(expected, data[:32])
1376 self.assertEqual(b'__FMAP__', fhdr.signature)
1377 self.assertEqual(1, fhdr.ver_major)
1378 self.assertEqual(0, fhdr.ver_minor)
1379 self.assertEqual(0, fhdr.base)
1380 self.assertEqual(16 + 16 +
1381 fmap_util.FMAP_HEADER_LEN +
1382 fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
1383 self.assertEqual(b'FMAP', fhdr.name)
1384 self.assertEqual(3, fhdr.nareas)
1385 for fentry in fentries:
1386 self.assertEqual(0, fentry.flags)
1388 self.assertEqual(0, fentries[0].offset)
1389 self.assertEqual(4, fentries[0].size)
1390 self.assertEqual(b'RO_U_BOOT', fentries[0].name)
1392 self.assertEqual(16, fentries[1].offset)
1393 self.assertEqual(4, fentries[1].size)
1394 self.assertEqual(b'RW_U_BOOT', fentries[1].name)
1396 self.assertEqual(32, fentries[2].offset)
1397 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1398 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1399 self.assertEqual(b'FMAP', fentries[2].name)
1401 def testBlobNamedByArg(self):
1402 """Test we can add a blob with the filename coming from an entry arg"""
1404 'cros-ec-rw-path': 'ecrw.bin',
1406 data, _, _, _ = self._DoReadFileDtb('068_blob_named_by_arg.dts',
1407 entry_args=entry_args)
1410 """Test for an fill entry type"""
1411 data = self._DoReadFile('069_fill.dts')
1412 expected = tools.GetBytes(0xff, 8) + tools.GetBytes(0, 8)
1413 self.assertEqual(expected, data)
1415 def testFillNoSize(self):
1416 """Test for an fill entry type with no size"""
1417 with self.assertRaises(ValueError) as e:
1418 self._DoReadFile('070_fill_no_size.dts')
1419 self.assertIn("'fill' entry must have a size property",
1422 def _HandleGbbCommand(self, pipe_list):
1423 """Fake calls to the futility utility"""
1424 if pipe_list[0][0] == 'futility':
1425 fname = pipe_list[0][-1]
1426 # Append our GBB data to the file, which will happen every time the
1427 # futility command is called.
1428 with open(fname, 'ab') as fd:
1430 return command.CommandResult()
1433 """Test for the Chromium OS Google Binary Block"""
1434 command.test_result = self._HandleGbbCommand
1436 'keydir': 'devkeys',
1437 'bmpblk': 'bmpblk.bin',
1439 data, _, _, _ = self._DoReadFileDtb('071_gbb.dts', entry_args=entry_args)
1442 expected = (GBB_DATA + GBB_DATA + tools.GetBytes(0, 8) +
1443 tools.GetBytes(0, 0x2180 - 16))
1444 self.assertEqual(expected, data)
1446 def testGbbTooSmall(self):
1447 """Test for the Chromium OS Google Binary Block being large enough"""
1448 with self.assertRaises(ValueError) as e:
1449 self._DoReadFileDtb('072_gbb_too_small.dts')
1450 self.assertIn("Node '/binman/gbb': GBB is too small",
1453 def testGbbNoSize(self):
1454 """Test for the Chromium OS Google Binary Block having a size"""
1455 with self.assertRaises(ValueError) as e:
1456 self._DoReadFileDtb('073_gbb_no_size.dts')
1457 self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
1460 def _HandleVblockCommand(self, pipe_list):
1461 """Fake calls to the futility utility"""
1462 if pipe_list[0][0] == 'futility':
1463 fname = pipe_list[0][3]
1464 with open(fname, 'wb') as fd:
1465 fd.write(VBLOCK_DATA)
1466 return command.CommandResult()
1468 def testVblock(self):
1469 """Test for the Chromium OS Verified Boot Block"""
1470 command.test_result = self._HandleVblockCommand
1472 'keydir': 'devkeys',
1474 data, _, _, _ = self._DoReadFileDtb('074_vblock.dts',
1475 entry_args=entry_args)
1476 expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
1477 self.assertEqual(expected, data)
1479 def testVblockNoContent(self):
1480 """Test we detect a vblock which has no content to sign"""
1481 with self.assertRaises(ValueError) as e:
1482 self._DoReadFile('075_vblock_no_content.dts')
1483 self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
1484 'property', str(e.exception))
1486 def testVblockBadPhandle(self):
1487 """Test that we detect a vblock with an invalid phandle in contents"""
1488 with self.assertRaises(ValueError) as e:
1489 self._DoReadFile('076_vblock_bad_phandle.dts')
1490 self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
1491 '1000', str(e.exception))
1493 def testVblockBadEntry(self):
1494 """Test that we detect an entry that points to a non-entry"""
1495 with self.assertRaises(ValueError) as e:
1496 self._DoReadFile('077_vblock_bad_entry.dts')
1497 self.assertIn("Node '/binman/vblock': Cannot find entry for node "
1498 "'other'", str(e.exception))
1501 """Test that an image with TPL and ots device tree can be created"""
1502 # ELF file with a '__bss_size' symbol
1503 with open(self.TestFile('bss_data'), 'rb') as fd:
1504 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1505 data = self._DoReadFile('078_u_boot_tpl.dts')
1506 self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
1508 def testUsesPos(self):
1509 """Test that the 'pos' property cannot be used anymore"""
1510 with self.assertRaises(ValueError) as e:
1511 data = self._DoReadFile('079_uses_pos.dts')
1512 self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
1513 "'pos'", str(e.exception))
1515 def testFillZero(self):
1516 """Test for an fill entry type with a size of 0"""
1517 data = self._DoReadFile('080_fill_empty.dts')
1518 self.assertEqual(tools.GetBytes(0, 16), data)
1520 def testTextMissing(self):
1521 """Test for a text entry type where there is no text"""
1522 with self.assertRaises(ValueError) as e:
1523 self._DoReadFileDtb('066_text.dts',)
1524 self.assertIn("Node '/binman/text': No value provided for text label "
1525 "'test-id'", str(e.exception))
1527 def testPackStart16Tpl(self):
1528 """Test that an image with an x86 start16 TPL region can be created"""
1529 data = self._DoReadFile('081_x86-start16-tpl.dts')
1530 self.assertEqual(X86_START16_TPL_DATA, data[:len(X86_START16_TPL_DATA)])
1532 def testSelectImage(self):
1533 """Test that we can select which images to build"""
1534 expected = 'Skipping images: image1'
1536 # We should only get the expected message in verbose mode
1537 for verbosity in (0, 2):
1538 with test_util.capture_sys_output() as (stdout, stderr):
1539 retcode = self._DoTestFile('006_dual_image.dts',
1540 verbosity=verbosity,
1542 self.assertEqual(0, retcode)
1544 self.assertIn(expected, stdout.getvalue())
1546 self.assertNotIn(expected, stdout.getvalue())
1548 self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
1549 self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
1551 def testUpdateFdtAll(self):
1552 """Test that all device trees are updated with offset/size info"""
1553 data = self._DoReadFileRealDtb('082_fdt_update_all.dts')
1556 'section:image-pos': 0,
1557 'u-boot-tpl-dtb:size': 513,
1558 'u-boot-spl-dtb:size': 513,
1559 'u-boot-spl-dtb:offset': 493,
1561 'section/u-boot-dtb:image-pos': 0,
1562 'u-boot-spl-dtb:image-pos': 493,
1563 'section/u-boot-dtb:size': 493,
1564 'u-boot-tpl-dtb:image-pos': 1006,
1565 'section/u-boot-dtb:offset': 0,
1566 'section:size': 493,
1568 'section:offset': 0,
1569 'u-boot-tpl-dtb:offset': 1006,
1573 # We expect three device-tree files in the output, one after the other.
1574 # Read them in sequence. We look for an 'spl' property in the SPL tree,
1575 # and 'tpl' in the TPL tree, to make sure they are distinct from the
1576 # main U-Boot tree. All three should have the same postions and offset.
1578 for item in ['', 'spl', 'tpl']:
1579 dtb = fdt.Fdt.FromData(data[start:])
1581 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos',
1583 expected = dict(base_expected)
1586 self.assertEqual(expected, props)
1587 start += dtb._fdt_obj.totalsize()
1589 def testUpdateFdtOutput(self):
1590 """Test that output DTB files are updated"""
1592 data, dtb_data, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
1593 use_real_dtb=True, update_dtb=True, reset_dtbs=False)
1595 # Unfortunately, compiling a source file always results in a file
1596 # called source.dtb (see fdt_util.EnsureCompiled()). The test
1597 # source file (e.g. test/075_fdt_update_all.dts) thus does not enter
1598 # binman as a file called u-boot.dtb. To fix this, copy the file
1599 # over to the expected place.
1600 #tools.WriteFile(os.path.join(self._indir, 'u-boot.dtb'),
1601 #tools.ReadFile(tools.GetOutputFilename('source.dtb')))
1603 for fname in ['u-boot.dtb.out', 'spl/u-boot-spl.dtb.out',
1604 'tpl/u-boot-tpl.dtb.out']:
1605 dtb = fdt.Fdt.FromData(data[start:])
1606 size = dtb._fdt_obj.totalsize()
1607 pathname = tools.GetOutputFilename(os.path.split(fname)[1])
1608 outdata = tools.ReadFile(pathname)
1609 name = os.path.split(fname)[0]
1612 orig_indata = self._GetDtbContentsForSplTpl(dtb_data, name)
1614 orig_indata = dtb_data
1615 self.assertNotEqual(outdata, orig_indata,
1616 "Expected output file '%s' be updated" % pathname)
1617 self.assertEqual(outdata, data[start:start + size],
1618 "Expected output file '%s' to match output image" %
1624 def _decompress(self, data):
1625 return tools.Decompress(data, 'lz4')
1627 def testCompress(self):
1628 """Test compression of blobs"""
1630 data, _, _, out_dtb_fname = self._DoReadFileDtb('083_compress.dts',
1631 use_real_dtb=True, update_dtb=True)
1632 dtb = fdt.Fdt(out_dtb_fname)
1634 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
1635 orig = self._decompress(data)
1636 self.assertEquals(COMPRESS_DATA, orig)
1638 'blob:uncomp-size': len(COMPRESS_DATA),
1639 'blob:size': len(data),
1642 self.assertEqual(expected, props)
1644 def testFiles(self):
1645 """Test bringing in multiple files"""
1646 data = self._DoReadFile('084_files.dts')
1647 self.assertEqual(FILES_DATA, data)
1649 def testFilesCompress(self):
1650 """Test bringing in multiple files and compressing them"""
1652 data = self._DoReadFile('085_files_compress.dts')
1654 image = control.images['image']
1655 entries = image.GetEntries()
1656 files = entries['files']
1657 entries = files._section._entries
1660 for i in range(1, 3):
1662 start = entries[key].image_pos
1663 len = entries[key].size
1664 chunk = data[start:start + len]
1665 orig += self._decompress(chunk)
1667 self.assertEqual(FILES_DATA, orig)
1669 def testFilesMissing(self):
1670 """Test missing files"""
1671 with self.assertRaises(ValueError) as e:
1672 data = self._DoReadFile('086_files_none.dts')
1673 self.assertIn("Node '/binman/files': Pattern \'files/*.none\' matched "
1674 'no files', str(e.exception))
1676 def testFilesNoPattern(self):
1677 """Test missing files"""
1678 with self.assertRaises(ValueError) as e:
1679 data = self._DoReadFile('087_files_no_pattern.dts')
1680 self.assertIn("Node '/binman/files': Missing 'pattern' property",
1683 def testExpandSize(self):
1684 """Test an expanding entry"""
1685 data, _, map_data, _ = self._DoReadFileDtb('088_expand_size.dts',
1687 expect = (tools.GetBytes(ord('a'), 8) + U_BOOT_DATA +
1688 MRC_DATA + tools.GetBytes(ord('b'), 1) + U_BOOT_DATA +
1689 tools.GetBytes(ord('c'), 8) + U_BOOT_DATA +
1690 tools.GetBytes(ord('d'), 8))
1691 self.assertEqual(expect, data)
1692 self.assertEqual('''ImagePos Offset Size Name
1693 00000000 00000000 00000028 main-section
1694 00000000 00000000 00000008 fill
1695 00000008 00000008 00000004 u-boot
1696 0000000c 0000000c 00000004 section
1697 0000000c 00000000 00000003 intel-mrc
1698 00000010 00000010 00000004 u-boot2
1699 00000014 00000014 0000000c section2
1700 00000014 00000000 00000008 fill
1701 0000001c 00000008 00000004 u-boot
1702 00000020 00000020 00000008 fill2
1705 def testExpandSizeBad(self):
1706 """Test an expanding entry which fails to provide contents"""
1707 with test_util.capture_sys_output() as (stdout, stderr):
1708 with self.assertRaises(ValueError) as e:
1709 self._DoReadFileDtb('089_expand_size_bad.dts', map=True)
1710 self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
1711 'expanding entry', str(e.exception))
1714 """Test hashing of the contents of an entry"""
1715 _, _, _, out_dtb_fname = self._DoReadFileDtb('090_hash.dts',
1716 use_real_dtb=True, update_dtb=True)
1717 dtb = fdt.Fdt(out_dtb_fname)
1719 hash_node = dtb.GetNode('/binman/u-boot/hash').props['value']
1720 m = hashlib.sha256()
1721 m.update(U_BOOT_DATA)
1722 self.assertEqual(m.digest(), b''.join(hash_node.value))
1724 def testHashNoAlgo(self):
1725 with self.assertRaises(ValueError) as e:
1726 self._DoReadFileDtb('091_hash_no_algo.dts', update_dtb=True)
1727 self.assertIn("Node \'/binman/u-boot\': Missing \'algo\' property for "
1728 'hash node', str(e.exception))
1730 def testHashBadAlgo(self):
1731 with self.assertRaises(ValueError) as e:
1732 self._DoReadFileDtb('092_hash_bad_algo.dts', update_dtb=True)
1733 self.assertIn("Node '/binman/u-boot': Unknown hash algorithm",
1736 def testHashSection(self):
1737 """Test hashing of the contents of an entry"""
1738 _, _, _, out_dtb_fname = self._DoReadFileDtb('099_hash_section.dts',
1739 use_real_dtb=True, update_dtb=True)
1740 dtb = fdt.Fdt(out_dtb_fname)
1742 hash_node = dtb.GetNode('/binman/section/hash').props['value']
1743 m = hashlib.sha256()
1744 m.update(U_BOOT_DATA)
1745 m.update(tools.GetBytes(ord('a'), 16))
1746 self.assertEqual(m.digest(), b''.join(hash_node.value))
1748 def testPackUBootTplMicrocode(self):
1749 """Test that x86 microcode can be handled correctly in TPL
1751 We expect to see the following in the image, in order:
1752 u-boot-tpl-nodtb.bin with a microcode pointer inserted at the correct
1754 u-boot-tpl.dtb with the microcode removed
1757 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
1758 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1759 first, pos_and_size = self._RunMicrocodeTest('093_x86_tpl_ucode.dts',
1760 U_BOOT_TPL_NODTB_DATA)
1761 self.assertEqual(b'tplnodtb with microc' + pos_and_size +
1762 b'ter somewhere in here', first)
1764 def testFmapX86(self):
1765 """Basic test of generation of a flashrom fmap"""
1766 data = self._DoReadFile('094_fmap_x86.dts')
1767 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1768 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('a'), 32 - 7)
1769 self.assertEqual(expected, data[:32])
1770 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1772 self.assertEqual(0x100, fhdr.image_size)
1774 self.assertEqual(0, fentries[0].offset)
1775 self.assertEqual(4, fentries[0].size)
1776 self.assertEqual(b'U_BOOT', fentries[0].name)
1778 self.assertEqual(4, fentries[1].offset)
1779 self.assertEqual(3, fentries[1].size)
1780 self.assertEqual(b'INTEL_MRC', fentries[1].name)
1782 self.assertEqual(32, fentries[2].offset)
1783 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1784 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1785 self.assertEqual(b'FMAP', fentries[2].name)
1787 def testFmapX86Section(self):
1788 """Basic test of generation of a flashrom fmap"""
1789 data = self._DoReadFile('095_fmap_x86_section.dts')
1790 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('b'), 32 - 7)
1791 self.assertEqual(expected, data[:32])
1792 fhdr, fentries = fmap_util.DecodeFmap(data[36:])
1794 self.assertEqual(0x100, fhdr.image_size)
1796 self.assertEqual(0, fentries[0].offset)
1797 self.assertEqual(4, fentries[0].size)
1798 self.assertEqual(b'U_BOOT', fentries[0].name)
1800 self.assertEqual(4, fentries[1].offset)
1801 self.assertEqual(3, fentries[1].size)
1802 self.assertEqual(b'INTEL_MRC', fentries[1].name)
1804 self.assertEqual(36, fentries[2].offset)
1805 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1806 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1807 self.assertEqual(b'FMAP', fentries[2].name)
1810 """Basic test of ELF entries"""
1812 with open(self.TestFile('bss_data'), 'rb') as fd:
1813 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1814 with open(self.TestFile('bss_data'), 'rb') as fd:
1815 TestFunctional._MakeInputFile('-boot', fd.read())
1816 data = self._DoReadFile('096_elf.dts')
1818 def testElfStrip(self):
1819 """Basic test of ELF entries"""
1821 with open(self.TestFile('bss_data'), 'rb') as fd:
1822 TestFunctional._MakeInputFile('-boot', fd.read())
1823 data = self._DoReadFile('097_elf_strip.dts')
1825 def testPackOverlapMap(self):
1826 """Test that overlapping regions are detected"""
1827 with test_util.capture_sys_output() as (stdout, stderr):
1828 with self.assertRaises(ValueError) as e:
1829 self._DoTestFile('014_pack_overlap.dts', map=True)
1830 map_fname = tools.GetOutputFilename('image.map')
1831 self.assertEqual("Wrote map file '%s' to show errors\n" % map_fname,
1834 # We should not get an inmage, but there should be a map file
1835 self.assertFalse(os.path.exists(tools.GetOutputFilename('image.bin')))
1836 self.assertTrue(os.path.exists(map_fname))
1837 map_data = tools.ReadFile(map_fname, binary=False)
1838 self.assertEqual('''ImagePos Offset Size Name
1839 <none> 00000000 00000007 main-section
1840 <none> 00000000 00000004 u-boot
1841 <none> 00000003 00000004 u-boot-align
1844 def testPackRefCode(self):
1845 """Test that an image with an Intel Reference code binary works"""
1846 data = self._DoReadFile('100_intel_refcode.dts')
1847 self.assertEqual(REFCODE_DATA, data[:len(REFCODE_DATA)])
1849 def testSectionOffset(self):
1850 """Tests use of a section with an offset"""
1851 data, _, map_data, _ = self._DoReadFileDtb('101_sections_offset.dts',
1853 self.assertEqual('''ImagePos Offset Size Name
1854 00000000 00000000 00000038 main-section
1855 00000004 00000004 00000010 section@0
1856 00000004 00000000 00000004 u-boot
1857 00000018 00000018 00000010 section@1
1858 00000018 00000000 00000004 u-boot
1859 0000002c 0000002c 00000004 section@2
1860 0000002c 00000000 00000004 u-boot
1862 self.assertEqual(data,
1863 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1864 tools.GetBytes(0x21, 12) +
1865 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1866 tools.GetBytes(0x61, 12) +
1867 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1868 tools.GetBytes(0x26, 8))
1870 def testCbfsRaw(self):
1871 """Test base handling of a Coreboot Filesystem (CBFS)
1873 The exact contents of the CBFS is verified by similar tests in
1874 cbfs_util_test.py. The tests here merely check that the files added to
1875 the CBFS can be found in the final image.
1877 data = self._DoReadFile('102_cbfs_raw.dts')
1880 cbfs = cbfs_util.CbfsReader(data)
1881 self.assertEqual(size, cbfs.rom_size)
1883 self.assertIn('u-boot-dtb', cbfs.files)
1884 cfile = cbfs.files['u-boot-dtb']
1885 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
1887 def testCbfsArch(self):
1888 """Test on non-x86 architecture"""
1889 data = self._DoReadFile('103_cbfs_raw_ppc.dts')
1892 cbfs = cbfs_util.CbfsReader(data)
1893 self.assertEqual(size, cbfs.rom_size)
1895 self.assertIn('u-boot-dtb', cbfs.files)
1896 cfile = cbfs.files['u-boot-dtb']
1897 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
1899 def testCbfsStage(self):
1900 """Tests handling of a Coreboot Filesystem (CBFS)"""
1901 if not elf.ELF_TOOLS:
1902 self.skipTest('Python elftools not available')
1903 elf_fname = os.path.join(self._indir, 'cbfs-stage.elf')
1904 elf.MakeElf(elf_fname, U_BOOT_DATA, U_BOOT_DTB_DATA)
1907 data = self._DoReadFile('104_cbfs_stage.dts')
1908 cbfs = cbfs_util.CbfsReader(data)
1909 self.assertEqual(size, cbfs.rom_size)
1911 self.assertIn('u-boot', cbfs.files)
1912 cfile = cbfs.files['u-boot']
1913 self.assertEqual(U_BOOT_DATA + U_BOOT_DTB_DATA, cfile.data)
1915 def testCbfsRawCompress(self):
1916 """Test handling of compressing raw files"""
1918 data = self._DoReadFile('105_cbfs_raw_compress.dts')
1921 cbfs = cbfs_util.CbfsReader(data)
1922 self.assertIn('u-boot', cbfs.files)
1923 cfile = cbfs.files['u-boot']
1924 self.assertEqual(COMPRESS_DATA, cfile.data)
1926 def testCbfsBadArch(self):
1927 """Test handling of a bad architecture"""
1928 with self.assertRaises(ValueError) as e:
1929 self._DoReadFile('106_cbfs_bad_arch.dts')
1930 self.assertIn("Invalid architecture 'bad-arch'", str(e.exception))
1932 def testCbfsNoSize(self):
1933 """Test handling of a missing size property"""
1934 with self.assertRaises(ValueError) as e:
1935 self._DoReadFile('107_cbfs_no_size.dts')
1936 self.assertIn('entry must have a size property', str(e.exception))
1938 def testCbfsNoCOntents(self):
1939 """Test handling of a CBFS entry which does not provide contentsy"""
1940 with self.assertRaises(ValueError) as e:
1941 self._DoReadFile('108_cbfs_no_contents.dts')
1942 self.assertIn('Could not complete processing of contents',
1945 def testCbfsBadCompress(self):
1946 """Test handling of a bad architecture"""
1947 with self.assertRaises(ValueError) as e:
1948 self._DoReadFile('109_cbfs_bad_compress.dts')
1949 self.assertIn("Invalid compression in 'u-boot': 'invalid-algo'",
1952 def testCbfsNamedEntries(self):
1953 """Test handling of named entries"""
1954 data = self._DoReadFile('110_cbfs_name.dts')
1956 cbfs = cbfs_util.CbfsReader(data)
1957 self.assertIn('FRED', cbfs.files)
1958 cfile1 = cbfs.files['FRED']
1959 self.assertEqual(U_BOOT_DATA, cfile1.data)
1961 self.assertIn('hello', cbfs.files)
1962 cfile2 = cbfs.files['hello']
1963 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
1965 def _SetupIfwi(self, fname):
1966 """Set up to run an IFWI test
1969 fname: Filename of input file to provide (fitimage.bin or ifwi.bin)
1973 # Intel Integrated Firmware Image (IFWI) file
1974 with gzip.open(self.TestFile('%s.gz' % fname), 'rb') as fd:
1976 TestFunctional._MakeInputFile(fname,data)
1978 def _CheckIfwi(self, data):
1979 """Check that an image with an IFWI contains the correct output
1982 data: Conents of output file
1984 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
1985 if data[:0x1000] != expected_desc:
1986 self.fail('Expected descriptor binary at start of image')
1988 # We expect to find the TPL wil in subpart IBBP entry IBBL
1989 image_fname = tools.GetOutputFilename('image.bin')
1990 tpl_fname = tools.GetOutputFilename('tpl.out')
1991 tools.RunIfwiTool(image_fname, tools.CMD_EXTRACT, fname=tpl_fname,
1992 subpart='IBBP', entry_name='IBBL')
1994 tpl_data = tools.ReadFile(tpl_fname)
1995 self.assertEqual(tpl_data[:len(U_BOOT_TPL_DATA)], U_BOOT_TPL_DATA)
1997 def testPackX86RomIfwi(self):
1998 """Test that an x86 ROM with Integrated Firmware Image can be created"""
1999 self._SetupIfwi('fitimage.bin')
2000 data = self._DoReadFile('111_x86-rom-ifwi.dts')
2001 self._CheckIfwi(data)
2003 def testPackX86RomIfwiNoDesc(self):
2004 """Test that an x86 ROM with IFWI can be created from an ifwi.bin file"""
2005 self._SetupIfwi('ifwi.bin')
2006 data = self._DoReadFile('112_x86-rom-ifwi-nodesc.dts')
2007 self._CheckIfwi(data)
2009 def testPackX86RomIfwiNoData(self):
2010 """Test that an x86 ROM with IFWI handles missing data"""
2011 self._SetupIfwi('ifwi.bin')
2012 with self.assertRaises(ValueError) as e:
2013 data = self._DoReadFile('113_x86-rom-ifwi-nodata.dts')
2014 self.assertIn('Could not complete processing of contents',
2017 def testCbfsOffset(self):
2018 """Test a CBFS with files at particular offsets
2020 Like all CFBS tests, this is just checking the logic that calls
2021 cbfs_util. See cbfs_util_test for fully tests (e.g. test_cbfs_offset()).
2023 data = self._DoReadFile('114_cbfs_offset.dts')
2026 cbfs = cbfs_util.CbfsReader(data)
2027 self.assertEqual(size, cbfs.rom_size)
2029 self.assertIn('u-boot', cbfs.files)
2030 cfile = cbfs.files['u-boot']
2031 self.assertEqual(U_BOOT_DATA, cfile.data)
2032 self.assertEqual(0x40, cfile.cbfs_offset)
2034 self.assertIn('u-boot-dtb', cbfs.files)
2035 cfile2 = cbfs.files['u-boot-dtb']
2036 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
2037 self.assertEqual(0x140, cfile2.cbfs_offset)
2039 def testFdtmap(self):
2040 """Test an FDT map can be inserted in the image"""
2041 data = self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
2042 fdtmap_data = data[len(U_BOOT_DATA):]
2043 magic = fdtmap_data[:8]
2044 self.assertEqual('_FDTMAP_', magic)
2045 self.assertEqual(tools.GetBytes(0, 8), fdtmap_data[8:16])
2047 fdt_data = fdtmap_data[16:]
2048 dtb = fdt.Fdt.FromData(fdt_data)
2050 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'],
2056 'u-boot:size': len(U_BOOT_DATA),
2057 'u-boot:image-pos': 0,
2058 'fdtmap:image-pos': 4,
2060 'fdtmap:size': len(fdtmap_data),
2064 def testFdtmapNoMatch(self):
2065 """Check handling of an FDT map when the section cannot be found"""
2066 self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
2068 # Mangle the section name, which should cause a mismatch between the
2069 # correct FDT path and the one expected by the section
2070 image = control.images['image']
2071 image._node.path += '-suffix'
2072 entries = image.GetEntries()
2073 fdtmap = entries['fdtmap']
2074 with self.assertRaises(ValueError) as e:
2076 self.assertIn("Cannot locate node for path '/binman-suffix'",
2079 def testFdtmapHeader(self):
2080 """Test an FDT map and image header can be inserted in the image"""
2081 data = self.data = self._DoReadFileRealDtb('116_fdtmap_hdr.dts')
2082 fdtmap_pos = len(U_BOOT_DATA)
2083 fdtmap_data = data[fdtmap_pos:]
2084 fdt_data = fdtmap_data[16:]
2085 dtb = fdt.Fdt.FromData(fdt_data)
2086 fdt_size = dtb.GetFdtObj().totalsize()
2087 hdr_data = data[-8:]
2088 self.assertEqual('BinM', hdr_data[:4])
2089 offset = struct.unpack('<I', hdr_data[4:])[0] & 0xffffffff
2090 self.assertEqual(fdtmap_pos - 0x400, offset - (1 << 32))
2092 def testFdtmapHeaderStart(self):
2093 """Test an image header can be inserted at the image start"""
2094 data = self.data = self._DoReadFileRealDtb('117_fdtmap_hdr_start.dts')
2095 fdtmap_pos = 0x100 + len(U_BOOT_DATA)
2097 self.assertEqual('BinM', hdr_data[:4])
2098 offset = struct.unpack('<I', hdr_data[4:])[0]
2099 self.assertEqual(fdtmap_pos, offset)
2101 def testFdtmapHeaderPos(self):
2102 """Test an image header can be inserted at a chosen position"""
2103 data = self.data = self._DoReadFileRealDtb('118_fdtmap_hdr_pos.dts')
2104 fdtmap_pos = 0x100 + len(U_BOOT_DATA)
2105 hdr_data = data[0x80:0x88]
2106 self.assertEqual('BinM', hdr_data[:4])
2107 offset = struct.unpack('<I', hdr_data[4:])[0]
2108 self.assertEqual(fdtmap_pos, offset)
2110 def testHeaderMissingFdtmap(self):
2111 """Test an image header requires an fdtmap"""
2112 with self.assertRaises(ValueError) as e:
2113 self.data = self._DoReadFileRealDtb('119_fdtmap_hdr_missing.dts')
2114 self.assertIn("'image_header' section must have an 'fdtmap' sibling",
2117 def testHeaderNoLocation(self):
2118 """Test an image header with a no specified location is detected"""
2119 with self.assertRaises(ValueError) as e:
2120 self.data = self._DoReadFileRealDtb('120_hdr_no_location.dts')
2121 self.assertIn("Invalid location 'None', expected 'start' or 'end'",
2124 def testEntryExpand(self):
2125 """Test expanding an entry after it is packed"""
2126 data = self._DoReadFile('121_entry_expand.dts')
2127 self.assertEqual(b'aa', data[:2])
2128 self.assertEqual(U_BOOT_DATA, data[2:2 + len(U_BOOT_DATA)])
2129 self.assertEqual(b'aa', data[-2:])
2131 def testEntryExpandBad(self):
2132 """Test expanding an entry after it is packed, twice"""
2133 with self.assertRaises(ValueError) as e:
2134 self._DoReadFile('122_entry_expand_twice.dts')
2135 self.assertIn("Image '/binman': Entries expanded after packing",
2138 def testEntryExpandSection(self):
2139 """Test expanding an entry within a section after it is packed"""
2140 data = self._DoReadFile('123_entry_expand_section.dts')
2141 self.assertEqual(b'aa', data[:2])
2142 self.assertEqual(U_BOOT_DATA, data[2:2 + len(U_BOOT_DATA)])
2143 self.assertEqual(b'aa', data[-2:])
2145 def testCompressDtb(self):
2146 """Test that compress of device-tree files is supported"""
2148 data = self.data = self._DoReadFileRealDtb('124_compress_dtb.dts')
2149 self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
2150 comp_data = data[len(U_BOOT_DATA):]
2151 orig = self._decompress(comp_data)
2152 dtb = fdt.Fdt.FromData(orig)
2154 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
2156 'u-boot:size': len(U_BOOT_DATA),
2157 'u-boot-dtb:uncomp-size': len(orig),
2158 'u-boot-dtb:size': len(comp_data),
2161 self.assertEqual(expected, props)
2164 if __name__ == "__main__":