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,
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
174 if not self.have_lz4:
175 self.skipTest('lz4 --no-frame-crc not available')
178 # Enable this to turn on debugging output
179 # tout.Init(tout.DEBUG)
180 command.test_result = None
183 """Remove the temporary output directory"""
184 if self.preserve_outdirs:
185 print('Preserving output dir: %s' % tools.outdir)
187 tools._FinaliseForTest()
190 def _ResetDtbs(self):
191 TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
192 TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
193 TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
195 def _GetVerbosity(self):
196 """Check if verbosity should be enabled
199 list containing either:
200 - Verbosity flag (e.g. '-v2') if it is present on the cmd line
201 - nothing if the flag is not present
203 for arg in sys.argv[1:]:
204 if arg.startswith('-v'):
208 def _RunBinman(self, *args, **kwargs):
209 """Run binman using the command line
212 Arguments to pass, as a list of strings
213 kwargs: Arguments to pass to Command.RunPipe()
215 result = command.RunPipe([[self._binman_pathname] + list(args)],
216 capture=True, capture_stderr=True, raise_on_error=False)
217 if result.return_code and kwargs.get('raise_on_error', True):
218 raise Exception("Error running '%s': %s" % (' '.join(args),
219 result.stdout + result.stderr))
222 def _DoBinman(self, *args):
223 """Run binman using directly (in the same process)
226 Arguments to pass, as a list of strings
228 Return value (0 for success)
233 (options, args) = cmdline.ParseArgs(args)
234 options.pager = 'binman-invalid-pager'
235 options.build_dir = self._indir
237 # For testing, you can force an increase in verbosity here
238 # options.verbosity = tout.DEBUG
239 return control.Binman(options, args)
241 def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
242 entry_args=None, images=None, use_real_dtb=False,
244 """Run binman with a given test file
247 fname: Device-tree source filename to use (e.g. 005_simple.dts)
248 debug: True to enable debugging output
249 map: True to output map files for the images
250 update_dtb: Update the offset and size of each entry in the device
251 tree before packing it into the image
252 entry_args: Dict of entry args to supply to binman
254 value: value of that arg
255 images: List of image names to build
257 args = ['-p', '-I', self._indir, '-d', self.TestFile(fname)]
265 args.append('--fake-dtb')
266 if verbosity is not None:
267 args.append('-v%d' % verbosity)
269 args += self._GetVerbosity()
271 for arg, value in entry_args.items():
272 args.append('-a%s=%s' % (arg, value))
275 args += ['-i', image]
277 for path in self.toolpath:
278 args += ['--toolpath', path]
279 return self._DoBinman(*args)
281 def _SetupDtb(self, fname, outfile='u-boot.dtb'):
282 """Set up a new test device-tree file
284 The given file is compiled and set up as the device tree to be used
288 fname: Filename of .dts file to read
289 outfile: Output filename for compiled device-tree binary
292 Contents of device-tree binary
294 tools.PrepareOutputDir(None)
295 dtb = fdt_util.EnsureCompiled(self.TestFile(fname))
296 with open(dtb, 'rb') as fd:
298 TestFunctional._MakeInputFile(outfile, data)
299 tools.FinaliseOutputDir()
302 def _GetDtbContentsForSplTpl(self, dtb_data, name):
303 """Create a version of the main DTB for SPL or SPL
305 For testing we don't actually have different versions of the DTB. With
306 U-Boot we normally run fdtgrep to remove unwanted nodes, but for tests
307 we don't normally have any unwanted nodes.
309 We still want the DTBs for SPL and TPL to be different though, since
310 otherwise it is confusing to know which one we are looking at. So add
311 an 'spl' or 'tpl' property to the top-level node.
313 dtb = fdt.Fdt.FromData(dtb_data)
315 dtb.GetNode('/binman').AddZeroProp(name)
316 dtb.Sync(auto_resize=True)
318 return dtb.GetContents()
320 def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
321 update_dtb=False, entry_args=None, reset_dtbs=True):
322 """Run binman and return the resulting image
324 This runs binman with a given test file and then reads the resulting
325 output file. It is a shortcut function since most tests need to do
328 Raises an assertion failure if binman returns a non-zero exit code.
331 fname: Device-tree source filename to use (e.g. 005_simple.dts)
332 use_real_dtb: True to use the test file as the contents of
333 the u-boot-dtb entry. Normally this is not needed and the
334 test contents (the U_BOOT_DTB_DATA string) can be used.
335 But in some test we need the real contents.
336 map: True to output map files for the images
337 update_dtb: Update the offset and size of each entry in the device
338 tree before packing it into the image
342 Resulting image contents
344 Map data showing contents of image (or None if none)
345 Output device tree binary filename ('u-boot.dtb' path)
348 # Use the compiled test file as the u-boot-dtb input
350 dtb_data = self._SetupDtb(fname)
352 # For testing purposes, make a copy of the DT for SPL and TPL. Add
353 # a node indicating which it is, so aid verification.
354 for name in ['spl', 'tpl']:
355 dtb_fname = '%s/u-boot-%s.dtb' % (name, name)
356 outfile = os.path.join(self._indir, dtb_fname)
357 TestFunctional._MakeInputFile(dtb_fname,
358 self._GetDtbContentsForSplTpl(dtb_data, name))
361 retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
362 entry_args=entry_args, use_real_dtb=use_real_dtb)
363 self.assertEqual(0, retcode)
364 out_dtb_fname = tools.GetOutputFilename('u-boot.dtb.out')
366 # Find the (only) image, read it and return its contents
367 image = control.images['image']
368 image_fname = tools.GetOutputFilename('image.bin')
369 self.assertTrue(os.path.exists(image_fname))
371 map_fname = tools.GetOutputFilename('image.map')
372 with open(map_fname) as fd:
376 with open(image_fname, 'rb') as fd:
377 return fd.read(), dtb_data, map_data, out_dtb_fname
379 # Put the test file back
380 if reset_dtbs and use_real_dtb:
383 def _DoReadFileRealDtb(self, fname):
384 """Run binman with a real .dtb file and return the resulting data
387 fname: DT source filename to use (e.g. 082_fdt_update_all.dts)
390 Resulting image contents
392 return self._DoReadFileDtb(fname, use_real_dtb=True, update_dtb=True)[0]
394 def _DoReadFile(self, fname, use_real_dtb=False):
395 """Helper function which discards the device-tree binary
398 fname: Device-tree source filename to use (e.g. 005_simple.dts)
399 use_real_dtb: True to use the test file as the contents of
400 the u-boot-dtb entry. Normally this is not needed and the
401 test contents (the U_BOOT_DTB_DATA string) can be used.
402 But in some test we need the real contents.
405 Resulting image contents
407 return self._DoReadFileDtb(fname, use_real_dtb)[0]
410 def _MakeInputFile(self, fname, contents):
411 """Create a new test input file, creating directories as needed
414 fname: Filename to create
415 contents: File contents to write in to the file
417 Full pathname of file created
419 pathname = os.path.join(self._indir, fname)
420 dirname = os.path.dirname(pathname)
421 if dirname and not os.path.exists(dirname):
423 with open(pathname, 'wb') as fd:
428 def _MakeInputDir(self, dirname):
429 """Create a new test input directory, creating directories as needed
432 dirname: Directory name to create
435 Full pathname of directory created
437 pathname = os.path.join(self._indir, dirname)
438 if not os.path.exists(pathname):
439 os.makedirs(pathname)
443 def _SetupSplElf(self, src_fname='bss_data'):
444 """Set up an ELF file with a '_dt_ucode_base_size' symbol
447 Filename of ELF file to use as SPL
449 with open(self.TestFile(src_fname), 'rb') as fd:
450 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
453 def TestFile(self, fname):
454 return os.path.join(self._binman_dir, 'test', fname)
456 def AssertInList(self, grep_list, target):
457 """Assert that at least one of a list of things is in a target
460 grep_list: List of strings to check
461 target: Target string
463 for grep in grep_list:
466 self.fail("Error: '%s' not found in '%s'" % (grep_list, target))
468 def CheckNoGaps(self, entries):
469 """Check that all entries fit together without gaps
472 entries: List of entries to check
475 for entry in entries.values():
476 self.assertEqual(offset, entry.offset)
479 def GetFdtLen(self, dtb):
480 """Get the totalsize field from a device-tree binary
483 dtb: Device-tree binary contents
486 Total size of device-tree binary, from the header
488 return struct.unpack('>L', dtb[4:8])[0]
490 def _GetPropTree(self, dtb, prop_names, prefix='/binman/'):
491 def AddNode(node, path):
493 path += '/' + node.name
494 for prop in node.props.values():
495 if prop.name in prop_names:
496 prop_path = path + ':' + prop.name
497 tree[prop_path[len(prefix):]] = fdt_util.fdt32_to_cpu(
499 for subnode in node.subnodes:
500 AddNode(subnode, path)
503 AddNode(dtb.GetRoot(), '')
507 """Test a basic run with valid args"""
508 result = self._RunBinman('-h')
510 def testFullHelp(self):
511 """Test that the full help is displayed with -H"""
512 result = self._RunBinman('-H')
513 help_file = os.path.join(self._binman_dir, 'README')
514 # Remove possible extraneous strings
515 extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
516 gothelp = result.stdout.replace(extra, '')
517 self.assertEqual(len(gothelp), os.path.getsize(help_file))
518 self.assertEqual(0, len(result.stderr))
519 self.assertEqual(0, result.return_code)
521 def testFullHelpInternal(self):
522 """Test that the full help is displayed with -H"""
524 command.test_result = command.CommandResult()
525 result = self._DoBinman('-H')
526 help_file = os.path.join(self._binman_dir, 'README')
528 command.test_result = None
531 """Test that the basic help is displayed with -h"""
532 result = self._RunBinman('-h')
533 self.assertTrue(len(result.stdout) > 200)
534 self.assertEqual(0, len(result.stderr))
535 self.assertEqual(0, result.return_code)
538 """Test that we can run it with a specific board"""
539 self._SetupDtb('005_simple.dts', 'sandbox/u-boot.dtb')
540 TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
541 result = self._DoBinman('-b', 'sandbox')
542 self.assertEqual(0, result)
544 def testNeedBoard(self):
545 """Test that we get an error when no board ius supplied"""
546 with self.assertRaises(ValueError) as e:
547 result = self._DoBinman()
548 self.assertIn("Must provide a board to process (use -b <board>)",
551 def testMissingDt(self):
552 """Test that an invalid device-tree file generates an error"""
553 with self.assertRaises(Exception) as e:
554 self._RunBinman('-d', 'missing_file')
555 # We get one error from libfdt, and a different one from fdtget.
556 self.AssertInList(["Couldn't open blob from 'missing_file'",
557 'No such file or directory'], str(e.exception))
559 def testBrokenDt(self):
560 """Test that an invalid device-tree source file generates an error
562 Since this is a source file it should be compiled and the error
563 will come from the device-tree compiler (dtc).
565 with self.assertRaises(Exception) as e:
566 self._RunBinman('-d', self.TestFile('001_invalid.dts'))
567 self.assertIn("FATAL ERROR: Unable to parse input tree",
570 def testMissingNode(self):
571 """Test that a device tree without a 'binman' node generates an error"""
572 with self.assertRaises(Exception) as e:
573 self._DoBinman('-d', self.TestFile('002_missing_node.dts'))
574 self.assertIn("does not have a 'binman' node", str(e.exception))
577 """Test that an empty binman node works OK (i.e. does nothing)"""
578 result = self._RunBinman('-d', self.TestFile('003_empty.dts'))
579 self.assertEqual(0, len(result.stderr))
580 self.assertEqual(0, result.return_code)
582 def testInvalidEntry(self):
583 """Test that an invalid entry is flagged"""
584 with self.assertRaises(Exception) as e:
585 result = self._RunBinman('-d',
586 self.TestFile('004_invalid_entry.dts'))
587 self.assertIn("Unknown entry type 'not-a-valid-type' in node "
588 "'/binman/not-a-valid-type'", str(e.exception))
590 def testSimple(self):
591 """Test a simple binman with a single file"""
592 data = self._DoReadFile('005_simple.dts')
593 self.assertEqual(U_BOOT_DATA, data)
595 def testSimpleDebug(self):
596 """Test a simple binman run with debugging enabled"""
597 data = self._DoTestFile('005_simple.dts', debug=True)
600 """Test that we can handle creating two images
602 This also tests image padding.
604 retcode = self._DoTestFile('006_dual_image.dts')
605 self.assertEqual(0, retcode)
607 image = control.images['image1']
608 self.assertEqual(len(U_BOOT_DATA), image._size)
609 fname = tools.GetOutputFilename('image1.bin')
610 self.assertTrue(os.path.exists(fname))
611 with open(fname, 'rb') as fd:
613 self.assertEqual(U_BOOT_DATA, data)
615 image = control.images['image2']
616 self.assertEqual(3 + len(U_BOOT_DATA) + 5, image._size)
617 fname = tools.GetOutputFilename('image2.bin')
618 self.assertTrue(os.path.exists(fname))
619 with open(fname, 'rb') as fd:
621 self.assertEqual(U_BOOT_DATA, data[3:7])
622 self.assertEqual(tools.GetBytes(0, 3), data[:3])
623 self.assertEqual(tools.GetBytes(0, 5), data[7:])
625 def testBadAlign(self):
626 """Test that an invalid alignment value is detected"""
627 with self.assertRaises(ValueError) as e:
628 self._DoTestFile('007_bad_align.dts')
629 self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
630 "of two", str(e.exception))
632 def testPackSimple(self):
633 """Test that packing works as expected"""
634 retcode = self._DoTestFile('008_pack.dts')
635 self.assertEqual(0, retcode)
636 self.assertIn('image', control.images)
637 image = control.images['image']
638 entries = image.GetEntries()
639 self.assertEqual(5, len(entries))
642 self.assertIn('u-boot', entries)
643 entry = entries['u-boot']
644 self.assertEqual(0, entry.offset)
645 self.assertEqual(len(U_BOOT_DATA), entry.size)
647 # Second u-boot, aligned to 16-byte boundary
648 self.assertIn('u-boot-align', entries)
649 entry = entries['u-boot-align']
650 self.assertEqual(16, entry.offset)
651 self.assertEqual(len(U_BOOT_DATA), entry.size)
653 # Third u-boot, size 23 bytes
654 self.assertIn('u-boot-size', entries)
655 entry = entries['u-boot-size']
656 self.assertEqual(20, entry.offset)
657 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
658 self.assertEqual(23, entry.size)
660 # Fourth u-boot, placed immediate after the above
661 self.assertIn('u-boot-next', entries)
662 entry = entries['u-boot-next']
663 self.assertEqual(43, entry.offset)
664 self.assertEqual(len(U_BOOT_DATA), entry.size)
666 # Fifth u-boot, placed at a fixed offset
667 self.assertIn('u-boot-fixed', entries)
668 entry = entries['u-boot-fixed']
669 self.assertEqual(61, entry.offset)
670 self.assertEqual(len(U_BOOT_DATA), entry.size)
672 self.assertEqual(65, image._size)
674 def testPackExtra(self):
675 """Test that extra packing feature works as expected"""
676 retcode = self._DoTestFile('009_pack_extra.dts')
678 self.assertEqual(0, retcode)
679 self.assertIn('image', control.images)
680 image = control.images['image']
681 entries = image.GetEntries()
682 self.assertEqual(5, len(entries))
684 # First u-boot with padding before and after
685 self.assertIn('u-boot', entries)
686 entry = entries['u-boot']
687 self.assertEqual(0, entry.offset)
688 self.assertEqual(3, entry.pad_before)
689 self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
691 # Second u-boot has an aligned size, but it has no effect
692 self.assertIn('u-boot-align-size-nop', entries)
693 entry = entries['u-boot-align-size-nop']
694 self.assertEqual(12, entry.offset)
695 self.assertEqual(4, entry.size)
697 # Third u-boot has an aligned size too
698 self.assertIn('u-boot-align-size', entries)
699 entry = entries['u-boot-align-size']
700 self.assertEqual(16, entry.offset)
701 self.assertEqual(32, entry.size)
703 # Fourth u-boot has an aligned end
704 self.assertIn('u-boot-align-end', entries)
705 entry = entries['u-boot-align-end']
706 self.assertEqual(48, entry.offset)
707 self.assertEqual(16, entry.size)
709 # Fifth u-boot immediately afterwards
710 self.assertIn('u-boot-align-both', entries)
711 entry = entries['u-boot-align-both']
712 self.assertEqual(64, entry.offset)
713 self.assertEqual(64, entry.size)
715 self.CheckNoGaps(entries)
716 self.assertEqual(128, image._size)
718 def testPackAlignPowerOf2(self):
719 """Test that invalid entry alignment is detected"""
720 with self.assertRaises(ValueError) as e:
721 self._DoTestFile('010_pack_align_power2.dts')
722 self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
723 "of two", str(e.exception))
725 def testPackAlignSizePowerOf2(self):
726 """Test that invalid entry size alignment is detected"""
727 with self.assertRaises(ValueError) as e:
728 self._DoTestFile('011_pack_align_size_power2.dts')
729 self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
730 "power of two", str(e.exception))
732 def testPackInvalidAlign(self):
733 """Test detection of an offset that does not match its alignment"""
734 with self.assertRaises(ValueError) as e:
735 self._DoTestFile('012_pack_inv_align.dts')
736 self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
737 "align 0x4 (4)", str(e.exception))
739 def testPackInvalidSizeAlign(self):
740 """Test that invalid entry size alignment is detected"""
741 with self.assertRaises(ValueError) as e:
742 self._DoTestFile('013_pack_inv_size_align.dts')
743 self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
744 "align-size 0x4 (4)", str(e.exception))
746 def testPackOverlap(self):
747 """Test that overlapping regions are detected"""
748 with self.assertRaises(ValueError) as e:
749 self._DoTestFile('014_pack_overlap.dts')
750 self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
751 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
754 def testPackEntryOverflow(self):
755 """Test that entries that overflow their size are detected"""
756 with self.assertRaises(ValueError) as e:
757 self._DoTestFile('015_pack_overflow.dts')
758 self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
759 "but entry size is 0x3 (3)", str(e.exception))
761 def testPackImageOverflow(self):
762 """Test that entries which overflow the image size are detected"""
763 with self.assertRaises(ValueError) as e:
764 self._DoTestFile('016_pack_image_overflow.dts')
765 self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section "
766 "size 0x3 (3)", str(e.exception))
768 def testPackImageSize(self):
769 """Test that the image size can be set"""
770 retcode = self._DoTestFile('017_pack_image_size.dts')
771 self.assertEqual(0, retcode)
772 self.assertIn('image', control.images)
773 image = control.images['image']
774 self.assertEqual(7, image._size)
776 def testPackImageSizeAlign(self):
777 """Test that image size alignemnt works as expected"""
778 retcode = self._DoTestFile('018_pack_image_align.dts')
779 self.assertEqual(0, retcode)
780 self.assertIn('image', control.images)
781 image = control.images['image']
782 self.assertEqual(16, image._size)
784 def testPackInvalidImageAlign(self):
785 """Test that invalid image alignment is detected"""
786 with self.assertRaises(ValueError) as e:
787 self._DoTestFile('019_pack_inv_image_align.dts')
788 self.assertIn("Section '/binman': Size 0x7 (7) does not match "
789 "align-size 0x8 (8)", str(e.exception))
791 def testPackAlignPowerOf2(self):
792 """Test that invalid image alignment is detected"""
793 with self.assertRaises(ValueError) as e:
794 self._DoTestFile('020_pack_inv_image_align_power2.dts')
795 self.assertIn("Section '/binman': Alignment size 131 must be a power of "
796 "two", str(e.exception))
798 def testImagePadByte(self):
799 """Test that the image pad byte can be specified"""
801 data = self._DoReadFile('021_image_pad.dts')
802 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0xff, 1) +
805 def testImageName(self):
806 """Test that image files can be named"""
807 retcode = self._DoTestFile('022_image_name.dts')
808 self.assertEqual(0, retcode)
809 image = control.images['image1']
810 fname = tools.GetOutputFilename('test-name')
811 self.assertTrue(os.path.exists(fname))
813 image = control.images['image2']
814 fname = tools.GetOutputFilename('test-name.xx')
815 self.assertTrue(os.path.exists(fname))
817 def testBlobFilename(self):
818 """Test that generic blobs can be provided by filename"""
819 data = self._DoReadFile('023_blob.dts')
820 self.assertEqual(BLOB_DATA, data)
822 def testPackSorted(self):
823 """Test that entries can be sorted"""
825 data = self._DoReadFile('024_sorted.dts')
826 self.assertEqual(tools.GetBytes(0, 1) + U_BOOT_SPL_DATA +
827 tools.GetBytes(0, 2) + U_BOOT_DATA, data)
829 def testPackZeroOffset(self):
830 """Test that an entry at offset 0 is not given a new offset"""
831 with self.assertRaises(ValueError) as e:
832 self._DoTestFile('025_pack_zero_size.dts')
833 self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
834 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
837 def testPackUbootDtb(self):
838 """Test that a device tree can be added to U-Boot"""
839 data = self._DoReadFile('026_pack_u_boot_dtb.dts')
840 self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
842 def testPackX86RomNoSize(self):
843 """Test that the end-at-4gb property requires a size property"""
844 with self.assertRaises(ValueError) as e:
845 self._DoTestFile('027_pack_4gb_no_size.dts')
846 self.assertIn("Section '/binman': Section size must be provided when "
847 "using end-at-4gb", str(e.exception))
849 def test4gbAndSkipAtStartTogether(self):
850 """Test that the end-at-4gb and skip-at-size property can't be used
852 with self.assertRaises(ValueError) as e:
853 self._DoTestFile('80_4gb_and_skip_at_start_together.dts')
854 self.assertIn("Section '/binman': Provide either 'end-at-4gb' or "
855 "'skip-at-start'", str(e.exception))
857 def testPackX86RomOutside(self):
858 """Test that the end-at-4gb property checks for offset boundaries"""
859 with self.assertRaises(ValueError) as e:
860 self._DoTestFile('028_pack_4gb_outside.dts')
861 self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
862 "the section starting at 0xffffffe0 (4294967264)",
865 def testPackX86Rom(self):
866 """Test that a basic x86 ROM can be created"""
868 data = self._DoReadFile('029_x86-rom.dts')
869 self.assertEqual(U_BOOT_DATA + tools.GetBytes(0, 7) + U_BOOT_SPL_DATA +
870 tools.GetBytes(0, 2), data)
872 def testPackX86RomMeNoDesc(self):
873 """Test that an invalid Intel descriptor entry is detected"""
874 TestFunctional._MakeInputFile('descriptor.bin', b'')
875 with self.assertRaises(ValueError) as e:
876 self._DoTestFile('031_x86-rom-me.dts')
877 self.assertIn("Node '/binman/intel-descriptor': Cannot find Intel Flash Descriptor (FD) signature",
880 def testPackX86RomBadDesc(self):
881 """Test that the Intel requires a descriptor entry"""
882 with self.assertRaises(ValueError) as e:
883 self._DoTestFile('030_x86-rom-me-no-desc.dts')
884 self.assertIn("Node '/binman/intel-me': No offset set with "
885 "offset-unset: should another entry provide this correct "
886 "offset?", str(e.exception))
888 def testPackX86RomMe(self):
889 """Test that an x86 ROM with an ME region can be created"""
890 data = self._DoReadFile('031_x86-rom-me.dts')
891 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
892 if data[:0x1000] != expected_desc:
893 self.fail('Expected descriptor binary at start of image')
894 self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
896 def testPackVga(self):
897 """Test that an image with a VGA binary can be created"""
898 data = self._DoReadFile('032_intel-vga.dts')
899 self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
901 def testPackStart16(self):
902 """Test that an image with an x86 start16 region can be created"""
903 data = self._DoReadFile('033_x86-start16.dts')
904 self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
906 def testPackPowerpcMpc85xxBootpgResetvec(self):
907 """Test that an image with powerpc-mpc85xx-bootpg-resetvec can be
909 data = self._DoReadFile('81_powerpc_mpc85xx_bootpg_resetvec.dts')
910 self.assertEqual(PPC_MPC85XX_BR_DATA, data[:len(PPC_MPC85XX_BR_DATA)])
912 def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False):
913 """Handle running a test for insertion of microcode
916 dts_fname: Name of test .dts file
917 nodtb_data: Data that we expect in the first section
918 ucode_second: True if the microsecond entry is second instead of
923 Contents of first region (U-Boot or SPL)
924 Offset and size components of microcode pointer, as inserted
925 in the above (two 4-byte words)
927 data = self._DoReadFile(dts_fname, True)
929 # Now check the device tree has no microcode
931 ucode_content = data[len(nodtb_data):]
932 ucode_pos = len(nodtb_data)
933 dtb_with_ucode = ucode_content[16:]
934 fdt_len = self.GetFdtLen(dtb_with_ucode)
936 dtb_with_ucode = data[len(nodtb_data):]
937 fdt_len = self.GetFdtLen(dtb_with_ucode)
938 ucode_content = dtb_with_ucode[fdt_len:]
939 ucode_pos = len(nodtb_data) + fdt_len
940 fname = tools.GetOutputFilename('test.dtb')
941 with open(fname, 'wb') as fd:
942 fd.write(dtb_with_ucode)
943 dtb = fdt.FdtScan(fname)
944 ucode = dtb.GetNode('/microcode')
945 self.assertTrue(ucode)
946 for node in ucode.subnodes:
947 self.assertFalse(node.props.get('data'))
949 # Check that the microcode appears immediately after the Fdt
950 # This matches the concatenation of the data properties in
951 # the /microcode/update@xxx nodes in 34_x86_ucode.dts.
952 ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
954 self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
956 # Check that the microcode pointer was inserted. It should match the
957 # expected offset and size
958 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
960 u_boot = data[:len(nodtb_data)]
961 return u_boot, pos_and_size
963 def testPackUbootMicrocode(self):
964 """Test that x86 microcode can be handled correctly
966 We expect to see the following in the image, in order:
967 u-boot-nodtb.bin with a microcode pointer inserted at the correct
969 u-boot.dtb with the microcode removed
972 first, pos_and_size = self._RunMicrocodeTest('034_x86_ucode.dts',
974 self.assertEqual(b'nodtb with microcode' + pos_and_size +
975 b' somewhere in here', first)
977 def _RunPackUbootSingleMicrocode(self):
978 """Test that x86 microcode can be handled correctly
980 We expect to see the following in the image, in order:
981 u-boot-nodtb.bin with a microcode pointer inserted at the correct
983 u-boot.dtb with the microcode
984 an empty microcode region
986 # We need the libfdt library to run this test since only that allows
987 # finding the offset of a property. This is required by
988 # Entry_u_boot_dtb_with_ucode.ObtainContents().
989 data = self._DoReadFile('035_x86_single_ucode.dts', True)
991 second = data[len(U_BOOT_NODTB_DATA):]
993 fdt_len = self.GetFdtLen(second)
994 third = second[fdt_len:]
995 second = second[:fdt_len]
997 ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
998 self.assertIn(ucode_data, second)
999 ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
1001 # Check that the microcode pointer was inserted. It should match the
1002 # expected offset and size
1003 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
1005 first = data[:len(U_BOOT_NODTB_DATA)]
1006 self.assertEqual(b'nodtb with microcode' + pos_and_size +
1007 b' somewhere in here', first)
1009 def testPackUbootSingleMicrocode(self):
1010 """Test that x86 microcode can be handled correctly with fdt_normal.
1012 self._RunPackUbootSingleMicrocode()
1014 def testUBootImg(self):
1015 """Test that u-boot.img can be put in a file"""
1016 data = self._DoReadFile('036_u_boot_img.dts')
1017 self.assertEqual(U_BOOT_IMG_DATA, data)
1019 def testNoMicrocode(self):
1020 """Test that a missing microcode region is detected"""
1021 with self.assertRaises(ValueError) as e:
1022 self._DoReadFile('037_x86_no_ucode.dts', True)
1023 self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
1024 "node found in ", str(e.exception))
1026 def testMicrocodeWithoutNode(self):
1027 """Test that a missing u-boot-dtb-with-ucode node is detected"""
1028 with self.assertRaises(ValueError) as e:
1029 self._DoReadFile('038_x86_ucode_missing_node.dts', True)
1030 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1031 "microcode region u-boot-dtb-with-ucode", str(e.exception))
1033 def testMicrocodeWithoutNode2(self):
1034 """Test that a missing u-boot-ucode node is detected"""
1035 with self.assertRaises(ValueError) as e:
1036 self._DoReadFile('039_x86_ucode_missing_node2.dts', True)
1037 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1038 "microcode region u-boot-ucode", str(e.exception))
1040 def testMicrocodeWithoutPtrInElf(self):
1041 """Test that a U-Boot binary without the microcode symbol is detected"""
1042 # ELF file without a '_dt_ucode_base_size' symbol
1044 with open(self.TestFile('u_boot_no_ucode_ptr'), 'rb') as fd:
1045 TestFunctional._MakeInputFile('u-boot', fd.read())
1047 with self.assertRaises(ValueError) as e:
1048 self._RunPackUbootSingleMicrocode()
1049 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
1050 "_dt_ucode_base_size symbol in u-boot", str(e.exception))
1053 # Put the original file back
1054 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
1055 TestFunctional._MakeInputFile('u-boot', fd.read())
1057 def testMicrocodeNotInImage(self):
1058 """Test that microcode must be placed within the image"""
1059 with self.assertRaises(ValueError) as e:
1060 self._DoReadFile('040_x86_ucode_not_in_image.dts', True)
1061 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
1062 "pointer _dt_ucode_base_size at fffffe14 is outside the "
1063 "section ranging from 00000000 to 0000002e", str(e.exception))
1065 def testWithoutMicrocode(self):
1066 """Test that we can cope with an image without microcode (e.g. qemu)"""
1067 with open(self.TestFile('u_boot_no_ucode_ptr'), 'rb') as fd:
1068 TestFunctional._MakeInputFile('u-boot', fd.read())
1069 data, dtb, _, _ = self._DoReadFileDtb('044_x86_optional_ucode.dts', True)
1071 # Now check the device tree has no microcode
1072 self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
1073 second = data[len(U_BOOT_NODTB_DATA):]
1075 fdt_len = self.GetFdtLen(second)
1076 self.assertEqual(dtb, second[:fdt_len])
1078 used_len = len(U_BOOT_NODTB_DATA) + fdt_len
1079 third = data[used_len:]
1080 self.assertEqual(tools.GetBytes(0, 0x200 - used_len), third)
1082 def testUnknownPosSize(self):
1083 """Test that microcode must be placed within the image"""
1084 with self.assertRaises(ValueError) as e:
1085 self._DoReadFile('041_unknown_pos_size.dts', True)
1086 self.assertIn("Section '/binman': Unable to set offset/size for unknown "
1087 "entry 'invalid-entry'", str(e.exception))
1089 def testPackFsp(self):
1090 """Test that an image with a FSP binary can be created"""
1091 data = self._DoReadFile('042_intel-fsp.dts')
1092 self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
1094 def testPackCmc(self):
1095 """Test that an image with a CMC binary can be created"""
1096 data = self._DoReadFile('043_intel-cmc.dts')
1097 self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
1099 def testPackVbt(self):
1100 """Test that an image with a VBT binary can be created"""
1101 data = self._DoReadFile('046_intel-vbt.dts')
1102 self.assertEqual(VBT_DATA, data[:len(VBT_DATA)])
1104 def testSplBssPad(self):
1105 """Test that we can pad SPL's BSS with zeros"""
1106 # ELF file with a '__bss_size' symbol
1108 data = self._DoReadFile('047_spl_bss_pad.dts')
1109 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0, 10) + U_BOOT_DATA,
1112 def testSplBssPadMissing(self):
1113 """Test that a missing symbol is detected"""
1114 self._SetupSplElf('u_boot_ucode_ptr')
1115 with self.assertRaises(ValueError) as e:
1116 self._DoReadFile('047_spl_bss_pad.dts')
1117 self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
1120 def testPackStart16Spl(self):
1121 """Test that an image with an x86 start16 SPL region can be created"""
1122 data = self._DoReadFile('048_x86-start16-spl.dts')
1123 self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)])
1125 def _PackUbootSplMicrocode(self, dts, ucode_second=False):
1126 """Helper function for microcode tests
1128 We expect to see the following in the image, in order:
1129 u-boot-spl-nodtb.bin with a microcode pointer inserted at the
1131 u-boot.dtb with the microcode removed
1135 dts: Device tree file to use for test
1136 ucode_second: True if the microsecond entry is second instead of
1139 self._SetupSplElf('u_boot_ucode_ptr')
1140 first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA,
1141 ucode_second=ucode_second)
1142 self.assertEqual(b'splnodtb with microc' + pos_and_size +
1143 b'ter somewhere in here', first)
1145 def testPackUbootSplMicrocode(self):
1146 """Test that x86 microcode can be handled correctly in SPL"""
1147 self._PackUbootSplMicrocode('049_x86_ucode_spl.dts')
1149 def testPackUbootSplMicrocodeReorder(self):
1150 """Test that order doesn't matter for microcode entries
1152 This is the same as testPackUbootSplMicrocode but when we process the
1153 u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode
1154 entry, so we reply on binman to try later.
1156 self._PackUbootSplMicrocode('058_x86_ucode_spl_needs_retry.dts',
1159 def testPackMrc(self):
1160 """Test that an image with an MRC binary can be created"""
1161 data = self._DoReadFile('050_intel_mrc.dts')
1162 self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
1164 def testSplDtb(self):
1165 """Test that an image with spl/u-boot-spl.dtb can be created"""
1166 data = self._DoReadFile('051_u_boot_spl_dtb.dts')
1167 self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
1169 def testSplNoDtb(self):
1170 """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
1171 data = self._DoReadFile('052_u_boot_spl_nodtb.dts')
1172 self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
1174 def testSymbols(self):
1175 """Test binman can assign symbols embedded in U-Boot"""
1176 elf_fname = self.TestFile('u_boot_binman_syms')
1177 syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
1178 addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
1179 self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
1181 self._SetupSplElf('u_boot_binman_syms')
1182 data = self._DoReadFile('053_symbols.dts')
1183 sym_values = struct.pack('<LQL', 0x24 + 0, 0x24 + 24, 0x24 + 20)
1184 expected = (sym_values + U_BOOT_SPL_DATA[16:] +
1185 tools.GetBytes(0xff, 1) + U_BOOT_DATA + sym_values +
1186 U_BOOT_SPL_DATA[16:])
1187 self.assertEqual(expected, data)
1189 def testPackUnitAddress(self):
1190 """Test that we support multiple binaries with the same name"""
1191 data = self._DoReadFile('054_unit_address.dts')
1192 self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
1194 def testSections(self):
1195 """Basic test of sections"""
1196 data = self._DoReadFile('055_sections.dts')
1197 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1198 U_BOOT_DATA + tools.GetBytes(ord('a'), 12) +
1199 U_BOOT_DATA + tools.GetBytes(ord('&'), 4))
1200 self.assertEqual(expected, data)
1203 """Tests outputting a map of the images"""
1204 _, _, map_data, _ = self._DoReadFileDtb('055_sections.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 u-boot
1209 00000010 00000010 00000010 section@1
1210 00000010 00000000 00000004 u-boot
1211 00000020 00000020 00000004 section@2
1212 00000020 00000000 00000004 u-boot
1215 def testNamePrefix(self):
1216 """Tests that name prefixes are used"""
1217 _, _, map_data, _ = self._DoReadFileDtb('056_name_prefix.dts', map=True)
1218 self.assertEqual('''ImagePos Offset Size Name
1219 00000000 00000000 00000028 main-section
1220 00000000 00000000 00000010 section@0
1221 00000000 00000000 00000004 ro-u-boot
1222 00000010 00000010 00000010 section@1
1223 00000010 00000000 00000004 rw-u-boot
1226 def testUnknownContents(self):
1227 """Test that obtaining the contents works as expected"""
1228 with self.assertRaises(ValueError) as e:
1229 self._DoReadFile('057_unknown_contents.dts', True)
1230 self.assertIn("Section '/binman': Internal error: Could not complete "
1231 "processing of contents: remaining [<_testing.Entry__testing ",
1234 def testBadChangeSize(self):
1235 """Test that trying to change the size of an entry fails"""
1236 with self.assertRaises(ValueError) as e:
1237 self._DoReadFile('059_change_size.dts', True)
1238 self.assertIn("Node '/binman/_testing': Cannot update entry size from "
1239 '2 to 1', str(e.exception))
1241 def testUpdateFdt(self):
1242 """Test that we can update the device tree with offset/size info"""
1243 _, _, _, out_dtb_fname = self._DoReadFileDtb('060_fdt_update.dts',
1245 dtb = fdt.Fdt(out_dtb_fname)
1247 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'])
1251 '_testing:offset': 32,
1253 '_testing:image-pos': 32,
1254 'section@0/u-boot:offset': 0,
1255 'section@0/u-boot:size': len(U_BOOT_DATA),
1256 'section@0/u-boot:image-pos': 0,
1257 'section@0:offset': 0,
1258 'section@0:size': 16,
1259 'section@0:image-pos': 0,
1261 'section@1/u-boot:offset': 0,
1262 'section@1/u-boot:size': len(U_BOOT_DATA),
1263 'section@1/u-boot:image-pos': 16,
1264 'section@1:offset': 16,
1265 'section@1:size': 16,
1266 'section@1:image-pos': 16,
1270 def testUpdateFdtBad(self):
1271 """Test that we detect when ProcessFdt never completes"""
1272 with self.assertRaises(ValueError) as e:
1273 self._DoReadFileDtb('061_fdt_update_bad.dts', update_dtb=True)
1274 self.assertIn('Could not complete processing of Fdt: remaining '
1275 '[<_testing.Entry__testing', str(e.exception))
1277 def testEntryArgs(self):
1278 """Test passing arguments to entries from the command line"""
1280 'test-str-arg': 'test1',
1281 'test-int-arg': '456',
1283 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
1284 self.assertIn('image', control.images)
1285 entry = control.images['image'].GetEntries()['_testing']
1286 self.assertEqual('test0', entry.test_str_fdt)
1287 self.assertEqual('test1', entry.test_str_arg)
1288 self.assertEqual(123, entry.test_int_fdt)
1289 self.assertEqual(456, entry.test_int_arg)
1291 def testEntryArgsMissing(self):
1292 """Test missing arguments and properties"""
1294 'test-int-arg': '456',
1296 self._DoReadFileDtb('063_entry_args_missing.dts', entry_args=entry_args)
1297 entry = control.images['image'].GetEntries()['_testing']
1298 self.assertEqual('test0', entry.test_str_fdt)
1299 self.assertEqual(None, entry.test_str_arg)
1300 self.assertEqual(None, entry.test_int_fdt)
1301 self.assertEqual(456, entry.test_int_arg)
1303 def testEntryArgsRequired(self):
1304 """Test missing arguments and properties"""
1306 'test-int-arg': '456',
1308 with self.assertRaises(ValueError) as e:
1309 self._DoReadFileDtb('064_entry_args_required.dts')
1310 self.assertIn("Node '/binman/_testing': Missing required "
1311 'properties/entry args: test-str-arg, test-int-fdt, test-int-arg',
1314 def testEntryArgsInvalidFormat(self):
1315 """Test that an invalid entry-argument format is detected"""
1316 args = ['-d', self.TestFile('064_entry_args_required.dts'), '-ano-value']
1317 with self.assertRaises(ValueError) as e:
1318 self._DoBinman(*args)
1319 self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
1321 def testEntryArgsInvalidInteger(self):
1322 """Test that an invalid entry-argument integer is detected"""
1324 'test-int-arg': 'abc',
1326 with self.assertRaises(ValueError) as e:
1327 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
1328 self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
1329 "'test-int-arg' (value 'abc') to integer",
1332 def testEntryArgsInvalidDatatype(self):
1333 """Test that an invalid entry-argument datatype is detected
1335 This test could be written in entry_test.py except that it needs
1336 access to control.entry_args, which seems more than that module should
1340 'test-bad-datatype-arg': '12',
1342 with self.assertRaises(ValueError) as e:
1343 self._DoReadFileDtb('065_entry_args_unknown_datatype.dts',
1344 entry_args=entry_args)
1345 self.assertIn('GetArg() internal error: Unknown data type ',
1349 """Test for a text entry type"""
1351 'test-id': TEXT_DATA,
1352 'test-id2': TEXT_DATA2,
1353 'test-id3': TEXT_DATA3,
1355 data, _, _, _ = self._DoReadFileDtb('066_text.dts',
1356 entry_args=entry_args)
1357 expected = (tools.ToBytes(TEXT_DATA) +
1358 tools.GetBytes(0, 8 - len(TEXT_DATA)) +
1359 tools.ToBytes(TEXT_DATA2) + tools.ToBytes(TEXT_DATA3) +
1360 b'some text' + b'more text')
1361 self.assertEqual(expected, data)
1363 def testEntryDocs(self):
1364 """Test for creation of entry documentation"""
1365 with test_util.capture_sys_output() as (stdout, stderr):
1366 control.WriteEntryDocs(binman.GetEntryModules())
1367 self.assertTrue(len(stdout.getvalue()) > 0)
1369 def testEntryDocsMissing(self):
1370 """Test handling of missing entry documentation"""
1371 with self.assertRaises(ValueError) as e:
1372 with test_util.capture_sys_output() as (stdout, stderr):
1373 control.WriteEntryDocs(binman.GetEntryModules(), 'u_boot')
1374 self.assertIn('Documentation is missing for modules: u_boot',
1378 """Basic test of generation of a flashrom fmap"""
1379 data = self._DoReadFile('067_fmap.dts')
1380 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1381 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1382 U_BOOT_DATA + tools.GetBytes(ord('a'), 12))
1383 self.assertEqual(expected, data[:32])
1384 self.assertEqual(b'__FMAP__', fhdr.signature)
1385 self.assertEqual(1, fhdr.ver_major)
1386 self.assertEqual(0, fhdr.ver_minor)
1387 self.assertEqual(0, fhdr.base)
1388 self.assertEqual(16 + 16 +
1389 fmap_util.FMAP_HEADER_LEN +
1390 fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
1391 self.assertEqual(b'FMAP', fhdr.name)
1392 self.assertEqual(3, fhdr.nareas)
1393 for fentry in fentries:
1394 self.assertEqual(0, fentry.flags)
1396 self.assertEqual(0, fentries[0].offset)
1397 self.assertEqual(4, fentries[0].size)
1398 self.assertEqual(b'RO_U_BOOT', fentries[0].name)
1400 self.assertEqual(16, fentries[1].offset)
1401 self.assertEqual(4, fentries[1].size)
1402 self.assertEqual(b'RW_U_BOOT', fentries[1].name)
1404 self.assertEqual(32, fentries[2].offset)
1405 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1406 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1407 self.assertEqual(b'FMAP', fentries[2].name)
1409 def testBlobNamedByArg(self):
1410 """Test we can add a blob with the filename coming from an entry arg"""
1412 'cros-ec-rw-path': 'ecrw.bin',
1414 data, _, _, _ = self._DoReadFileDtb('068_blob_named_by_arg.dts',
1415 entry_args=entry_args)
1418 """Test for an fill entry type"""
1419 data = self._DoReadFile('069_fill.dts')
1420 expected = tools.GetBytes(0xff, 8) + tools.GetBytes(0, 8)
1421 self.assertEqual(expected, data)
1423 def testFillNoSize(self):
1424 """Test for an fill entry type with no size"""
1425 with self.assertRaises(ValueError) as e:
1426 self._DoReadFile('070_fill_no_size.dts')
1427 self.assertIn("'fill' entry must have a size property",
1430 def _HandleGbbCommand(self, pipe_list):
1431 """Fake calls to the futility utility"""
1432 if pipe_list[0][0] == 'futility':
1433 fname = pipe_list[0][-1]
1434 # Append our GBB data to the file, which will happen every time the
1435 # futility command is called.
1436 with open(fname, 'ab') as fd:
1438 return command.CommandResult()
1441 """Test for the Chromium OS Google Binary Block"""
1442 command.test_result = self._HandleGbbCommand
1444 'keydir': 'devkeys',
1445 'bmpblk': 'bmpblk.bin',
1447 data, _, _, _ = self._DoReadFileDtb('071_gbb.dts', entry_args=entry_args)
1450 expected = (GBB_DATA + GBB_DATA + tools.GetBytes(0, 8) +
1451 tools.GetBytes(0, 0x2180 - 16))
1452 self.assertEqual(expected, data)
1454 def testGbbTooSmall(self):
1455 """Test for the Chromium OS Google Binary Block being large enough"""
1456 with self.assertRaises(ValueError) as e:
1457 self._DoReadFileDtb('072_gbb_too_small.dts')
1458 self.assertIn("Node '/binman/gbb': GBB is too small",
1461 def testGbbNoSize(self):
1462 """Test for the Chromium OS Google Binary Block having a size"""
1463 with self.assertRaises(ValueError) as e:
1464 self._DoReadFileDtb('073_gbb_no_size.dts')
1465 self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
1468 def _HandleVblockCommand(self, pipe_list):
1469 """Fake calls to the futility utility"""
1470 if pipe_list[0][0] == 'futility':
1471 fname = pipe_list[0][3]
1472 with open(fname, 'wb') as fd:
1473 fd.write(VBLOCK_DATA)
1474 return command.CommandResult()
1476 def testVblock(self):
1477 """Test for the Chromium OS Verified Boot Block"""
1478 command.test_result = self._HandleVblockCommand
1480 'keydir': 'devkeys',
1482 data, _, _, _ = self._DoReadFileDtb('074_vblock.dts',
1483 entry_args=entry_args)
1484 expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
1485 self.assertEqual(expected, data)
1487 def testVblockNoContent(self):
1488 """Test we detect a vblock which has no content to sign"""
1489 with self.assertRaises(ValueError) as e:
1490 self._DoReadFile('075_vblock_no_content.dts')
1491 self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
1492 'property', str(e.exception))
1494 def testVblockBadPhandle(self):
1495 """Test that we detect a vblock with an invalid phandle in contents"""
1496 with self.assertRaises(ValueError) as e:
1497 self._DoReadFile('076_vblock_bad_phandle.dts')
1498 self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
1499 '1000', str(e.exception))
1501 def testVblockBadEntry(self):
1502 """Test that we detect an entry that points to a non-entry"""
1503 with self.assertRaises(ValueError) as e:
1504 self._DoReadFile('077_vblock_bad_entry.dts')
1505 self.assertIn("Node '/binman/vblock': Cannot find entry for node "
1506 "'other'", str(e.exception))
1509 """Test that an image with TPL and ots device tree can be created"""
1510 # ELF file with a '__bss_size' symbol
1511 with open(self.TestFile('bss_data'), 'rb') as fd:
1512 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1513 data = self._DoReadFile('078_u_boot_tpl.dts')
1514 self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
1516 def testUsesPos(self):
1517 """Test that the 'pos' property cannot be used anymore"""
1518 with self.assertRaises(ValueError) as e:
1519 data = self._DoReadFile('079_uses_pos.dts')
1520 self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
1521 "'pos'", str(e.exception))
1523 def testFillZero(self):
1524 """Test for an fill entry type with a size of 0"""
1525 data = self._DoReadFile('080_fill_empty.dts')
1526 self.assertEqual(tools.GetBytes(0, 16), data)
1528 def testTextMissing(self):
1529 """Test for a text entry type where there is no text"""
1530 with self.assertRaises(ValueError) as e:
1531 self._DoReadFileDtb('066_text.dts',)
1532 self.assertIn("Node '/binman/text': No value provided for text label "
1533 "'test-id'", str(e.exception))
1535 def testPackStart16Tpl(self):
1536 """Test that an image with an x86 start16 TPL region can be created"""
1537 data = self._DoReadFile('081_x86-start16-tpl.dts')
1538 self.assertEqual(X86_START16_TPL_DATA, data[:len(X86_START16_TPL_DATA)])
1540 def testSelectImage(self):
1541 """Test that we can select which images to build"""
1542 expected = 'Skipping images: image1'
1544 # We should only get the expected message in verbose mode
1545 for verbosity in (0, 2):
1546 with test_util.capture_sys_output() as (stdout, stderr):
1547 retcode = self._DoTestFile('006_dual_image.dts',
1548 verbosity=verbosity,
1550 self.assertEqual(0, retcode)
1552 self.assertIn(expected, stdout.getvalue())
1554 self.assertNotIn(expected, stdout.getvalue())
1556 self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
1557 self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
1559 def testUpdateFdtAll(self):
1560 """Test that all device trees are updated with offset/size info"""
1561 data = self._DoReadFileRealDtb('082_fdt_update_all.dts')
1564 'section:image-pos': 0,
1565 'u-boot-tpl-dtb:size': 513,
1566 'u-boot-spl-dtb:size': 513,
1567 'u-boot-spl-dtb:offset': 493,
1569 'section/u-boot-dtb:image-pos': 0,
1570 'u-boot-spl-dtb:image-pos': 493,
1571 'section/u-boot-dtb:size': 493,
1572 'u-boot-tpl-dtb:image-pos': 1006,
1573 'section/u-boot-dtb:offset': 0,
1574 'section:size': 493,
1576 'section:offset': 0,
1577 'u-boot-tpl-dtb:offset': 1006,
1581 # We expect three device-tree files in the output, one after the other.
1582 # Read them in sequence. We look for an 'spl' property in the SPL tree,
1583 # and 'tpl' in the TPL tree, to make sure they are distinct from the
1584 # main U-Boot tree. All three should have the same postions and offset.
1586 for item in ['', 'spl', 'tpl']:
1587 dtb = fdt.Fdt.FromData(data[start:])
1589 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos',
1591 expected = dict(base_expected)
1594 self.assertEqual(expected, props)
1595 start += dtb._fdt_obj.totalsize()
1597 def testUpdateFdtOutput(self):
1598 """Test that output DTB files are updated"""
1600 data, dtb_data, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
1601 use_real_dtb=True, update_dtb=True, reset_dtbs=False)
1603 # Unfortunately, compiling a source file always results in a file
1604 # called source.dtb (see fdt_util.EnsureCompiled()). The test
1605 # source file (e.g. test/075_fdt_update_all.dts) thus does not enter
1606 # binman as a file called u-boot.dtb. To fix this, copy the file
1607 # over to the expected place.
1608 #tools.WriteFile(os.path.join(self._indir, 'u-boot.dtb'),
1609 #tools.ReadFile(tools.GetOutputFilename('source.dtb')))
1611 for fname in ['u-boot.dtb.out', 'spl/u-boot-spl.dtb.out',
1612 'tpl/u-boot-tpl.dtb.out']:
1613 dtb = fdt.Fdt.FromData(data[start:])
1614 size = dtb._fdt_obj.totalsize()
1615 pathname = tools.GetOutputFilename(os.path.split(fname)[1])
1616 outdata = tools.ReadFile(pathname)
1617 name = os.path.split(fname)[0]
1620 orig_indata = self._GetDtbContentsForSplTpl(dtb_data, name)
1622 orig_indata = dtb_data
1623 self.assertNotEqual(outdata, orig_indata,
1624 "Expected output file '%s' be updated" % pathname)
1625 self.assertEqual(outdata, data[start:start + size],
1626 "Expected output file '%s' to match output image" %
1632 def _decompress(self, data):
1633 return tools.Decompress(data, 'lz4')
1635 def testCompress(self):
1636 """Test compression of blobs"""
1638 data, _, _, out_dtb_fname = self._DoReadFileDtb('083_compress.dts',
1639 use_real_dtb=True, update_dtb=True)
1640 dtb = fdt.Fdt(out_dtb_fname)
1642 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
1643 orig = self._decompress(data)
1644 self.assertEquals(COMPRESS_DATA, orig)
1646 'blob:uncomp-size': len(COMPRESS_DATA),
1647 'blob:size': len(data),
1650 self.assertEqual(expected, props)
1652 def testFiles(self):
1653 """Test bringing in multiple files"""
1654 data = self._DoReadFile('084_files.dts')
1655 self.assertEqual(FILES_DATA, data)
1657 def testFilesCompress(self):
1658 """Test bringing in multiple files and compressing them"""
1660 data = self._DoReadFile('085_files_compress.dts')
1662 image = control.images['image']
1663 entries = image.GetEntries()
1664 files = entries['files']
1665 entries = files._section._entries
1668 for i in range(1, 3):
1670 start = entries[key].image_pos
1671 len = entries[key].size
1672 chunk = data[start:start + len]
1673 orig += self._decompress(chunk)
1675 self.assertEqual(FILES_DATA, orig)
1677 def testFilesMissing(self):
1678 """Test missing files"""
1679 with self.assertRaises(ValueError) as e:
1680 data = self._DoReadFile('086_files_none.dts')
1681 self.assertIn("Node '/binman/files': Pattern \'files/*.none\' matched "
1682 'no files', str(e.exception))
1684 def testFilesNoPattern(self):
1685 """Test missing files"""
1686 with self.assertRaises(ValueError) as e:
1687 data = self._DoReadFile('087_files_no_pattern.dts')
1688 self.assertIn("Node '/binman/files': Missing 'pattern' property",
1691 def testExpandSize(self):
1692 """Test an expanding entry"""
1693 data, _, map_data, _ = self._DoReadFileDtb('088_expand_size.dts',
1695 expect = (tools.GetBytes(ord('a'), 8) + U_BOOT_DATA +
1696 MRC_DATA + tools.GetBytes(ord('b'), 1) + U_BOOT_DATA +
1697 tools.GetBytes(ord('c'), 8) + U_BOOT_DATA +
1698 tools.GetBytes(ord('d'), 8))
1699 self.assertEqual(expect, data)
1700 self.assertEqual('''ImagePos Offset Size Name
1701 00000000 00000000 00000028 main-section
1702 00000000 00000000 00000008 fill
1703 00000008 00000008 00000004 u-boot
1704 0000000c 0000000c 00000004 section
1705 0000000c 00000000 00000003 intel-mrc
1706 00000010 00000010 00000004 u-boot2
1707 00000014 00000014 0000000c section2
1708 00000014 00000000 00000008 fill
1709 0000001c 00000008 00000004 u-boot
1710 00000020 00000020 00000008 fill2
1713 def testExpandSizeBad(self):
1714 """Test an expanding entry which fails to provide contents"""
1715 with test_util.capture_sys_output() as (stdout, stderr):
1716 with self.assertRaises(ValueError) as e:
1717 self._DoReadFileDtb('089_expand_size_bad.dts', map=True)
1718 self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
1719 'expanding entry', str(e.exception))
1722 """Test hashing of the contents of an entry"""
1723 _, _, _, out_dtb_fname = self._DoReadFileDtb('090_hash.dts',
1724 use_real_dtb=True, update_dtb=True)
1725 dtb = fdt.Fdt(out_dtb_fname)
1727 hash_node = dtb.GetNode('/binman/u-boot/hash').props['value']
1728 m = hashlib.sha256()
1729 m.update(U_BOOT_DATA)
1730 self.assertEqual(m.digest(), b''.join(hash_node.value))
1732 def testHashNoAlgo(self):
1733 with self.assertRaises(ValueError) as e:
1734 self._DoReadFileDtb('091_hash_no_algo.dts', update_dtb=True)
1735 self.assertIn("Node \'/binman/u-boot\': Missing \'algo\' property for "
1736 'hash node', str(e.exception))
1738 def testHashBadAlgo(self):
1739 with self.assertRaises(ValueError) as e:
1740 self._DoReadFileDtb('092_hash_bad_algo.dts', update_dtb=True)
1741 self.assertIn("Node '/binman/u-boot': Unknown hash algorithm",
1744 def testHashSection(self):
1745 """Test hashing of the contents of an entry"""
1746 _, _, _, out_dtb_fname = self._DoReadFileDtb('099_hash_section.dts',
1747 use_real_dtb=True, update_dtb=True)
1748 dtb = fdt.Fdt(out_dtb_fname)
1750 hash_node = dtb.GetNode('/binman/section/hash').props['value']
1751 m = hashlib.sha256()
1752 m.update(U_BOOT_DATA)
1753 m.update(tools.GetBytes(ord('a'), 16))
1754 self.assertEqual(m.digest(), b''.join(hash_node.value))
1756 def testPackUBootTplMicrocode(self):
1757 """Test that x86 microcode can be handled correctly in TPL
1759 We expect to see the following in the image, in order:
1760 u-boot-tpl-nodtb.bin with a microcode pointer inserted at the correct
1762 u-boot-tpl.dtb with the microcode removed
1765 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
1766 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1767 first, pos_and_size = self._RunMicrocodeTest('093_x86_tpl_ucode.dts',
1768 U_BOOT_TPL_NODTB_DATA)
1769 self.assertEqual(b'tplnodtb with microc' + pos_and_size +
1770 b'ter somewhere in here', first)
1772 def testFmapX86(self):
1773 """Basic test of generation of a flashrom fmap"""
1774 data = self._DoReadFile('094_fmap_x86.dts')
1775 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1776 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('a'), 32 - 7)
1777 self.assertEqual(expected, data[:32])
1778 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1780 self.assertEqual(0x100, fhdr.image_size)
1782 self.assertEqual(0, fentries[0].offset)
1783 self.assertEqual(4, fentries[0].size)
1784 self.assertEqual(b'U_BOOT', fentries[0].name)
1786 self.assertEqual(4, fentries[1].offset)
1787 self.assertEqual(3, fentries[1].size)
1788 self.assertEqual(b'INTEL_MRC', fentries[1].name)
1790 self.assertEqual(32, fentries[2].offset)
1791 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1792 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1793 self.assertEqual(b'FMAP', fentries[2].name)
1795 def testFmapX86Section(self):
1796 """Basic test of generation of a flashrom fmap"""
1797 data = self._DoReadFile('095_fmap_x86_section.dts')
1798 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('b'), 32 - 7)
1799 self.assertEqual(expected, data[:32])
1800 fhdr, fentries = fmap_util.DecodeFmap(data[36:])
1802 self.assertEqual(0x100, fhdr.image_size)
1804 self.assertEqual(0, fentries[0].offset)
1805 self.assertEqual(4, fentries[0].size)
1806 self.assertEqual(b'U_BOOT', fentries[0].name)
1808 self.assertEqual(4, fentries[1].offset)
1809 self.assertEqual(3, fentries[1].size)
1810 self.assertEqual(b'INTEL_MRC', fentries[1].name)
1812 self.assertEqual(36, fentries[2].offset)
1813 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1814 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1815 self.assertEqual(b'FMAP', fentries[2].name)
1818 """Basic test of ELF entries"""
1820 with open(self.TestFile('bss_data'), 'rb') as fd:
1821 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1822 with open(self.TestFile('bss_data'), 'rb') as fd:
1823 TestFunctional._MakeInputFile('-boot', fd.read())
1824 data = self._DoReadFile('096_elf.dts')
1826 def testElfStrip(self):
1827 """Basic test of ELF entries"""
1829 with open(self.TestFile('bss_data'), 'rb') as fd:
1830 TestFunctional._MakeInputFile('-boot', fd.read())
1831 data = self._DoReadFile('097_elf_strip.dts')
1833 def testPackOverlapMap(self):
1834 """Test that overlapping regions are detected"""
1835 with test_util.capture_sys_output() as (stdout, stderr):
1836 with self.assertRaises(ValueError) as e:
1837 self._DoTestFile('014_pack_overlap.dts', map=True)
1838 map_fname = tools.GetOutputFilename('image.map')
1839 self.assertEqual("Wrote map file '%s' to show errors\n" % map_fname,
1842 # We should not get an inmage, but there should be a map file
1843 self.assertFalse(os.path.exists(tools.GetOutputFilename('image.bin')))
1844 self.assertTrue(os.path.exists(map_fname))
1845 map_data = tools.ReadFile(map_fname, binary=False)
1846 self.assertEqual('''ImagePos Offset Size Name
1847 <none> 00000000 00000007 main-section
1848 <none> 00000000 00000004 u-boot
1849 <none> 00000003 00000004 u-boot-align
1852 def testPackRefCode(self):
1853 """Test that an image with an Intel Reference code binary works"""
1854 data = self._DoReadFile('100_intel_refcode.dts')
1855 self.assertEqual(REFCODE_DATA, data[:len(REFCODE_DATA)])
1857 def testSectionOffset(self):
1858 """Tests use of a section with an offset"""
1859 data, _, map_data, _ = self._DoReadFileDtb('101_sections_offset.dts',
1861 self.assertEqual('''ImagePos Offset Size Name
1862 00000000 00000000 00000038 main-section
1863 00000004 00000004 00000010 section@0
1864 00000004 00000000 00000004 u-boot
1865 00000018 00000018 00000010 section@1
1866 00000018 00000000 00000004 u-boot
1867 0000002c 0000002c 00000004 section@2
1868 0000002c 00000000 00000004 u-boot
1870 self.assertEqual(data,
1871 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1872 tools.GetBytes(0x21, 12) +
1873 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1874 tools.GetBytes(0x61, 12) +
1875 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1876 tools.GetBytes(0x26, 8))
1878 def testCbfsRaw(self):
1879 """Test base handling of a Coreboot Filesystem (CBFS)
1881 The exact contents of the CBFS is verified by similar tests in
1882 cbfs_util_test.py. The tests here merely check that the files added to
1883 the CBFS can be found in the final image.
1885 data = self._DoReadFile('102_cbfs_raw.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 testCbfsArch(self):
1896 """Test on non-x86 architecture"""
1897 data = self._DoReadFile('103_cbfs_raw_ppc.dts')
1900 cbfs = cbfs_util.CbfsReader(data)
1901 self.assertEqual(size, cbfs.rom_size)
1903 self.assertIn('u-boot-dtb', cbfs.files)
1904 cfile = cbfs.files['u-boot-dtb']
1905 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
1907 def testCbfsStage(self):
1908 """Tests handling of a Coreboot Filesystem (CBFS)"""
1909 if not elf.ELF_TOOLS:
1910 self.skipTest('Python elftools not available')
1911 elf_fname = os.path.join(self._indir, 'cbfs-stage.elf')
1912 elf.MakeElf(elf_fname, U_BOOT_DATA, U_BOOT_DTB_DATA)
1915 data = self._DoReadFile('104_cbfs_stage.dts')
1916 cbfs = cbfs_util.CbfsReader(data)
1917 self.assertEqual(size, cbfs.rom_size)
1919 self.assertIn('u-boot', cbfs.files)
1920 cfile = cbfs.files['u-boot']
1921 self.assertEqual(U_BOOT_DATA + U_BOOT_DTB_DATA, cfile.data)
1923 def testCbfsRawCompress(self):
1924 """Test handling of compressing raw files"""
1926 data = self._DoReadFile('105_cbfs_raw_compress.dts')
1929 cbfs = cbfs_util.CbfsReader(data)
1930 self.assertIn('u-boot', cbfs.files)
1931 cfile = cbfs.files['u-boot']
1932 self.assertEqual(COMPRESS_DATA, cfile.data)
1934 def testCbfsBadArch(self):
1935 """Test handling of a bad architecture"""
1936 with self.assertRaises(ValueError) as e:
1937 self._DoReadFile('106_cbfs_bad_arch.dts')
1938 self.assertIn("Invalid architecture 'bad-arch'", str(e.exception))
1940 def testCbfsNoSize(self):
1941 """Test handling of a missing size property"""
1942 with self.assertRaises(ValueError) as e:
1943 self._DoReadFile('107_cbfs_no_size.dts')
1944 self.assertIn('entry must have a size property', str(e.exception))
1946 def testCbfsNoCOntents(self):
1947 """Test handling of a CBFS entry which does not provide contentsy"""
1948 with self.assertRaises(ValueError) as e:
1949 self._DoReadFile('108_cbfs_no_contents.dts')
1950 self.assertIn('Could not complete processing of contents',
1953 def testCbfsBadCompress(self):
1954 """Test handling of a bad architecture"""
1955 with self.assertRaises(ValueError) as e:
1956 self._DoReadFile('109_cbfs_bad_compress.dts')
1957 self.assertIn("Invalid compression in 'u-boot': 'invalid-algo'",
1960 def testCbfsNamedEntries(self):
1961 """Test handling of named entries"""
1962 data = self._DoReadFile('110_cbfs_name.dts')
1964 cbfs = cbfs_util.CbfsReader(data)
1965 self.assertIn('FRED', cbfs.files)
1966 cfile1 = cbfs.files['FRED']
1967 self.assertEqual(U_BOOT_DATA, cfile1.data)
1969 self.assertIn('hello', cbfs.files)
1970 cfile2 = cbfs.files['hello']
1971 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
1973 def _SetupIfwi(self, fname):
1974 """Set up to run an IFWI test
1977 fname: Filename of input file to provide (fitimage.bin or ifwi.bin)
1981 # Intel Integrated Firmware Image (IFWI) file
1982 with gzip.open(self.TestFile('%s.gz' % fname), 'rb') as fd:
1984 TestFunctional._MakeInputFile(fname,data)
1986 def _CheckIfwi(self, data):
1987 """Check that an image with an IFWI contains the correct output
1990 data: Conents of output file
1992 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
1993 if data[:0x1000] != expected_desc:
1994 self.fail('Expected descriptor binary at start of image')
1996 # We expect to find the TPL wil in subpart IBBP entry IBBL
1997 image_fname = tools.GetOutputFilename('image.bin')
1998 tpl_fname = tools.GetOutputFilename('tpl.out')
1999 tools.RunIfwiTool(image_fname, tools.CMD_EXTRACT, fname=tpl_fname,
2000 subpart='IBBP', entry_name='IBBL')
2002 tpl_data = tools.ReadFile(tpl_fname)
2003 self.assertEqual(tpl_data[:len(U_BOOT_TPL_DATA)], U_BOOT_TPL_DATA)
2005 def testPackX86RomIfwi(self):
2006 """Test that an x86 ROM with Integrated Firmware Image can be created"""
2007 self._SetupIfwi('fitimage.bin')
2008 data = self._DoReadFile('111_x86-rom-ifwi.dts')
2009 self._CheckIfwi(data)
2011 def testPackX86RomIfwiNoDesc(self):
2012 """Test that an x86 ROM with IFWI can be created from an ifwi.bin file"""
2013 self._SetupIfwi('ifwi.bin')
2014 data = self._DoReadFile('112_x86-rom-ifwi-nodesc.dts')
2015 self._CheckIfwi(data)
2017 def testPackX86RomIfwiNoData(self):
2018 """Test that an x86 ROM with IFWI handles missing data"""
2019 self._SetupIfwi('ifwi.bin')
2020 with self.assertRaises(ValueError) as e:
2021 data = self._DoReadFile('113_x86-rom-ifwi-nodata.dts')
2022 self.assertIn('Could not complete processing of contents',
2025 def testCbfsOffset(self):
2026 """Test a CBFS with files at particular offsets
2028 Like all CFBS tests, this is just checking the logic that calls
2029 cbfs_util. See cbfs_util_test for fully tests (e.g. test_cbfs_offset()).
2031 data = self._DoReadFile('114_cbfs_offset.dts')
2034 cbfs = cbfs_util.CbfsReader(data)
2035 self.assertEqual(size, cbfs.rom_size)
2037 self.assertIn('u-boot', cbfs.files)
2038 cfile = cbfs.files['u-boot']
2039 self.assertEqual(U_BOOT_DATA, cfile.data)
2040 self.assertEqual(0x40, cfile.cbfs_offset)
2042 self.assertIn('u-boot-dtb', cbfs.files)
2043 cfile2 = cbfs.files['u-boot-dtb']
2044 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
2045 self.assertEqual(0x140, cfile2.cbfs_offset)
2047 def testFdtmap(self):
2048 """Test an FDT map can be inserted in the image"""
2049 data = self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
2050 fdtmap_data = data[len(U_BOOT_DATA):]
2051 magic = fdtmap_data[:8]
2052 self.assertEqual('_FDTMAP_', magic)
2053 self.assertEqual(tools.GetBytes(0, 8), fdtmap_data[8:16])
2055 fdt_data = fdtmap_data[16:]
2056 dtb = fdt.Fdt.FromData(fdt_data)
2058 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'],
2064 'u-boot:size': len(U_BOOT_DATA),
2065 'u-boot:image-pos': 0,
2066 'fdtmap:image-pos': 4,
2068 'fdtmap:size': len(fdtmap_data),
2072 def testFdtmapNoMatch(self):
2073 """Check handling of an FDT map when the section cannot be found"""
2074 self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
2076 # Mangle the section name, which should cause a mismatch between the
2077 # correct FDT path and the one expected by the section
2078 image = control.images['image']
2079 image._section._node.path += '-suffix'
2080 entries = image.GetEntries()
2081 fdtmap = entries['fdtmap']
2082 with self.assertRaises(ValueError) as e:
2084 self.assertIn("Cannot locate node for path '/binman-suffix'",
2088 if __name__ == "__main__":