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
27 from etype import fdtmap
28 from etype import image_header
33 from image import Image
38 # Contents of test files, corresponding to different entry types
40 U_BOOT_IMG_DATA = b'img'
41 U_BOOT_SPL_DATA = b'56780123456789abcde'
42 U_BOOT_TPL_DATA = b'tpl'
46 U_BOOT_DTB_DATA = b'udtb'
47 U_BOOT_SPL_DTB_DATA = b'spldtb'
48 U_BOOT_TPL_DTB_DATA = b'tpldtb'
49 X86_START16_DATA = b'start16'
50 X86_START16_SPL_DATA = b'start16spl'
51 X86_START16_TPL_DATA = b'start16tpl'
52 PPC_MPC85XX_BR_DATA = b'ppcmpc85xxbr'
53 U_BOOT_NODTB_DATA = b'nodtb with microcode pointer somewhere in here'
54 U_BOOT_SPL_NODTB_DATA = b'splnodtb with microcode pointer somewhere in here'
55 U_BOOT_TPL_NODTB_DATA = b'tplnodtb with microcode pointer somewhere in here'
63 CROS_EC_RW_DATA = b'ecrw'
67 FILES_DATA = (b"sorry I'm late\nOh, don't bother apologising, I'm " +
68 b"sorry you're alive\n")
69 COMPRESS_DATA = b'compress xxxxxxxxxxxxxxxxxxxxxx data'
70 REFCODE_DATA = b'refcode'
72 EXTRACT_DTB_SIZE = 0x3c9
75 class TestFunctional(unittest.TestCase):
76 """Functional tests for binman
78 Most of these use a sample .dts file to build an image and then check
79 that it looks correct. The sample files are in the test/ subdirectory
82 For each entry type a very small test file is created using fixed
83 string contents. This makes it easy to test that things look right, and
86 In some cases a 'real' file must be used - these are also supplied in
94 # Handle the case where argv[0] is 'python'
95 self._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
96 self._binman_pathname = os.path.join(self._binman_dir, 'binman')
98 # Create a temporary directory for input files
99 self._indir = tempfile.mkdtemp(prefix='binmant.')
101 # Create some test files
102 TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
103 TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
104 TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
105 TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
106 TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
107 TestFunctional._MakeInputFile('me.bin', ME_DATA)
108 TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
110 TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
111 TestFunctional._MakeInputFile('u-boot-br.bin', PPC_MPC85XX_BR_DATA)
112 TestFunctional._MakeInputFile('spl/u-boot-x86-16bit-spl.bin',
113 X86_START16_SPL_DATA)
114 TestFunctional._MakeInputFile('tpl/u-boot-x86-16bit-tpl.bin',
115 X86_START16_TPL_DATA)
116 TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
117 TestFunctional._MakeInputFile('spl/u-boot-spl-nodtb.bin',
118 U_BOOT_SPL_NODTB_DATA)
119 TestFunctional._MakeInputFile('tpl/u-boot-tpl-nodtb.bin',
120 U_BOOT_TPL_NODTB_DATA)
121 TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
122 TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
123 TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
124 TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
125 TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
126 TestFunctional._MakeInputDir('devkeys')
127 TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
128 TestFunctional._MakeInputFile('refcode.bin', REFCODE_DATA)
130 # ELF file with a '_dt_ucode_base_size' symbol
131 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
132 TestFunctional._MakeInputFile('u-boot', fd.read())
134 # Intel flash descriptor file
135 with open(self.TestFile('descriptor.bin'), 'rb') as fd:
136 TestFunctional._MakeInputFile('descriptor.bin', fd.read())
138 shutil.copytree(self.TestFile('files'),
139 os.path.join(self._indir, 'files'))
141 TestFunctional._MakeInputFile('compress', COMPRESS_DATA)
143 # Travis-CI may have an old lz4
146 tools.Run('lz4', '--no-frame-crc', '-c',
147 os.path.join(self._indir, 'u-boot.bin'))
149 self.have_lz4 = False
152 def tearDownClass(self):
153 """Remove the temporary input directory and its contents"""
154 if self.preserve_indir:
155 print('Preserving input dir: %s' % self._indir)
158 shutil.rmtree(self._indir)
162 def setup_test_args(cls, preserve_indir=False, preserve_outdirs=False,
163 toolpath=None, verbosity=None):
164 """Accept arguments controlling test execution
167 preserve_indir: Preserve the shared input directory used by all
169 preserve_outdir: Preserve the output directories used by tests. Each
170 test has its own, so this is normally only useful when running a
172 toolpath: ist of paths to use for tools
174 cls.preserve_indir = preserve_indir
175 cls.preserve_outdirs = preserve_outdirs
176 cls.toolpath = toolpath
177 cls.verbosity = verbosity
180 if not self.have_lz4:
181 self.skipTest('lz4 --no-frame-crc not available')
184 # Enable this to turn on debugging output
185 # tout.Init(tout.DEBUG)
186 command.test_result = None
189 """Remove the temporary output directory"""
190 if self.preserve_outdirs:
191 print('Preserving output dir: %s' % tools.outdir)
193 tools._FinaliseForTest()
196 def _ResetDtbs(self):
197 TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
198 TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
199 TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
201 def _RunBinman(self, *args, **kwargs):
202 """Run binman using the command line
205 Arguments to pass, as a list of strings
206 kwargs: Arguments to pass to Command.RunPipe()
208 result = command.RunPipe([[self._binman_pathname] + list(args)],
209 capture=True, capture_stderr=True, raise_on_error=False)
210 if result.return_code and kwargs.get('raise_on_error', True):
211 raise Exception("Error running '%s': %s" % (' '.join(args),
212 result.stdout + result.stderr))
215 def _DoBinman(self, *argv):
216 """Run binman using directly (in the same process)
219 Arguments to pass, as a list of strings
221 Return value (0 for success)
224 args = cmdline.ParseArgs(argv)
225 args.pager = 'binman-invalid-pager'
226 args.build_dir = self._indir
228 # For testing, you can force an increase in verbosity here
229 # args.verbosity = tout.DEBUG
230 return control.Binman(args)
232 def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
233 entry_args=None, images=None, use_real_dtb=False,
235 """Run binman with a given test file
238 fname: Device-tree source filename to use (e.g. 005_simple.dts)
239 debug: True to enable debugging output
240 map: True to output map files for the images
241 update_dtb: Update the offset and size of each entry in the device
242 tree before packing it into the image
243 entry_args: Dict of entry args to supply to binman
245 value: value of that arg
246 images: List of image names to build
251 if verbosity is not None:
252 args.append('-v%d' % verbosity)
254 args.append('-v%d' % self.verbosity)
256 for path in self.toolpath:
257 args += ['--toolpath', path]
258 args += ['build', '-p', '-I', self._indir, '-d', self.TestFile(fname)]
264 args.append('--fake-dtb')
266 for arg, value in entry_args.items():
267 args.append('-a%s=%s' % (arg, value))
270 args += ['-i', image]
271 return self._DoBinman(*args)
273 def _SetupDtb(self, fname, outfile='u-boot.dtb'):
274 """Set up a new test device-tree file
276 The given file is compiled and set up as the device tree to be used
280 fname: Filename of .dts file to read
281 outfile: Output filename for compiled device-tree binary
284 Contents of device-tree binary
286 tools.PrepareOutputDir(None)
287 dtb = fdt_util.EnsureCompiled(self.TestFile(fname))
288 with open(dtb, 'rb') as fd:
290 TestFunctional._MakeInputFile(outfile, data)
291 tools.FinaliseOutputDir()
294 def _GetDtbContentsForSplTpl(self, dtb_data, name):
295 """Create a version of the main DTB for SPL or SPL
297 For testing we don't actually have different versions of the DTB. With
298 U-Boot we normally run fdtgrep to remove unwanted nodes, but for tests
299 we don't normally have any unwanted nodes.
301 We still want the DTBs for SPL and TPL to be different though, since
302 otherwise it is confusing to know which one we are looking at. So add
303 an 'spl' or 'tpl' property to the top-level node.
305 dtb = fdt.Fdt.FromData(dtb_data)
307 dtb.GetNode('/binman').AddZeroProp(name)
308 dtb.Sync(auto_resize=True)
310 return dtb.GetContents()
312 def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
313 update_dtb=False, entry_args=None, reset_dtbs=True):
314 """Run binman and return the resulting image
316 This runs binman with a given test file and then reads the resulting
317 output file. It is a shortcut function since most tests need to do
320 Raises an assertion failure if binman returns a non-zero exit code.
323 fname: Device-tree source filename to use (e.g. 005_simple.dts)
324 use_real_dtb: True to use the test file as the contents of
325 the u-boot-dtb entry. Normally this is not needed and the
326 test contents (the U_BOOT_DTB_DATA string) can be used.
327 But in some test we need the real contents.
328 map: True to output map files for the images
329 update_dtb: Update the offset and size of each entry in the device
330 tree before packing it into the image
334 Resulting image contents
336 Map data showing contents of image (or None if none)
337 Output device tree binary filename ('u-boot.dtb' path)
340 # Use the compiled test file as the u-boot-dtb input
342 dtb_data = self._SetupDtb(fname)
344 # For testing purposes, make a copy of the DT for SPL and TPL. Add
345 # a node indicating which it is, so aid verification.
346 for name in ['spl', 'tpl']:
347 dtb_fname = '%s/u-boot-%s.dtb' % (name, name)
348 outfile = os.path.join(self._indir, dtb_fname)
349 TestFunctional._MakeInputFile(dtb_fname,
350 self._GetDtbContentsForSplTpl(dtb_data, name))
353 retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
354 entry_args=entry_args, use_real_dtb=use_real_dtb)
355 self.assertEqual(0, retcode)
356 out_dtb_fname = tools.GetOutputFilename('u-boot.dtb.out')
358 # Find the (only) image, read it and return its contents
359 image = control.images['image']
360 image_fname = tools.GetOutputFilename('image.bin')
361 self.assertTrue(os.path.exists(image_fname))
363 map_fname = tools.GetOutputFilename('image.map')
364 with open(map_fname) as fd:
368 with open(image_fname, 'rb') as fd:
369 return fd.read(), dtb_data, map_data, out_dtb_fname
371 # Put the test file back
372 if reset_dtbs and use_real_dtb:
375 def _DoReadFileRealDtb(self, fname):
376 """Run binman with a real .dtb file and return the resulting data
379 fname: DT source filename to use (e.g. 082_fdt_update_all.dts)
382 Resulting image contents
384 return self._DoReadFileDtb(fname, use_real_dtb=True, update_dtb=True)[0]
386 def _DoReadFile(self, fname, use_real_dtb=False):
387 """Helper function which discards the device-tree binary
390 fname: Device-tree source filename to use (e.g. 005_simple.dts)
391 use_real_dtb: True to use the test file as the contents of
392 the u-boot-dtb entry. Normally this is not needed and the
393 test contents (the U_BOOT_DTB_DATA string) can be used.
394 But in some test we need the real contents.
397 Resulting image contents
399 return self._DoReadFileDtb(fname, use_real_dtb)[0]
402 def _MakeInputFile(self, fname, contents):
403 """Create a new test input file, creating directories as needed
406 fname: Filename to create
407 contents: File contents to write in to the file
409 Full pathname of file created
411 pathname = os.path.join(self._indir, fname)
412 dirname = os.path.dirname(pathname)
413 if dirname and not os.path.exists(dirname):
415 with open(pathname, 'wb') as fd:
420 def _MakeInputDir(self, dirname):
421 """Create a new test input directory, creating directories as needed
424 dirname: Directory name to create
427 Full pathname of directory created
429 pathname = os.path.join(self._indir, dirname)
430 if not os.path.exists(pathname):
431 os.makedirs(pathname)
435 def _SetupSplElf(self, src_fname='bss_data'):
436 """Set up an ELF file with a '_dt_ucode_base_size' symbol
439 Filename of ELF file to use as SPL
441 with open(self.TestFile(src_fname), 'rb') as fd:
442 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
445 def TestFile(self, fname):
446 return os.path.join(self._binman_dir, 'test', fname)
448 def AssertInList(self, grep_list, target):
449 """Assert that at least one of a list of things is in a target
452 grep_list: List of strings to check
453 target: Target string
455 for grep in grep_list:
458 self.fail("Error: '%s' not found in '%s'" % (grep_list, target))
460 def CheckNoGaps(self, entries):
461 """Check that all entries fit together without gaps
464 entries: List of entries to check
467 for entry in entries.values():
468 self.assertEqual(offset, entry.offset)
471 def GetFdtLen(self, dtb):
472 """Get the totalsize field from a device-tree binary
475 dtb: Device-tree binary contents
478 Total size of device-tree binary, from the header
480 return struct.unpack('>L', dtb[4:8])[0]
482 def _GetPropTree(self, dtb, prop_names, prefix='/binman/'):
483 def AddNode(node, path):
485 path += '/' + node.name
486 for prop in node.props.values():
487 if prop.name in prop_names:
488 prop_path = path + ':' + prop.name
489 tree[prop_path[len(prefix):]] = fdt_util.fdt32_to_cpu(
491 for subnode in node.subnodes:
492 AddNode(subnode, path)
495 AddNode(dtb.GetRoot(), '')
499 """Test a basic run with valid args"""
500 result = self._RunBinman('-h')
502 def testFullHelp(self):
503 """Test that the full help is displayed with -H"""
504 result = self._RunBinman('-H')
505 help_file = os.path.join(self._binman_dir, 'README')
506 # Remove possible extraneous strings
507 extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
508 gothelp = result.stdout.replace(extra, '')
509 self.assertEqual(len(gothelp), os.path.getsize(help_file))
510 self.assertEqual(0, len(result.stderr))
511 self.assertEqual(0, result.return_code)
513 def testFullHelpInternal(self):
514 """Test that the full help is displayed with -H"""
516 command.test_result = command.CommandResult()
517 result = self._DoBinman('-H')
518 help_file = os.path.join(self._binman_dir, 'README')
520 command.test_result = None
523 """Test that the basic help is displayed with -h"""
524 result = self._RunBinman('-h')
525 self.assertTrue(len(result.stdout) > 200)
526 self.assertEqual(0, len(result.stderr))
527 self.assertEqual(0, result.return_code)
530 """Test that we can run it with a specific board"""
531 self._SetupDtb('005_simple.dts', 'sandbox/u-boot.dtb')
532 TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
533 result = self._DoBinman('build', '-b', 'sandbox')
534 self.assertEqual(0, result)
536 def testNeedBoard(self):
537 """Test that we get an error when no board ius supplied"""
538 with self.assertRaises(ValueError) as e:
539 result = self._DoBinman('build')
540 self.assertIn("Must provide a board to process (use -b <board>)",
543 def testMissingDt(self):
544 """Test that an invalid device-tree file generates an error"""
545 with self.assertRaises(Exception) as e:
546 self._RunBinman('build', '-d', 'missing_file')
547 # We get one error from libfdt, and a different one from fdtget.
548 self.AssertInList(["Couldn't open blob from 'missing_file'",
549 'No such file or directory'], str(e.exception))
551 def testBrokenDt(self):
552 """Test that an invalid device-tree source file generates an error
554 Since this is a source file it should be compiled and the error
555 will come from the device-tree compiler (dtc).
557 with self.assertRaises(Exception) as e:
558 self._RunBinman('build', '-d', self.TestFile('001_invalid.dts'))
559 self.assertIn("FATAL ERROR: Unable to parse input tree",
562 def testMissingNode(self):
563 """Test that a device tree without a 'binman' node generates an error"""
564 with self.assertRaises(Exception) as e:
565 self._DoBinman('build', '-d', self.TestFile('002_missing_node.dts'))
566 self.assertIn("does not have a 'binman' node", str(e.exception))
569 """Test that an empty binman node works OK (i.e. does nothing)"""
570 result = self._RunBinman('build', '-d', self.TestFile('003_empty.dts'))
571 self.assertEqual(0, len(result.stderr))
572 self.assertEqual(0, result.return_code)
574 def testInvalidEntry(self):
575 """Test that an invalid entry is flagged"""
576 with self.assertRaises(Exception) as e:
577 result = self._RunBinman('build', '-d',
578 self.TestFile('004_invalid_entry.dts'))
579 self.assertIn("Unknown entry type 'not-a-valid-type' in node "
580 "'/binman/not-a-valid-type'", str(e.exception))
582 def testSimple(self):
583 """Test a simple binman with a single file"""
584 data = self._DoReadFile('005_simple.dts')
585 self.assertEqual(U_BOOT_DATA, data)
587 def testSimpleDebug(self):
588 """Test a simple binman run with debugging enabled"""
589 self._DoTestFile('005_simple.dts', debug=True)
592 """Test that we can handle creating two images
594 This also tests image padding.
596 retcode = self._DoTestFile('006_dual_image.dts')
597 self.assertEqual(0, retcode)
599 image = control.images['image1']
600 self.assertEqual(len(U_BOOT_DATA), image.size)
601 fname = tools.GetOutputFilename('image1.bin')
602 self.assertTrue(os.path.exists(fname))
603 with open(fname, 'rb') as fd:
605 self.assertEqual(U_BOOT_DATA, data)
607 image = control.images['image2']
608 self.assertEqual(3 + len(U_BOOT_DATA) + 5, image.size)
609 fname = tools.GetOutputFilename('image2.bin')
610 self.assertTrue(os.path.exists(fname))
611 with open(fname, 'rb') as fd:
613 self.assertEqual(U_BOOT_DATA, data[3:7])
614 self.assertEqual(tools.GetBytes(0, 3), data[:3])
615 self.assertEqual(tools.GetBytes(0, 5), data[7:])
617 def testBadAlign(self):
618 """Test that an invalid alignment value is detected"""
619 with self.assertRaises(ValueError) as e:
620 self._DoTestFile('007_bad_align.dts')
621 self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
622 "of two", str(e.exception))
624 def testPackSimple(self):
625 """Test that packing works as expected"""
626 retcode = self._DoTestFile('008_pack.dts')
627 self.assertEqual(0, retcode)
628 self.assertIn('image', control.images)
629 image = control.images['image']
630 entries = image.GetEntries()
631 self.assertEqual(5, len(entries))
634 self.assertIn('u-boot', entries)
635 entry = entries['u-boot']
636 self.assertEqual(0, entry.offset)
637 self.assertEqual(len(U_BOOT_DATA), entry.size)
639 # Second u-boot, aligned to 16-byte boundary
640 self.assertIn('u-boot-align', entries)
641 entry = entries['u-boot-align']
642 self.assertEqual(16, entry.offset)
643 self.assertEqual(len(U_BOOT_DATA), entry.size)
645 # Third u-boot, size 23 bytes
646 self.assertIn('u-boot-size', entries)
647 entry = entries['u-boot-size']
648 self.assertEqual(20, entry.offset)
649 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
650 self.assertEqual(23, entry.size)
652 # Fourth u-boot, placed immediate after the above
653 self.assertIn('u-boot-next', entries)
654 entry = entries['u-boot-next']
655 self.assertEqual(43, entry.offset)
656 self.assertEqual(len(U_BOOT_DATA), entry.size)
658 # Fifth u-boot, placed at a fixed offset
659 self.assertIn('u-boot-fixed', entries)
660 entry = entries['u-boot-fixed']
661 self.assertEqual(61, entry.offset)
662 self.assertEqual(len(U_BOOT_DATA), entry.size)
664 self.assertEqual(65, image.size)
666 def testPackExtra(self):
667 """Test that extra packing feature works as expected"""
668 retcode = self._DoTestFile('009_pack_extra.dts')
670 self.assertEqual(0, retcode)
671 self.assertIn('image', control.images)
672 image = control.images['image']
673 entries = image.GetEntries()
674 self.assertEqual(5, len(entries))
676 # First u-boot with padding before and after
677 self.assertIn('u-boot', entries)
678 entry = entries['u-boot']
679 self.assertEqual(0, entry.offset)
680 self.assertEqual(3, entry.pad_before)
681 self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
683 # Second u-boot has an aligned size, but it has no effect
684 self.assertIn('u-boot-align-size-nop', entries)
685 entry = entries['u-boot-align-size-nop']
686 self.assertEqual(12, entry.offset)
687 self.assertEqual(4, entry.size)
689 # Third u-boot has an aligned size too
690 self.assertIn('u-boot-align-size', entries)
691 entry = entries['u-boot-align-size']
692 self.assertEqual(16, entry.offset)
693 self.assertEqual(32, entry.size)
695 # Fourth u-boot has an aligned end
696 self.assertIn('u-boot-align-end', entries)
697 entry = entries['u-boot-align-end']
698 self.assertEqual(48, entry.offset)
699 self.assertEqual(16, entry.size)
701 # Fifth u-boot immediately afterwards
702 self.assertIn('u-boot-align-both', entries)
703 entry = entries['u-boot-align-both']
704 self.assertEqual(64, entry.offset)
705 self.assertEqual(64, entry.size)
707 self.CheckNoGaps(entries)
708 self.assertEqual(128, image.size)
710 def testPackAlignPowerOf2(self):
711 """Test that invalid entry alignment is detected"""
712 with self.assertRaises(ValueError) as e:
713 self._DoTestFile('010_pack_align_power2.dts')
714 self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
715 "of two", str(e.exception))
717 def testPackAlignSizePowerOf2(self):
718 """Test that invalid entry size alignment is detected"""
719 with self.assertRaises(ValueError) as e:
720 self._DoTestFile('011_pack_align_size_power2.dts')
721 self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
722 "power of two", str(e.exception))
724 def testPackInvalidAlign(self):
725 """Test detection of an offset that does not match its alignment"""
726 with self.assertRaises(ValueError) as e:
727 self._DoTestFile('012_pack_inv_align.dts')
728 self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
729 "align 0x4 (4)", str(e.exception))
731 def testPackInvalidSizeAlign(self):
732 """Test that invalid entry size alignment is detected"""
733 with self.assertRaises(ValueError) as e:
734 self._DoTestFile('013_pack_inv_size_align.dts')
735 self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
736 "align-size 0x4 (4)", str(e.exception))
738 def testPackOverlap(self):
739 """Test that overlapping regions are detected"""
740 with self.assertRaises(ValueError) as e:
741 self._DoTestFile('014_pack_overlap.dts')
742 self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
743 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
746 def testPackEntryOverflow(self):
747 """Test that entries that overflow their size are detected"""
748 with self.assertRaises(ValueError) as e:
749 self._DoTestFile('015_pack_overflow.dts')
750 self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
751 "but entry size is 0x3 (3)", str(e.exception))
753 def testPackImageOverflow(self):
754 """Test that entries which overflow the image size are detected"""
755 with self.assertRaises(ValueError) as e:
756 self._DoTestFile('016_pack_image_overflow.dts')
757 self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section "
758 "size 0x3 (3)", str(e.exception))
760 def testPackImageSize(self):
761 """Test that the image size can be set"""
762 retcode = self._DoTestFile('017_pack_image_size.dts')
763 self.assertEqual(0, retcode)
764 self.assertIn('image', control.images)
765 image = control.images['image']
766 self.assertEqual(7, image.size)
768 def testPackImageSizeAlign(self):
769 """Test that image size alignemnt works as expected"""
770 retcode = self._DoTestFile('018_pack_image_align.dts')
771 self.assertEqual(0, retcode)
772 self.assertIn('image', control.images)
773 image = control.images['image']
774 self.assertEqual(16, image.size)
776 def testPackInvalidImageAlign(self):
777 """Test that invalid image alignment is detected"""
778 with self.assertRaises(ValueError) as e:
779 self._DoTestFile('019_pack_inv_image_align.dts')
780 self.assertIn("Section '/binman': Size 0x7 (7) does not match "
781 "align-size 0x8 (8)", str(e.exception))
783 def testPackAlignPowerOf2(self):
784 """Test that invalid image alignment is detected"""
785 with self.assertRaises(ValueError) as e:
786 self._DoTestFile('020_pack_inv_image_align_power2.dts')
787 self.assertIn("Image '/binman': Alignment size 131 must be a power of "
788 "two", str(e.exception))
790 def testImagePadByte(self):
791 """Test that the image pad byte can be specified"""
793 data = self._DoReadFile('021_image_pad.dts')
794 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0xff, 1) +
797 def testImageName(self):
798 """Test that image files can be named"""
799 retcode = self._DoTestFile('022_image_name.dts')
800 self.assertEqual(0, retcode)
801 image = control.images['image1']
802 fname = tools.GetOutputFilename('test-name')
803 self.assertTrue(os.path.exists(fname))
805 image = control.images['image2']
806 fname = tools.GetOutputFilename('test-name.xx')
807 self.assertTrue(os.path.exists(fname))
809 def testBlobFilename(self):
810 """Test that generic blobs can be provided by filename"""
811 data = self._DoReadFile('023_blob.dts')
812 self.assertEqual(BLOB_DATA, data)
814 def testPackSorted(self):
815 """Test that entries can be sorted"""
817 data = self._DoReadFile('024_sorted.dts')
818 self.assertEqual(tools.GetBytes(0, 1) + U_BOOT_SPL_DATA +
819 tools.GetBytes(0, 2) + U_BOOT_DATA, data)
821 def testPackZeroOffset(self):
822 """Test that an entry at offset 0 is not given a new offset"""
823 with self.assertRaises(ValueError) as e:
824 self._DoTestFile('025_pack_zero_size.dts')
825 self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
826 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
829 def testPackUbootDtb(self):
830 """Test that a device tree can be added to U-Boot"""
831 data = self._DoReadFile('026_pack_u_boot_dtb.dts')
832 self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
834 def testPackX86RomNoSize(self):
835 """Test that the end-at-4gb property requires a size property"""
836 with self.assertRaises(ValueError) as e:
837 self._DoTestFile('027_pack_4gb_no_size.dts')
838 self.assertIn("Image '/binman': Section size must be provided when "
839 "using end-at-4gb", str(e.exception))
841 def test4gbAndSkipAtStartTogether(self):
842 """Test that the end-at-4gb and skip-at-size property can't be used
844 with self.assertRaises(ValueError) as e:
845 self._DoTestFile('80_4gb_and_skip_at_start_together.dts')
846 self.assertIn("Image '/binman': Provide either 'end-at-4gb' or "
847 "'skip-at-start'", str(e.exception))
849 def testPackX86RomOutside(self):
850 """Test that the end-at-4gb property checks for offset boundaries"""
851 with self.assertRaises(ValueError) as e:
852 self._DoTestFile('028_pack_4gb_outside.dts')
853 self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
854 "the section starting at 0xffffffe0 (4294967264)",
857 def testPackX86Rom(self):
858 """Test that a basic x86 ROM can be created"""
860 data = self._DoReadFile('029_x86-rom.dts')
861 self.assertEqual(U_BOOT_DATA + tools.GetBytes(0, 7) + U_BOOT_SPL_DATA +
862 tools.GetBytes(0, 2), data)
864 def testPackX86RomMeNoDesc(self):
865 """Test that an invalid Intel descriptor entry is detected"""
866 TestFunctional._MakeInputFile('descriptor.bin', b'')
867 with self.assertRaises(ValueError) as e:
868 self._DoTestFile('031_x86-rom-me.dts')
869 self.assertIn("Node '/binman/intel-descriptor': Cannot find Intel Flash Descriptor (FD) signature",
872 def testPackX86RomBadDesc(self):
873 """Test that the Intel requires a descriptor entry"""
874 with self.assertRaises(ValueError) as e:
875 self._DoTestFile('030_x86-rom-me-no-desc.dts')
876 self.assertIn("Node '/binman/intel-me': No offset set with "
877 "offset-unset: should another entry provide this correct "
878 "offset?", str(e.exception))
880 def testPackX86RomMe(self):
881 """Test that an x86 ROM with an ME region can be created"""
882 data = self._DoReadFile('031_x86-rom-me.dts')
883 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
884 if data[:0x1000] != expected_desc:
885 self.fail('Expected descriptor binary at start of image')
886 self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
888 def testPackVga(self):
889 """Test that an image with a VGA binary can be created"""
890 data = self._DoReadFile('032_intel-vga.dts')
891 self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
893 def testPackStart16(self):
894 """Test that an image with an x86 start16 region can be created"""
895 data = self._DoReadFile('033_x86-start16.dts')
896 self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
898 def testPackPowerpcMpc85xxBootpgResetvec(self):
899 """Test that an image with powerpc-mpc85xx-bootpg-resetvec can be
901 data = self._DoReadFile('81_powerpc_mpc85xx_bootpg_resetvec.dts')
902 self.assertEqual(PPC_MPC85XX_BR_DATA, data[:len(PPC_MPC85XX_BR_DATA)])
904 def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False):
905 """Handle running a test for insertion of microcode
908 dts_fname: Name of test .dts file
909 nodtb_data: Data that we expect in the first section
910 ucode_second: True if the microsecond entry is second instead of
915 Contents of first region (U-Boot or SPL)
916 Offset and size components of microcode pointer, as inserted
917 in the above (two 4-byte words)
919 data = self._DoReadFile(dts_fname, True)
921 # Now check the device tree has no microcode
923 ucode_content = data[len(nodtb_data):]
924 ucode_pos = len(nodtb_data)
925 dtb_with_ucode = ucode_content[16:]
926 fdt_len = self.GetFdtLen(dtb_with_ucode)
928 dtb_with_ucode = data[len(nodtb_data):]
929 fdt_len = self.GetFdtLen(dtb_with_ucode)
930 ucode_content = dtb_with_ucode[fdt_len:]
931 ucode_pos = len(nodtb_data) + fdt_len
932 fname = tools.GetOutputFilename('test.dtb')
933 with open(fname, 'wb') as fd:
934 fd.write(dtb_with_ucode)
935 dtb = fdt.FdtScan(fname)
936 ucode = dtb.GetNode('/microcode')
937 self.assertTrue(ucode)
938 for node in ucode.subnodes:
939 self.assertFalse(node.props.get('data'))
941 # Check that the microcode appears immediately after the Fdt
942 # This matches the concatenation of the data properties in
943 # the /microcode/update@xxx nodes in 34_x86_ucode.dts.
944 ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
946 self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
948 # Check that the microcode pointer was inserted. It should match the
949 # expected offset and size
950 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
952 u_boot = data[:len(nodtb_data)]
953 return u_boot, pos_and_size
955 def testPackUbootMicrocode(self):
956 """Test that x86 microcode can be handled correctly
958 We expect to see the following in the image, in order:
959 u-boot-nodtb.bin with a microcode pointer inserted at the correct
961 u-boot.dtb with the microcode removed
964 first, pos_and_size = self._RunMicrocodeTest('034_x86_ucode.dts',
966 self.assertEqual(b'nodtb with microcode' + pos_and_size +
967 b' somewhere in here', first)
969 def _RunPackUbootSingleMicrocode(self):
970 """Test that x86 microcode can be handled correctly
972 We expect to see the following in the image, in order:
973 u-boot-nodtb.bin with a microcode pointer inserted at the correct
975 u-boot.dtb with the microcode
976 an empty microcode region
978 # We need the libfdt library to run this test since only that allows
979 # finding the offset of a property. This is required by
980 # Entry_u_boot_dtb_with_ucode.ObtainContents().
981 data = self._DoReadFile('035_x86_single_ucode.dts', True)
983 second = data[len(U_BOOT_NODTB_DATA):]
985 fdt_len = self.GetFdtLen(second)
986 third = second[fdt_len:]
987 second = second[:fdt_len]
989 ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
990 self.assertIn(ucode_data, second)
991 ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
993 # Check that the microcode pointer was inserted. It should match the
994 # expected offset and size
995 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
997 first = data[:len(U_BOOT_NODTB_DATA)]
998 self.assertEqual(b'nodtb with microcode' + pos_and_size +
999 b' somewhere in here', first)
1001 def testPackUbootSingleMicrocode(self):
1002 """Test that x86 microcode can be handled correctly with fdt_normal.
1004 self._RunPackUbootSingleMicrocode()
1006 def testUBootImg(self):
1007 """Test that u-boot.img can be put in a file"""
1008 data = self._DoReadFile('036_u_boot_img.dts')
1009 self.assertEqual(U_BOOT_IMG_DATA, data)
1011 def testNoMicrocode(self):
1012 """Test that a missing microcode region is detected"""
1013 with self.assertRaises(ValueError) as e:
1014 self._DoReadFile('037_x86_no_ucode.dts', True)
1015 self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
1016 "node found in ", str(e.exception))
1018 def testMicrocodeWithoutNode(self):
1019 """Test that a missing u-boot-dtb-with-ucode node is detected"""
1020 with self.assertRaises(ValueError) as e:
1021 self._DoReadFile('038_x86_ucode_missing_node.dts', True)
1022 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1023 "microcode region u-boot-dtb-with-ucode", str(e.exception))
1025 def testMicrocodeWithoutNode2(self):
1026 """Test that a missing u-boot-ucode node is detected"""
1027 with self.assertRaises(ValueError) as e:
1028 self._DoReadFile('039_x86_ucode_missing_node2.dts', True)
1029 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1030 "microcode region u-boot-ucode", str(e.exception))
1032 def testMicrocodeWithoutPtrInElf(self):
1033 """Test that a U-Boot binary without the microcode symbol is detected"""
1034 # ELF file without a '_dt_ucode_base_size' symbol
1036 with open(self.TestFile('u_boot_no_ucode_ptr'), 'rb') as fd:
1037 TestFunctional._MakeInputFile('u-boot', fd.read())
1039 with self.assertRaises(ValueError) as e:
1040 self._RunPackUbootSingleMicrocode()
1041 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
1042 "_dt_ucode_base_size symbol in u-boot", str(e.exception))
1045 # Put the original file back
1046 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
1047 TestFunctional._MakeInputFile('u-boot', fd.read())
1049 def testMicrocodeNotInImage(self):
1050 """Test that microcode must be placed within the image"""
1051 with self.assertRaises(ValueError) as e:
1052 self._DoReadFile('040_x86_ucode_not_in_image.dts', True)
1053 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
1054 "pointer _dt_ucode_base_size at fffffe14 is outside the "
1055 "section ranging from 00000000 to 0000002e", str(e.exception))
1057 def testWithoutMicrocode(self):
1058 """Test that we can cope with an image without microcode (e.g. qemu)"""
1059 with open(self.TestFile('u_boot_no_ucode_ptr'), 'rb') as fd:
1060 TestFunctional._MakeInputFile('u-boot', fd.read())
1061 data, dtb, _, _ = self._DoReadFileDtb('044_x86_optional_ucode.dts', True)
1063 # Now check the device tree has no microcode
1064 self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
1065 second = data[len(U_BOOT_NODTB_DATA):]
1067 fdt_len = self.GetFdtLen(second)
1068 self.assertEqual(dtb, second[:fdt_len])
1070 used_len = len(U_BOOT_NODTB_DATA) + fdt_len
1071 third = data[used_len:]
1072 self.assertEqual(tools.GetBytes(0, 0x200 - used_len), third)
1074 def testUnknownPosSize(self):
1075 """Test that microcode must be placed within the image"""
1076 with self.assertRaises(ValueError) as e:
1077 self._DoReadFile('041_unknown_pos_size.dts', True)
1078 self.assertIn("Section '/binman': Unable to set offset/size for unknown "
1079 "entry 'invalid-entry'", str(e.exception))
1081 def testPackFsp(self):
1082 """Test that an image with a FSP binary can be created"""
1083 data = self._DoReadFile('042_intel-fsp.dts')
1084 self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
1086 def testPackCmc(self):
1087 """Test that an image with a CMC binary can be created"""
1088 data = self._DoReadFile('043_intel-cmc.dts')
1089 self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
1091 def testPackVbt(self):
1092 """Test that an image with a VBT binary can be created"""
1093 data = self._DoReadFile('046_intel-vbt.dts')
1094 self.assertEqual(VBT_DATA, data[:len(VBT_DATA)])
1096 def testSplBssPad(self):
1097 """Test that we can pad SPL's BSS with zeros"""
1098 # ELF file with a '__bss_size' symbol
1100 data = self._DoReadFile('047_spl_bss_pad.dts')
1101 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0, 10) + U_BOOT_DATA,
1104 def testSplBssPadMissing(self):
1105 """Test that a missing symbol is detected"""
1106 self._SetupSplElf('u_boot_ucode_ptr')
1107 with self.assertRaises(ValueError) as e:
1108 self._DoReadFile('047_spl_bss_pad.dts')
1109 self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
1112 def testPackStart16Spl(self):
1113 """Test that an image with an x86 start16 SPL region can be created"""
1114 data = self._DoReadFile('048_x86-start16-spl.dts')
1115 self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)])
1117 def _PackUbootSplMicrocode(self, dts, ucode_second=False):
1118 """Helper function for microcode tests
1120 We expect to see the following in the image, in order:
1121 u-boot-spl-nodtb.bin with a microcode pointer inserted at the
1123 u-boot.dtb with the microcode removed
1127 dts: Device tree file to use for test
1128 ucode_second: True if the microsecond entry is second instead of
1131 self._SetupSplElf('u_boot_ucode_ptr')
1132 first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA,
1133 ucode_second=ucode_second)
1134 self.assertEqual(b'splnodtb with microc' + pos_and_size +
1135 b'ter somewhere in here', first)
1137 def testPackUbootSplMicrocode(self):
1138 """Test that x86 microcode can be handled correctly in SPL"""
1139 self._PackUbootSplMicrocode('049_x86_ucode_spl.dts')
1141 def testPackUbootSplMicrocodeReorder(self):
1142 """Test that order doesn't matter for microcode entries
1144 This is the same as testPackUbootSplMicrocode but when we process the
1145 u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode
1146 entry, so we reply on binman to try later.
1148 self._PackUbootSplMicrocode('058_x86_ucode_spl_needs_retry.dts',
1151 def testPackMrc(self):
1152 """Test that an image with an MRC binary can be created"""
1153 data = self._DoReadFile('050_intel_mrc.dts')
1154 self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
1156 def testSplDtb(self):
1157 """Test that an image with spl/u-boot-spl.dtb can be created"""
1158 data = self._DoReadFile('051_u_boot_spl_dtb.dts')
1159 self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
1161 def testSplNoDtb(self):
1162 """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
1163 data = self._DoReadFile('052_u_boot_spl_nodtb.dts')
1164 self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
1166 def testSymbols(self):
1167 """Test binman can assign symbols embedded in U-Boot"""
1168 elf_fname = self.TestFile('u_boot_binman_syms')
1169 syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
1170 addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
1171 self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
1173 self._SetupSplElf('u_boot_binman_syms')
1174 data = self._DoReadFile('053_symbols.dts')
1175 sym_values = struct.pack('<LQL', 0x24 + 0, 0x24 + 24, 0x24 + 20)
1176 expected = (sym_values + U_BOOT_SPL_DATA[16:] +
1177 tools.GetBytes(0xff, 1) + U_BOOT_DATA + sym_values +
1178 U_BOOT_SPL_DATA[16:])
1179 self.assertEqual(expected, data)
1181 def testPackUnitAddress(self):
1182 """Test that we support multiple binaries with the same name"""
1183 data = self._DoReadFile('054_unit_address.dts')
1184 self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
1186 def testSections(self):
1187 """Basic test of sections"""
1188 data = self._DoReadFile('055_sections.dts')
1189 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1190 U_BOOT_DATA + tools.GetBytes(ord('a'), 12) +
1191 U_BOOT_DATA + tools.GetBytes(ord('&'), 4))
1192 self.assertEqual(expected, data)
1195 """Tests outputting a map of the images"""
1196 _, _, map_data, _ = self._DoReadFileDtb('055_sections.dts', map=True)
1197 self.assertEqual('''ImagePos Offset Size Name
1198 00000000 00000000 00000028 main-section
1199 00000000 00000000 00000010 section@0
1200 00000000 00000000 00000004 u-boot
1201 00000010 00000010 00000010 section@1
1202 00000010 00000000 00000004 u-boot
1203 00000020 00000020 00000004 section@2
1204 00000020 00000000 00000004 u-boot
1207 def testNamePrefix(self):
1208 """Tests that name prefixes are used"""
1209 _, _, map_data, _ = self._DoReadFileDtb('056_name_prefix.dts', map=True)
1210 self.assertEqual('''ImagePos Offset Size Name
1211 00000000 00000000 00000028 main-section
1212 00000000 00000000 00000010 section@0
1213 00000000 00000000 00000004 ro-u-boot
1214 00000010 00000010 00000010 section@1
1215 00000010 00000000 00000004 rw-u-boot
1218 def testUnknownContents(self):
1219 """Test that obtaining the contents works as expected"""
1220 with self.assertRaises(ValueError) as e:
1221 self._DoReadFile('057_unknown_contents.dts', True)
1222 self.assertIn("Image '/binman': Internal error: Could not complete "
1223 "processing of contents: remaining [<_testing.Entry__testing ",
1226 def testBadChangeSize(self):
1227 """Test that trying to change the size of an entry fails"""
1229 state.SetAllowEntryExpansion(False)
1230 with self.assertRaises(ValueError) as e:
1231 self._DoReadFile('059_change_size.dts', True)
1232 self.assertIn("Node '/binman/_testing': Cannot update entry size from 1 to 2",
1235 state.SetAllowEntryExpansion(True)
1237 def testUpdateFdt(self):
1238 """Test that we can update the device tree with offset/size info"""
1239 _, _, _, out_dtb_fname = self._DoReadFileDtb('060_fdt_update.dts',
1241 dtb = fdt.Fdt(out_dtb_fname)
1243 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'])
1247 '_testing:offset': 32,
1249 '_testing:image-pos': 32,
1250 'section@0/u-boot:offset': 0,
1251 'section@0/u-boot:size': len(U_BOOT_DATA),
1252 'section@0/u-boot:image-pos': 0,
1253 'section@0:offset': 0,
1254 'section@0:size': 16,
1255 'section@0:image-pos': 0,
1257 'section@1/u-boot:offset': 0,
1258 'section@1/u-boot:size': len(U_BOOT_DATA),
1259 'section@1/u-boot:image-pos': 16,
1260 'section@1:offset': 16,
1261 'section@1:size': 16,
1262 'section@1:image-pos': 16,
1266 def testUpdateFdtBad(self):
1267 """Test that we detect when ProcessFdt never completes"""
1268 with self.assertRaises(ValueError) as e:
1269 self._DoReadFileDtb('061_fdt_update_bad.dts', update_dtb=True)
1270 self.assertIn('Could not complete processing of Fdt: remaining '
1271 '[<_testing.Entry__testing', str(e.exception))
1273 def testEntryArgs(self):
1274 """Test passing arguments to entries from the command line"""
1276 'test-str-arg': 'test1',
1277 'test-int-arg': '456',
1279 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
1280 self.assertIn('image', control.images)
1281 entry = control.images['image'].GetEntries()['_testing']
1282 self.assertEqual('test0', entry.test_str_fdt)
1283 self.assertEqual('test1', entry.test_str_arg)
1284 self.assertEqual(123, entry.test_int_fdt)
1285 self.assertEqual(456, entry.test_int_arg)
1287 def testEntryArgsMissing(self):
1288 """Test missing arguments and properties"""
1290 'test-int-arg': '456',
1292 self._DoReadFileDtb('063_entry_args_missing.dts', entry_args=entry_args)
1293 entry = control.images['image'].GetEntries()['_testing']
1294 self.assertEqual('test0', entry.test_str_fdt)
1295 self.assertEqual(None, entry.test_str_arg)
1296 self.assertEqual(None, entry.test_int_fdt)
1297 self.assertEqual(456, entry.test_int_arg)
1299 def testEntryArgsRequired(self):
1300 """Test missing arguments and properties"""
1302 'test-int-arg': '456',
1304 with self.assertRaises(ValueError) as e:
1305 self._DoReadFileDtb('064_entry_args_required.dts')
1306 self.assertIn("Node '/binman/_testing': Missing required "
1307 'properties/entry args: test-str-arg, test-int-fdt, test-int-arg',
1310 def testEntryArgsInvalidFormat(self):
1311 """Test that an invalid entry-argument format is detected"""
1312 args = ['build', '-d', self.TestFile('064_entry_args_required.dts'),
1314 with self.assertRaises(ValueError) as e:
1315 self._DoBinman(*args)
1316 self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
1318 def testEntryArgsInvalidInteger(self):
1319 """Test that an invalid entry-argument integer is detected"""
1321 'test-int-arg': 'abc',
1323 with self.assertRaises(ValueError) as e:
1324 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
1325 self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
1326 "'test-int-arg' (value 'abc') to integer",
1329 def testEntryArgsInvalidDatatype(self):
1330 """Test that an invalid entry-argument datatype is detected
1332 This test could be written in entry_test.py except that it needs
1333 access to control.entry_args, which seems more than that module should
1337 'test-bad-datatype-arg': '12',
1339 with self.assertRaises(ValueError) as e:
1340 self._DoReadFileDtb('065_entry_args_unknown_datatype.dts',
1341 entry_args=entry_args)
1342 self.assertIn('GetArg() internal error: Unknown data type ',
1346 """Test for a text entry type"""
1348 'test-id': TEXT_DATA,
1349 'test-id2': TEXT_DATA2,
1350 'test-id3': TEXT_DATA3,
1352 data, _, _, _ = self._DoReadFileDtb('066_text.dts',
1353 entry_args=entry_args)
1354 expected = (tools.ToBytes(TEXT_DATA) +
1355 tools.GetBytes(0, 8 - len(TEXT_DATA)) +
1356 tools.ToBytes(TEXT_DATA2) + tools.ToBytes(TEXT_DATA3) +
1357 b'some text' + b'more text')
1358 self.assertEqual(expected, data)
1360 def testEntryDocs(self):
1361 """Test for creation of entry documentation"""
1362 with test_util.capture_sys_output() as (stdout, stderr):
1363 control.WriteEntryDocs(binman.GetEntryModules())
1364 self.assertTrue(len(stdout.getvalue()) > 0)
1366 def testEntryDocsMissing(self):
1367 """Test handling of missing entry documentation"""
1368 with self.assertRaises(ValueError) as e:
1369 with test_util.capture_sys_output() as (stdout, stderr):
1370 control.WriteEntryDocs(binman.GetEntryModules(), 'u_boot')
1371 self.assertIn('Documentation is missing for modules: u_boot',
1375 """Basic test of generation of a flashrom fmap"""
1376 data = self._DoReadFile('067_fmap.dts')
1377 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1378 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1379 U_BOOT_DATA + tools.GetBytes(ord('a'), 12))
1380 self.assertEqual(expected, data[:32])
1381 self.assertEqual(b'__FMAP__', fhdr.signature)
1382 self.assertEqual(1, fhdr.ver_major)
1383 self.assertEqual(0, fhdr.ver_minor)
1384 self.assertEqual(0, fhdr.base)
1385 self.assertEqual(16 + 16 +
1386 fmap_util.FMAP_HEADER_LEN +
1387 fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
1388 self.assertEqual(b'FMAP', fhdr.name)
1389 self.assertEqual(3, fhdr.nareas)
1390 for fentry in fentries:
1391 self.assertEqual(0, fentry.flags)
1393 self.assertEqual(0, fentries[0].offset)
1394 self.assertEqual(4, fentries[0].size)
1395 self.assertEqual(b'RO_U_BOOT', fentries[0].name)
1397 self.assertEqual(16, fentries[1].offset)
1398 self.assertEqual(4, fentries[1].size)
1399 self.assertEqual(b'RW_U_BOOT', fentries[1].name)
1401 self.assertEqual(32, fentries[2].offset)
1402 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1403 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1404 self.assertEqual(b'FMAP', fentries[2].name)
1406 def testBlobNamedByArg(self):
1407 """Test we can add a blob with the filename coming from an entry arg"""
1409 'cros-ec-rw-path': 'ecrw.bin',
1411 data, _, _, _ = self._DoReadFileDtb('068_blob_named_by_arg.dts',
1412 entry_args=entry_args)
1415 """Test for an fill entry type"""
1416 data = self._DoReadFile('069_fill.dts')
1417 expected = tools.GetBytes(0xff, 8) + tools.GetBytes(0, 8)
1418 self.assertEqual(expected, data)
1420 def testFillNoSize(self):
1421 """Test for an fill entry type with no size"""
1422 with self.assertRaises(ValueError) as e:
1423 self._DoReadFile('070_fill_no_size.dts')
1424 self.assertIn("'fill' entry must have a size property",
1427 def _HandleGbbCommand(self, pipe_list):
1428 """Fake calls to the futility utility"""
1429 if pipe_list[0][0] == 'futility':
1430 fname = pipe_list[0][-1]
1431 # Append our GBB data to the file, which will happen every time the
1432 # futility command is called.
1433 with open(fname, 'ab') as fd:
1435 return command.CommandResult()
1438 """Test for the Chromium OS Google Binary Block"""
1439 command.test_result = self._HandleGbbCommand
1441 'keydir': 'devkeys',
1442 'bmpblk': 'bmpblk.bin',
1444 data, _, _, _ = self._DoReadFileDtb('071_gbb.dts', entry_args=entry_args)
1447 expected = (GBB_DATA + GBB_DATA + tools.GetBytes(0, 8) +
1448 tools.GetBytes(0, 0x2180 - 16))
1449 self.assertEqual(expected, data)
1451 def testGbbTooSmall(self):
1452 """Test for the Chromium OS Google Binary Block being large enough"""
1453 with self.assertRaises(ValueError) as e:
1454 self._DoReadFileDtb('072_gbb_too_small.dts')
1455 self.assertIn("Node '/binman/gbb': GBB is too small",
1458 def testGbbNoSize(self):
1459 """Test for the Chromium OS Google Binary Block having a size"""
1460 with self.assertRaises(ValueError) as e:
1461 self._DoReadFileDtb('073_gbb_no_size.dts')
1462 self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
1465 def _HandleVblockCommand(self, pipe_list):
1466 """Fake calls to the futility utility"""
1467 if pipe_list[0][0] == 'futility':
1468 fname = pipe_list[0][3]
1469 with open(fname, 'wb') as fd:
1470 fd.write(VBLOCK_DATA)
1471 return command.CommandResult()
1473 def testVblock(self):
1474 """Test for the Chromium OS Verified Boot Block"""
1475 command.test_result = self._HandleVblockCommand
1477 'keydir': 'devkeys',
1479 data, _, _, _ = self._DoReadFileDtb('074_vblock.dts',
1480 entry_args=entry_args)
1481 expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
1482 self.assertEqual(expected, data)
1484 def testVblockNoContent(self):
1485 """Test we detect a vblock which has no content to sign"""
1486 with self.assertRaises(ValueError) as e:
1487 self._DoReadFile('075_vblock_no_content.dts')
1488 self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
1489 'property', str(e.exception))
1491 def testVblockBadPhandle(self):
1492 """Test that we detect a vblock with an invalid phandle in contents"""
1493 with self.assertRaises(ValueError) as e:
1494 self._DoReadFile('076_vblock_bad_phandle.dts')
1495 self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
1496 '1000', str(e.exception))
1498 def testVblockBadEntry(self):
1499 """Test that we detect an entry that points to a non-entry"""
1500 with self.assertRaises(ValueError) as e:
1501 self._DoReadFile('077_vblock_bad_entry.dts')
1502 self.assertIn("Node '/binman/vblock': Cannot find entry for node "
1503 "'other'", str(e.exception))
1506 """Test that an image with TPL and ots device tree can be created"""
1507 # ELF file with a '__bss_size' symbol
1508 with open(self.TestFile('bss_data'), 'rb') as fd:
1509 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1510 data = self._DoReadFile('078_u_boot_tpl.dts')
1511 self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
1513 def testUsesPos(self):
1514 """Test that the 'pos' property cannot be used anymore"""
1515 with self.assertRaises(ValueError) as e:
1516 data = self._DoReadFile('079_uses_pos.dts')
1517 self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
1518 "'pos'", str(e.exception))
1520 def testFillZero(self):
1521 """Test for an fill entry type with a size of 0"""
1522 data = self._DoReadFile('080_fill_empty.dts')
1523 self.assertEqual(tools.GetBytes(0, 16), data)
1525 def testTextMissing(self):
1526 """Test for a text entry type where there is no text"""
1527 with self.assertRaises(ValueError) as e:
1528 self._DoReadFileDtb('066_text.dts',)
1529 self.assertIn("Node '/binman/text': No value provided for text label "
1530 "'test-id'", str(e.exception))
1532 def testPackStart16Tpl(self):
1533 """Test that an image with an x86 start16 TPL region can be created"""
1534 data = self._DoReadFile('081_x86-start16-tpl.dts')
1535 self.assertEqual(X86_START16_TPL_DATA, data[:len(X86_START16_TPL_DATA)])
1537 def testSelectImage(self):
1538 """Test that we can select which images to build"""
1539 expected = 'Skipping images: image1'
1541 # We should only get the expected message in verbose mode
1542 for verbosity in (0, 2):
1543 with test_util.capture_sys_output() as (stdout, stderr):
1544 retcode = self._DoTestFile('006_dual_image.dts',
1545 verbosity=verbosity,
1547 self.assertEqual(0, retcode)
1549 self.assertIn(expected, stdout.getvalue())
1551 self.assertNotIn(expected, stdout.getvalue())
1553 self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
1554 self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
1556 def testUpdateFdtAll(self):
1557 """Test that all device trees are updated with offset/size info"""
1558 data = self._DoReadFileRealDtb('082_fdt_update_all.dts')
1561 'section:image-pos': 0,
1562 'u-boot-tpl-dtb:size': 513,
1563 'u-boot-spl-dtb:size': 513,
1564 'u-boot-spl-dtb:offset': 493,
1566 'section/u-boot-dtb:image-pos': 0,
1567 'u-boot-spl-dtb:image-pos': 493,
1568 'section/u-boot-dtb:size': 493,
1569 'u-boot-tpl-dtb:image-pos': 1006,
1570 'section/u-boot-dtb:offset': 0,
1571 'section:size': 493,
1573 'section:offset': 0,
1574 'u-boot-tpl-dtb:offset': 1006,
1578 # We expect three device-tree files in the output, one after the other.
1579 # Read them in sequence. We look for an 'spl' property in the SPL tree,
1580 # and 'tpl' in the TPL tree, to make sure they are distinct from the
1581 # main U-Boot tree. All three should have the same postions and offset.
1583 for item in ['', 'spl', 'tpl']:
1584 dtb = fdt.Fdt.FromData(data[start:])
1586 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos',
1588 expected = dict(base_expected)
1591 self.assertEqual(expected, props)
1592 start += dtb._fdt_obj.totalsize()
1594 def testUpdateFdtOutput(self):
1595 """Test that output DTB files are updated"""
1597 data, dtb_data, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
1598 use_real_dtb=True, update_dtb=True, reset_dtbs=False)
1600 # Unfortunately, compiling a source file always results in a file
1601 # called source.dtb (see fdt_util.EnsureCompiled()). The test
1602 # source file (e.g. test/075_fdt_update_all.dts) thus does not enter
1603 # binman as a file called u-boot.dtb. To fix this, copy the file
1604 # over to the expected place.
1605 #tools.WriteFile(os.path.join(self._indir, 'u-boot.dtb'),
1606 #tools.ReadFile(tools.GetOutputFilename('source.dtb')))
1608 for fname in ['u-boot.dtb.out', 'spl/u-boot-spl.dtb.out',
1609 'tpl/u-boot-tpl.dtb.out']:
1610 dtb = fdt.Fdt.FromData(data[start:])
1611 size = dtb._fdt_obj.totalsize()
1612 pathname = tools.GetOutputFilename(os.path.split(fname)[1])
1613 outdata = tools.ReadFile(pathname)
1614 name = os.path.split(fname)[0]
1617 orig_indata = self._GetDtbContentsForSplTpl(dtb_data, name)
1619 orig_indata = dtb_data
1620 self.assertNotEqual(outdata, orig_indata,
1621 "Expected output file '%s' be updated" % pathname)
1622 self.assertEqual(outdata, data[start:start + size],
1623 "Expected output file '%s' to match output image" %
1629 def _decompress(self, data):
1630 return tools.Decompress(data, 'lz4')
1632 def testCompress(self):
1633 """Test compression of blobs"""
1635 data, _, _, out_dtb_fname = self._DoReadFileDtb('083_compress.dts',
1636 use_real_dtb=True, update_dtb=True)
1637 dtb = fdt.Fdt(out_dtb_fname)
1639 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
1640 orig = self._decompress(data)
1641 self.assertEquals(COMPRESS_DATA, orig)
1643 'blob:uncomp-size': len(COMPRESS_DATA),
1644 'blob:size': len(data),
1647 self.assertEqual(expected, props)
1649 def testFiles(self):
1650 """Test bringing in multiple files"""
1651 data = self._DoReadFile('084_files.dts')
1652 self.assertEqual(FILES_DATA, data)
1654 def testFilesCompress(self):
1655 """Test bringing in multiple files and compressing them"""
1657 data = self._DoReadFile('085_files_compress.dts')
1659 image = control.images['image']
1660 entries = image.GetEntries()
1661 files = entries['files']
1662 entries = files._entries
1665 for i in range(1, 3):
1667 start = entries[key].image_pos
1668 len = entries[key].size
1669 chunk = data[start:start + len]
1670 orig += self._decompress(chunk)
1672 self.assertEqual(FILES_DATA, orig)
1674 def testFilesMissing(self):
1675 """Test missing files"""
1676 with self.assertRaises(ValueError) as e:
1677 data = self._DoReadFile('086_files_none.dts')
1678 self.assertIn("Node '/binman/files': Pattern \'files/*.none\' matched "
1679 'no files', str(e.exception))
1681 def testFilesNoPattern(self):
1682 """Test missing files"""
1683 with self.assertRaises(ValueError) as e:
1684 data = self._DoReadFile('087_files_no_pattern.dts')
1685 self.assertIn("Node '/binman/files': Missing 'pattern' property",
1688 def testExpandSize(self):
1689 """Test an expanding entry"""
1690 data, _, map_data, _ = self._DoReadFileDtb('088_expand_size.dts',
1692 expect = (tools.GetBytes(ord('a'), 8) + U_BOOT_DATA +
1693 MRC_DATA + tools.GetBytes(ord('b'), 1) + U_BOOT_DATA +
1694 tools.GetBytes(ord('c'), 8) + U_BOOT_DATA +
1695 tools.GetBytes(ord('d'), 8))
1696 self.assertEqual(expect, data)
1697 self.assertEqual('''ImagePos Offset Size Name
1698 00000000 00000000 00000028 main-section
1699 00000000 00000000 00000008 fill
1700 00000008 00000008 00000004 u-boot
1701 0000000c 0000000c 00000004 section
1702 0000000c 00000000 00000003 intel-mrc
1703 00000010 00000010 00000004 u-boot2
1704 00000014 00000014 0000000c section2
1705 00000014 00000000 00000008 fill
1706 0000001c 00000008 00000004 u-boot
1707 00000020 00000020 00000008 fill2
1710 def testExpandSizeBad(self):
1711 """Test an expanding entry which fails to provide contents"""
1712 with test_util.capture_sys_output() as (stdout, stderr):
1713 with self.assertRaises(ValueError) as e:
1714 self._DoReadFileDtb('089_expand_size_bad.dts', map=True)
1715 self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
1716 'expanding entry', str(e.exception))
1719 """Test hashing of the contents of an entry"""
1720 _, _, _, out_dtb_fname = self._DoReadFileDtb('090_hash.dts',
1721 use_real_dtb=True, update_dtb=True)
1722 dtb = fdt.Fdt(out_dtb_fname)
1724 hash_node = dtb.GetNode('/binman/u-boot/hash').props['value']
1725 m = hashlib.sha256()
1726 m.update(U_BOOT_DATA)
1727 self.assertEqual(m.digest(), b''.join(hash_node.value))
1729 def testHashNoAlgo(self):
1730 with self.assertRaises(ValueError) as e:
1731 self._DoReadFileDtb('091_hash_no_algo.dts', update_dtb=True)
1732 self.assertIn("Node \'/binman/u-boot\': Missing \'algo\' property for "
1733 'hash node', str(e.exception))
1735 def testHashBadAlgo(self):
1736 with self.assertRaises(ValueError) as e:
1737 self._DoReadFileDtb('092_hash_bad_algo.dts', update_dtb=True)
1738 self.assertIn("Node '/binman/u-boot': Unknown hash algorithm",
1741 def testHashSection(self):
1742 """Test hashing of the contents of an entry"""
1743 _, _, _, out_dtb_fname = self._DoReadFileDtb('099_hash_section.dts',
1744 use_real_dtb=True, update_dtb=True)
1745 dtb = fdt.Fdt(out_dtb_fname)
1747 hash_node = dtb.GetNode('/binman/section/hash').props['value']
1748 m = hashlib.sha256()
1749 m.update(U_BOOT_DATA)
1750 m.update(tools.GetBytes(ord('a'), 16))
1751 self.assertEqual(m.digest(), b''.join(hash_node.value))
1753 def testPackUBootTplMicrocode(self):
1754 """Test that x86 microcode can be handled correctly in TPL
1756 We expect to see the following in the image, in order:
1757 u-boot-tpl-nodtb.bin with a microcode pointer inserted at the correct
1759 u-boot-tpl.dtb with the microcode removed
1762 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
1763 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1764 first, pos_and_size = self._RunMicrocodeTest('093_x86_tpl_ucode.dts',
1765 U_BOOT_TPL_NODTB_DATA)
1766 self.assertEqual(b'tplnodtb with microc' + pos_and_size +
1767 b'ter somewhere in here', first)
1769 def testFmapX86(self):
1770 """Basic test of generation of a flashrom fmap"""
1771 data = self._DoReadFile('094_fmap_x86.dts')
1772 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1773 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('a'), 32 - 7)
1774 self.assertEqual(expected, data[:32])
1775 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1777 self.assertEqual(0x100, fhdr.image_size)
1779 self.assertEqual(0, fentries[0].offset)
1780 self.assertEqual(4, fentries[0].size)
1781 self.assertEqual(b'U_BOOT', fentries[0].name)
1783 self.assertEqual(4, fentries[1].offset)
1784 self.assertEqual(3, fentries[1].size)
1785 self.assertEqual(b'INTEL_MRC', fentries[1].name)
1787 self.assertEqual(32, fentries[2].offset)
1788 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1789 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1790 self.assertEqual(b'FMAP', fentries[2].name)
1792 def testFmapX86Section(self):
1793 """Basic test of generation of a flashrom fmap"""
1794 data = self._DoReadFile('095_fmap_x86_section.dts')
1795 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('b'), 32 - 7)
1796 self.assertEqual(expected, data[:32])
1797 fhdr, fentries = fmap_util.DecodeFmap(data[36:])
1799 self.assertEqual(0x100, fhdr.image_size)
1801 self.assertEqual(0, fentries[0].offset)
1802 self.assertEqual(4, fentries[0].size)
1803 self.assertEqual(b'U_BOOT', fentries[0].name)
1805 self.assertEqual(4, fentries[1].offset)
1806 self.assertEqual(3, fentries[1].size)
1807 self.assertEqual(b'INTEL_MRC', fentries[1].name)
1809 self.assertEqual(36, fentries[2].offset)
1810 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1811 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1812 self.assertEqual(b'FMAP', fentries[2].name)
1815 """Basic test of ELF entries"""
1817 with open(self.TestFile('bss_data'), 'rb') as fd:
1818 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1819 with open(self.TestFile('bss_data'), 'rb') as fd:
1820 TestFunctional._MakeInputFile('-boot', fd.read())
1821 data = self._DoReadFile('096_elf.dts')
1823 def testElfStrip(self):
1824 """Basic test of ELF entries"""
1826 with open(self.TestFile('bss_data'), 'rb') as fd:
1827 TestFunctional._MakeInputFile('-boot', fd.read())
1828 data = self._DoReadFile('097_elf_strip.dts')
1830 def testPackOverlapMap(self):
1831 """Test that overlapping regions are detected"""
1832 with test_util.capture_sys_output() as (stdout, stderr):
1833 with self.assertRaises(ValueError) as e:
1834 self._DoTestFile('014_pack_overlap.dts', map=True)
1835 map_fname = tools.GetOutputFilename('image.map')
1836 self.assertEqual("Wrote map file '%s' to show errors\n" % map_fname,
1839 # We should not get an inmage, but there should be a map file
1840 self.assertFalse(os.path.exists(tools.GetOutputFilename('image.bin')))
1841 self.assertTrue(os.path.exists(map_fname))
1842 map_data = tools.ReadFile(map_fname, binary=False)
1843 self.assertEqual('''ImagePos Offset Size Name
1844 <none> 00000000 00000007 main-section
1845 <none> 00000000 00000004 u-boot
1846 <none> 00000003 00000004 u-boot-align
1849 def testPackRefCode(self):
1850 """Test that an image with an Intel Reference code binary works"""
1851 data = self._DoReadFile('100_intel_refcode.dts')
1852 self.assertEqual(REFCODE_DATA, data[:len(REFCODE_DATA)])
1854 def testSectionOffset(self):
1855 """Tests use of a section with an offset"""
1856 data, _, map_data, _ = self._DoReadFileDtb('101_sections_offset.dts',
1858 self.assertEqual('''ImagePos Offset Size Name
1859 00000000 00000000 00000038 main-section
1860 00000004 00000004 00000010 section@0
1861 00000004 00000000 00000004 u-boot
1862 00000018 00000018 00000010 section@1
1863 00000018 00000000 00000004 u-boot
1864 0000002c 0000002c 00000004 section@2
1865 0000002c 00000000 00000004 u-boot
1867 self.assertEqual(data,
1868 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1869 tools.GetBytes(0x21, 12) +
1870 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1871 tools.GetBytes(0x61, 12) +
1872 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1873 tools.GetBytes(0x26, 8))
1875 def testCbfsRaw(self):
1876 """Test base handling of a Coreboot Filesystem (CBFS)
1878 The exact contents of the CBFS is verified by similar tests in
1879 cbfs_util_test.py. The tests here merely check that the files added to
1880 the CBFS can be found in the final image.
1882 data = self._DoReadFile('102_cbfs_raw.dts')
1885 cbfs = cbfs_util.CbfsReader(data)
1886 self.assertEqual(size, cbfs.rom_size)
1888 self.assertIn('u-boot-dtb', cbfs.files)
1889 cfile = cbfs.files['u-boot-dtb']
1890 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
1892 def testCbfsArch(self):
1893 """Test on non-x86 architecture"""
1894 data = self._DoReadFile('103_cbfs_raw_ppc.dts')
1897 cbfs = cbfs_util.CbfsReader(data)
1898 self.assertEqual(size, cbfs.rom_size)
1900 self.assertIn('u-boot-dtb', cbfs.files)
1901 cfile = cbfs.files['u-boot-dtb']
1902 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
1904 def testCbfsStage(self):
1905 """Tests handling of a Coreboot Filesystem (CBFS)"""
1906 if not elf.ELF_TOOLS:
1907 self.skipTest('Python elftools not available')
1908 elf_fname = os.path.join(self._indir, 'cbfs-stage.elf')
1909 elf.MakeElf(elf_fname, U_BOOT_DATA, U_BOOT_DTB_DATA)
1912 data = self._DoReadFile('104_cbfs_stage.dts')
1913 cbfs = cbfs_util.CbfsReader(data)
1914 self.assertEqual(size, cbfs.rom_size)
1916 self.assertIn('u-boot', cbfs.files)
1917 cfile = cbfs.files['u-boot']
1918 self.assertEqual(U_BOOT_DATA + U_BOOT_DTB_DATA, cfile.data)
1920 def testCbfsRawCompress(self):
1921 """Test handling of compressing raw files"""
1923 data = self._DoReadFile('105_cbfs_raw_compress.dts')
1926 cbfs = cbfs_util.CbfsReader(data)
1927 self.assertIn('u-boot', cbfs.files)
1928 cfile = cbfs.files['u-boot']
1929 self.assertEqual(COMPRESS_DATA, cfile.data)
1931 def testCbfsBadArch(self):
1932 """Test handling of a bad architecture"""
1933 with self.assertRaises(ValueError) as e:
1934 self._DoReadFile('106_cbfs_bad_arch.dts')
1935 self.assertIn("Invalid architecture 'bad-arch'", str(e.exception))
1937 def testCbfsNoSize(self):
1938 """Test handling of a missing size property"""
1939 with self.assertRaises(ValueError) as e:
1940 self._DoReadFile('107_cbfs_no_size.dts')
1941 self.assertIn('entry must have a size property', str(e.exception))
1943 def testCbfsNoCOntents(self):
1944 """Test handling of a CBFS entry which does not provide contentsy"""
1945 with self.assertRaises(ValueError) as e:
1946 self._DoReadFile('108_cbfs_no_contents.dts')
1947 self.assertIn('Could not complete processing of contents',
1950 def testCbfsBadCompress(self):
1951 """Test handling of a bad architecture"""
1952 with self.assertRaises(ValueError) as e:
1953 self._DoReadFile('109_cbfs_bad_compress.dts')
1954 self.assertIn("Invalid compression in 'u-boot': 'invalid-algo'",
1957 def testCbfsNamedEntries(self):
1958 """Test handling of named entries"""
1959 data = self._DoReadFile('110_cbfs_name.dts')
1961 cbfs = cbfs_util.CbfsReader(data)
1962 self.assertIn('FRED', cbfs.files)
1963 cfile1 = cbfs.files['FRED']
1964 self.assertEqual(U_BOOT_DATA, cfile1.data)
1966 self.assertIn('hello', cbfs.files)
1967 cfile2 = cbfs.files['hello']
1968 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
1970 def _SetupIfwi(self, fname):
1971 """Set up to run an IFWI test
1974 fname: Filename of input file to provide (fitimage.bin or ifwi.bin)
1978 # Intel Integrated Firmware Image (IFWI) file
1979 with gzip.open(self.TestFile('%s.gz' % fname), 'rb') as fd:
1981 TestFunctional._MakeInputFile(fname,data)
1983 def _CheckIfwi(self, data):
1984 """Check that an image with an IFWI contains the correct output
1987 data: Conents of output file
1989 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
1990 if data[:0x1000] != expected_desc:
1991 self.fail('Expected descriptor binary at start of image')
1993 # We expect to find the TPL wil in subpart IBBP entry IBBL
1994 image_fname = tools.GetOutputFilename('image.bin')
1995 tpl_fname = tools.GetOutputFilename('tpl.out')
1996 tools.RunIfwiTool(image_fname, tools.CMD_EXTRACT, fname=tpl_fname,
1997 subpart='IBBP', entry_name='IBBL')
1999 tpl_data = tools.ReadFile(tpl_fname)
2000 self.assertEqual(tpl_data[:len(U_BOOT_TPL_DATA)], U_BOOT_TPL_DATA)
2002 def testPackX86RomIfwi(self):
2003 """Test that an x86 ROM with Integrated Firmware Image can be created"""
2004 self._SetupIfwi('fitimage.bin')
2005 data = self._DoReadFile('111_x86-rom-ifwi.dts')
2006 self._CheckIfwi(data)
2008 def testPackX86RomIfwiNoDesc(self):
2009 """Test that an x86 ROM with IFWI can be created from an ifwi.bin file"""
2010 self._SetupIfwi('ifwi.bin')
2011 data = self._DoReadFile('112_x86-rom-ifwi-nodesc.dts')
2012 self._CheckIfwi(data)
2014 def testPackX86RomIfwiNoData(self):
2015 """Test that an x86 ROM with IFWI handles missing data"""
2016 self._SetupIfwi('ifwi.bin')
2017 with self.assertRaises(ValueError) as e:
2018 data = self._DoReadFile('113_x86-rom-ifwi-nodata.dts')
2019 self.assertIn('Could not complete processing of contents',
2022 def testCbfsOffset(self):
2023 """Test a CBFS with files at particular offsets
2025 Like all CFBS tests, this is just checking the logic that calls
2026 cbfs_util. See cbfs_util_test for fully tests (e.g. test_cbfs_offset()).
2028 data = self._DoReadFile('114_cbfs_offset.dts')
2031 cbfs = cbfs_util.CbfsReader(data)
2032 self.assertEqual(size, cbfs.rom_size)
2034 self.assertIn('u-boot', cbfs.files)
2035 cfile = cbfs.files['u-boot']
2036 self.assertEqual(U_BOOT_DATA, cfile.data)
2037 self.assertEqual(0x40, cfile.cbfs_offset)
2039 self.assertIn('u-boot-dtb', cbfs.files)
2040 cfile2 = cbfs.files['u-boot-dtb']
2041 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
2042 self.assertEqual(0x140, cfile2.cbfs_offset)
2044 def testFdtmap(self):
2045 """Test an FDT map can be inserted in the image"""
2046 data = self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
2047 fdtmap_data = data[len(U_BOOT_DATA):]
2048 magic = fdtmap_data[:8]
2049 self.assertEqual('_FDTMAP_', magic)
2050 self.assertEqual(tools.GetBytes(0, 8), fdtmap_data[8:16])
2052 fdt_data = fdtmap_data[16:]
2053 dtb = fdt.Fdt.FromData(fdt_data)
2055 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'],
2061 'u-boot:size': len(U_BOOT_DATA),
2062 'u-boot:image-pos': 0,
2063 'fdtmap:image-pos': 4,
2065 'fdtmap:size': len(fdtmap_data),
2069 def testFdtmapNoMatch(self):
2070 """Check handling of an FDT map when the section cannot be found"""
2071 self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
2073 # Mangle the section name, which should cause a mismatch between the
2074 # correct FDT path and the one expected by the section
2075 image = control.images['image']
2076 image._node.path += '-suffix'
2077 entries = image.GetEntries()
2078 fdtmap = entries['fdtmap']
2079 with self.assertRaises(ValueError) as e:
2081 self.assertIn("Cannot locate node for path '/binman-suffix'",
2084 def testFdtmapHeader(self):
2085 """Test an FDT map and image header can be inserted in the image"""
2086 data = self.data = self._DoReadFileRealDtb('116_fdtmap_hdr.dts')
2087 fdtmap_pos = len(U_BOOT_DATA)
2088 fdtmap_data = data[fdtmap_pos:]
2089 fdt_data = fdtmap_data[16:]
2090 dtb = fdt.Fdt.FromData(fdt_data)
2091 fdt_size = dtb.GetFdtObj().totalsize()
2092 hdr_data = data[-8:]
2093 self.assertEqual('BinM', hdr_data[:4])
2094 offset = struct.unpack('<I', hdr_data[4:])[0] & 0xffffffff
2095 self.assertEqual(fdtmap_pos - 0x400, offset - (1 << 32))
2097 def testFdtmapHeaderStart(self):
2098 """Test an image header can be inserted at the image start"""
2099 data = self.data = self._DoReadFileRealDtb('117_fdtmap_hdr_start.dts')
2100 fdtmap_pos = 0x100 + len(U_BOOT_DATA)
2102 self.assertEqual('BinM', hdr_data[:4])
2103 offset = struct.unpack('<I', hdr_data[4:])[0]
2104 self.assertEqual(fdtmap_pos, offset)
2106 def testFdtmapHeaderPos(self):
2107 """Test an image header can be inserted at a chosen position"""
2108 data = self.data = self._DoReadFileRealDtb('118_fdtmap_hdr_pos.dts')
2109 fdtmap_pos = 0x100 + len(U_BOOT_DATA)
2110 hdr_data = data[0x80:0x88]
2111 self.assertEqual('BinM', hdr_data[:4])
2112 offset = struct.unpack('<I', hdr_data[4:])[0]
2113 self.assertEqual(fdtmap_pos, offset)
2115 def testHeaderMissingFdtmap(self):
2116 """Test an image header requires an fdtmap"""
2117 with self.assertRaises(ValueError) as e:
2118 self.data = self._DoReadFileRealDtb('119_fdtmap_hdr_missing.dts')
2119 self.assertIn("'image_header' section must have an 'fdtmap' sibling",
2122 def testHeaderNoLocation(self):
2123 """Test an image header with a no specified location is detected"""
2124 with self.assertRaises(ValueError) as e:
2125 self.data = self._DoReadFileRealDtb('120_hdr_no_location.dts')
2126 self.assertIn("Invalid location 'None', expected 'start' or 'end'",
2129 def testEntryExpand(self):
2130 """Test expanding an entry after it is packed"""
2131 data = self._DoReadFile('121_entry_expand.dts')
2132 self.assertEqual(b'aa', data[:2])
2133 self.assertEqual(U_BOOT_DATA, data[2:2 + len(U_BOOT_DATA)])
2134 self.assertEqual(b'aa', data[-2:])
2136 def testEntryExpandBad(self):
2137 """Test expanding an entry after it is packed, twice"""
2138 with self.assertRaises(ValueError) as e:
2139 self._DoReadFile('122_entry_expand_twice.dts')
2140 self.assertIn("Image '/binman': Entries expanded after packing",
2143 def testEntryExpandSection(self):
2144 """Test expanding an entry within a section after it is packed"""
2145 data = self._DoReadFile('123_entry_expand_section.dts')
2146 self.assertEqual(b'aa', data[:2])
2147 self.assertEqual(U_BOOT_DATA, data[2:2 + len(U_BOOT_DATA)])
2148 self.assertEqual(b'aa', data[-2:])
2150 def testCompressDtb(self):
2151 """Test that compress of device-tree files is supported"""
2153 data = self.data = self._DoReadFileRealDtb('124_compress_dtb.dts')
2154 self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
2155 comp_data = data[len(U_BOOT_DATA):]
2156 orig = self._decompress(comp_data)
2157 dtb = fdt.Fdt.FromData(orig)
2159 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
2161 'u-boot:size': len(U_BOOT_DATA),
2162 'u-boot-dtb:uncomp-size': len(orig),
2163 'u-boot-dtb:size': len(comp_data),
2166 self.assertEqual(expected, props)
2168 def testCbfsUpdateFdt(self):
2169 """Test that we can update the device tree with CBFS offset/size info"""
2171 data, _, _, out_dtb_fname = self._DoReadFileDtb('125_cbfs_update.dts',
2173 dtb = fdt.Fdt(out_dtb_fname)
2175 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos',
2177 del props['cbfs/u-boot:size']
2183 'cbfs:size': len(data),
2184 'cbfs:image-pos': 0,
2185 'cbfs/u-boot:offset': 0x38,
2186 'cbfs/u-boot:uncomp-size': len(U_BOOT_DATA),
2187 'cbfs/u-boot:image-pos': 0x38,
2188 'cbfs/u-boot-dtb:offset': 0xb8,
2189 'cbfs/u-boot-dtb:size': len(U_BOOT_DATA),
2190 'cbfs/u-boot-dtb:image-pos': 0xb8,
2193 def testCbfsBadType(self):
2194 """Test an image header with a no specified location is detected"""
2195 with self.assertRaises(ValueError) as e:
2196 self._DoReadFile('126_cbfs_bad_type.dts')
2197 self.assertIn("Unknown cbfs-type 'badtype'", str(e.exception))
2200 """Test listing the files in an image"""
2202 data = self._DoReadFile('127_list.dts')
2203 image = control.images['image']
2204 entries = image.BuildEntryList()
2205 self.assertEqual(7, len(entries))
2208 self.assertEqual(0, ent.indent)
2209 self.assertEqual('main-section', ent.name)
2210 self.assertEqual('section', ent.etype)
2211 self.assertEqual(len(data), ent.size)
2212 self.assertEqual(0, ent.image_pos)
2213 self.assertEqual(None, ent.uncomp_size)
2214 self.assertEqual(0, ent.offset)
2217 self.assertEqual(1, ent.indent)
2218 self.assertEqual('u-boot', ent.name)
2219 self.assertEqual('u-boot', ent.etype)
2220 self.assertEqual(len(U_BOOT_DATA), ent.size)
2221 self.assertEqual(0, ent.image_pos)
2222 self.assertEqual(None, ent.uncomp_size)
2223 self.assertEqual(0, ent.offset)
2226 self.assertEqual(1, ent.indent)
2227 self.assertEqual('section', ent.name)
2228 self.assertEqual('section', ent.etype)
2229 section_size = ent.size
2230 self.assertEqual(0x100, ent.image_pos)
2231 self.assertEqual(None, ent.uncomp_size)
2232 self.assertEqual(0x100, ent.offset)
2235 self.assertEqual(2, ent.indent)
2236 self.assertEqual('cbfs', ent.name)
2237 self.assertEqual('cbfs', ent.etype)
2238 self.assertEqual(0x400, ent.size)
2239 self.assertEqual(0x100, ent.image_pos)
2240 self.assertEqual(None, ent.uncomp_size)
2241 self.assertEqual(0, ent.offset)
2244 self.assertEqual(3, ent.indent)
2245 self.assertEqual('u-boot', ent.name)
2246 self.assertEqual('u-boot', ent.etype)
2247 self.assertEqual(len(U_BOOT_DATA), ent.size)
2248 self.assertEqual(0x138, ent.image_pos)
2249 self.assertEqual(None, ent.uncomp_size)
2250 self.assertEqual(0x38, ent.offset)
2253 self.assertEqual(3, ent.indent)
2254 self.assertEqual('u-boot-dtb', ent.name)
2255 self.assertEqual('text', ent.etype)
2256 self.assertGreater(len(COMPRESS_DATA), ent.size)
2257 self.assertEqual(0x178, ent.image_pos)
2258 self.assertEqual(len(COMPRESS_DATA), ent.uncomp_size)
2259 self.assertEqual(0x78, ent.offset)
2262 self.assertEqual(2, ent.indent)
2263 self.assertEqual('u-boot-dtb', ent.name)
2264 self.assertEqual('u-boot-dtb', ent.etype)
2265 self.assertEqual(0x500, ent.image_pos)
2266 self.assertEqual(len(U_BOOT_DTB_DATA), ent.uncomp_size)
2268 # Compressing this data expands it since headers are added
2269 self.assertGreater(dtb_size, len(U_BOOT_DTB_DATA))
2270 self.assertEqual(0x400, ent.offset)
2272 self.assertEqual(len(data), 0x100 + section_size)
2273 self.assertEqual(section_size, 0x400 + dtb_size)
2275 def testFindFdtmap(self):
2276 """Test locating an FDT map in an image"""
2278 data = self.data = self._DoReadFileRealDtb('128_decode_image.dts')
2279 image = control.images['image']
2280 entries = image.GetEntries()
2281 entry = entries['fdtmap']
2282 self.assertEqual(entry.image_pos, fdtmap.LocateFdtmap(data))
2284 def testFindFdtmapMissing(self):
2285 """Test failing to locate an FDP map"""
2286 data = self._DoReadFile('005_simple.dts')
2287 self.assertEqual(None, fdtmap.LocateFdtmap(data))
2289 def testFindImageHeader(self):
2290 """Test locating a image header"""
2292 data = self.data = self._DoReadFileRealDtb('128_decode_image.dts')
2293 image = control.images['image']
2294 entries = image.GetEntries()
2295 entry = entries['fdtmap']
2296 # The header should point to the FDT map
2297 self.assertEqual(entry.image_pos, image_header.LocateHeaderOffset(data))
2299 def testFindImageHeaderStart(self):
2300 """Test locating a image header located at the start of an image"""
2301 data = self.data = self._DoReadFileRealDtb('117_fdtmap_hdr_start.dts')
2302 image = control.images['image']
2303 entries = image.GetEntries()
2304 entry = entries['fdtmap']
2305 # The header should point to the FDT map
2306 self.assertEqual(entry.image_pos, image_header.LocateHeaderOffset(data))
2308 def testFindImageHeaderMissing(self):
2309 """Test failing to locate an image header"""
2310 data = self._DoReadFile('005_simple.dts')
2311 self.assertEqual(None, image_header.LocateHeaderOffset(data))
2313 def testReadImage(self):
2314 """Test reading an image and accessing its FDT map"""
2316 data = self.data = self._DoReadFileRealDtb('128_decode_image.dts')
2317 image_fname = tools.GetOutputFilename('image.bin')
2318 orig_image = control.images['image']
2319 image = Image.FromFile(image_fname)
2320 self.assertEqual(orig_image.GetEntries().keys(),
2321 image.GetEntries().keys())
2323 orig_entry = orig_image.GetEntries()['fdtmap']
2324 entry = image.GetEntries()['fdtmap']
2325 self.assertEquals(orig_entry.offset, entry.offset)
2326 self.assertEquals(orig_entry.size, entry.size)
2327 self.assertEquals(orig_entry.image_pos, entry.image_pos)
2329 def testReadImageNoHeader(self):
2330 """Test accessing an image's FDT map without an image header"""
2332 data = self._DoReadFileRealDtb('129_decode_image_nohdr.dts')
2333 image_fname = tools.GetOutputFilename('image.bin')
2334 image = Image.FromFile(image_fname)
2335 self.assertTrue(isinstance(image, Image))
2336 self.assertEqual('image', image.image_name)
2338 def testReadImageFail(self):
2339 """Test failing to read an image image's FDT map"""
2340 self._DoReadFile('005_simple.dts')
2341 image_fname = tools.GetOutputFilename('image.bin')
2342 with self.assertRaises(ValueError) as e:
2343 image = Image.FromFile(image_fname)
2344 self.assertIn("Cannot find FDT map in image", str(e.exception))
2346 def testListCmd(self):
2347 """Test listing the files in an image using an Fdtmap"""
2349 data = self._DoReadFileRealDtb('130_list_fdtmap.dts')
2351 # lz4 compression size differs depending on the version
2352 image = control.images['image']
2353 entries = image.GetEntries()
2354 section_size = entries['section'].size
2355 fdt_size = entries['section'].GetEntries()['u-boot-dtb'].size
2356 fdtmap_offset = entries['fdtmap'].offset
2358 image_fname = tools.GetOutputFilename('image.bin')
2359 with test_util.capture_sys_output() as (stdout, stderr):
2360 self._DoBinman('ls', '-i', image_fname)
2361 lines = stdout.getvalue().splitlines()
2363 'Name Image-pos Size Entry-type Offset Uncomp-size',
2364 '----------------------------------------------------------------------',
2365 'main-section 0 c00 section 0',
2366 ' u-boot 0 4 u-boot 0',
2367 ' section 100 %x section 100' % section_size,
2368 ' cbfs 100 400 cbfs 0',
2369 ' u-boot 138 4 u-boot 38',
2370 ' u-boot-dtb 180 10f u-boot-dtb 80 3c9',
2371 ' u-boot-dtb 500 %x u-boot-dtb 400 3c9' % fdt_size,
2372 ' fdtmap %x 395 fdtmap %x' %
2373 (fdtmap_offset, fdtmap_offset),
2374 ' image-header bf8 8 image-header bf8',
2376 self.assertEqual(expected, lines)
2378 def testListCmdFail(self):
2379 """Test failing to list an image"""
2380 self._DoReadFile('005_simple.dts')
2381 image_fname = tools.GetOutputFilename('image.bin')
2382 with self.assertRaises(ValueError) as e:
2383 self._DoBinman('ls', '-i', image_fname)
2384 self.assertIn("Cannot find FDT map in image", str(e.exception))
2386 def _RunListCmd(self, paths, expected):
2387 """List out entries and check the result
2390 paths: List of paths to pass to the list command
2391 expected: Expected list of filenames to be returned, in order
2394 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2395 image_fname = tools.GetOutputFilename('image.bin')
2396 image = Image.FromFile(image_fname)
2397 lines = image.GetListEntries(paths)[1]
2398 files = [line[0].strip() for line in lines[1:]]
2399 self.assertEqual(expected, files)
2401 def testListCmdSection(self):
2402 """Test listing the files in a section"""
2403 self._RunListCmd(['section'],
2404 ['section', 'cbfs', 'u-boot', 'u-boot-dtb', 'u-boot-dtb'])
2406 def testListCmdFile(self):
2407 """Test listing a particular file"""
2408 self._RunListCmd(['*u-boot-dtb'], ['u-boot-dtb', 'u-boot-dtb'])
2410 def testListCmdWildcard(self):
2411 """Test listing a wildcarded file"""
2412 self._RunListCmd(['*boot*'],
2413 ['u-boot', 'u-boot', 'u-boot-dtb', 'u-boot-dtb'])
2415 def testListCmdWildcardMulti(self):
2416 """Test listing a wildcarded file"""
2417 self._RunListCmd(['*cb*', '*head*'],
2418 ['cbfs', 'u-boot', 'u-boot-dtb', 'image-header'])
2420 def testListCmdEmpty(self):
2421 """Test listing a wildcarded file"""
2422 self._RunListCmd(['nothing'], [])
2424 def testListCmdPath(self):
2425 """Test listing the files in a sub-entry of a section"""
2426 self._RunListCmd(['section/cbfs'], ['cbfs', 'u-boot', 'u-boot-dtb'])
2428 def _RunExtractCmd(self, entry_name, decomp=True):
2429 """Extract an entry from an image
2432 entry_name: Entry name to extract
2433 decomp: True to decompress the data if compressed, False to leave
2434 it in its raw uncompressed format
2440 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2441 image_fname = tools.GetOutputFilename('image.bin')
2442 return control.ReadEntry(image_fname, entry_name, decomp)
2444 def testExtractSimple(self):
2445 """Test extracting a single file"""
2446 data = self._RunExtractCmd('u-boot')
2447 self.assertEqual(U_BOOT_DATA, data)
2449 def testExtractSection(self):
2450 """Test extracting the files in a section"""
2451 data = self._RunExtractCmd('section')
2452 cbfs_data = data[:0x400]
2453 cbfs = cbfs_util.CbfsReader(cbfs_data)
2454 self.assertEqual(['u-boot', 'u-boot-dtb', ''], cbfs.files.keys())
2455 dtb_data = data[0x400:]
2456 dtb = self._decompress(dtb_data)
2457 self.assertEqual(EXTRACT_DTB_SIZE, len(dtb))
2459 def testExtractCompressed(self):
2460 """Test extracting compressed data"""
2461 data = self._RunExtractCmd('section/u-boot-dtb')
2462 self.assertEqual(EXTRACT_DTB_SIZE, len(data))
2464 def testExtractRaw(self):
2465 """Test extracting compressed data without decompressing it"""
2466 data = self._RunExtractCmd('section/u-boot-dtb', decomp=False)
2467 dtb = self._decompress(data)
2468 self.assertEqual(EXTRACT_DTB_SIZE, len(dtb))
2470 def testExtractCbfs(self):
2471 """Test extracting CBFS data"""
2472 data = self._RunExtractCmd('section/cbfs/u-boot')
2473 self.assertEqual(U_BOOT_DATA, data)
2475 def testExtractCbfsCompressed(self):
2476 """Test extracting CBFS compressed data"""
2477 data = self._RunExtractCmd('section/cbfs/u-boot-dtb')
2478 self.assertEqual(EXTRACT_DTB_SIZE, len(data))
2480 def testExtractCbfsRaw(self):
2481 """Test extracting CBFS compressed data without decompressing it"""
2482 data = self._RunExtractCmd('section/cbfs/u-boot-dtb', decomp=False)
2483 dtb = tools.Decompress(data, 'lzma')
2484 self.assertEqual(EXTRACT_DTB_SIZE, len(dtb))
2486 def testExtractBadEntry(self):
2487 """Test extracting a bad section path"""
2488 with self.assertRaises(ValueError) as e:
2489 self._RunExtractCmd('section/does-not-exist')
2490 self.assertIn("Entry 'does-not-exist' not found in '/section'",
2493 def testExtractMissingFile(self):
2494 """Test extracting file that does not exist"""
2495 with self.assertRaises(IOError) as e:
2496 control.ReadEntry('missing-file', 'name')
2498 def testExtractBadFile(self):
2499 """Test extracting an invalid file"""
2500 fname = os.path.join(self._indir, 'badfile')
2501 tools.WriteFile(fname, b'')
2502 with self.assertRaises(ValueError) as e:
2503 control.ReadEntry(fname, 'name')
2505 def testExtractCmd(self):
2506 """Test extracting a file fron an image on the command line"""
2508 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2509 image_fname = tools.GetOutputFilename('image.bin')
2510 fname = os.path.join(self._indir, 'output.extact')
2511 with test_util.capture_sys_output() as (stdout, stderr):
2512 self._DoBinman('extract', '-i', image_fname, 'u-boot', '-f', fname)
2513 data = tools.ReadFile(fname)
2514 self.assertEqual(U_BOOT_DATA, data)
2516 def testExtractOneEntry(self):
2517 """Test extracting a single entry fron an image """
2519 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2520 image_fname = tools.GetOutputFilename('image.bin')
2521 fname = os.path.join(self._indir, 'output.extact')
2522 control.ExtractEntries(image_fname, fname, None, ['u-boot'])
2523 data = tools.ReadFile(fname)
2524 self.assertEqual(U_BOOT_DATA, data)
2526 def _CheckExtractOutput(self, decomp):
2527 """Helper to test file output with and without decompression
2530 decomp: True to decompress entry data, False to output it raw
2532 def _CheckPresent(entry_path, expect_data, expect_size=None):
2533 """Check and remove expected file
2535 This checks the data/size of a file and removes the file both from
2536 the outfiles set and from the output directory. Once all files are
2537 processed, both the set and directory should be empty.
2540 entry_path: Entry path
2541 expect_data: Data to expect in file, or None to skip check
2542 expect_size: Size of data to expect in file, or None to skip
2544 path = os.path.join(outdir, entry_path)
2545 data = tools.ReadFile(path)
2548 self.assertEqual(expect_data, data)
2550 self.assertEqual(expect_size, len(data))
2551 outfiles.remove(path)
2553 def _CheckDirPresent(name):
2554 """Remove expected directory
2556 This gives an error if the directory does not exist as expected
2559 name: Name of directory to remove
2561 path = os.path.join(outdir, name)
2564 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2565 image_fname = tools.GetOutputFilename('image.bin')
2566 outdir = os.path.join(self._indir, 'extract')
2567 einfos = control.ExtractEntries(image_fname, None, outdir, [], decomp)
2569 # Create a set of all file that were output (should be 9)
2571 for root, dirs, files in os.walk(outdir):
2572 outfiles |= set([os.path.join(root, fname) for fname in files])
2573 self.assertEqual(9, len(outfiles))
2574 self.assertEqual(9, len(einfos))
2576 image = control.images['image']
2577 entries = image.GetEntries()
2579 # Check the 9 files in various ways
2580 section = entries['section']
2581 section_entries = section.GetEntries()
2582 cbfs_entries = section_entries['cbfs'].GetEntries()
2583 _CheckPresent('u-boot', U_BOOT_DATA)
2584 _CheckPresent('section/cbfs/u-boot', U_BOOT_DATA)
2585 dtb_len = EXTRACT_DTB_SIZE
2587 dtb_len = cbfs_entries['u-boot-dtb'].size
2588 _CheckPresent('section/cbfs/u-boot-dtb', None, dtb_len)
2590 dtb_len = section_entries['u-boot-dtb'].size
2591 _CheckPresent('section/u-boot-dtb', None, dtb_len)
2593 fdtmap = entries['fdtmap']
2594 _CheckPresent('fdtmap', fdtmap.data)
2595 hdr = entries['image-header']
2596 _CheckPresent('image-header', hdr.data)
2598 _CheckPresent('section/root', section.data)
2599 cbfs = section_entries['cbfs']
2600 _CheckPresent('section/cbfs/root', cbfs.data)
2601 data = tools.ReadFile(image_fname)
2602 _CheckPresent('root', data)
2604 # There should be no files left. Remove all the directories to check.
2605 # If there are any files/dirs remaining, one of these checks will fail.
2606 self.assertEqual(0, len(outfiles))
2607 _CheckDirPresent('section/cbfs')
2608 _CheckDirPresent('section')
2609 _CheckDirPresent('')
2610 self.assertFalse(os.path.exists(outdir))
2612 def testExtractAllEntries(self):
2613 """Test extracting all entries"""
2615 self._CheckExtractOutput(decomp=True)
2617 def testExtractAllEntriesRaw(self):
2618 """Test extracting all entries without decompressing them"""
2620 self._CheckExtractOutput(decomp=False)
2622 def testExtractSelectedEntries(self):
2623 """Test extracting some entries"""
2625 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2626 image_fname = tools.GetOutputFilename('image.bin')
2627 outdir = os.path.join(self._indir, 'extract')
2628 einfos = control.ExtractEntries(image_fname, None, outdir,
2631 # File output is tested by testExtractAllEntries(), so just check that
2632 # the expected entries are selected
2633 names = [einfo.name for einfo in einfos]
2634 self.assertEqual(names,
2635 ['cbfs', 'u-boot', 'u-boot-dtb', 'image-header'])
2637 def testExtractNoEntryPaths(self):
2638 """Test extracting some entries"""
2640 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2641 image_fname = tools.GetOutputFilename('image.bin')
2642 with self.assertRaises(ValueError) as e:
2643 control.ExtractEntries(image_fname, 'fname', None, [])
2644 self.assertIn('Must specify an entry path to write with -o',
2647 def testExtractTooManyEntryPaths(self):
2648 """Test extracting some entries"""
2650 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2651 image_fname = tools.GetOutputFilename('image.bin')
2652 with self.assertRaises(ValueError) as e:
2653 control.ExtractEntries(image_fname, 'fname', None, ['a', 'b'])
2654 self.assertIn('Must specify exactly one entry path to write with -o',
2657 def testPackAlignSection(self):
2658 """Test that sections can have alignment"""
2659 self._DoReadFile('131_pack_align_section.dts')
2661 self.assertIn('image', control.images)
2662 image = control.images['image']
2663 entries = image.GetEntries()
2664 self.assertEqual(3, len(entries))
2667 self.assertIn('u-boot', entries)
2668 entry = entries['u-boot']
2669 self.assertEqual(0, entry.offset)
2670 self.assertEqual(0, entry.image_pos)
2671 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2672 self.assertEqual(len(U_BOOT_DATA), entry.size)
2675 self.assertIn('section0', entries)
2676 section0 = entries['section0']
2677 self.assertEqual(0x10, section0.offset)
2678 self.assertEqual(0x10, section0.image_pos)
2679 self.assertEqual(len(U_BOOT_DATA), section0.size)
2682 section_entries = section0.GetEntries()
2683 self.assertIn('u-boot', section_entries)
2684 entry = section_entries['u-boot']
2685 self.assertEqual(0, entry.offset)
2686 self.assertEqual(0x10, entry.image_pos)
2687 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2688 self.assertEqual(len(U_BOOT_DATA), entry.size)
2691 self.assertIn('section1', entries)
2692 section1 = entries['section1']
2693 self.assertEqual(0x14, section1.offset)
2694 self.assertEqual(0x14, section1.image_pos)
2695 self.assertEqual(0x20, section1.size)
2698 section_entries = section1.GetEntries()
2699 self.assertIn('u-boot', section_entries)
2700 entry = section_entries['u-boot']
2701 self.assertEqual(0, entry.offset)
2702 self.assertEqual(0x14, entry.image_pos)
2703 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2704 self.assertEqual(len(U_BOOT_DATA), entry.size)
2707 self.assertIn('section2', section_entries)
2708 section2 = section_entries['section2']
2709 self.assertEqual(0x4, section2.offset)
2710 self.assertEqual(0x18, section2.image_pos)
2711 self.assertEqual(4, section2.size)
2714 section_entries = section2.GetEntries()
2715 self.assertIn('u-boot', section_entries)
2716 entry = section_entries['u-boot']
2717 self.assertEqual(0, entry.offset)
2718 self.assertEqual(0x18, entry.image_pos)
2719 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2720 self.assertEqual(len(U_BOOT_DATA), entry.size)
2723 if __name__ == "__main__":