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 # The expected size for the device tree in some tests
73 EXTRACT_DTB_SIZE = 0x3c9
75 # Properties expected to be in the device tree when update_dtb is used
76 BASE_DTB_PROPS = ['offset', 'size', 'image-pos']
79 class TestFunctional(unittest.TestCase):
80 """Functional tests for binman
82 Most of these use a sample .dts file to build an image and then check
83 that it looks correct. The sample files are in the test/ subdirectory
86 For each entry type a very small test file is created using fixed
87 string contents. This makes it easy to test that things look right, and
90 In some cases a 'real' file must be used - these are also supplied in
98 # Handle the case where argv[0] is 'python'
99 self._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
100 self._binman_pathname = os.path.join(self._binman_dir, 'binman')
102 # Create a temporary directory for input files
103 self._indir = tempfile.mkdtemp(prefix='binmant.')
105 # Create some test files
106 TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
107 TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
108 TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
109 TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
110 TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
111 TestFunctional._MakeInputFile('me.bin', ME_DATA)
112 TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
114 TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
115 TestFunctional._MakeInputFile('u-boot-br.bin', PPC_MPC85XX_BR_DATA)
116 TestFunctional._MakeInputFile('spl/u-boot-x86-16bit-spl.bin',
117 X86_START16_SPL_DATA)
118 TestFunctional._MakeInputFile('tpl/u-boot-x86-16bit-tpl.bin',
119 X86_START16_TPL_DATA)
120 TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
121 TestFunctional._MakeInputFile('spl/u-boot-spl-nodtb.bin',
122 U_BOOT_SPL_NODTB_DATA)
123 TestFunctional._MakeInputFile('tpl/u-boot-tpl-nodtb.bin',
124 U_BOOT_TPL_NODTB_DATA)
125 TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
126 TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
127 TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
128 TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
129 TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
130 TestFunctional._MakeInputDir('devkeys')
131 TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
132 TestFunctional._MakeInputFile('refcode.bin', REFCODE_DATA)
134 # ELF file with a '_dt_ucode_base_size' symbol
135 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
136 TestFunctional._MakeInputFile('u-boot', fd.read())
138 # Intel flash descriptor file
139 with open(self.TestFile('descriptor.bin'), 'rb') as fd:
140 TestFunctional._MakeInputFile('descriptor.bin', fd.read())
142 shutil.copytree(self.TestFile('files'),
143 os.path.join(self._indir, 'files'))
145 TestFunctional._MakeInputFile('compress', COMPRESS_DATA)
147 # Travis-CI may have an old lz4
150 tools.Run('lz4', '--no-frame-crc', '-c',
151 os.path.join(self._indir, 'u-boot.bin'))
153 self.have_lz4 = False
156 def tearDownClass(self):
157 """Remove the temporary input directory and its contents"""
158 if self.preserve_indir:
159 print('Preserving input dir: %s' % self._indir)
162 shutil.rmtree(self._indir)
166 def setup_test_args(cls, preserve_indir=False, preserve_outdirs=False,
167 toolpath=None, verbosity=None):
168 """Accept arguments controlling test execution
171 preserve_indir: Preserve the shared input directory used by all
173 preserve_outdir: Preserve the output directories used by tests. Each
174 test has its own, so this is normally only useful when running a
176 toolpath: ist of paths to use for tools
178 cls.preserve_indir = preserve_indir
179 cls.preserve_outdirs = preserve_outdirs
180 cls.toolpath = toolpath
181 cls.verbosity = verbosity
184 if not self.have_lz4:
185 self.skipTest('lz4 --no-frame-crc not available')
188 # Enable this to turn on debugging output
189 # tout.Init(tout.DEBUG)
190 command.test_result = None
193 """Remove the temporary output directory"""
194 if self.preserve_outdirs:
195 print('Preserving output dir: %s' % tools.outdir)
197 tools._FinaliseForTest()
200 def _ResetDtbs(self):
201 TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
202 TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
203 TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
205 def _RunBinman(self, *args, **kwargs):
206 """Run binman using the command line
209 Arguments to pass, as a list of strings
210 kwargs: Arguments to pass to Command.RunPipe()
212 result = command.RunPipe([[self._binman_pathname] + list(args)],
213 capture=True, capture_stderr=True, raise_on_error=False)
214 if result.return_code and kwargs.get('raise_on_error', True):
215 raise Exception("Error running '%s': %s" % (' '.join(args),
216 result.stdout + result.stderr))
219 def _DoBinman(self, *argv):
220 """Run binman using directly (in the same process)
223 Arguments to pass, as a list of strings
225 Return value (0 for success)
228 args = cmdline.ParseArgs(argv)
229 args.pager = 'binman-invalid-pager'
230 args.build_dir = self._indir
232 # For testing, you can force an increase in verbosity here
233 # args.verbosity = tout.DEBUG
234 return control.Binman(args)
236 def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
237 entry_args=None, images=None, use_real_dtb=False,
239 """Run binman with a given test file
242 fname: Device-tree source filename to use (e.g. 005_simple.dts)
243 debug: True to enable debugging output
244 map: True to output map files for the images
245 update_dtb: Update the offset and size of each entry in the device
246 tree before packing it into the image
247 entry_args: Dict of entry args to supply to binman
249 value: value of that arg
250 images: List of image names to build
255 if verbosity is not None:
256 args.append('-v%d' % verbosity)
258 args.append('-v%d' % self.verbosity)
260 for path in self.toolpath:
261 args += ['--toolpath', path]
262 args += ['build', '-p', '-I', self._indir, '-d', self.TestFile(fname)]
268 args.append('--fake-dtb')
270 for arg, value in entry_args.items():
271 args.append('-a%s=%s' % (arg, value))
274 args += ['-i', image]
275 return self._DoBinman(*args)
277 def _SetupDtb(self, fname, outfile='u-boot.dtb'):
278 """Set up a new test device-tree file
280 The given file is compiled and set up as the device tree to be used
284 fname: Filename of .dts file to read
285 outfile: Output filename for compiled device-tree binary
288 Contents of device-tree binary
290 tmpdir = tempfile.mkdtemp(prefix='binmant.')
291 dtb = fdt_util.EnsureCompiled(self.TestFile(fname), tmpdir)
292 with open(dtb, 'rb') as fd:
294 TestFunctional._MakeInputFile(outfile, data)
295 shutil.rmtree(tmpdir)
298 def _GetDtbContentsForSplTpl(self, dtb_data, name):
299 """Create a version of the main DTB for SPL or SPL
301 For testing we don't actually have different versions of the DTB. With
302 U-Boot we normally run fdtgrep to remove unwanted nodes, but for tests
303 we don't normally have any unwanted nodes.
305 We still want the DTBs for SPL and TPL to be different though, since
306 otherwise it is confusing to know which one we are looking at. So add
307 an 'spl' or 'tpl' property to the top-level node.
309 dtb = fdt.Fdt.FromData(dtb_data)
311 dtb.GetNode('/binman').AddZeroProp(name)
312 dtb.Sync(auto_resize=True)
314 return dtb.GetContents()
316 def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
317 update_dtb=False, entry_args=None, reset_dtbs=True):
318 """Run binman and return the resulting image
320 This runs binman with a given test file and then reads the resulting
321 output file. It is a shortcut function since most tests need to do
324 Raises an assertion failure if binman returns a non-zero exit code.
327 fname: Device-tree source filename to use (e.g. 005_simple.dts)
328 use_real_dtb: True to use the test file as the contents of
329 the u-boot-dtb entry. Normally this is not needed and the
330 test contents (the U_BOOT_DTB_DATA string) can be used.
331 But in some test we need the real contents.
332 map: True to output map files for the images
333 update_dtb: Update the offset and size of each entry in the device
334 tree before packing it into the image
338 Resulting image contents
340 Map data showing contents of image (or None if none)
341 Output device tree binary filename ('u-boot.dtb' path)
344 # Use the compiled test file as the u-boot-dtb input
346 dtb_data = self._SetupDtb(fname)
348 # For testing purposes, make a copy of the DT for SPL and TPL. Add
349 # a node indicating which it is, so aid verification.
350 for name in ['spl', 'tpl']:
351 dtb_fname = '%s/u-boot-%s.dtb' % (name, name)
352 outfile = os.path.join(self._indir, dtb_fname)
353 TestFunctional._MakeInputFile(dtb_fname,
354 self._GetDtbContentsForSplTpl(dtb_data, name))
357 retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
358 entry_args=entry_args, use_real_dtb=use_real_dtb)
359 self.assertEqual(0, retcode)
360 out_dtb_fname = tools.GetOutputFilename('u-boot.dtb.out')
362 # Find the (only) image, read it and return its contents
363 image = control.images['image']
364 image_fname = tools.GetOutputFilename('image.bin')
365 self.assertTrue(os.path.exists(image_fname))
367 map_fname = tools.GetOutputFilename('image.map')
368 with open(map_fname) as fd:
372 with open(image_fname, 'rb') as fd:
373 return fd.read(), dtb_data, map_data, out_dtb_fname
375 # Put the test file back
376 if reset_dtbs and use_real_dtb:
379 def _DoReadFileRealDtb(self, fname):
380 """Run binman with a real .dtb file and return the resulting data
383 fname: DT source filename to use (e.g. 082_fdt_update_all.dts)
386 Resulting image contents
388 return self._DoReadFileDtb(fname, use_real_dtb=True, update_dtb=True)[0]
390 def _DoReadFile(self, fname, use_real_dtb=False):
391 """Helper function which discards the device-tree binary
394 fname: Device-tree source filename to use (e.g. 005_simple.dts)
395 use_real_dtb: True to use the test file as the contents of
396 the u-boot-dtb entry. Normally this is not needed and the
397 test contents (the U_BOOT_DTB_DATA string) can be used.
398 But in some test we need the real contents.
401 Resulting image contents
403 return self._DoReadFileDtb(fname, use_real_dtb)[0]
406 def _MakeInputFile(self, fname, contents):
407 """Create a new test input file, creating directories as needed
410 fname: Filename to create
411 contents: File contents to write in to the file
413 Full pathname of file created
415 pathname = os.path.join(self._indir, fname)
416 dirname = os.path.dirname(pathname)
417 if dirname and not os.path.exists(dirname):
419 with open(pathname, 'wb') as fd:
424 def _MakeInputDir(self, dirname):
425 """Create a new test input directory, creating directories as needed
428 dirname: Directory name to create
431 Full pathname of directory created
433 pathname = os.path.join(self._indir, dirname)
434 if not os.path.exists(pathname):
435 os.makedirs(pathname)
439 def _SetupSplElf(self, src_fname='bss_data'):
440 """Set up an ELF file with a '_dt_ucode_base_size' symbol
443 Filename of ELF file to use as SPL
445 with open(self.TestFile(src_fname), 'rb') as fd:
446 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
449 def TestFile(self, fname):
450 return os.path.join(self._binman_dir, 'test', fname)
452 def AssertInList(self, grep_list, target):
453 """Assert that at least one of a list of things is in a target
456 grep_list: List of strings to check
457 target: Target string
459 for grep in grep_list:
462 self.fail("Error: '%s' not found in '%s'" % (grep_list, target))
464 def CheckNoGaps(self, entries):
465 """Check that all entries fit together without gaps
468 entries: List of entries to check
471 for entry in entries.values():
472 self.assertEqual(offset, entry.offset)
475 def GetFdtLen(self, dtb):
476 """Get the totalsize field from a device-tree binary
479 dtb: Device-tree binary contents
482 Total size of device-tree binary, from the header
484 return struct.unpack('>L', dtb[4:8])[0]
486 def _GetPropTree(self, dtb, prop_names, prefix='/binman/'):
487 def AddNode(node, path):
489 path += '/' + node.name
490 for prop in node.props.values():
491 if prop.name in prop_names:
492 prop_path = path + ':' + prop.name
493 tree[prop_path[len(prefix):]] = fdt_util.fdt32_to_cpu(
495 for subnode in node.subnodes:
496 AddNode(subnode, path)
499 AddNode(dtb.GetRoot(), '')
503 """Test a basic run with valid args"""
504 result = self._RunBinman('-h')
506 def testFullHelp(self):
507 """Test that the full help is displayed with -H"""
508 result = self._RunBinman('-H')
509 help_file = os.path.join(self._binman_dir, 'README')
510 # Remove possible extraneous strings
511 extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
512 gothelp = result.stdout.replace(extra, '')
513 self.assertEqual(len(gothelp), os.path.getsize(help_file))
514 self.assertEqual(0, len(result.stderr))
515 self.assertEqual(0, result.return_code)
517 def testFullHelpInternal(self):
518 """Test that the full help is displayed with -H"""
520 command.test_result = command.CommandResult()
521 result = self._DoBinman('-H')
522 help_file = os.path.join(self._binman_dir, 'README')
524 command.test_result = None
527 """Test that the basic help is displayed with -h"""
528 result = self._RunBinman('-h')
529 self.assertTrue(len(result.stdout) > 200)
530 self.assertEqual(0, len(result.stderr))
531 self.assertEqual(0, result.return_code)
534 """Test that we can run it with a specific board"""
535 self._SetupDtb('005_simple.dts', 'sandbox/u-boot.dtb')
536 TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
537 result = self._DoBinman('build', '-b', 'sandbox')
538 self.assertEqual(0, result)
540 def testNeedBoard(self):
541 """Test that we get an error when no board ius supplied"""
542 with self.assertRaises(ValueError) as e:
543 result = self._DoBinman('build')
544 self.assertIn("Must provide a board to process (use -b <board>)",
547 def testMissingDt(self):
548 """Test that an invalid device-tree file generates an error"""
549 with self.assertRaises(Exception) as e:
550 self._RunBinman('build', '-d', 'missing_file')
551 # We get one error from libfdt, and a different one from fdtget.
552 self.AssertInList(["Couldn't open blob from 'missing_file'",
553 'No such file or directory'], str(e.exception))
555 def testBrokenDt(self):
556 """Test that an invalid device-tree source file generates an error
558 Since this is a source file it should be compiled and the error
559 will come from the device-tree compiler (dtc).
561 with self.assertRaises(Exception) as e:
562 self._RunBinman('build', '-d', self.TestFile('001_invalid.dts'))
563 self.assertIn("FATAL ERROR: Unable to parse input tree",
566 def testMissingNode(self):
567 """Test that a device tree without a 'binman' node generates an error"""
568 with self.assertRaises(Exception) as e:
569 self._DoBinman('build', '-d', self.TestFile('002_missing_node.dts'))
570 self.assertIn("does not have a 'binman' node", str(e.exception))
573 """Test that an empty binman node works OK (i.e. does nothing)"""
574 result = self._RunBinman('build', '-d', self.TestFile('003_empty.dts'))
575 self.assertEqual(0, len(result.stderr))
576 self.assertEqual(0, result.return_code)
578 def testInvalidEntry(self):
579 """Test that an invalid entry is flagged"""
580 with self.assertRaises(Exception) as e:
581 result = self._RunBinman('build', '-d',
582 self.TestFile('004_invalid_entry.dts'))
583 self.assertIn("Unknown entry type 'not-a-valid-type' in node "
584 "'/binman/not-a-valid-type'", str(e.exception))
586 def testSimple(self):
587 """Test a simple binman with a single file"""
588 data = self._DoReadFile('005_simple.dts')
589 self.assertEqual(U_BOOT_DATA, data)
591 def testSimpleDebug(self):
592 """Test a simple binman run with debugging enabled"""
593 self._DoTestFile('005_simple.dts', debug=True)
596 """Test that we can handle creating two images
598 This also tests image padding.
600 retcode = self._DoTestFile('006_dual_image.dts')
601 self.assertEqual(0, retcode)
603 image = control.images['image1']
604 self.assertEqual(len(U_BOOT_DATA), image.size)
605 fname = tools.GetOutputFilename('image1.bin')
606 self.assertTrue(os.path.exists(fname))
607 with open(fname, 'rb') as fd:
609 self.assertEqual(U_BOOT_DATA, data)
611 image = control.images['image2']
612 self.assertEqual(3 + len(U_BOOT_DATA) + 5, image.size)
613 fname = tools.GetOutputFilename('image2.bin')
614 self.assertTrue(os.path.exists(fname))
615 with open(fname, 'rb') as fd:
617 self.assertEqual(U_BOOT_DATA, data[3:7])
618 self.assertEqual(tools.GetBytes(0, 3), data[:3])
619 self.assertEqual(tools.GetBytes(0, 5), data[7:])
621 def testBadAlign(self):
622 """Test that an invalid alignment value is detected"""
623 with self.assertRaises(ValueError) as e:
624 self._DoTestFile('007_bad_align.dts')
625 self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
626 "of two", str(e.exception))
628 def testPackSimple(self):
629 """Test that packing works as expected"""
630 retcode = self._DoTestFile('008_pack.dts')
631 self.assertEqual(0, retcode)
632 self.assertIn('image', control.images)
633 image = control.images['image']
634 entries = image.GetEntries()
635 self.assertEqual(5, len(entries))
638 self.assertIn('u-boot', entries)
639 entry = entries['u-boot']
640 self.assertEqual(0, entry.offset)
641 self.assertEqual(len(U_BOOT_DATA), entry.size)
643 # Second u-boot, aligned to 16-byte boundary
644 self.assertIn('u-boot-align', entries)
645 entry = entries['u-boot-align']
646 self.assertEqual(16, entry.offset)
647 self.assertEqual(len(U_BOOT_DATA), entry.size)
649 # Third u-boot, size 23 bytes
650 self.assertIn('u-boot-size', entries)
651 entry = entries['u-boot-size']
652 self.assertEqual(20, entry.offset)
653 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
654 self.assertEqual(23, entry.size)
656 # Fourth u-boot, placed immediate after the above
657 self.assertIn('u-boot-next', entries)
658 entry = entries['u-boot-next']
659 self.assertEqual(43, entry.offset)
660 self.assertEqual(len(U_BOOT_DATA), entry.size)
662 # Fifth u-boot, placed at a fixed offset
663 self.assertIn('u-boot-fixed', entries)
664 entry = entries['u-boot-fixed']
665 self.assertEqual(61, entry.offset)
666 self.assertEqual(len(U_BOOT_DATA), entry.size)
668 self.assertEqual(65, image.size)
670 def testPackExtra(self):
671 """Test that extra packing feature works as expected"""
672 retcode = self._DoTestFile('009_pack_extra.dts')
674 self.assertEqual(0, retcode)
675 self.assertIn('image', control.images)
676 image = control.images['image']
677 entries = image.GetEntries()
678 self.assertEqual(5, len(entries))
680 # First u-boot with padding before and after
681 self.assertIn('u-boot', entries)
682 entry = entries['u-boot']
683 self.assertEqual(0, entry.offset)
684 self.assertEqual(3, entry.pad_before)
685 self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
687 # Second u-boot has an aligned size, but it has no effect
688 self.assertIn('u-boot-align-size-nop', entries)
689 entry = entries['u-boot-align-size-nop']
690 self.assertEqual(12, entry.offset)
691 self.assertEqual(4, entry.size)
693 # Third u-boot has an aligned size too
694 self.assertIn('u-boot-align-size', entries)
695 entry = entries['u-boot-align-size']
696 self.assertEqual(16, entry.offset)
697 self.assertEqual(32, entry.size)
699 # Fourth u-boot has an aligned end
700 self.assertIn('u-boot-align-end', entries)
701 entry = entries['u-boot-align-end']
702 self.assertEqual(48, entry.offset)
703 self.assertEqual(16, entry.size)
705 # Fifth u-boot immediately afterwards
706 self.assertIn('u-boot-align-both', entries)
707 entry = entries['u-boot-align-both']
708 self.assertEqual(64, entry.offset)
709 self.assertEqual(64, entry.size)
711 self.CheckNoGaps(entries)
712 self.assertEqual(128, image.size)
714 def testPackAlignPowerOf2(self):
715 """Test that invalid entry alignment is detected"""
716 with self.assertRaises(ValueError) as e:
717 self._DoTestFile('010_pack_align_power2.dts')
718 self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
719 "of two", str(e.exception))
721 def testPackAlignSizePowerOf2(self):
722 """Test that invalid entry size alignment is detected"""
723 with self.assertRaises(ValueError) as e:
724 self._DoTestFile('011_pack_align_size_power2.dts')
725 self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
726 "power of two", str(e.exception))
728 def testPackInvalidAlign(self):
729 """Test detection of an offset that does not match its alignment"""
730 with self.assertRaises(ValueError) as e:
731 self._DoTestFile('012_pack_inv_align.dts')
732 self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
733 "align 0x4 (4)", str(e.exception))
735 def testPackInvalidSizeAlign(self):
736 """Test that invalid entry size alignment is detected"""
737 with self.assertRaises(ValueError) as e:
738 self._DoTestFile('013_pack_inv_size_align.dts')
739 self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
740 "align-size 0x4 (4)", str(e.exception))
742 def testPackOverlap(self):
743 """Test that overlapping regions are detected"""
744 with self.assertRaises(ValueError) as e:
745 self._DoTestFile('014_pack_overlap.dts')
746 self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
747 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
750 def testPackEntryOverflow(self):
751 """Test that entries that overflow their size are detected"""
752 with self.assertRaises(ValueError) as e:
753 self._DoTestFile('015_pack_overflow.dts')
754 self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
755 "but entry size is 0x3 (3)", str(e.exception))
757 def testPackImageOverflow(self):
758 """Test that entries which overflow the image size are detected"""
759 with self.assertRaises(ValueError) as e:
760 self._DoTestFile('016_pack_image_overflow.dts')
761 self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section "
762 "size 0x3 (3)", str(e.exception))
764 def testPackImageSize(self):
765 """Test that the image size can be set"""
766 retcode = self._DoTestFile('017_pack_image_size.dts')
767 self.assertEqual(0, retcode)
768 self.assertIn('image', control.images)
769 image = control.images['image']
770 self.assertEqual(7, image.size)
772 def testPackImageSizeAlign(self):
773 """Test that image size alignemnt works as expected"""
774 retcode = self._DoTestFile('018_pack_image_align.dts')
775 self.assertEqual(0, retcode)
776 self.assertIn('image', control.images)
777 image = control.images['image']
778 self.assertEqual(16, image.size)
780 def testPackInvalidImageAlign(self):
781 """Test that invalid image alignment is detected"""
782 with self.assertRaises(ValueError) as e:
783 self._DoTestFile('019_pack_inv_image_align.dts')
784 self.assertIn("Section '/binman': Size 0x7 (7) does not match "
785 "align-size 0x8 (8)", str(e.exception))
787 def testPackAlignPowerOf2(self):
788 """Test that invalid image alignment is detected"""
789 with self.assertRaises(ValueError) as e:
790 self._DoTestFile('020_pack_inv_image_align_power2.dts')
791 self.assertIn("Image '/binman': Alignment size 131 must be a power of "
792 "two", str(e.exception))
794 def testImagePadByte(self):
795 """Test that the image pad byte can be specified"""
797 data = self._DoReadFile('021_image_pad.dts')
798 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0xff, 1) +
801 def testImageName(self):
802 """Test that image files can be named"""
803 retcode = self._DoTestFile('022_image_name.dts')
804 self.assertEqual(0, retcode)
805 image = control.images['image1']
806 fname = tools.GetOutputFilename('test-name')
807 self.assertTrue(os.path.exists(fname))
809 image = control.images['image2']
810 fname = tools.GetOutputFilename('test-name.xx')
811 self.assertTrue(os.path.exists(fname))
813 def testBlobFilename(self):
814 """Test that generic blobs can be provided by filename"""
815 data = self._DoReadFile('023_blob.dts')
816 self.assertEqual(BLOB_DATA, data)
818 def testPackSorted(self):
819 """Test that entries can be sorted"""
821 data = self._DoReadFile('024_sorted.dts')
822 self.assertEqual(tools.GetBytes(0, 1) + U_BOOT_SPL_DATA +
823 tools.GetBytes(0, 2) + U_BOOT_DATA, data)
825 def testPackZeroOffset(self):
826 """Test that an entry at offset 0 is not given a new offset"""
827 with self.assertRaises(ValueError) as e:
828 self._DoTestFile('025_pack_zero_size.dts')
829 self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
830 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
833 def testPackUbootDtb(self):
834 """Test that a device tree can be added to U-Boot"""
835 data = self._DoReadFile('026_pack_u_boot_dtb.dts')
836 self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
838 def testPackX86RomNoSize(self):
839 """Test that the end-at-4gb property requires a size property"""
840 with self.assertRaises(ValueError) as e:
841 self._DoTestFile('027_pack_4gb_no_size.dts')
842 self.assertIn("Image '/binman': Section size must be provided when "
843 "using end-at-4gb", str(e.exception))
845 def test4gbAndSkipAtStartTogether(self):
846 """Test that the end-at-4gb and skip-at-size property can't be used
848 with self.assertRaises(ValueError) as e:
849 self._DoTestFile('80_4gb_and_skip_at_start_together.dts')
850 self.assertIn("Image '/binman': Provide either 'end-at-4gb' or "
851 "'skip-at-start'", str(e.exception))
853 def testPackX86RomOutside(self):
854 """Test that the end-at-4gb property checks for offset boundaries"""
855 with self.assertRaises(ValueError) as e:
856 self._DoTestFile('028_pack_4gb_outside.dts')
857 self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
858 "the section starting at 0xffffffe0 (4294967264)",
861 def testPackX86Rom(self):
862 """Test that a basic x86 ROM can be created"""
864 data = self._DoReadFile('029_x86-rom.dts')
865 self.assertEqual(U_BOOT_DATA + tools.GetBytes(0, 7) + U_BOOT_SPL_DATA +
866 tools.GetBytes(0, 2), data)
868 def testPackX86RomMeNoDesc(self):
869 """Test that an invalid Intel descriptor entry is detected"""
870 TestFunctional._MakeInputFile('descriptor.bin', b'')
871 with self.assertRaises(ValueError) as e:
872 self._DoTestFile('031_x86-rom-me.dts')
873 self.assertIn("Node '/binman/intel-descriptor': Cannot find Intel Flash Descriptor (FD) signature",
876 def testPackX86RomBadDesc(self):
877 """Test that the Intel requires a descriptor entry"""
878 with self.assertRaises(ValueError) as e:
879 self._DoTestFile('030_x86-rom-me-no-desc.dts')
880 self.assertIn("Node '/binman/intel-me': No offset set with "
881 "offset-unset: should another entry provide this correct "
882 "offset?", str(e.exception))
884 def testPackX86RomMe(self):
885 """Test that an x86 ROM with an ME region can be created"""
886 data = self._DoReadFile('031_x86-rom-me.dts')
887 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
888 if data[:0x1000] != expected_desc:
889 self.fail('Expected descriptor binary at start of image')
890 self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
892 def testPackVga(self):
893 """Test that an image with a VGA binary can be created"""
894 data = self._DoReadFile('032_intel-vga.dts')
895 self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
897 def testPackStart16(self):
898 """Test that an image with an x86 start16 region can be created"""
899 data = self._DoReadFile('033_x86-start16.dts')
900 self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
902 def testPackPowerpcMpc85xxBootpgResetvec(self):
903 """Test that an image with powerpc-mpc85xx-bootpg-resetvec can be
905 data = self._DoReadFile('81_powerpc_mpc85xx_bootpg_resetvec.dts')
906 self.assertEqual(PPC_MPC85XX_BR_DATA, data[:len(PPC_MPC85XX_BR_DATA)])
908 def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False):
909 """Handle running a test for insertion of microcode
912 dts_fname: Name of test .dts file
913 nodtb_data: Data that we expect in the first section
914 ucode_second: True if the microsecond entry is second instead of
919 Contents of first region (U-Boot or SPL)
920 Offset and size components of microcode pointer, as inserted
921 in the above (two 4-byte words)
923 data = self._DoReadFile(dts_fname, True)
925 # Now check the device tree has no microcode
927 ucode_content = data[len(nodtb_data):]
928 ucode_pos = len(nodtb_data)
929 dtb_with_ucode = ucode_content[16:]
930 fdt_len = self.GetFdtLen(dtb_with_ucode)
932 dtb_with_ucode = data[len(nodtb_data):]
933 fdt_len = self.GetFdtLen(dtb_with_ucode)
934 ucode_content = dtb_with_ucode[fdt_len:]
935 ucode_pos = len(nodtb_data) + fdt_len
936 fname = tools.GetOutputFilename('test.dtb')
937 with open(fname, 'wb') as fd:
938 fd.write(dtb_with_ucode)
939 dtb = fdt.FdtScan(fname)
940 ucode = dtb.GetNode('/microcode')
941 self.assertTrue(ucode)
942 for node in ucode.subnodes:
943 self.assertFalse(node.props.get('data'))
945 # Check that the microcode appears immediately after the Fdt
946 # This matches the concatenation of the data properties in
947 # the /microcode/update@xxx nodes in 34_x86_ucode.dts.
948 ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
950 self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
952 # Check that the microcode pointer was inserted. It should match the
953 # expected offset and size
954 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
956 u_boot = data[:len(nodtb_data)]
957 return u_boot, pos_and_size
959 def testPackUbootMicrocode(self):
960 """Test that x86 microcode can be handled correctly
962 We expect to see the following in the image, in order:
963 u-boot-nodtb.bin with a microcode pointer inserted at the correct
965 u-boot.dtb with the microcode removed
968 first, pos_and_size = self._RunMicrocodeTest('034_x86_ucode.dts',
970 self.assertEqual(b'nodtb with microcode' + pos_and_size +
971 b' somewhere in here', first)
973 def _RunPackUbootSingleMicrocode(self):
974 """Test that x86 microcode can be handled correctly
976 We expect to see the following in the image, in order:
977 u-boot-nodtb.bin with a microcode pointer inserted at the correct
979 u-boot.dtb with the microcode
980 an empty microcode region
982 # We need the libfdt library to run this test since only that allows
983 # finding the offset of a property. This is required by
984 # Entry_u_boot_dtb_with_ucode.ObtainContents().
985 data = self._DoReadFile('035_x86_single_ucode.dts', True)
987 second = data[len(U_BOOT_NODTB_DATA):]
989 fdt_len = self.GetFdtLen(second)
990 third = second[fdt_len:]
991 second = second[:fdt_len]
993 ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
994 self.assertIn(ucode_data, second)
995 ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
997 # Check that the microcode pointer was inserted. It should match the
998 # expected offset and size
999 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
1001 first = data[:len(U_BOOT_NODTB_DATA)]
1002 self.assertEqual(b'nodtb with microcode' + pos_and_size +
1003 b' somewhere in here', first)
1005 def testPackUbootSingleMicrocode(self):
1006 """Test that x86 microcode can be handled correctly with fdt_normal.
1008 self._RunPackUbootSingleMicrocode()
1010 def testUBootImg(self):
1011 """Test that u-boot.img can be put in a file"""
1012 data = self._DoReadFile('036_u_boot_img.dts')
1013 self.assertEqual(U_BOOT_IMG_DATA, data)
1015 def testNoMicrocode(self):
1016 """Test that a missing microcode region is detected"""
1017 with self.assertRaises(ValueError) as e:
1018 self._DoReadFile('037_x86_no_ucode.dts', True)
1019 self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
1020 "node found in ", str(e.exception))
1022 def testMicrocodeWithoutNode(self):
1023 """Test that a missing u-boot-dtb-with-ucode node is detected"""
1024 with self.assertRaises(ValueError) as e:
1025 self._DoReadFile('038_x86_ucode_missing_node.dts', True)
1026 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1027 "microcode region u-boot-dtb-with-ucode", str(e.exception))
1029 def testMicrocodeWithoutNode2(self):
1030 """Test that a missing u-boot-ucode node is detected"""
1031 with self.assertRaises(ValueError) as e:
1032 self._DoReadFile('039_x86_ucode_missing_node2.dts', True)
1033 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1034 "microcode region u-boot-ucode", str(e.exception))
1036 def testMicrocodeWithoutPtrInElf(self):
1037 """Test that a U-Boot binary without the microcode symbol is detected"""
1038 # ELF file without a '_dt_ucode_base_size' symbol
1040 with open(self.TestFile('u_boot_no_ucode_ptr'), 'rb') as fd:
1041 TestFunctional._MakeInputFile('u-boot', fd.read())
1043 with self.assertRaises(ValueError) as e:
1044 self._RunPackUbootSingleMicrocode()
1045 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
1046 "_dt_ucode_base_size symbol in u-boot", str(e.exception))
1049 # Put the original file back
1050 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
1051 TestFunctional._MakeInputFile('u-boot', fd.read())
1053 def testMicrocodeNotInImage(self):
1054 """Test that microcode must be placed within the image"""
1055 with self.assertRaises(ValueError) as e:
1056 self._DoReadFile('040_x86_ucode_not_in_image.dts', True)
1057 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
1058 "pointer _dt_ucode_base_size at fffffe14 is outside the "
1059 "section ranging from 00000000 to 0000002e", str(e.exception))
1061 def testWithoutMicrocode(self):
1062 """Test that we can cope with an image without microcode (e.g. qemu)"""
1063 with open(self.TestFile('u_boot_no_ucode_ptr'), 'rb') as fd:
1064 TestFunctional._MakeInputFile('u-boot', fd.read())
1065 data, dtb, _, _ = self._DoReadFileDtb('044_x86_optional_ucode.dts', True)
1067 # Now check the device tree has no microcode
1068 self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
1069 second = data[len(U_BOOT_NODTB_DATA):]
1071 fdt_len = self.GetFdtLen(second)
1072 self.assertEqual(dtb, second[:fdt_len])
1074 used_len = len(U_BOOT_NODTB_DATA) + fdt_len
1075 third = data[used_len:]
1076 self.assertEqual(tools.GetBytes(0, 0x200 - used_len), third)
1078 def testUnknownPosSize(self):
1079 """Test that microcode must be placed within the image"""
1080 with self.assertRaises(ValueError) as e:
1081 self._DoReadFile('041_unknown_pos_size.dts', True)
1082 self.assertIn("Section '/binman': Unable to set offset/size for unknown "
1083 "entry 'invalid-entry'", str(e.exception))
1085 def testPackFsp(self):
1086 """Test that an image with a FSP binary can be created"""
1087 data = self._DoReadFile('042_intel-fsp.dts')
1088 self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
1090 def testPackCmc(self):
1091 """Test that an image with a CMC binary can be created"""
1092 data = self._DoReadFile('043_intel-cmc.dts')
1093 self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
1095 def testPackVbt(self):
1096 """Test that an image with a VBT binary can be created"""
1097 data = self._DoReadFile('046_intel-vbt.dts')
1098 self.assertEqual(VBT_DATA, data[:len(VBT_DATA)])
1100 def testSplBssPad(self):
1101 """Test that we can pad SPL's BSS with zeros"""
1102 # ELF file with a '__bss_size' symbol
1104 data = self._DoReadFile('047_spl_bss_pad.dts')
1105 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0, 10) + U_BOOT_DATA,
1108 def testSplBssPadMissing(self):
1109 """Test that a missing symbol is detected"""
1110 self._SetupSplElf('u_boot_ucode_ptr')
1111 with self.assertRaises(ValueError) as e:
1112 self._DoReadFile('047_spl_bss_pad.dts')
1113 self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
1116 def testPackStart16Spl(self):
1117 """Test that an image with an x86 start16 SPL region can be created"""
1118 data = self._DoReadFile('048_x86-start16-spl.dts')
1119 self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)])
1121 def _PackUbootSplMicrocode(self, dts, ucode_second=False):
1122 """Helper function for microcode tests
1124 We expect to see the following in the image, in order:
1125 u-boot-spl-nodtb.bin with a microcode pointer inserted at the
1127 u-boot.dtb with the microcode removed
1131 dts: Device tree file to use for test
1132 ucode_second: True if the microsecond entry is second instead of
1135 self._SetupSplElf('u_boot_ucode_ptr')
1136 first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA,
1137 ucode_second=ucode_second)
1138 self.assertEqual(b'splnodtb with microc' + pos_and_size +
1139 b'ter somewhere in here', first)
1141 def testPackUbootSplMicrocode(self):
1142 """Test that x86 microcode can be handled correctly in SPL"""
1143 self._PackUbootSplMicrocode('049_x86_ucode_spl.dts')
1145 def testPackUbootSplMicrocodeReorder(self):
1146 """Test that order doesn't matter for microcode entries
1148 This is the same as testPackUbootSplMicrocode but when we process the
1149 u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode
1150 entry, so we reply on binman to try later.
1152 self._PackUbootSplMicrocode('058_x86_ucode_spl_needs_retry.dts',
1155 def testPackMrc(self):
1156 """Test that an image with an MRC binary can be created"""
1157 data = self._DoReadFile('050_intel_mrc.dts')
1158 self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
1160 def testSplDtb(self):
1161 """Test that an image with spl/u-boot-spl.dtb can be created"""
1162 data = self._DoReadFile('051_u_boot_spl_dtb.dts')
1163 self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
1165 def testSplNoDtb(self):
1166 """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
1167 data = self._DoReadFile('052_u_boot_spl_nodtb.dts')
1168 self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
1170 def testSymbols(self):
1171 """Test binman can assign symbols embedded in U-Boot"""
1172 elf_fname = self.TestFile('u_boot_binman_syms')
1173 syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
1174 addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
1175 self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
1177 self._SetupSplElf('u_boot_binman_syms')
1178 data = self._DoReadFile('053_symbols.dts')
1179 sym_values = struct.pack('<LQL', 0x24 + 0, 0x24 + 24, 0x24 + 20)
1180 expected = (sym_values + U_BOOT_SPL_DATA[16:] +
1181 tools.GetBytes(0xff, 1) + U_BOOT_DATA + sym_values +
1182 U_BOOT_SPL_DATA[16:])
1183 self.assertEqual(expected, data)
1185 def testPackUnitAddress(self):
1186 """Test that we support multiple binaries with the same name"""
1187 data = self._DoReadFile('054_unit_address.dts')
1188 self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
1190 def testSections(self):
1191 """Basic test of sections"""
1192 data = self._DoReadFile('055_sections.dts')
1193 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1194 U_BOOT_DATA + tools.GetBytes(ord('a'), 12) +
1195 U_BOOT_DATA + tools.GetBytes(ord('&'), 4))
1196 self.assertEqual(expected, data)
1199 """Tests outputting a map of the images"""
1200 _, _, map_data, _ = self._DoReadFileDtb('055_sections.dts', map=True)
1201 self.assertEqual('''ImagePos Offset Size Name
1202 00000000 00000000 00000028 main-section
1203 00000000 00000000 00000010 section@0
1204 00000000 00000000 00000004 u-boot
1205 00000010 00000010 00000010 section@1
1206 00000010 00000000 00000004 u-boot
1207 00000020 00000020 00000004 section@2
1208 00000020 00000000 00000004 u-boot
1211 def testNamePrefix(self):
1212 """Tests that name prefixes are used"""
1213 _, _, map_data, _ = self._DoReadFileDtb('056_name_prefix.dts', map=True)
1214 self.assertEqual('''ImagePos Offset Size Name
1215 00000000 00000000 00000028 main-section
1216 00000000 00000000 00000010 section@0
1217 00000000 00000000 00000004 ro-u-boot
1218 00000010 00000010 00000010 section@1
1219 00000010 00000000 00000004 rw-u-boot
1222 def testUnknownContents(self):
1223 """Test that obtaining the contents works as expected"""
1224 with self.assertRaises(ValueError) as e:
1225 self._DoReadFile('057_unknown_contents.dts', True)
1226 self.assertIn("Image '/binman': Internal error: Could not complete "
1227 "processing of contents: remaining [<_testing.Entry__testing ",
1230 def testBadChangeSize(self):
1231 """Test that trying to change the size of an entry fails"""
1233 state.SetAllowEntryExpansion(False)
1234 with self.assertRaises(ValueError) as e:
1235 self._DoReadFile('059_change_size.dts', True)
1236 self.assertIn("Node '/binman/_testing': Cannot update entry size from 1 to 2",
1239 state.SetAllowEntryExpansion(True)
1241 def testUpdateFdt(self):
1242 """Test that we can update the device tree with offset/size info"""
1243 _, _, _, out_dtb_fname = self._DoReadFileDtb('060_fdt_update.dts',
1245 dtb = fdt.Fdt(out_dtb_fname)
1247 props = self._GetPropTree(dtb, BASE_DTB_PROPS)
1251 '_testing:offset': 32,
1253 '_testing:image-pos': 32,
1254 'section@0/u-boot:offset': 0,
1255 'section@0/u-boot:size': len(U_BOOT_DATA),
1256 'section@0/u-boot:image-pos': 0,
1257 'section@0:offset': 0,
1258 'section@0:size': 16,
1259 'section@0:image-pos': 0,
1261 'section@1/u-boot:offset': 0,
1262 'section@1/u-boot:size': len(U_BOOT_DATA),
1263 'section@1/u-boot:image-pos': 16,
1264 'section@1:offset': 16,
1265 'section@1:size': 16,
1266 'section@1:image-pos': 16,
1270 def testUpdateFdtBad(self):
1271 """Test that we detect when ProcessFdt never completes"""
1272 with self.assertRaises(ValueError) as e:
1273 self._DoReadFileDtb('061_fdt_update_bad.dts', update_dtb=True)
1274 self.assertIn('Could not complete processing of Fdt: remaining '
1275 '[<_testing.Entry__testing', str(e.exception))
1277 def testEntryArgs(self):
1278 """Test passing arguments to entries from the command line"""
1280 'test-str-arg': 'test1',
1281 'test-int-arg': '456',
1283 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
1284 self.assertIn('image', control.images)
1285 entry = control.images['image'].GetEntries()['_testing']
1286 self.assertEqual('test0', entry.test_str_fdt)
1287 self.assertEqual('test1', entry.test_str_arg)
1288 self.assertEqual(123, entry.test_int_fdt)
1289 self.assertEqual(456, entry.test_int_arg)
1291 def testEntryArgsMissing(self):
1292 """Test missing arguments and properties"""
1294 'test-int-arg': '456',
1296 self._DoReadFileDtb('063_entry_args_missing.dts', entry_args=entry_args)
1297 entry = control.images['image'].GetEntries()['_testing']
1298 self.assertEqual('test0', entry.test_str_fdt)
1299 self.assertEqual(None, entry.test_str_arg)
1300 self.assertEqual(None, entry.test_int_fdt)
1301 self.assertEqual(456, entry.test_int_arg)
1303 def testEntryArgsRequired(self):
1304 """Test missing arguments and properties"""
1306 'test-int-arg': '456',
1308 with self.assertRaises(ValueError) as e:
1309 self._DoReadFileDtb('064_entry_args_required.dts')
1310 self.assertIn("Node '/binman/_testing': Missing required "
1311 'properties/entry args: test-str-arg, test-int-fdt, test-int-arg',
1314 def testEntryArgsInvalidFormat(self):
1315 """Test that an invalid entry-argument format is detected"""
1316 args = ['build', '-d', self.TestFile('064_entry_args_required.dts'),
1318 with self.assertRaises(ValueError) as e:
1319 self._DoBinman(*args)
1320 self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
1322 def testEntryArgsInvalidInteger(self):
1323 """Test that an invalid entry-argument integer is detected"""
1325 'test-int-arg': 'abc',
1327 with self.assertRaises(ValueError) as e:
1328 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
1329 self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
1330 "'test-int-arg' (value 'abc') to integer",
1333 def testEntryArgsInvalidDatatype(self):
1334 """Test that an invalid entry-argument datatype is detected
1336 This test could be written in entry_test.py except that it needs
1337 access to control.entry_args, which seems more than that module should
1341 'test-bad-datatype-arg': '12',
1343 with self.assertRaises(ValueError) as e:
1344 self._DoReadFileDtb('065_entry_args_unknown_datatype.dts',
1345 entry_args=entry_args)
1346 self.assertIn('GetArg() internal error: Unknown data type ',
1350 """Test for a text entry type"""
1352 'test-id': TEXT_DATA,
1353 'test-id2': TEXT_DATA2,
1354 'test-id3': TEXT_DATA3,
1356 data, _, _, _ = self._DoReadFileDtb('066_text.dts',
1357 entry_args=entry_args)
1358 expected = (tools.ToBytes(TEXT_DATA) +
1359 tools.GetBytes(0, 8 - len(TEXT_DATA)) +
1360 tools.ToBytes(TEXT_DATA2) + tools.ToBytes(TEXT_DATA3) +
1361 b'some text' + b'more text')
1362 self.assertEqual(expected, data)
1364 def testEntryDocs(self):
1365 """Test for creation of entry documentation"""
1366 with test_util.capture_sys_output() as (stdout, stderr):
1367 control.WriteEntryDocs(binman.GetEntryModules())
1368 self.assertTrue(len(stdout.getvalue()) > 0)
1370 def testEntryDocsMissing(self):
1371 """Test handling of missing entry documentation"""
1372 with self.assertRaises(ValueError) as e:
1373 with test_util.capture_sys_output() as (stdout, stderr):
1374 control.WriteEntryDocs(binman.GetEntryModules(), 'u_boot')
1375 self.assertIn('Documentation is missing for modules: u_boot',
1379 """Basic test of generation of a flashrom fmap"""
1380 data = self._DoReadFile('067_fmap.dts')
1381 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1382 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1383 U_BOOT_DATA + tools.GetBytes(ord('a'), 12))
1384 self.assertEqual(expected, data[:32])
1385 self.assertEqual(b'__FMAP__', fhdr.signature)
1386 self.assertEqual(1, fhdr.ver_major)
1387 self.assertEqual(0, fhdr.ver_minor)
1388 self.assertEqual(0, fhdr.base)
1389 self.assertEqual(16 + 16 +
1390 fmap_util.FMAP_HEADER_LEN +
1391 fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
1392 self.assertEqual(b'FMAP', fhdr.name)
1393 self.assertEqual(3, fhdr.nareas)
1394 for fentry in fentries:
1395 self.assertEqual(0, fentry.flags)
1397 self.assertEqual(0, fentries[0].offset)
1398 self.assertEqual(4, fentries[0].size)
1399 self.assertEqual(b'RO_U_BOOT', fentries[0].name)
1401 self.assertEqual(16, fentries[1].offset)
1402 self.assertEqual(4, fentries[1].size)
1403 self.assertEqual(b'RW_U_BOOT', fentries[1].name)
1405 self.assertEqual(32, fentries[2].offset)
1406 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1407 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1408 self.assertEqual(b'FMAP', fentries[2].name)
1410 def testBlobNamedByArg(self):
1411 """Test we can add a blob with the filename coming from an entry arg"""
1413 'cros-ec-rw-path': 'ecrw.bin',
1415 data, _, _, _ = self._DoReadFileDtb('068_blob_named_by_arg.dts',
1416 entry_args=entry_args)
1419 """Test for an fill entry type"""
1420 data = self._DoReadFile('069_fill.dts')
1421 expected = tools.GetBytes(0xff, 8) + tools.GetBytes(0, 8)
1422 self.assertEqual(expected, data)
1424 def testFillNoSize(self):
1425 """Test for an fill entry type with no size"""
1426 with self.assertRaises(ValueError) as e:
1427 self._DoReadFile('070_fill_no_size.dts')
1428 self.assertIn("'fill' entry must have a size property",
1431 def _HandleGbbCommand(self, pipe_list):
1432 """Fake calls to the futility utility"""
1433 if pipe_list[0][0] == 'futility':
1434 fname = pipe_list[0][-1]
1435 # Append our GBB data to the file, which will happen every time the
1436 # futility command is called.
1437 with open(fname, 'ab') as fd:
1439 return command.CommandResult()
1442 """Test for the Chromium OS Google Binary Block"""
1443 command.test_result = self._HandleGbbCommand
1445 'keydir': 'devkeys',
1446 'bmpblk': 'bmpblk.bin',
1448 data, _, _, _ = self._DoReadFileDtb('071_gbb.dts', entry_args=entry_args)
1451 expected = (GBB_DATA + GBB_DATA + tools.GetBytes(0, 8) +
1452 tools.GetBytes(0, 0x2180 - 16))
1453 self.assertEqual(expected, data)
1455 def testGbbTooSmall(self):
1456 """Test for the Chromium OS Google Binary Block being large enough"""
1457 with self.assertRaises(ValueError) as e:
1458 self._DoReadFileDtb('072_gbb_too_small.dts')
1459 self.assertIn("Node '/binman/gbb': GBB is too small",
1462 def testGbbNoSize(self):
1463 """Test for the Chromium OS Google Binary Block having a size"""
1464 with self.assertRaises(ValueError) as e:
1465 self._DoReadFileDtb('073_gbb_no_size.dts')
1466 self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
1469 def _HandleVblockCommand(self, pipe_list):
1470 """Fake calls to the futility utility"""
1471 if pipe_list[0][0] == 'futility':
1472 fname = pipe_list[0][3]
1473 with open(fname, 'wb') as fd:
1474 fd.write(VBLOCK_DATA)
1475 return command.CommandResult()
1477 def testVblock(self):
1478 """Test for the Chromium OS Verified Boot Block"""
1479 command.test_result = self._HandleVblockCommand
1481 'keydir': 'devkeys',
1483 data, _, _, _ = self._DoReadFileDtb('074_vblock.dts',
1484 entry_args=entry_args)
1485 expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
1486 self.assertEqual(expected, data)
1488 def testVblockNoContent(self):
1489 """Test we detect a vblock which has no content to sign"""
1490 with self.assertRaises(ValueError) as e:
1491 self._DoReadFile('075_vblock_no_content.dts')
1492 self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
1493 'property', str(e.exception))
1495 def testVblockBadPhandle(self):
1496 """Test that we detect a vblock with an invalid phandle in contents"""
1497 with self.assertRaises(ValueError) as e:
1498 self._DoReadFile('076_vblock_bad_phandle.dts')
1499 self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
1500 '1000', str(e.exception))
1502 def testVblockBadEntry(self):
1503 """Test that we detect an entry that points to a non-entry"""
1504 with self.assertRaises(ValueError) as e:
1505 self._DoReadFile('077_vblock_bad_entry.dts')
1506 self.assertIn("Node '/binman/vblock': Cannot find entry for node "
1507 "'other'", str(e.exception))
1510 """Test that an image with TPL and ots device tree can be created"""
1511 # ELF file with a '__bss_size' symbol
1512 with open(self.TestFile('bss_data'), 'rb') as fd:
1513 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1514 data = self._DoReadFile('078_u_boot_tpl.dts')
1515 self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
1517 def testUsesPos(self):
1518 """Test that the 'pos' property cannot be used anymore"""
1519 with self.assertRaises(ValueError) as e:
1520 data = self._DoReadFile('079_uses_pos.dts')
1521 self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
1522 "'pos'", str(e.exception))
1524 def testFillZero(self):
1525 """Test for an fill entry type with a size of 0"""
1526 data = self._DoReadFile('080_fill_empty.dts')
1527 self.assertEqual(tools.GetBytes(0, 16), data)
1529 def testTextMissing(self):
1530 """Test for a text entry type where there is no text"""
1531 with self.assertRaises(ValueError) as e:
1532 self._DoReadFileDtb('066_text.dts',)
1533 self.assertIn("Node '/binman/text': No value provided for text label "
1534 "'test-id'", str(e.exception))
1536 def testPackStart16Tpl(self):
1537 """Test that an image with an x86 start16 TPL region can be created"""
1538 data = self._DoReadFile('081_x86-start16-tpl.dts')
1539 self.assertEqual(X86_START16_TPL_DATA, data[:len(X86_START16_TPL_DATA)])
1541 def testSelectImage(self):
1542 """Test that we can select which images to build"""
1543 expected = 'Skipping images: image1'
1545 # We should only get the expected message in verbose mode
1546 for verbosity in (0, 2):
1547 with test_util.capture_sys_output() as (stdout, stderr):
1548 retcode = self._DoTestFile('006_dual_image.dts',
1549 verbosity=verbosity,
1551 self.assertEqual(0, retcode)
1553 self.assertIn(expected, stdout.getvalue())
1555 self.assertNotIn(expected, stdout.getvalue())
1557 self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
1558 self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
1560 def testUpdateFdtAll(self):
1561 """Test that all device trees are updated with offset/size info"""
1562 data = self._DoReadFileRealDtb('082_fdt_update_all.dts')
1565 'section:image-pos': 0,
1566 'u-boot-tpl-dtb:size': 513,
1567 'u-boot-spl-dtb:size': 513,
1568 'u-boot-spl-dtb:offset': 493,
1570 'section/u-boot-dtb:image-pos': 0,
1571 'u-boot-spl-dtb:image-pos': 493,
1572 'section/u-boot-dtb:size': 493,
1573 'u-boot-tpl-dtb:image-pos': 1006,
1574 'section/u-boot-dtb:offset': 0,
1575 'section:size': 493,
1577 'section:offset': 0,
1578 'u-boot-tpl-dtb:offset': 1006,
1582 # We expect three device-tree files in the output, one after the other.
1583 # Read them in sequence. We look for an 'spl' property in the SPL tree,
1584 # and 'tpl' in the TPL tree, to make sure they are distinct from the
1585 # main U-Boot tree. All three should have the same postions and offset.
1587 for item in ['', 'spl', 'tpl']:
1588 dtb = fdt.Fdt.FromData(data[start:])
1590 props = self._GetPropTree(dtb, BASE_DTB_PROPS + ['spl', 'tpl'])
1591 expected = dict(base_expected)
1594 self.assertEqual(expected, props)
1595 start += dtb._fdt_obj.totalsize()
1597 def testUpdateFdtOutput(self):
1598 """Test that output DTB files are updated"""
1600 data, dtb_data, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
1601 use_real_dtb=True, update_dtb=True, reset_dtbs=False)
1603 # Unfortunately, compiling a source file always results in a file
1604 # called source.dtb (see fdt_util.EnsureCompiled()). The test
1605 # source file (e.g. test/075_fdt_update_all.dts) thus does not enter
1606 # binman as a file called u-boot.dtb. To fix this, copy the file
1607 # over to the expected place.
1608 #tools.WriteFile(os.path.join(self._indir, 'u-boot.dtb'),
1609 #tools.ReadFile(tools.GetOutputFilename('source.dtb')))
1611 for fname in ['u-boot.dtb.out', 'spl/u-boot-spl.dtb.out',
1612 'tpl/u-boot-tpl.dtb.out']:
1613 dtb = fdt.Fdt.FromData(data[start:])
1614 size = dtb._fdt_obj.totalsize()
1615 pathname = tools.GetOutputFilename(os.path.split(fname)[1])
1616 outdata = tools.ReadFile(pathname)
1617 name = os.path.split(fname)[0]
1620 orig_indata = self._GetDtbContentsForSplTpl(dtb_data, name)
1622 orig_indata = dtb_data
1623 self.assertNotEqual(outdata, orig_indata,
1624 "Expected output file '%s' be updated" % pathname)
1625 self.assertEqual(outdata, data[start:start + size],
1626 "Expected output file '%s' to match output image" %
1632 def _decompress(self, data):
1633 return tools.Decompress(data, 'lz4')
1635 def testCompress(self):
1636 """Test compression of blobs"""
1638 data, _, _, out_dtb_fname = self._DoReadFileDtb('083_compress.dts',
1639 use_real_dtb=True, update_dtb=True)
1640 dtb = fdt.Fdt(out_dtb_fname)
1642 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
1643 orig = self._decompress(data)
1644 self.assertEquals(COMPRESS_DATA, orig)
1646 'blob:uncomp-size': len(COMPRESS_DATA),
1647 'blob:size': len(data),
1650 self.assertEqual(expected, props)
1652 def testFiles(self):
1653 """Test bringing in multiple files"""
1654 data = self._DoReadFile('084_files.dts')
1655 self.assertEqual(FILES_DATA, data)
1657 def testFilesCompress(self):
1658 """Test bringing in multiple files and compressing them"""
1660 data = self._DoReadFile('085_files_compress.dts')
1662 image = control.images['image']
1663 entries = image.GetEntries()
1664 files = entries['files']
1665 entries = files._entries
1668 for i in range(1, 3):
1670 start = entries[key].image_pos
1671 len = entries[key].size
1672 chunk = data[start:start + len]
1673 orig += self._decompress(chunk)
1675 self.assertEqual(FILES_DATA, orig)
1677 def testFilesMissing(self):
1678 """Test missing files"""
1679 with self.assertRaises(ValueError) as e:
1680 data = self._DoReadFile('086_files_none.dts')
1681 self.assertIn("Node '/binman/files': Pattern \'files/*.none\' matched "
1682 'no files', str(e.exception))
1684 def testFilesNoPattern(self):
1685 """Test missing files"""
1686 with self.assertRaises(ValueError) as e:
1687 data = self._DoReadFile('087_files_no_pattern.dts')
1688 self.assertIn("Node '/binman/files': Missing 'pattern' property",
1691 def testExpandSize(self):
1692 """Test an expanding entry"""
1693 data, _, map_data, _ = self._DoReadFileDtb('088_expand_size.dts',
1695 expect = (tools.GetBytes(ord('a'), 8) + U_BOOT_DATA +
1696 MRC_DATA + tools.GetBytes(ord('b'), 1) + U_BOOT_DATA +
1697 tools.GetBytes(ord('c'), 8) + U_BOOT_DATA +
1698 tools.GetBytes(ord('d'), 8))
1699 self.assertEqual(expect, data)
1700 self.assertEqual('''ImagePos Offset Size Name
1701 00000000 00000000 00000028 main-section
1702 00000000 00000000 00000008 fill
1703 00000008 00000008 00000004 u-boot
1704 0000000c 0000000c 00000004 section
1705 0000000c 00000000 00000003 intel-mrc
1706 00000010 00000010 00000004 u-boot2
1707 00000014 00000014 0000000c section2
1708 00000014 00000000 00000008 fill
1709 0000001c 00000008 00000004 u-boot
1710 00000020 00000020 00000008 fill2
1713 def testExpandSizeBad(self):
1714 """Test an expanding entry which fails to provide contents"""
1715 with test_util.capture_sys_output() as (stdout, stderr):
1716 with self.assertRaises(ValueError) as e:
1717 self._DoReadFileDtb('089_expand_size_bad.dts', map=True)
1718 self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
1719 'expanding entry', str(e.exception))
1722 """Test hashing of the contents of an entry"""
1723 _, _, _, out_dtb_fname = self._DoReadFileDtb('090_hash.dts',
1724 use_real_dtb=True, update_dtb=True)
1725 dtb = fdt.Fdt(out_dtb_fname)
1727 hash_node = dtb.GetNode('/binman/u-boot/hash').props['value']
1728 m = hashlib.sha256()
1729 m.update(U_BOOT_DATA)
1730 self.assertEqual(m.digest(), b''.join(hash_node.value))
1732 def testHashNoAlgo(self):
1733 with self.assertRaises(ValueError) as e:
1734 self._DoReadFileDtb('091_hash_no_algo.dts', update_dtb=True)
1735 self.assertIn("Node \'/binman/u-boot\': Missing \'algo\' property for "
1736 'hash node', str(e.exception))
1738 def testHashBadAlgo(self):
1739 with self.assertRaises(ValueError) as e:
1740 self._DoReadFileDtb('092_hash_bad_algo.dts', update_dtb=True)
1741 self.assertIn("Node '/binman/u-boot': Unknown hash algorithm",
1744 def testHashSection(self):
1745 """Test hashing of the contents of an entry"""
1746 _, _, _, out_dtb_fname = self._DoReadFileDtb('099_hash_section.dts',
1747 use_real_dtb=True, update_dtb=True)
1748 dtb = fdt.Fdt(out_dtb_fname)
1750 hash_node = dtb.GetNode('/binman/section/hash').props['value']
1751 m = hashlib.sha256()
1752 m.update(U_BOOT_DATA)
1753 m.update(tools.GetBytes(ord('a'), 16))
1754 self.assertEqual(m.digest(), b''.join(hash_node.value))
1756 def testPackUBootTplMicrocode(self):
1757 """Test that x86 microcode can be handled correctly in TPL
1759 We expect to see the following in the image, in order:
1760 u-boot-tpl-nodtb.bin with a microcode pointer inserted at the correct
1762 u-boot-tpl.dtb with the microcode removed
1765 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
1766 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1767 first, pos_and_size = self._RunMicrocodeTest('093_x86_tpl_ucode.dts',
1768 U_BOOT_TPL_NODTB_DATA)
1769 self.assertEqual(b'tplnodtb with microc' + pos_and_size +
1770 b'ter somewhere in here', first)
1772 def testFmapX86(self):
1773 """Basic test of generation of a flashrom fmap"""
1774 data = self._DoReadFile('094_fmap_x86.dts')
1775 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1776 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('a'), 32 - 7)
1777 self.assertEqual(expected, data[:32])
1778 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1780 self.assertEqual(0x100, fhdr.image_size)
1782 self.assertEqual(0, fentries[0].offset)
1783 self.assertEqual(4, fentries[0].size)
1784 self.assertEqual(b'U_BOOT', fentries[0].name)
1786 self.assertEqual(4, fentries[1].offset)
1787 self.assertEqual(3, fentries[1].size)
1788 self.assertEqual(b'INTEL_MRC', fentries[1].name)
1790 self.assertEqual(32, fentries[2].offset)
1791 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1792 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1793 self.assertEqual(b'FMAP', fentries[2].name)
1795 def testFmapX86Section(self):
1796 """Basic test of generation of a flashrom fmap"""
1797 data = self._DoReadFile('095_fmap_x86_section.dts')
1798 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('b'), 32 - 7)
1799 self.assertEqual(expected, data[:32])
1800 fhdr, fentries = fmap_util.DecodeFmap(data[36:])
1802 self.assertEqual(0x100, fhdr.image_size)
1804 self.assertEqual(0, fentries[0].offset)
1805 self.assertEqual(4, fentries[0].size)
1806 self.assertEqual(b'U_BOOT', fentries[0].name)
1808 self.assertEqual(4, fentries[1].offset)
1809 self.assertEqual(3, fentries[1].size)
1810 self.assertEqual(b'INTEL_MRC', fentries[1].name)
1812 self.assertEqual(36, fentries[2].offset)
1813 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1814 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1815 self.assertEqual(b'FMAP', fentries[2].name)
1818 """Basic test of ELF entries"""
1820 with open(self.TestFile('bss_data'), 'rb') as fd:
1821 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1822 with open(self.TestFile('bss_data'), 'rb') as fd:
1823 TestFunctional._MakeInputFile('-boot', fd.read())
1824 data = self._DoReadFile('096_elf.dts')
1826 def testElfStrip(self):
1827 """Basic test of ELF entries"""
1829 with open(self.TestFile('bss_data'), 'rb') as fd:
1830 TestFunctional._MakeInputFile('-boot', fd.read())
1831 data = self._DoReadFile('097_elf_strip.dts')
1833 def testPackOverlapMap(self):
1834 """Test that overlapping regions are detected"""
1835 with test_util.capture_sys_output() as (stdout, stderr):
1836 with self.assertRaises(ValueError) as e:
1837 self._DoTestFile('014_pack_overlap.dts', map=True)
1838 map_fname = tools.GetOutputFilename('image.map')
1839 self.assertEqual("Wrote map file '%s' to show errors\n" % map_fname,
1842 # We should not get an inmage, but there should be a map file
1843 self.assertFalse(os.path.exists(tools.GetOutputFilename('image.bin')))
1844 self.assertTrue(os.path.exists(map_fname))
1845 map_data = tools.ReadFile(map_fname, binary=False)
1846 self.assertEqual('''ImagePos Offset Size Name
1847 <none> 00000000 00000007 main-section
1848 <none> 00000000 00000004 u-boot
1849 <none> 00000003 00000004 u-boot-align
1852 def testPackRefCode(self):
1853 """Test that an image with an Intel Reference code binary works"""
1854 data = self._DoReadFile('100_intel_refcode.dts')
1855 self.assertEqual(REFCODE_DATA, data[:len(REFCODE_DATA)])
1857 def testSectionOffset(self):
1858 """Tests use of a section with an offset"""
1859 data, _, map_data, _ = self._DoReadFileDtb('101_sections_offset.dts',
1861 self.assertEqual('''ImagePos Offset Size Name
1862 00000000 00000000 00000038 main-section
1863 00000004 00000004 00000010 section@0
1864 00000004 00000000 00000004 u-boot
1865 00000018 00000018 00000010 section@1
1866 00000018 00000000 00000004 u-boot
1867 0000002c 0000002c 00000004 section@2
1868 0000002c 00000000 00000004 u-boot
1870 self.assertEqual(data,
1871 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1872 tools.GetBytes(0x21, 12) +
1873 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1874 tools.GetBytes(0x61, 12) +
1875 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1876 tools.GetBytes(0x26, 8))
1878 def testCbfsRaw(self):
1879 """Test base handling of a Coreboot Filesystem (CBFS)
1881 The exact contents of the CBFS is verified by similar tests in
1882 cbfs_util_test.py. The tests here merely check that the files added to
1883 the CBFS can be found in the final image.
1885 data = self._DoReadFile('102_cbfs_raw.dts')
1888 cbfs = cbfs_util.CbfsReader(data)
1889 self.assertEqual(size, cbfs.rom_size)
1891 self.assertIn('u-boot-dtb', cbfs.files)
1892 cfile = cbfs.files['u-boot-dtb']
1893 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
1895 def testCbfsArch(self):
1896 """Test on non-x86 architecture"""
1897 data = self._DoReadFile('103_cbfs_raw_ppc.dts')
1900 cbfs = cbfs_util.CbfsReader(data)
1901 self.assertEqual(size, cbfs.rom_size)
1903 self.assertIn('u-boot-dtb', cbfs.files)
1904 cfile = cbfs.files['u-boot-dtb']
1905 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
1907 def testCbfsStage(self):
1908 """Tests handling of a Coreboot Filesystem (CBFS)"""
1909 if not elf.ELF_TOOLS:
1910 self.skipTest('Python elftools not available')
1911 elf_fname = os.path.join(self._indir, 'cbfs-stage.elf')
1912 elf.MakeElf(elf_fname, U_BOOT_DATA, U_BOOT_DTB_DATA)
1915 data = self._DoReadFile('104_cbfs_stage.dts')
1916 cbfs = cbfs_util.CbfsReader(data)
1917 self.assertEqual(size, cbfs.rom_size)
1919 self.assertIn('u-boot', cbfs.files)
1920 cfile = cbfs.files['u-boot']
1921 self.assertEqual(U_BOOT_DATA + U_BOOT_DTB_DATA, cfile.data)
1923 def testCbfsRawCompress(self):
1924 """Test handling of compressing raw files"""
1926 data = self._DoReadFile('105_cbfs_raw_compress.dts')
1929 cbfs = cbfs_util.CbfsReader(data)
1930 self.assertIn('u-boot', cbfs.files)
1931 cfile = cbfs.files['u-boot']
1932 self.assertEqual(COMPRESS_DATA, cfile.data)
1934 def testCbfsBadArch(self):
1935 """Test handling of a bad architecture"""
1936 with self.assertRaises(ValueError) as e:
1937 self._DoReadFile('106_cbfs_bad_arch.dts')
1938 self.assertIn("Invalid architecture 'bad-arch'", str(e.exception))
1940 def testCbfsNoSize(self):
1941 """Test handling of a missing size property"""
1942 with self.assertRaises(ValueError) as e:
1943 self._DoReadFile('107_cbfs_no_size.dts')
1944 self.assertIn('entry must have a size property', str(e.exception))
1946 def testCbfsNoCOntents(self):
1947 """Test handling of a CBFS entry which does not provide contentsy"""
1948 with self.assertRaises(ValueError) as e:
1949 self._DoReadFile('108_cbfs_no_contents.dts')
1950 self.assertIn('Could not complete processing of contents',
1953 def testCbfsBadCompress(self):
1954 """Test handling of a bad architecture"""
1955 with self.assertRaises(ValueError) as e:
1956 self._DoReadFile('109_cbfs_bad_compress.dts')
1957 self.assertIn("Invalid compression in 'u-boot': 'invalid-algo'",
1960 def testCbfsNamedEntries(self):
1961 """Test handling of named entries"""
1962 data = self._DoReadFile('110_cbfs_name.dts')
1964 cbfs = cbfs_util.CbfsReader(data)
1965 self.assertIn('FRED', cbfs.files)
1966 cfile1 = cbfs.files['FRED']
1967 self.assertEqual(U_BOOT_DATA, cfile1.data)
1969 self.assertIn('hello', cbfs.files)
1970 cfile2 = cbfs.files['hello']
1971 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
1973 def _SetupIfwi(self, fname):
1974 """Set up to run an IFWI test
1977 fname: Filename of input file to provide (fitimage.bin or ifwi.bin)
1981 # Intel Integrated Firmware Image (IFWI) file
1982 with gzip.open(self.TestFile('%s.gz' % fname), 'rb') as fd:
1984 TestFunctional._MakeInputFile(fname,data)
1986 def _CheckIfwi(self, data):
1987 """Check that an image with an IFWI contains the correct output
1990 data: Conents of output file
1992 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
1993 if data[:0x1000] != expected_desc:
1994 self.fail('Expected descriptor binary at start of image')
1996 # We expect to find the TPL wil in subpart IBBP entry IBBL
1997 image_fname = tools.GetOutputFilename('image.bin')
1998 tpl_fname = tools.GetOutputFilename('tpl.out')
1999 tools.RunIfwiTool(image_fname, tools.CMD_EXTRACT, fname=tpl_fname,
2000 subpart='IBBP', entry_name='IBBL')
2002 tpl_data = tools.ReadFile(tpl_fname)
2003 self.assertEqual(tpl_data[:len(U_BOOT_TPL_DATA)], U_BOOT_TPL_DATA)
2005 def testPackX86RomIfwi(self):
2006 """Test that an x86 ROM with Integrated Firmware Image can be created"""
2007 self._SetupIfwi('fitimage.bin')
2008 data = self._DoReadFile('111_x86-rom-ifwi.dts')
2009 self._CheckIfwi(data)
2011 def testPackX86RomIfwiNoDesc(self):
2012 """Test that an x86 ROM with IFWI can be created from an ifwi.bin file"""
2013 self._SetupIfwi('ifwi.bin')
2014 data = self._DoReadFile('112_x86-rom-ifwi-nodesc.dts')
2015 self._CheckIfwi(data)
2017 def testPackX86RomIfwiNoData(self):
2018 """Test that an x86 ROM with IFWI handles missing data"""
2019 self._SetupIfwi('ifwi.bin')
2020 with self.assertRaises(ValueError) as e:
2021 data = self._DoReadFile('113_x86-rom-ifwi-nodata.dts')
2022 self.assertIn('Could not complete processing of contents',
2025 def testCbfsOffset(self):
2026 """Test a CBFS with files at particular offsets
2028 Like all CFBS tests, this is just checking the logic that calls
2029 cbfs_util. See cbfs_util_test for fully tests (e.g. test_cbfs_offset()).
2031 data = self._DoReadFile('114_cbfs_offset.dts')
2034 cbfs = cbfs_util.CbfsReader(data)
2035 self.assertEqual(size, cbfs.rom_size)
2037 self.assertIn('u-boot', cbfs.files)
2038 cfile = cbfs.files['u-boot']
2039 self.assertEqual(U_BOOT_DATA, cfile.data)
2040 self.assertEqual(0x40, cfile.cbfs_offset)
2042 self.assertIn('u-boot-dtb', cbfs.files)
2043 cfile2 = cbfs.files['u-boot-dtb']
2044 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
2045 self.assertEqual(0x140, cfile2.cbfs_offset)
2047 def testFdtmap(self):
2048 """Test an FDT map can be inserted in the image"""
2049 data = self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
2050 fdtmap_data = data[len(U_BOOT_DATA):]
2051 magic = fdtmap_data[:8]
2052 self.assertEqual('_FDTMAP_', magic)
2053 self.assertEqual(tools.GetBytes(0, 8), fdtmap_data[8:16])
2055 fdt_data = fdtmap_data[16:]
2056 dtb = fdt.Fdt.FromData(fdt_data)
2058 props = self._GetPropTree(dtb, BASE_DTB_PROPS, prefix='/')
2063 'u-boot:size': len(U_BOOT_DATA),
2064 'u-boot:image-pos': 0,
2065 'fdtmap:image-pos': 4,
2067 'fdtmap:size': len(fdtmap_data),
2071 def testFdtmapNoMatch(self):
2072 """Check handling of an FDT map when the section cannot be found"""
2073 self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
2075 # Mangle the section name, which should cause a mismatch between the
2076 # correct FDT path and the one expected by the section
2077 image = control.images['image']
2078 image._node.path += '-suffix'
2079 entries = image.GetEntries()
2080 fdtmap = entries['fdtmap']
2081 with self.assertRaises(ValueError) as e:
2083 self.assertIn("Cannot locate node for path '/binman-suffix'",
2086 def testFdtmapHeader(self):
2087 """Test an FDT map and image header can be inserted in the image"""
2088 data = self.data = self._DoReadFileRealDtb('116_fdtmap_hdr.dts')
2089 fdtmap_pos = len(U_BOOT_DATA)
2090 fdtmap_data = data[fdtmap_pos:]
2091 fdt_data = fdtmap_data[16:]
2092 dtb = fdt.Fdt.FromData(fdt_data)
2093 fdt_size = dtb.GetFdtObj().totalsize()
2094 hdr_data = data[-8:]
2095 self.assertEqual('BinM', hdr_data[:4])
2096 offset = struct.unpack('<I', hdr_data[4:])[0] & 0xffffffff
2097 self.assertEqual(fdtmap_pos - 0x400, offset - (1 << 32))
2099 def testFdtmapHeaderStart(self):
2100 """Test an image header can be inserted at the image start"""
2101 data = self.data = self._DoReadFileRealDtb('117_fdtmap_hdr_start.dts')
2102 fdtmap_pos = 0x100 + len(U_BOOT_DATA)
2104 self.assertEqual('BinM', hdr_data[:4])
2105 offset = struct.unpack('<I', hdr_data[4:])[0]
2106 self.assertEqual(fdtmap_pos, offset)
2108 def testFdtmapHeaderPos(self):
2109 """Test an image header can be inserted at a chosen position"""
2110 data = self.data = self._DoReadFileRealDtb('118_fdtmap_hdr_pos.dts')
2111 fdtmap_pos = 0x100 + len(U_BOOT_DATA)
2112 hdr_data = data[0x80:0x88]
2113 self.assertEqual('BinM', hdr_data[:4])
2114 offset = struct.unpack('<I', hdr_data[4:])[0]
2115 self.assertEqual(fdtmap_pos, offset)
2117 def testHeaderMissingFdtmap(self):
2118 """Test an image header requires an fdtmap"""
2119 with self.assertRaises(ValueError) as e:
2120 self.data = self._DoReadFileRealDtb('119_fdtmap_hdr_missing.dts')
2121 self.assertIn("'image_header' section must have an 'fdtmap' sibling",
2124 def testHeaderNoLocation(self):
2125 """Test an image header with a no specified location is detected"""
2126 with self.assertRaises(ValueError) as e:
2127 self.data = self._DoReadFileRealDtb('120_hdr_no_location.dts')
2128 self.assertIn("Invalid location 'None', expected 'start' or 'end'",
2131 def testEntryExpand(self):
2132 """Test expanding an entry after it is packed"""
2133 data = self._DoReadFile('121_entry_expand.dts')
2134 self.assertEqual(b'aa', data[:2])
2135 self.assertEqual(U_BOOT_DATA, data[2:2 + len(U_BOOT_DATA)])
2136 self.assertEqual(b'aa', data[-2:])
2138 def testEntryExpandBad(self):
2139 """Test expanding an entry after it is packed, twice"""
2140 with self.assertRaises(ValueError) as e:
2141 self._DoReadFile('122_entry_expand_twice.dts')
2142 self.assertIn("Image '/binman': Entries expanded after packing",
2145 def testEntryExpandSection(self):
2146 """Test expanding an entry within a section after it is packed"""
2147 data = self._DoReadFile('123_entry_expand_section.dts')
2148 self.assertEqual(b'aa', data[:2])
2149 self.assertEqual(U_BOOT_DATA, data[2:2 + len(U_BOOT_DATA)])
2150 self.assertEqual(b'aa', data[-2:])
2152 def testCompressDtb(self):
2153 """Test that compress of device-tree files is supported"""
2155 data = self.data = self._DoReadFileRealDtb('124_compress_dtb.dts')
2156 self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
2157 comp_data = data[len(U_BOOT_DATA):]
2158 orig = self._decompress(comp_data)
2159 dtb = fdt.Fdt.FromData(orig)
2161 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
2163 'u-boot:size': len(U_BOOT_DATA),
2164 'u-boot-dtb:uncomp-size': len(orig),
2165 'u-boot-dtb:size': len(comp_data),
2168 self.assertEqual(expected, props)
2170 def testCbfsUpdateFdt(self):
2171 """Test that we can update the device tree with CBFS offset/size info"""
2173 data, _, _, out_dtb_fname = self._DoReadFileDtb('125_cbfs_update.dts',
2175 dtb = fdt.Fdt(out_dtb_fname)
2177 props = self._GetPropTree(dtb, BASE_DTB_PROPS + ['uncomp-size'])
2178 del props['cbfs/u-boot:size']
2184 'cbfs:size': len(data),
2185 'cbfs:image-pos': 0,
2186 'cbfs/u-boot:offset': 0x38,
2187 'cbfs/u-boot:uncomp-size': len(U_BOOT_DATA),
2188 'cbfs/u-boot:image-pos': 0x38,
2189 'cbfs/u-boot-dtb:offset': 0xb8,
2190 'cbfs/u-boot-dtb:size': len(U_BOOT_DATA),
2191 'cbfs/u-boot-dtb:image-pos': 0xb8,
2194 def testCbfsBadType(self):
2195 """Test an image header with a no specified location is detected"""
2196 with self.assertRaises(ValueError) as e:
2197 self._DoReadFile('126_cbfs_bad_type.dts')
2198 self.assertIn("Unknown cbfs-type 'badtype'", str(e.exception))
2201 """Test listing the files in an image"""
2203 data = self._DoReadFile('127_list.dts')
2204 image = control.images['image']
2205 entries = image.BuildEntryList()
2206 self.assertEqual(7, len(entries))
2209 self.assertEqual(0, ent.indent)
2210 self.assertEqual('main-section', ent.name)
2211 self.assertEqual('section', ent.etype)
2212 self.assertEqual(len(data), ent.size)
2213 self.assertEqual(0, ent.image_pos)
2214 self.assertEqual(None, ent.uncomp_size)
2215 self.assertEqual(0, ent.offset)
2218 self.assertEqual(1, ent.indent)
2219 self.assertEqual('u-boot', ent.name)
2220 self.assertEqual('u-boot', ent.etype)
2221 self.assertEqual(len(U_BOOT_DATA), ent.size)
2222 self.assertEqual(0, ent.image_pos)
2223 self.assertEqual(None, ent.uncomp_size)
2224 self.assertEqual(0, ent.offset)
2227 self.assertEqual(1, ent.indent)
2228 self.assertEqual('section', ent.name)
2229 self.assertEqual('section', ent.etype)
2230 section_size = ent.size
2231 self.assertEqual(0x100, ent.image_pos)
2232 self.assertEqual(None, ent.uncomp_size)
2233 self.assertEqual(0x100, ent.offset)
2236 self.assertEqual(2, ent.indent)
2237 self.assertEqual('cbfs', ent.name)
2238 self.assertEqual('cbfs', ent.etype)
2239 self.assertEqual(0x400, ent.size)
2240 self.assertEqual(0x100, ent.image_pos)
2241 self.assertEqual(None, ent.uncomp_size)
2242 self.assertEqual(0, ent.offset)
2245 self.assertEqual(3, ent.indent)
2246 self.assertEqual('u-boot', ent.name)
2247 self.assertEqual('u-boot', ent.etype)
2248 self.assertEqual(len(U_BOOT_DATA), ent.size)
2249 self.assertEqual(0x138, ent.image_pos)
2250 self.assertEqual(None, ent.uncomp_size)
2251 self.assertEqual(0x38, ent.offset)
2254 self.assertEqual(3, ent.indent)
2255 self.assertEqual('u-boot-dtb', ent.name)
2256 self.assertEqual('text', ent.etype)
2257 self.assertGreater(len(COMPRESS_DATA), ent.size)
2258 self.assertEqual(0x178, ent.image_pos)
2259 self.assertEqual(len(COMPRESS_DATA), ent.uncomp_size)
2260 self.assertEqual(0x78, ent.offset)
2263 self.assertEqual(2, ent.indent)
2264 self.assertEqual('u-boot-dtb', ent.name)
2265 self.assertEqual('u-boot-dtb', ent.etype)
2266 self.assertEqual(0x500, ent.image_pos)
2267 self.assertEqual(len(U_BOOT_DTB_DATA), ent.uncomp_size)
2269 # Compressing this data expands it since headers are added
2270 self.assertGreater(dtb_size, len(U_BOOT_DTB_DATA))
2271 self.assertEqual(0x400, ent.offset)
2273 self.assertEqual(len(data), 0x100 + section_size)
2274 self.assertEqual(section_size, 0x400 + dtb_size)
2276 def testFindFdtmap(self):
2277 """Test locating an FDT map in an image"""
2279 data = self.data = self._DoReadFileRealDtb('128_decode_image.dts')
2280 image = control.images['image']
2281 entries = image.GetEntries()
2282 entry = entries['fdtmap']
2283 self.assertEqual(entry.image_pos, fdtmap.LocateFdtmap(data))
2285 def testFindFdtmapMissing(self):
2286 """Test failing to locate an FDP map"""
2287 data = self._DoReadFile('005_simple.dts')
2288 self.assertEqual(None, fdtmap.LocateFdtmap(data))
2290 def testFindImageHeader(self):
2291 """Test locating a image header"""
2293 data = self.data = self._DoReadFileRealDtb('128_decode_image.dts')
2294 image = control.images['image']
2295 entries = image.GetEntries()
2296 entry = entries['fdtmap']
2297 # The header should point to the FDT map
2298 self.assertEqual(entry.image_pos, image_header.LocateHeaderOffset(data))
2300 def testFindImageHeaderStart(self):
2301 """Test locating a image header located at the start of an image"""
2302 data = self.data = self._DoReadFileRealDtb('117_fdtmap_hdr_start.dts')
2303 image = control.images['image']
2304 entries = image.GetEntries()
2305 entry = entries['fdtmap']
2306 # The header should point to the FDT map
2307 self.assertEqual(entry.image_pos, image_header.LocateHeaderOffset(data))
2309 def testFindImageHeaderMissing(self):
2310 """Test failing to locate an image header"""
2311 data = self._DoReadFile('005_simple.dts')
2312 self.assertEqual(None, image_header.LocateHeaderOffset(data))
2314 def testReadImage(self):
2315 """Test reading an image and accessing its FDT map"""
2317 data = self.data = self._DoReadFileRealDtb('128_decode_image.dts')
2318 image_fname = tools.GetOutputFilename('image.bin')
2319 orig_image = control.images['image']
2320 image = Image.FromFile(image_fname)
2321 self.assertEqual(orig_image.GetEntries().keys(),
2322 image.GetEntries().keys())
2324 orig_entry = orig_image.GetEntries()['fdtmap']
2325 entry = image.GetEntries()['fdtmap']
2326 self.assertEquals(orig_entry.offset, entry.offset)
2327 self.assertEquals(orig_entry.size, entry.size)
2328 self.assertEquals(orig_entry.image_pos, entry.image_pos)
2330 def testReadImageNoHeader(self):
2331 """Test accessing an image's FDT map without an image header"""
2333 data = self._DoReadFileRealDtb('129_decode_image_nohdr.dts')
2334 image_fname = tools.GetOutputFilename('image.bin')
2335 image = Image.FromFile(image_fname)
2336 self.assertTrue(isinstance(image, Image))
2337 self.assertEqual('image', image.image_name)
2339 def testReadImageFail(self):
2340 """Test failing to read an image image's FDT map"""
2341 self._DoReadFile('005_simple.dts')
2342 image_fname = tools.GetOutputFilename('image.bin')
2343 with self.assertRaises(ValueError) as e:
2344 image = Image.FromFile(image_fname)
2345 self.assertIn("Cannot find FDT map in image", str(e.exception))
2347 def testListCmd(self):
2348 """Test listing the files in an image using an Fdtmap"""
2350 data = self._DoReadFileRealDtb('130_list_fdtmap.dts')
2352 # lz4 compression size differs depending on the version
2353 image = control.images['image']
2354 entries = image.GetEntries()
2355 section_size = entries['section'].size
2356 fdt_size = entries['section'].GetEntries()['u-boot-dtb'].size
2357 fdtmap_offset = entries['fdtmap'].offset
2359 image_fname = tools.GetOutputFilename('image.bin')
2360 with test_util.capture_sys_output() as (stdout, stderr):
2361 self._DoBinman('ls', '-i', image_fname)
2362 lines = stdout.getvalue().splitlines()
2364 'Name Image-pos Size Entry-type Offset Uncomp-size',
2365 '----------------------------------------------------------------------',
2366 'main-section 0 c00 section 0',
2367 ' u-boot 0 4 u-boot 0',
2368 ' section 100 %x section 100' % section_size,
2369 ' cbfs 100 400 cbfs 0',
2370 ' u-boot 138 4 u-boot 38',
2371 ' u-boot-dtb 180 10f u-boot-dtb 80 3c9',
2372 ' u-boot-dtb 500 %x u-boot-dtb 400 3c9' % fdt_size,
2373 ' fdtmap %x 3b4 fdtmap %x' %
2374 (fdtmap_offset, fdtmap_offset),
2375 ' image-header bf8 8 image-header bf8',
2377 self.assertEqual(expected, lines)
2379 def testListCmdFail(self):
2380 """Test failing to list an image"""
2381 self._DoReadFile('005_simple.dts')
2382 image_fname = tools.GetOutputFilename('image.bin')
2383 with self.assertRaises(ValueError) as e:
2384 self._DoBinman('ls', '-i', image_fname)
2385 self.assertIn("Cannot find FDT map in image", str(e.exception))
2387 def _RunListCmd(self, paths, expected):
2388 """List out entries and check the result
2391 paths: List of paths to pass to the list command
2392 expected: Expected list of filenames to be returned, in order
2395 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2396 image_fname = tools.GetOutputFilename('image.bin')
2397 image = Image.FromFile(image_fname)
2398 lines = image.GetListEntries(paths)[1]
2399 files = [line[0].strip() for line in lines[1:]]
2400 self.assertEqual(expected, files)
2402 def testListCmdSection(self):
2403 """Test listing the files in a section"""
2404 self._RunListCmd(['section'],
2405 ['section', 'cbfs', 'u-boot', 'u-boot-dtb', 'u-boot-dtb'])
2407 def testListCmdFile(self):
2408 """Test listing a particular file"""
2409 self._RunListCmd(['*u-boot-dtb'], ['u-boot-dtb', 'u-boot-dtb'])
2411 def testListCmdWildcard(self):
2412 """Test listing a wildcarded file"""
2413 self._RunListCmd(['*boot*'],
2414 ['u-boot', 'u-boot', 'u-boot-dtb', 'u-boot-dtb'])
2416 def testListCmdWildcardMulti(self):
2417 """Test listing a wildcarded file"""
2418 self._RunListCmd(['*cb*', '*head*'],
2419 ['cbfs', 'u-boot', 'u-boot-dtb', 'image-header'])
2421 def testListCmdEmpty(self):
2422 """Test listing a wildcarded file"""
2423 self._RunListCmd(['nothing'], [])
2425 def testListCmdPath(self):
2426 """Test listing the files in a sub-entry of a section"""
2427 self._RunListCmd(['section/cbfs'], ['cbfs', 'u-boot', 'u-boot-dtb'])
2429 def _RunExtractCmd(self, entry_name, decomp=True):
2430 """Extract an entry from an image
2433 entry_name: Entry name to extract
2434 decomp: True to decompress the data if compressed, False to leave
2435 it in its raw uncompressed format
2441 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2442 image_fname = tools.GetOutputFilename('image.bin')
2443 return control.ReadEntry(image_fname, entry_name, decomp)
2445 def testExtractSimple(self):
2446 """Test extracting a single file"""
2447 data = self._RunExtractCmd('u-boot')
2448 self.assertEqual(U_BOOT_DATA, data)
2450 def testExtractSection(self):
2451 """Test extracting the files in a section"""
2452 data = self._RunExtractCmd('section')
2453 cbfs_data = data[:0x400]
2454 cbfs = cbfs_util.CbfsReader(cbfs_data)
2455 self.assertEqual(['u-boot', 'u-boot-dtb', ''], cbfs.files.keys())
2456 dtb_data = data[0x400:]
2457 dtb = self._decompress(dtb_data)
2458 self.assertEqual(EXTRACT_DTB_SIZE, len(dtb))
2460 def testExtractCompressed(self):
2461 """Test extracting compressed data"""
2462 data = self._RunExtractCmd('section/u-boot-dtb')
2463 self.assertEqual(EXTRACT_DTB_SIZE, len(data))
2465 def testExtractRaw(self):
2466 """Test extracting compressed data without decompressing it"""
2467 data = self._RunExtractCmd('section/u-boot-dtb', decomp=False)
2468 dtb = self._decompress(data)
2469 self.assertEqual(EXTRACT_DTB_SIZE, len(dtb))
2471 def testExtractCbfs(self):
2472 """Test extracting CBFS data"""
2473 data = self._RunExtractCmd('section/cbfs/u-boot')
2474 self.assertEqual(U_BOOT_DATA, data)
2476 def testExtractCbfsCompressed(self):
2477 """Test extracting CBFS compressed data"""
2478 data = self._RunExtractCmd('section/cbfs/u-boot-dtb')
2479 self.assertEqual(EXTRACT_DTB_SIZE, len(data))
2481 def testExtractCbfsRaw(self):
2482 """Test extracting CBFS compressed data without decompressing it"""
2483 data = self._RunExtractCmd('section/cbfs/u-boot-dtb', decomp=False)
2484 dtb = tools.Decompress(data, 'lzma')
2485 self.assertEqual(EXTRACT_DTB_SIZE, len(dtb))
2487 def testExtractBadEntry(self):
2488 """Test extracting a bad section path"""
2489 with self.assertRaises(ValueError) as e:
2490 self._RunExtractCmd('section/does-not-exist')
2491 self.assertIn("Entry 'does-not-exist' not found in '/section'",
2494 def testExtractMissingFile(self):
2495 """Test extracting file that does not exist"""
2496 with self.assertRaises(IOError) as e:
2497 control.ReadEntry('missing-file', 'name')
2499 def testExtractBadFile(self):
2500 """Test extracting an invalid file"""
2501 fname = os.path.join(self._indir, 'badfile')
2502 tools.WriteFile(fname, b'')
2503 with self.assertRaises(ValueError) as e:
2504 control.ReadEntry(fname, 'name')
2506 def testExtractCmd(self):
2507 """Test extracting a file fron an image on the command line"""
2509 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2510 image_fname = tools.GetOutputFilename('image.bin')
2511 fname = os.path.join(self._indir, 'output.extact')
2512 with test_util.capture_sys_output() as (stdout, stderr):
2513 self._DoBinman('extract', '-i', image_fname, 'u-boot', '-f', fname)
2514 data = tools.ReadFile(fname)
2515 self.assertEqual(U_BOOT_DATA, data)
2517 def testExtractOneEntry(self):
2518 """Test extracting a single entry fron an image """
2520 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2521 image_fname = tools.GetOutputFilename('image.bin')
2522 fname = os.path.join(self._indir, 'output.extact')
2523 control.ExtractEntries(image_fname, fname, None, ['u-boot'])
2524 data = tools.ReadFile(fname)
2525 self.assertEqual(U_BOOT_DATA, data)
2527 def _CheckExtractOutput(self, decomp):
2528 """Helper to test file output with and without decompression
2531 decomp: True to decompress entry data, False to output it raw
2533 def _CheckPresent(entry_path, expect_data, expect_size=None):
2534 """Check and remove expected file
2536 This checks the data/size of a file and removes the file both from
2537 the outfiles set and from the output directory. Once all files are
2538 processed, both the set and directory should be empty.
2541 entry_path: Entry path
2542 expect_data: Data to expect in file, or None to skip check
2543 expect_size: Size of data to expect in file, or None to skip
2545 path = os.path.join(outdir, entry_path)
2546 data = tools.ReadFile(path)
2549 self.assertEqual(expect_data, data)
2551 self.assertEqual(expect_size, len(data))
2552 outfiles.remove(path)
2554 def _CheckDirPresent(name):
2555 """Remove expected directory
2557 This gives an error if the directory does not exist as expected
2560 name: Name of directory to remove
2562 path = os.path.join(outdir, name)
2565 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2566 image_fname = tools.GetOutputFilename('image.bin')
2567 outdir = os.path.join(self._indir, 'extract')
2568 einfos = control.ExtractEntries(image_fname, None, outdir, [], decomp)
2570 # Create a set of all file that were output (should be 9)
2572 for root, dirs, files in os.walk(outdir):
2573 outfiles |= set([os.path.join(root, fname) for fname in files])
2574 self.assertEqual(9, len(outfiles))
2575 self.assertEqual(9, len(einfos))
2577 image = control.images['image']
2578 entries = image.GetEntries()
2580 # Check the 9 files in various ways
2581 section = entries['section']
2582 section_entries = section.GetEntries()
2583 cbfs_entries = section_entries['cbfs'].GetEntries()
2584 _CheckPresent('u-boot', U_BOOT_DATA)
2585 _CheckPresent('section/cbfs/u-boot', U_BOOT_DATA)
2586 dtb_len = EXTRACT_DTB_SIZE
2588 dtb_len = cbfs_entries['u-boot-dtb'].size
2589 _CheckPresent('section/cbfs/u-boot-dtb', None, dtb_len)
2591 dtb_len = section_entries['u-boot-dtb'].size
2592 _CheckPresent('section/u-boot-dtb', None, dtb_len)
2594 fdtmap = entries['fdtmap']
2595 _CheckPresent('fdtmap', fdtmap.data)
2596 hdr = entries['image-header']
2597 _CheckPresent('image-header', hdr.data)
2599 _CheckPresent('section/root', section.data)
2600 cbfs = section_entries['cbfs']
2601 _CheckPresent('section/cbfs/root', cbfs.data)
2602 data = tools.ReadFile(image_fname)
2603 _CheckPresent('root', data)
2605 # There should be no files left. Remove all the directories to check.
2606 # If there are any files/dirs remaining, one of these checks will fail.
2607 self.assertEqual(0, len(outfiles))
2608 _CheckDirPresent('section/cbfs')
2609 _CheckDirPresent('section')
2610 _CheckDirPresent('')
2611 self.assertFalse(os.path.exists(outdir))
2613 def testExtractAllEntries(self):
2614 """Test extracting all entries"""
2616 self._CheckExtractOutput(decomp=True)
2618 def testExtractAllEntriesRaw(self):
2619 """Test extracting all entries without decompressing them"""
2621 self._CheckExtractOutput(decomp=False)
2623 def testExtractSelectedEntries(self):
2624 """Test extracting some entries"""
2626 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2627 image_fname = tools.GetOutputFilename('image.bin')
2628 outdir = os.path.join(self._indir, 'extract')
2629 einfos = control.ExtractEntries(image_fname, None, outdir,
2632 # File output is tested by testExtractAllEntries(), so just check that
2633 # the expected entries are selected
2634 names = [einfo.name for einfo in einfos]
2635 self.assertEqual(names,
2636 ['cbfs', 'u-boot', 'u-boot-dtb', 'image-header'])
2638 def testExtractNoEntryPaths(self):
2639 """Test extracting some entries"""
2641 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2642 image_fname = tools.GetOutputFilename('image.bin')
2643 with self.assertRaises(ValueError) as e:
2644 control.ExtractEntries(image_fname, 'fname', None, [])
2645 self.assertIn('Must specify an entry path to write with -o',
2648 def testExtractTooManyEntryPaths(self):
2649 """Test extracting some entries"""
2651 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2652 image_fname = tools.GetOutputFilename('image.bin')
2653 with self.assertRaises(ValueError) as e:
2654 control.ExtractEntries(image_fname, 'fname', None, ['a', 'b'])
2655 self.assertIn('Must specify exactly one entry path to write with -o',
2658 def testPackAlignSection(self):
2659 """Test that sections can have alignment"""
2660 self._DoReadFile('131_pack_align_section.dts')
2662 self.assertIn('image', control.images)
2663 image = control.images['image']
2664 entries = image.GetEntries()
2665 self.assertEqual(3, len(entries))
2668 self.assertIn('u-boot', entries)
2669 entry = entries['u-boot']
2670 self.assertEqual(0, entry.offset)
2671 self.assertEqual(0, entry.image_pos)
2672 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2673 self.assertEqual(len(U_BOOT_DATA), entry.size)
2676 self.assertIn('section0', entries)
2677 section0 = entries['section0']
2678 self.assertEqual(0x10, section0.offset)
2679 self.assertEqual(0x10, section0.image_pos)
2680 self.assertEqual(len(U_BOOT_DATA), section0.size)
2683 section_entries = section0.GetEntries()
2684 self.assertIn('u-boot', section_entries)
2685 entry = section_entries['u-boot']
2686 self.assertEqual(0, entry.offset)
2687 self.assertEqual(0x10, entry.image_pos)
2688 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2689 self.assertEqual(len(U_BOOT_DATA), entry.size)
2692 self.assertIn('section1', entries)
2693 section1 = entries['section1']
2694 self.assertEqual(0x14, section1.offset)
2695 self.assertEqual(0x14, section1.image_pos)
2696 self.assertEqual(0x20, section1.size)
2699 section_entries = section1.GetEntries()
2700 self.assertIn('u-boot', section_entries)
2701 entry = section_entries['u-boot']
2702 self.assertEqual(0, entry.offset)
2703 self.assertEqual(0x14, entry.image_pos)
2704 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2705 self.assertEqual(len(U_BOOT_DATA), entry.size)
2708 self.assertIn('section2', section_entries)
2709 section2 = section_entries['section2']
2710 self.assertEqual(0x4, section2.offset)
2711 self.assertEqual(0x18, section2.image_pos)
2712 self.assertEqual(4, section2.size)
2715 section_entries = section2.GetEntries()
2716 self.assertIn('u-boot', section_entries)
2717 entry = section_entries['u-boot']
2718 self.assertEqual(0, entry.offset)
2719 self.assertEqual(0x18, entry.image_pos)
2720 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2721 self.assertEqual(len(U_BOOT_DATA), entry.size)
2724 if __name__ == "__main__":