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"""
1223 with self.assertRaises(ValueError) as e:
1224 self._DoReadFile('059_change_size.dts', True)
1225 self.assertIn("Node '/binman/_testing': Cannot update entry size from "
1226 '1 to 2', str(e.exception))
1228 def testUpdateFdt(self):
1229 """Test that we can update the device tree with offset/size info"""
1230 _, _, _, out_dtb_fname = self._DoReadFileDtb('060_fdt_update.dts',
1232 dtb = fdt.Fdt(out_dtb_fname)
1234 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'])
1238 '_testing:offset': 32,
1240 '_testing:image-pos': 32,
1241 'section@0/u-boot:offset': 0,
1242 'section@0/u-boot:size': len(U_BOOT_DATA),
1243 'section@0/u-boot:image-pos': 0,
1244 'section@0:offset': 0,
1245 'section@0:size': 16,
1246 'section@0:image-pos': 0,
1248 'section@1/u-boot:offset': 0,
1249 'section@1/u-boot:size': len(U_BOOT_DATA),
1250 'section@1/u-boot:image-pos': 16,
1251 'section@1:offset': 16,
1252 'section@1:size': 16,
1253 'section@1:image-pos': 16,
1257 def testUpdateFdtBad(self):
1258 """Test that we detect when ProcessFdt never completes"""
1259 with self.assertRaises(ValueError) as e:
1260 self._DoReadFileDtb('061_fdt_update_bad.dts', update_dtb=True)
1261 self.assertIn('Could not complete processing of Fdt: remaining '
1262 '[<_testing.Entry__testing', str(e.exception))
1264 def testEntryArgs(self):
1265 """Test passing arguments to entries from the command line"""
1267 'test-str-arg': 'test1',
1268 'test-int-arg': '456',
1270 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
1271 self.assertIn('image', control.images)
1272 entry = control.images['image'].GetEntries()['_testing']
1273 self.assertEqual('test0', entry.test_str_fdt)
1274 self.assertEqual('test1', entry.test_str_arg)
1275 self.assertEqual(123, entry.test_int_fdt)
1276 self.assertEqual(456, entry.test_int_arg)
1278 def testEntryArgsMissing(self):
1279 """Test missing arguments and properties"""
1281 'test-int-arg': '456',
1283 self._DoReadFileDtb('063_entry_args_missing.dts', entry_args=entry_args)
1284 entry = control.images['image'].GetEntries()['_testing']
1285 self.assertEqual('test0', entry.test_str_fdt)
1286 self.assertEqual(None, entry.test_str_arg)
1287 self.assertEqual(None, entry.test_int_fdt)
1288 self.assertEqual(456, entry.test_int_arg)
1290 def testEntryArgsRequired(self):
1291 """Test missing arguments and properties"""
1293 'test-int-arg': '456',
1295 with self.assertRaises(ValueError) as e:
1296 self._DoReadFileDtb('064_entry_args_required.dts')
1297 self.assertIn("Node '/binman/_testing': Missing required "
1298 'properties/entry args: test-str-arg, test-int-fdt, test-int-arg',
1301 def testEntryArgsInvalidFormat(self):
1302 """Test that an invalid entry-argument format is detected"""
1303 args = ['build', '-d', self.TestFile('064_entry_args_required.dts'),
1305 with self.assertRaises(ValueError) as e:
1306 self._DoBinman(*args)
1307 self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
1309 def testEntryArgsInvalidInteger(self):
1310 """Test that an invalid entry-argument integer is detected"""
1312 'test-int-arg': 'abc',
1314 with self.assertRaises(ValueError) as e:
1315 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
1316 self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
1317 "'test-int-arg' (value 'abc') to integer",
1320 def testEntryArgsInvalidDatatype(self):
1321 """Test that an invalid entry-argument datatype is detected
1323 This test could be written in entry_test.py except that it needs
1324 access to control.entry_args, which seems more than that module should
1328 'test-bad-datatype-arg': '12',
1330 with self.assertRaises(ValueError) as e:
1331 self._DoReadFileDtb('065_entry_args_unknown_datatype.dts',
1332 entry_args=entry_args)
1333 self.assertIn('GetArg() internal error: Unknown data type ',
1337 """Test for a text entry type"""
1339 'test-id': TEXT_DATA,
1340 'test-id2': TEXT_DATA2,
1341 'test-id3': TEXT_DATA3,
1343 data, _, _, _ = self._DoReadFileDtb('066_text.dts',
1344 entry_args=entry_args)
1345 expected = (tools.ToBytes(TEXT_DATA) +
1346 tools.GetBytes(0, 8 - len(TEXT_DATA)) +
1347 tools.ToBytes(TEXT_DATA2) + tools.ToBytes(TEXT_DATA3) +
1348 b'some text' + b'more text')
1349 self.assertEqual(expected, data)
1351 def testEntryDocs(self):
1352 """Test for creation of entry documentation"""
1353 with test_util.capture_sys_output() as (stdout, stderr):
1354 control.WriteEntryDocs(binman.GetEntryModules())
1355 self.assertTrue(len(stdout.getvalue()) > 0)
1357 def testEntryDocsMissing(self):
1358 """Test handling of missing entry documentation"""
1359 with self.assertRaises(ValueError) as e:
1360 with test_util.capture_sys_output() as (stdout, stderr):
1361 control.WriteEntryDocs(binman.GetEntryModules(), 'u_boot')
1362 self.assertIn('Documentation is missing for modules: u_boot',
1366 """Basic test of generation of a flashrom fmap"""
1367 data = self._DoReadFile('067_fmap.dts')
1368 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1369 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1370 U_BOOT_DATA + tools.GetBytes(ord('a'), 12))
1371 self.assertEqual(expected, data[:32])
1372 self.assertEqual(b'__FMAP__', fhdr.signature)
1373 self.assertEqual(1, fhdr.ver_major)
1374 self.assertEqual(0, fhdr.ver_minor)
1375 self.assertEqual(0, fhdr.base)
1376 self.assertEqual(16 + 16 +
1377 fmap_util.FMAP_HEADER_LEN +
1378 fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
1379 self.assertEqual(b'FMAP', fhdr.name)
1380 self.assertEqual(3, fhdr.nareas)
1381 for fentry in fentries:
1382 self.assertEqual(0, fentry.flags)
1384 self.assertEqual(0, fentries[0].offset)
1385 self.assertEqual(4, fentries[0].size)
1386 self.assertEqual(b'RO_U_BOOT', fentries[0].name)
1388 self.assertEqual(16, fentries[1].offset)
1389 self.assertEqual(4, fentries[1].size)
1390 self.assertEqual(b'RW_U_BOOT', fentries[1].name)
1392 self.assertEqual(32, fentries[2].offset)
1393 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1394 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1395 self.assertEqual(b'FMAP', fentries[2].name)
1397 def testBlobNamedByArg(self):
1398 """Test we can add a blob with the filename coming from an entry arg"""
1400 'cros-ec-rw-path': 'ecrw.bin',
1402 data, _, _, _ = self._DoReadFileDtb('068_blob_named_by_arg.dts',
1403 entry_args=entry_args)
1406 """Test for an fill entry type"""
1407 data = self._DoReadFile('069_fill.dts')
1408 expected = tools.GetBytes(0xff, 8) + tools.GetBytes(0, 8)
1409 self.assertEqual(expected, data)
1411 def testFillNoSize(self):
1412 """Test for an fill entry type with no size"""
1413 with self.assertRaises(ValueError) as e:
1414 self._DoReadFile('070_fill_no_size.dts')
1415 self.assertIn("'fill' entry must have a size property",
1418 def _HandleGbbCommand(self, pipe_list):
1419 """Fake calls to the futility utility"""
1420 if pipe_list[0][0] == 'futility':
1421 fname = pipe_list[0][-1]
1422 # Append our GBB data to the file, which will happen every time the
1423 # futility command is called.
1424 with open(fname, 'ab') as fd:
1426 return command.CommandResult()
1429 """Test for the Chromium OS Google Binary Block"""
1430 command.test_result = self._HandleGbbCommand
1432 'keydir': 'devkeys',
1433 'bmpblk': 'bmpblk.bin',
1435 data, _, _, _ = self._DoReadFileDtb('071_gbb.dts', entry_args=entry_args)
1438 expected = (GBB_DATA + GBB_DATA + tools.GetBytes(0, 8) +
1439 tools.GetBytes(0, 0x2180 - 16))
1440 self.assertEqual(expected, data)
1442 def testGbbTooSmall(self):
1443 """Test for the Chromium OS Google Binary Block being large enough"""
1444 with self.assertRaises(ValueError) as e:
1445 self._DoReadFileDtb('072_gbb_too_small.dts')
1446 self.assertIn("Node '/binman/gbb': GBB is too small",
1449 def testGbbNoSize(self):
1450 """Test for the Chromium OS Google Binary Block having a size"""
1451 with self.assertRaises(ValueError) as e:
1452 self._DoReadFileDtb('073_gbb_no_size.dts')
1453 self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
1456 def _HandleVblockCommand(self, pipe_list):
1457 """Fake calls to the futility utility"""
1458 if pipe_list[0][0] == 'futility':
1459 fname = pipe_list[0][3]
1460 with open(fname, 'wb') as fd:
1461 fd.write(VBLOCK_DATA)
1462 return command.CommandResult()
1464 def testVblock(self):
1465 """Test for the Chromium OS Verified Boot Block"""
1466 command.test_result = self._HandleVblockCommand
1468 'keydir': 'devkeys',
1470 data, _, _, _ = self._DoReadFileDtb('074_vblock.dts',
1471 entry_args=entry_args)
1472 expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
1473 self.assertEqual(expected, data)
1475 def testVblockNoContent(self):
1476 """Test we detect a vblock which has no content to sign"""
1477 with self.assertRaises(ValueError) as e:
1478 self._DoReadFile('075_vblock_no_content.dts')
1479 self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
1480 'property', str(e.exception))
1482 def testVblockBadPhandle(self):
1483 """Test that we detect a vblock with an invalid phandle in contents"""
1484 with self.assertRaises(ValueError) as e:
1485 self._DoReadFile('076_vblock_bad_phandle.dts')
1486 self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
1487 '1000', str(e.exception))
1489 def testVblockBadEntry(self):
1490 """Test that we detect an entry that points to a non-entry"""
1491 with self.assertRaises(ValueError) as e:
1492 self._DoReadFile('077_vblock_bad_entry.dts')
1493 self.assertIn("Node '/binman/vblock': Cannot find entry for node "
1494 "'other'", str(e.exception))
1497 """Test that an image with TPL and ots device tree can be created"""
1498 # ELF file with a '__bss_size' symbol
1499 with open(self.TestFile('bss_data'), 'rb') as fd:
1500 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1501 data = self._DoReadFile('078_u_boot_tpl.dts')
1502 self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
1504 def testUsesPos(self):
1505 """Test that the 'pos' property cannot be used anymore"""
1506 with self.assertRaises(ValueError) as e:
1507 data = self._DoReadFile('079_uses_pos.dts')
1508 self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
1509 "'pos'", str(e.exception))
1511 def testFillZero(self):
1512 """Test for an fill entry type with a size of 0"""
1513 data = self._DoReadFile('080_fill_empty.dts')
1514 self.assertEqual(tools.GetBytes(0, 16), data)
1516 def testTextMissing(self):
1517 """Test for a text entry type where there is no text"""
1518 with self.assertRaises(ValueError) as e:
1519 self._DoReadFileDtb('066_text.dts',)
1520 self.assertIn("Node '/binman/text': No value provided for text label "
1521 "'test-id'", str(e.exception))
1523 def testPackStart16Tpl(self):
1524 """Test that an image with an x86 start16 TPL region can be created"""
1525 data = self._DoReadFile('081_x86-start16-tpl.dts')
1526 self.assertEqual(X86_START16_TPL_DATA, data[:len(X86_START16_TPL_DATA)])
1528 def testSelectImage(self):
1529 """Test that we can select which images to build"""
1530 expected = 'Skipping images: image1'
1532 # We should only get the expected message in verbose mode
1533 for verbosity in (0, 2):
1534 with test_util.capture_sys_output() as (stdout, stderr):
1535 retcode = self._DoTestFile('006_dual_image.dts',
1536 verbosity=verbosity,
1538 self.assertEqual(0, retcode)
1540 self.assertIn(expected, stdout.getvalue())
1542 self.assertNotIn(expected, stdout.getvalue())
1544 self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
1545 self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
1547 def testUpdateFdtAll(self):
1548 """Test that all device trees are updated with offset/size info"""
1549 data = self._DoReadFileRealDtb('082_fdt_update_all.dts')
1552 'section:image-pos': 0,
1553 'u-boot-tpl-dtb:size': 513,
1554 'u-boot-spl-dtb:size': 513,
1555 'u-boot-spl-dtb:offset': 493,
1557 'section/u-boot-dtb:image-pos': 0,
1558 'u-boot-spl-dtb:image-pos': 493,
1559 'section/u-boot-dtb:size': 493,
1560 'u-boot-tpl-dtb:image-pos': 1006,
1561 'section/u-boot-dtb:offset': 0,
1562 'section:size': 493,
1564 'section:offset': 0,
1565 'u-boot-tpl-dtb:offset': 1006,
1569 # We expect three device-tree files in the output, one after the other.
1570 # Read them in sequence. We look for an 'spl' property in the SPL tree,
1571 # and 'tpl' in the TPL tree, to make sure they are distinct from the
1572 # main U-Boot tree. All three should have the same postions and offset.
1574 for item in ['', 'spl', 'tpl']:
1575 dtb = fdt.Fdt.FromData(data[start:])
1577 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos',
1579 expected = dict(base_expected)
1582 self.assertEqual(expected, props)
1583 start += dtb._fdt_obj.totalsize()
1585 def testUpdateFdtOutput(self):
1586 """Test that output DTB files are updated"""
1588 data, dtb_data, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
1589 use_real_dtb=True, update_dtb=True, reset_dtbs=False)
1591 # Unfortunately, compiling a source file always results in a file
1592 # called source.dtb (see fdt_util.EnsureCompiled()). The test
1593 # source file (e.g. test/075_fdt_update_all.dts) thus does not enter
1594 # binman as a file called u-boot.dtb. To fix this, copy the file
1595 # over to the expected place.
1596 #tools.WriteFile(os.path.join(self._indir, 'u-boot.dtb'),
1597 #tools.ReadFile(tools.GetOutputFilename('source.dtb')))
1599 for fname in ['u-boot.dtb.out', 'spl/u-boot-spl.dtb.out',
1600 'tpl/u-boot-tpl.dtb.out']:
1601 dtb = fdt.Fdt.FromData(data[start:])
1602 size = dtb._fdt_obj.totalsize()
1603 pathname = tools.GetOutputFilename(os.path.split(fname)[1])
1604 outdata = tools.ReadFile(pathname)
1605 name = os.path.split(fname)[0]
1608 orig_indata = self._GetDtbContentsForSplTpl(dtb_data, name)
1610 orig_indata = dtb_data
1611 self.assertNotEqual(outdata, orig_indata,
1612 "Expected output file '%s' be updated" % pathname)
1613 self.assertEqual(outdata, data[start:start + size],
1614 "Expected output file '%s' to match output image" %
1620 def _decompress(self, data):
1621 return tools.Decompress(data, 'lz4')
1623 def testCompress(self):
1624 """Test compression of blobs"""
1626 data, _, _, out_dtb_fname = self._DoReadFileDtb('083_compress.dts',
1627 use_real_dtb=True, update_dtb=True)
1628 dtb = fdt.Fdt(out_dtb_fname)
1630 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
1631 orig = self._decompress(data)
1632 self.assertEquals(COMPRESS_DATA, orig)
1634 'blob:uncomp-size': len(COMPRESS_DATA),
1635 'blob:size': len(data),
1638 self.assertEqual(expected, props)
1640 def testFiles(self):
1641 """Test bringing in multiple files"""
1642 data = self._DoReadFile('084_files.dts')
1643 self.assertEqual(FILES_DATA, data)
1645 def testFilesCompress(self):
1646 """Test bringing in multiple files and compressing them"""
1648 data = self._DoReadFile('085_files_compress.dts')
1650 image = control.images['image']
1651 entries = image.GetEntries()
1652 files = entries['files']
1653 entries = files._section._entries
1656 for i in range(1, 3):
1658 start = entries[key].image_pos
1659 len = entries[key].size
1660 chunk = data[start:start + len]
1661 orig += self._decompress(chunk)
1663 self.assertEqual(FILES_DATA, orig)
1665 def testFilesMissing(self):
1666 """Test missing files"""
1667 with self.assertRaises(ValueError) as e:
1668 data = self._DoReadFile('086_files_none.dts')
1669 self.assertIn("Node '/binman/files': Pattern \'files/*.none\' matched "
1670 'no files', str(e.exception))
1672 def testFilesNoPattern(self):
1673 """Test missing files"""
1674 with self.assertRaises(ValueError) as e:
1675 data = self._DoReadFile('087_files_no_pattern.dts')
1676 self.assertIn("Node '/binman/files': Missing 'pattern' property",
1679 def testExpandSize(self):
1680 """Test an expanding entry"""
1681 data, _, map_data, _ = self._DoReadFileDtb('088_expand_size.dts',
1683 expect = (tools.GetBytes(ord('a'), 8) + U_BOOT_DATA +
1684 MRC_DATA + tools.GetBytes(ord('b'), 1) + U_BOOT_DATA +
1685 tools.GetBytes(ord('c'), 8) + U_BOOT_DATA +
1686 tools.GetBytes(ord('d'), 8))
1687 self.assertEqual(expect, data)
1688 self.assertEqual('''ImagePos Offset Size Name
1689 00000000 00000000 00000028 main-section
1690 00000000 00000000 00000008 fill
1691 00000008 00000008 00000004 u-boot
1692 0000000c 0000000c 00000004 section
1693 0000000c 00000000 00000003 intel-mrc
1694 00000010 00000010 00000004 u-boot2
1695 00000014 00000014 0000000c section2
1696 00000014 00000000 00000008 fill
1697 0000001c 00000008 00000004 u-boot
1698 00000020 00000020 00000008 fill2
1701 def testExpandSizeBad(self):
1702 """Test an expanding entry which fails to provide contents"""
1703 with test_util.capture_sys_output() as (stdout, stderr):
1704 with self.assertRaises(ValueError) as e:
1705 self._DoReadFileDtb('089_expand_size_bad.dts', map=True)
1706 self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
1707 'expanding entry', str(e.exception))
1710 """Test hashing of the contents of an entry"""
1711 _, _, _, out_dtb_fname = self._DoReadFileDtb('090_hash.dts',
1712 use_real_dtb=True, update_dtb=True)
1713 dtb = fdt.Fdt(out_dtb_fname)
1715 hash_node = dtb.GetNode('/binman/u-boot/hash').props['value']
1716 m = hashlib.sha256()
1717 m.update(U_BOOT_DATA)
1718 self.assertEqual(m.digest(), b''.join(hash_node.value))
1720 def testHashNoAlgo(self):
1721 with self.assertRaises(ValueError) as e:
1722 self._DoReadFileDtb('091_hash_no_algo.dts', update_dtb=True)
1723 self.assertIn("Node \'/binman/u-boot\': Missing \'algo\' property for "
1724 'hash node', str(e.exception))
1726 def testHashBadAlgo(self):
1727 with self.assertRaises(ValueError) as e:
1728 self._DoReadFileDtb('092_hash_bad_algo.dts', update_dtb=True)
1729 self.assertIn("Node '/binman/u-boot': Unknown hash algorithm",
1732 def testHashSection(self):
1733 """Test hashing of the contents of an entry"""
1734 _, _, _, out_dtb_fname = self._DoReadFileDtb('099_hash_section.dts',
1735 use_real_dtb=True, update_dtb=True)
1736 dtb = fdt.Fdt(out_dtb_fname)
1738 hash_node = dtb.GetNode('/binman/section/hash').props['value']
1739 m = hashlib.sha256()
1740 m.update(U_BOOT_DATA)
1741 m.update(tools.GetBytes(ord('a'), 16))
1742 self.assertEqual(m.digest(), b''.join(hash_node.value))
1744 def testPackUBootTplMicrocode(self):
1745 """Test that x86 microcode can be handled correctly in TPL
1747 We expect to see the following in the image, in order:
1748 u-boot-tpl-nodtb.bin with a microcode pointer inserted at the correct
1750 u-boot-tpl.dtb with the microcode removed
1753 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
1754 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1755 first, pos_and_size = self._RunMicrocodeTest('093_x86_tpl_ucode.dts',
1756 U_BOOT_TPL_NODTB_DATA)
1757 self.assertEqual(b'tplnodtb with microc' + pos_and_size +
1758 b'ter somewhere in here', first)
1760 def testFmapX86(self):
1761 """Basic test of generation of a flashrom fmap"""
1762 data = self._DoReadFile('094_fmap_x86.dts')
1763 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1764 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('a'), 32 - 7)
1765 self.assertEqual(expected, data[:32])
1766 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1768 self.assertEqual(0x100, fhdr.image_size)
1770 self.assertEqual(0, fentries[0].offset)
1771 self.assertEqual(4, fentries[0].size)
1772 self.assertEqual(b'U_BOOT', fentries[0].name)
1774 self.assertEqual(4, fentries[1].offset)
1775 self.assertEqual(3, fentries[1].size)
1776 self.assertEqual(b'INTEL_MRC', fentries[1].name)
1778 self.assertEqual(32, fentries[2].offset)
1779 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1780 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1781 self.assertEqual(b'FMAP', fentries[2].name)
1783 def testFmapX86Section(self):
1784 """Basic test of generation of a flashrom fmap"""
1785 data = self._DoReadFile('095_fmap_x86_section.dts')
1786 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('b'), 32 - 7)
1787 self.assertEqual(expected, data[:32])
1788 fhdr, fentries = fmap_util.DecodeFmap(data[36:])
1790 self.assertEqual(0x100, fhdr.image_size)
1792 self.assertEqual(0, fentries[0].offset)
1793 self.assertEqual(4, fentries[0].size)
1794 self.assertEqual(b'U_BOOT', fentries[0].name)
1796 self.assertEqual(4, fentries[1].offset)
1797 self.assertEqual(3, fentries[1].size)
1798 self.assertEqual(b'INTEL_MRC', fentries[1].name)
1800 self.assertEqual(36, fentries[2].offset)
1801 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1802 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1803 self.assertEqual(b'FMAP', fentries[2].name)
1806 """Basic test of ELF entries"""
1808 with open(self.TestFile('bss_data'), 'rb') as fd:
1809 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1810 with open(self.TestFile('bss_data'), 'rb') as fd:
1811 TestFunctional._MakeInputFile('-boot', fd.read())
1812 data = self._DoReadFile('096_elf.dts')
1814 def testElfStrip(self):
1815 """Basic test of ELF entries"""
1817 with open(self.TestFile('bss_data'), 'rb') as fd:
1818 TestFunctional._MakeInputFile('-boot', fd.read())
1819 data = self._DoReadFile('097_elf_strip.dts')
1821 def testPackOverlapMap(self):
1822 """Test that overlapping regions are detected"""
1823 with test_util.capture_sys_output() as (stdout, stderr):
1824 with self.assertRaises(ValueError) as e:
1825 self._DoTestFile('014_pack_overlap.dts', map=True)
1826 map_fname = tools.GetOutputFilename('image.map')
1827 self.assertEqual("Wrote map file '%s' to show errors\n" % map_fname,
1830 # We should not get an inmage, but there should be a map file
1831 self.assertFalse(os.path.exists(tools.GetOutputFilename('image.bin')))
1832 self.assertTrue(os.path.exists(map_fname))
1833 map_data = tools.ReadFile(map_fname, binary=False)
1834 self.assertEqual('''ImagePos Offset Size Name
1835 <none> 00000000 00000007 main-section
1836 <none> 00000000 00000004 u-boot
1837 <none> 00000003 00000004 u-boot-align
1840 def testPackRefCode(self):
1841 """Test that an image with an Intel Reference code binary works"""
1842 data = self._DoReadFile('100_intel_refcode.dts')
1843 self.assertEqual(REFCODE_DATA, data[:len(REFCODE_DATA)])
1845 def testSectionOffset(self):
1846 """Tests use of a section with an offset"""
1847 data, _, map_data, _ = self._DoReadFileDtb('101_sections_offset.dts',
1849 self.assertEqual('''ImagePos Offset Size Name
1850 00000000 00000000 00000038 main-section
1851 00000004 00000004 00000010 section@0
1852 00000004 00000000 00000004 u-boot
1853 00000018 00000018 00000010 section@1
1854 00000018 00000000 00000004 u-boot
1855 0000002c 0000002c 00000004 section@2
1856 0000002c 00000000 00000004 u-boot
1858 self.assertEqual(data,
1859 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1860 tools.GetBytes(0x21, 12) +
1861 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1862 tools.GetBytes(0x61, 12) +
1863 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1864 tools.GetBytes(0x26, 8))
1866 def testCbfsRaw(self):
1867 """Test base handling of a Coreboot Filesystem (CBFS)
1869 The exact contents of the CBFS is verified by similar tests in
1870 cbfs_util_test.py. The tests here merely check that the files added to
1871 the CBFS can be found in the final image.
1873 data = self._DoReadFile('102_cbfs_raw.dts')
1876 cbfs = cbfs_util.CbfsReader(data)
1877 self.assertEqual(size, cbfs.rom_size)
1879 self.assertIn('u-boot-dtb', cbfs.files)
1880 cfile = cbfs.files['u-boot-dtb']
1881 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
1883 def testCbfsArch(self):
1884 """Test on non-x86 architecture"""
1885 data = self._DoReadFile('103_cbfs_raw_ppc.dts')
1888 cbfs = cbfs_util.CbfsReader(data)
1889 self.assertEqual(size, cbfs.rom_size)
1891 self.assertIn('u-boot-dtb', cbfs.files)
1892 cfile = cbfs.files['u-boot-dtb']
1893 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
1895 def testCbfsStage(self):
1896 """Tests handling of a Coreboot Filesystem (CBFS)"""
1897 if not elf.ELF_TOOLS:
1898 self.skipTest('Python elftools not available')
1899 elf_fname = os.path.join(self._indir, 'cbfs-stage.elf')
1900 elf.MakeElf(elf_fname, U_BOOT_DATA, U_BOOT_DTB_DATA)
1903 data = self._DoReadFile('104_cbfs_stage.dts')
1904 cbfs = cbfs_util.CbfsReader(data)
1905 self.assertEqual(size, cbfs.rom_size)
1907 self.assertIn('u-boot', cbfs.files)
1908 cfile = cbfs.files['u-boot']
1909 self.assertEqual(U_BOOT_DATA + U_BOOT_DTB_DATA, cfile.data)
1911 def testCbfsRawCompress(self):
1912 """Test handling of compressing raw files"""
1914 data = self._DoReadFile('105_cbfs_raw_compress.dts')
1917 cbfs = cbfs_util.CbfsReader(data)
1918 self.assertIn('u-boot', cbfs.files)
1919 cfile = cbfs.files['u-boot']
1920 self.assertEqual(COMPRESS_DATA, cfile.data)
1922 def testCbfsBadArch(self):
1923 """Test handling of a bad architecture"""
1924 with self.assertRaises(ValueError) as e:
1925 self._DoReadFile('106_cbfs_bad_arch.dts')
1926 self.assertIn("Invalid architecture 'bad-arch'", str(e.exception))
1928 def testCbfsNoSize(self):
1929 """Test handling of a missing size property"""
1930 with self.assertRaises(ValueError) as e:
1931 self._DoReadFile('107_cbfs_no_size.dts')
1932 self.assertIn('entry must have a size property', str(e.exception))
1934 def testCbfsNoCOntents(self):
1935 """Test handling of a CBFS entry which does not provide contentsy"""
1936 with self.assertRaises(ValueError) as e:
1937 self._DoReadFile('108_cbfs_no_contents.dts')
1938 self.assertIn('Could not complete processing of contents',
1941 def testCbfsBadCompress(self):
1942 """Test handling of a bad architecture"""
1943 with self.assertRaises(ValueError) as e:
1944 self._DoReadFile('109_cbfs_bad_compress.dts')
1945 self.assertIn("Invalid compression in 'u-boot': 'invalid-algo'",
1948 def testCbfsNamedEntries(self):
1949 """Test handling of named entries"""
1950 data = self._DoReadFile('110_cbfs_name.dts')
1952 cbfs = cbfs_util.CbfsReader(data)
1953 self.assertIn('FRED', cbfs.files)
1954 cfile1 = cbfs.files['FRED']
1955 self.assertEqual(U_BOOT_DATA, cfile1.data)
1957 self.assertIn('hello', cbfs.files)
1958 cfile2 = cbfs.files['hello']
1959 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
1961 def _SetupIfwi(self, fname):
1962 """Set up to run an IFWI test
1965 fname: Filename of input file to provide (fitimage.bin or ifwi.bin)
1969 # Intel Integrated Firmware Image (IFWI) file
1970 with gzip.open(self.TestFile('%s.gz' % fname), 'rb') as fd:
1972 TestFunctional._MakeInputFile(fname,data)
1974 def _CheckIfwi(self, data):
1975 """Check that an image with an IFWI contains the correct output
1978 data: Conents of output file
1980 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
1981 if data[:0x1000] != expected_desc:
1982 self.fail('Expected descriptor binary at start of image')
1984 # We expect to find the TPL wil in subpart IBBP entry IBBL
1985 image_fname = tools.GetOutputFilename('image.bin')
1986 tpl_fname = tools.GetOutputFilename('tpl.out')
1987 tools.RunIfwiTool(image_fname, tools.CMD_EXTRACT, fname=tpl_fname,
1988 subpart='IBBP', entry_name='IBBL')
1990 tpl_data = tools.ReadFile(tpl_fname)
1991 self.assertEqual(tpl_data[:len(U_BOOT_TPL_DATA)], U_BOOT_TPL_DATA)
1993 def testPackX86RomIfwi(self):
1994 """Test that an x86 ROM with Integrated Firmware Image can be created"""
1995 self._SetupIfwi('fitimage.bin')
1996 data = self._DoReadFile('111_x86-rom-ifwi.dts')
1997 self._CheckIfwi(data)
1999 def testPackX86RomIfwiNoDesc(self):
2000 """Test that an x86 ROM with IFWI can be created from an ifwi.bin file"""
2001 self._SetupIfwi('ifwi.bin')
2002 data = self._DoReadFile('112_x86-rom-ifwi-nodesc.dts')
2003 self._CheckIfwi(data)
2005 def testPackX86RomIfwiNoData(self):
2006 """Test that an x86 ROM with IFWI handles missing data"""
2007 self._SetupIfwi('ifwi.bin')
2008 with self.assertRaises(ValueError) as e:
2009 data = self._DoReadFile('113_x86-rom-ifwi-nodata.dts')
2010 self.assertIn('Could not complete processing of contents',
2013 def testCbfsOffset(self):
2014 """Test a CBFS with files at particular offsets
2016 Like all CFBS tests, this is just checking the logic that calls
2017 cbfs_util. See cbfs_util_test for fully tests (e.g. test_cbfs_offset()).
2019 data = self._DoReadFile('114_cbfs_offset.dts')
2022 cbfs = cbfs_util.CbfsReader(data)
2023 self.assertEqual(size, cbfs.rom_size)
2025 self.assertIn('u-boot', cbfs.files)
2026 cfile = cbfs.files['u-boot']
2027 self.assertEqual(U_BOOT_DATA, cfile.data)
2028 self.assertEqual(0x40, cfile.cbfs_offset)
2030 self.assertIn('u-boot-dtb', cbfs.files)
2031 cfile2 = cbfs.files['u-boot-dtb']
2032 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
2033 self.assertEqual(0x140, cfile2.cbfs_offset)
2035 def testFdtmap(self):
2036 """Test an FDT map can be inserted in the image"""
2037 data = self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
2038 fdtmap_data = data[len(U_BOOT_DATA):]
2039 magic = fdtmap_data[:8]
2040 self.assertEqual('_FDTMAP_', magic)
2041 self.assertEqual(tools.GetBytes(0, 8), fdtmap_data[8:16])
2043 fdt_data = fdtmap_data[16:]
2044 dtb = fdt.Fdt.FromData(fdt_data)
2046 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'],
2052 'u-boot:size': len(U_BOOT_DATA),
2053 'u-boot:image-pos': 0,
2054 'fdtmap:image-pos': 4,
2056 'fdtmap:size': len(fdtmap_data),
2060 def testFdtmapNoMatch(self):
2061 """Check handling of an FDT map when the section cannot be found"""
2062 self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
2064 # Mangle the section name, which should cause a mismatch between the
2065 # correct FDT path and the one expected by the section
2066 image = control.images['image']
2067 image._node.path += '-suffix'
2068 entries = image.GetEntries()
2069 fdtmap = entries['fdtmap']
2070 with self.assertRaises(ValueError) as e:
2072 self.assertIn("Cannot locate node for path '/binman-suffix'",
2075 def testFdtmapHeader(self):
2076 """Test an FDT map and image header can be inserted in the image"""
2077 data = self.data = self._DoReadFileRealDtb('116_fdtmap_hdr.dts')
2078 fdtmap_pos = len(U_BOOT_DATA)
2079 fdtmap_data = data[fdtmap_pos:]
2080 fdt_data = fdtmap_data[16:]
2081 dtb = fdt.Fdt.FromData(fdt_data)
2082 fdt_size = dtb.GetFdtObj().totalsize()
2083 hdr_data = data[-8:]
2084 self.assertEqual('BinM', hdr_data[:4])
2085 offset = struct.unpack('<I', hdr_data[4:])[0] & 0xffffffff
2086 self.assertEqual(fdtmap_pos - 0x400, offset - (1 << 32))
2088 def testFdtmapHeaderStart(self):
2089 """Test an image header can be inserted at the image start"""
2090 data = self.data = self._DoReadFileRealDtb('117_fdtmap_hdr_start.dts')
2091 fdtmap_pos = 0x100 + len(U_BOOT_DATA)
2093 self.assertEqual('BinM', hdr_data[:4])
2094 offset = struct.unpack('<I', hdr_data[4:])[0]
2095 self.assertEqual(fdtmap_pos, offset)
2097 def testFdtmapHeaderPos(self):
2098 """Test an image header can be inserted at a chosen position"""
2099 data = self.data = self._DoReadFileRealDtb('118_fdtmap_hdr_pos.dts')
2100 fdtmap_pos = 0x100 + len(U_BOOT_DATA)
2101 hdr_data = data[0x80:0x88]
2102 self.assertEqual('BinM', hdr_data[:4])
2103 offset = struct.unpack('<I', hdr_data[4:])[0]
2104 self.assertEqual(fdtmap_pos, offset)
2106 def testHeaderMissingFdtmap(self):
2107 """Test an image header requires an fdtmap"""
2108 with self.assertRaises(ValueError) as e:
2109 self.data = self._DoReadFileRealDtb('119_fdtmap_hdr_missing.dts')
2110 self.assertIn("'image_header' section must have an 'fdtmap' sibling",
2113 def testHeaderNoLocation(self):
2114 """Test an image header with a no specified location is detected"""
2115 with self.assertRaises(ValueError) as e:
2116 self.data = self._DoReadFileRealDtb('120_hdr_no_location.dts')
2117 self.assertIn("Invalid location 'None', expected 'start' or 'end'",
2121 if __name__ == "__main__":