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
12 from optparse import OptionParser
21 from binman import cbfs_util
22 from binman import cmdline
23 from binman import control
24 from binman import elf
25 from binman import elf_test
26 from binman import fmap_util
27 from binman import state
29 from dtoc import fdt_util
30 from binman.etype import fdtmap
31 from binman.etype import image_header
32 from binman.image import Image
33 from patman import command
34 from patman import test_util
35 from patman import tools
36 from patman import tout
38 # Contents of test files, corresponding to different entry types
40 U_BOOT_IMG_DATA = b'img'
41 U_BOOT_SPL_DATA = b'56780123456789abcdefghi'
42 U_BOOT_TPL_DATA = b'tpl9876543210fedcbazyw'
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 X86_RESET16_DATA = b'reset16'
53 X86_RESET16_SPL_DATA = b'reset16spl'
54 X86_RESET16_TPL_DATA = b'reset16tpl'
55 PPC_MPC85XX_BR_DATA = b'ppcmpc85xxbr'
56 U_BOOT_NODTB_DATA = b'nodtb with microcode pointer somewhere in here'
57 U_BOOT_SPL_NODTB_DATA = b'splnodtb with microcode pointer somewhere in here'
58 U_BOOT_TPL_NODTB_DATA = b'tplnodtb with microcode pointer somewhere in here'
66 CROS_EC_RW_DATA = b'ecrw'
70 FILES_DATA = (b"sorry I'm late\nOh, don't bother apologising, I'm " +
71 b"sorry you're alive\n")
72 COMPRESS_DATA = b'compress xxxxxxxxxxxxxxxxxxxxxx data'
73 REFCODE_DATA = b'refcode'
77 ATF_BL31_DATA = b'bl31'
78 TEST_FDT1_DATA = b'fdt1'
79 TEST_FDT2_DATA = b'test-fdt2'
80 ENV_DATA = b'var1=1\nvar2="2"'
82 # Subdirectory of the input dir to use to put test FDTs
83 TEST_FDT_SUBDIR = 'fdts'
85 # The expected size for the device tree in some tests
86 EXTRACT_DTB_SIZE = 0x3c9
88 # Properties expected to be in the device tree when update_dtb is used
89 BASE_DTB_PROPS = ['offset', 'size', 'image-pos']
91 # Extra properties expected to be in the device tree when allow-repack is used
92 REPACK_DTB_PROPS = ['orig-offset', 'orig-size']
95 class TestFunctional(unittest.TestCase):
96 """Functional tests for binman
98 Most of these use a sample .dts file to build an image and then check
99 that it looks correct. The sample files are in the test/ subdirectory
102 For each entry type a very small test file is created using fixed
103 string contents. This makes it easy to test that things look right, and
106 In some cases a 'real' file must be used - these are also supplied in
107 the test/ diurectory.
112 from binman import entry
114 # Handle the case where argv[0] is 'python'
115 cls._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
116 cls._binman_pathname = os.path.join(cls._binman_dir, 'binman')
118 # Create a temporary directory for input files
119 cls._indir = tempfile.mkdtemp(prefix='binmant.')
121 # Create some test files
122 TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
123 TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
124 TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
125 TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
126 TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
127 TestFunctional._MakeInputFile('me.bin', ME_DATA)
128 TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
131 TestFunctional._MakeInputFile('u-boot-br.bin', PPC_MPC85XX_BR_DATA)
133 TestFunctional._MakeInputFile('u-boot-x86-start16.bin', X86_START16_DATA)
134 TestFunctional._MakeInputFile('spl/u-boot-x86-start16-spl.bin',
135 X86_START16_SPL_DATA)
136 TestFunctional._MakeInputFile('tpl/u-boot-x86-start16-tpl.bin',
137 X86_START16_TPL_DATA)
139 TestFunctional._MakeInputFile('u-boot-x86-reset16.bin',
141 TestFunctional._MakeInputFile('spl/u-boot-x86-reset16-spl.bin',
142 X86_RESET16_SPL_DATA)
143 TestFunctional._MakeInputFile('tpl/u-boot-x86-reset16-tpl.bin',
144 X86_RESET16_TPL_DATA)
146 TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
147 TestFunctional._MakeInputFile('spl/u-boot-spl-nodtb.bin',
148 U_BOOT_SPL_NODTB_DATA)
149 TestFunctional._MakeInputFile('tpl/u-boot-tpl-nodtb.bin',
150 U_BOOT_TPL_NODTB_DATA)
151 TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
152 TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
153 TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
154 TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
155 TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
156 TestFunctional._MakeInputDir('devkeys')
157 TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
158 TestFunctional._MakeInputFile('refcode.bin', REFCODE_DATA)
159 TestFunctional._MakeInputFile('fsp_m.bin', FSP_M_DATA)
160 TestFunctional._MakeInputFile('fsp_s.bin', FSP_S_DATA)
161 TestFunctional._MakeInputFile('fsp_t.bin', FSP_T_DATA)
163 cls._elf_testdir = os.path.join(cls._indir, 'elftest')
164 elf_test.BuildElfTestFiles(cls._elf_testdir)
166 # ELF file with a '_dt_ucode_base_size' symbol
167 TestFunctional._MakeInputFile('u-boot',
168 tools.ReadFile(cls.ElfTestFile('u_boot_ucode_ptr')))
170 # Intel flash descriptor file
171 cls._SetupDescriptor()
173 shutil.copytree(cls.TestFile('files'),
174 os.path.join(cls._indir, 'files'))
176 TestFunctional._MakeInputFile('compress', COMPRESS_DATA)
177 TestFunctional._MakeInputFile('bl31.bin', ATF_BL31_DATA)
179 # Add a few .dtb files for testing
180 TestFunctional._MakeInputFile('%s/test-fdt1.dtb' % TEST_FDT_SUBDIR,
182 TestFunctional._MakeInputFile('%s/test-fdt2.dtb' % TEST_FDT_SUBDIR,
185 TestFunctional._MakeInputFile('env.txt', ENV_DATA)
187 # Travis-CI may have an old lz4
190 tools.Run('lz4', '--no-frame-crc', '-c',
191 os.path.join(cls._indir, 'u-boot.bin'), binary=True)
196 def tearDownClass(cls):
197 """Remove the temporary input directory and its contents"""
198 if cls.preserve_indir:
199 print('Preserving input dir: %s' % cls._indir)
202 shutil.rmtree(cls._indir)
206 def setup_test_args(cls, preserve_indir=False, preserve_outdirs=False,
207 toolpath=None, verbosity=None):
208 """Accept arguments controlling test execution
211 preserve_indir: Preserve the shared input directory used by all
213 preserve_outdir: Preserve the output directories used by tests. Each
214 test has its own, so this is normally only useful when running a
216 toolpath: ist of paths to use for tools
218 cls.preserve_indir = preserve_indir
219 cls.preserve_outdirs = preserve_outdirs
220 cls.toolpath = toolpath
221 cls.verbosity = verbosity
224 if not self.have_lz4:
225 self.skipTest('lz4 --no-frame-crc not available')
227 def _CleanupOutputDir(self):
228 """Remove the temporary output directory"""
229 if self.preserve_outdirs:
230 print('Preserving output dir: %s' % tools.outdir)
232 tools._FinaliseForTest()
235 # Enable this to turn on debugging output
236 # tout.Init(tout.DEBUG)
237 command.test_result = None
240 """Remove the temporary output directory"""
241 self._CleanupOutputDir()
243 def _SetupImageInTmpdir(self):
244 """Set up the output image in a new temporary directory
246 This is used when an image has been generated in the output directory,
247 but we want to run binman again. This will create a new output
248 directory and fail to delete the original one.
250 This creates a new temporary directory, copies the image to it (with a
251 new name) and removes the old output directory.
255 Temporary directory to use
258 image_fname = tools.GetOutputFilename('image.bin')
259 tmpdir = tempfile.mkdtemp(prefix='binman.')
260 updated_fname = os.path.join(tmpdir, 'image-updated.bin')
261 tools.WriteFile(updated_fname, tools.ReadFile(image_fname))
262 self._CleanupOutputDir()
263 return tmpdir, updated_fname
267 TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
268 TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
269 TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
271 def _RunBinman(self, *args, **kwargs):
272 """Run binman using the command line
275 Arguments to pass, as a list of strings
276 kwargs: Arguments to pass to Command.RunPipe()
278 result = command.RunPipe([[self._binman_pathname] + list(args)],
279 capture=True, capture_stderr=True, raise_on_error=False)
280 if result.return_code and kwargs.get('raise_on_error', True):
281 raise Exception("Error running '%s': %s" % (' '.join(args),
282 result.stdout + result.stderr))
285 def _DoBinman(self, *argv):
286 """Run binman using directly (in the same process)
289 Arguments to pass, as a list of strings
291 Return value (0 for success)
294 args = cmdline.ParseArgs(argv)
295 args.pager = 'binman-invalid-pager'
296 args.build_dir = self._indir
298 # For testing, you can force an increase in verbosity here
299 # args.verbosity = tout.DEBUG
300 return control.Binman(args)
302 def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
303 entry_args=None, images=None, use_real_dtb=False,
304 verbosity=None, allow_missing=False, extra_indirs=None):
305 """Run binman with a given test file
308 fname: Device-tree source filename to use (e.g. 005_simple.dts)
309 debug: True to enable debugging output
310 map: True to output map files for the images
311 update_dtb: Update the offset and size of each entry in the device
312 tree before packing it into the image
313 entry_args: Dict of entry args to supply to binman
315 value: value of that arg
316 images: List of image names to build
317 use_real_dtb: True to use the test file as the contents of
318 the u-boot-dtb entry. Normally this is not needed and the
319 test contents (the U_BOOT_DTB_DATA string) can be used.
320 But in some test we need the real contents.
321 verbosity: Verbosity level to use (0-3, None=don't set it)
322 allow_missing: Set the '--allow-missing' flag so that missing
323 external binaries just produce a warning instead of an error
324 extra_indirs: Extra input directories to add using -I
329 if verbosity is not None:
330 args.append('-v%d' % verbosity)
332 args.append('-v%d' % self.verbosity)
334 for path in self.toolpath:
335 args += ['--toolpath', path]
336 args += ['build', '-p', '-I', self._indir, '-d', self.TestFile(fname)]
342 args.append('--fake-dtb')
344 for arg, value in entry_args.items():
345 args.append('-a%s=%s' % (arg, value))
350 args += ['-i', image]
352 for indir in extra_indirs:
353 args += ['-I', indir]
354 return self._DoBinman(*args)
356 def _SetupDtb(self, fname, outfile='u-boot.dtb'):
357 """Set up a new test device-tree file
359 The given file is compiled and set up as the device tree to be used
363 fname: Filename of .dts file to read
364 outfile: Output filename for compiled device-tree binary
367 Contents of device-tree binary
369 tmpdir = tempfile.mkdtemp(prefix='binmant.')
370 dtb = fdt_util.EnsureCompiled(self.TestFile(fname), tmpdir)
371 with open(dtb, 'rb') as fd:
373 TestFunctional._MakeInputFile(outfile, data)
374 shutil.rmtree(tmpdir)
377 def _GetDtbContentsForSplTpl(self, dtb_data, name):
378 """Create a version of the main DTB for SPL or SPL
380 For testing we don't actually have different versions of the DTB. With
381 U-Boot we normally run fdtgrep to remove unwanted nodes, but for tests
382 we don't normally have any unwanted nodes.
384 We still want the DTBs for SPL and TPL to be different though, since
385 otherwise it is confusing to know which one we are looking at. So add
386 an 'spl' or 'tpl' property to the top-level node.
389 dtb_data: dtb data to modify (this should be a value devicetree)
390 name: Name of a new property to add
393 New dtb data with the property added
395 dtb = fdt.Fdt.FromData(dtb_data)
397 dtb.GetNode('/binman').AddZeroProp(name)
398 dtb.Sync(auto_resize=True)
400 return dtb.GetContents()
402 def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
403 update_dtb=False, entry_args=None, reset_dtbs=True,
405 """Run binman and return the resulting image
407 This runs binman with a given test file and then reads the resulting
408 output file. It is a shortcut function since most tests need to do
411 Raises an assertion failure if binman returns a non-zero exit code.
414 fname: Device-tree source filename to use (e.g. 005_simple.dts)
415 use_real_dtb: True to use the test file as the contents of
416 the u-boot-dtb entry. Normally this is not needed and the
417 test contents (the U_BOOT_DTB_DATA string) can be used.
418 But in some test we need the real contents.
419 map: True to output map files for the images
420 update_dtb: Update the offset and size of each entry in the device
421 tree before packing it into the image
422 entry_args: Dict of entry args to supply to binman
424 value: value of that arg
425 reset_dtbs: With use_real_dtb the test dtb is overwritten by this
426 function. If reset_dtbs is True, then the original test dtb
427 is written back before this function finishes
428 extra_indirs: Extra input directories to add using -I
432 Resulting image contents
434 Map data showing contents of image (or None if none)
435 Output device tree binary filename ('u-boot.dtb' path)
438 # Use the compiled test file as the u-boot-dtb input
440 dtb_data = self._SetupDtb(fname)
442 # For testing purposes, make a copy of the DT for SPL and TPL. Add
443 # a node indicating which it is, so aid verification.
444 for name in ['spl', 'tpl']:
445 dtb_fname = '%s/u-boot-%s.dtb' % (name, name)
446 outfile = os.path.join(self._indir, dtb_fname)
447 TestFunctional._MakeInputFile(dtb_fname,
448 self._GetDtbContentsForSplTpl(dtb_data, name))
451 retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
452 entry_args=entry_args, use_real_dtb=use_real_dtb,
453 extra_indirs=extra_indirs)
454 self.assertEqual(0, retcode)
455 out_dtb_fname = tools.GetOutputFilename('u-boot.dtb.out')
457 # Find the (only) image, read it and return its contents
458 image = control.images['image']
459 image_fname = tools.GetOutputFilename('image.bin')
460 self.assertTrue(os.path.exists(image_fname))
462 map_fname = tools.GetOutputFilename('image.map')
463 with open(map_fname) as fd:
467 with open(image_fname, 'rb') as fd:
468 return fd.read(), dtb_data, map_data, out_dtb_fname
470 # Put the test file back
471 if reset_dtbs and use_real_dtb:
474 def _DoReadFileRealDtb(self, fname):
475 """Run binman with a real .dtb file and return the resulting data
478 fname: DT source filename to use (e.g. 082_fdt_update_all.dts)
481 Resulting image contents
483 return self._DoReadFileDtb(fname, use_real_dtb=True, update_dtb=True)[0]
485 def _DoReadFile(self, fname, use_real_dtb=False):
486 """Helper function which discards the device-tree binary
489 fname: Device-tree source filename to use (e.g. 005_simple.dts)
490 use_real_dtb: True to use the test file as the contents of
491 the u-boot-dtb entry. Normally this is not needed and the
492 test contents (the U_BOOT_DTB_DATA string) can be used.
493 But in some test we need the real contents.
496 Resulting image contents
498 return self._DoReadFileDtb(fname, use_real_dtb)[0]
501 def _MakeInputFile(cls, fname, contents):
502 """Create a new test input file, creating directories as needed
505 fname: Filename to create
506 contents: File contents to write in to the file
508 Full pathname of file created
510 pathname = os.path.join(cls._indir, fname)
511 dirname = os.path.dirname(pathname)
512 if dirname and not os.path.exists(dirname):
514 with open(pathname, 'wb') as fd:
519 def _MakeInputDir(cls, dirname):
520 """Create a new test input directory, creating directories as needed
523 dirname: Directory name to create
526 Full pathname of directory created
528 pathname = os.path.join(cls._indir, dirname)
529 if not os.path.exists(pathname):
530 os.makedirs(pathname)
534 def _SetupSplElf(cls, src_fname='bss_data'):
535 """Set up an ELF file with a '_dt_ucode_base_size' symbol
538 Filename of ELF file to use as SPL
540 TestFunctional._MakeInputFile('spl/u-boot-spl',
541 tools.ReadFile(cls.ElfTestFile(src_fname)))
544 def _SetupTplElf(cls, src_fname='bss_data'):
545 """Set up an ELF file with a '_dt_ucode_base_size' symbol
548 Filename of ELF file to use as TPL
550 TestFunctional._MakeInputFile('tpl/u-boot-tpl',
551 tools.ReadFile(cls.ElfTestFile(src_fname)))
554 def _SetupDescriptor(cls):
555 with open(cls.TestFile('descriptor.bin'), 'rb') as fd:
556 TestFunctional._MakeInputFile('descriptor.bin', fd.read())
559 def TestFile(cls, fname):
560 return os.path.join(cls._binman_dir, 'test', fname)
563 def ElfTestFile(cls, fname):
564 return os.path.join(cls._elf_testdir, fname)
566 def AssertInList(self, grep_list, target):
567 """Assert that at least one of a list of things is in a target
570 grep_list: List of strings to check
571 target: Target string
573 for grep in grep_list:
576 self.fail("Error: '%s' not found in '%s'" % (grep_list, target))
578 def CheckNoGaps(self, entries):
579 """Check that all entries fit together without gaps
582 entries: List of entries to check
585 for entry in entries.values():
586 self.assertEqual(offset, entry.offset)
589 def GetFdtLen(self, dtb):
590 """Get the totalsize field from a device-tree binary
593 dtb: Device-tree binary contents
596 Total size of device-tree binary, from the header
598 return struct.unpack('>L', dtb[4:8])[0]
600 def _GetPropTree(self, dtb, prop_names, prefix='/binman/'):
601 def AddNode(node, path):
603 path += '/' + node.name
604 for prop in node.props.values():
605 if prop.name in prop_names:
606 prop_path = path + ':' + prop.name
607 tree[prop_path[len(prefix):]] = fdt_util.fdt32_to_cpu(
609 for subnode in node.subnodes:
610 AddNode(subnode, path)
613 AddNode(dtb.GetRoot(), '')
617 """Test a basic run with valid args"""
618 result = self._RunBinman('-h')
620 def testFullHelp(self):
621 """Test that the full help is displayed with -H"""
622 result = self._RunBinman('-H')
623 help_file = os.path.join(self._binman_dir, 'README')
624 # Remove possible extraneous strings
625 extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
626 gothelp = result.stdout.replace(extra, '')
627 self.assertEqual(len(gothelp), os.path.getsize(help_file))
628 self.assertEqual(0, len(result.stderr))
629 self.assertEqual(0, result.return_code)
631 def testFullHelpInternal(self):
632 """Test that the full help is displayed with -H"""
634 command.test_result = command.CommandResult()
635 result = self._DoBinman('-H')
636 help_file = os.path.join(self._binman_dir, 'README')
638 command.test_result = None
641 """Test that the basic help is displayed with -h"""
642 result = self._RunBinman('-h')
643 self.assertTrue(len(result.stdout) > 200)
644 self.assertEqual(0, len(result.stderr))
645 self.assertEqual(0, result.return_code)
648 """Test that we can run it with a specific board"""
649 self._SetupDtb('005_simple.dts', 'sandbox/u-boot.dtb')
650 TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
651 result = self._DoBinman('build', '-b', 'sandbox')
652 self.assertEqual(0, result)
654 def testNeedBoard(self):
655 """Test that we get an error when no board ius supplied"""
656 with self.assertRaises(ValueError) as e:
657 result = self._DoBinman('build')
658 self.assertIn("Must provide a board to process (use -b <board>)",
661 def testMissingDt(self):
662 """Test that an invalid device-tree file generates an error"""
663 with self.assertRaises(Exception) as e:
664 self._RunBinman('build', '-d', 'missing_file')
665 # We get one error from libfdt, and a different one from fdtget.
666 self.AssertInList(["Couldn't open blob from 'missing_file'",
667 'No such file or directory'], str(e.exception))
669 def testBrokenDt(self):
670 """Test that an invalid device-tree source file generates an error
672 Since this is a source file it should be compiled and the error
673 will come from the device-tree compiler (dtc).
675 with self.assertRaises(Exception) as e:
676 self._RunBinman('build', '-d', self.TestFile('001_invalid.dts'))
677 self.assertIn("FATAL ERROR: Unable to parse input tree",
680 def testMissingNode(self):
681 """Test that a device tree without a 'binman' node generates an error"""
682 with self.assertRaises(Exception) as e:
683 self._DoBinman('build', '-d', self.TestFile('002_missing_node.dts'))
684 self.assertIn("does not have a 'binman' node", str(e.exception))
687 """Test that an empty binman node works OK (i.e. does nothing)"""
688 result = self._RunBinman('build', '-d', self.TestFile('003_empty.dts'))
689 self.assertEqual(0, len(result.stderr))
690 self.assertEqual(0, result.return_code)
692 def testInvalidEntry(self):
693 """Test that an invalid entry is flagged"""
694 with self.assertRaises(Exception) as e:
695 result = self._RunBinman('build', '-d',
696 self.TestFile('004_invalid_entry.dts'))
697 self.assertIn("Unknown entry type 'not-a-valid-type' in node "
698 "'/binman/not-a-valid-type'", str(e.exception))
700 def testSimple(self):
701 """Test a simple binman with a single file"""
702 data = self._DoReadFile('005_simple.dts')
703 self.assertEqual(U_BOOT_DATA, data)
705 def testSimpleDebug(self):
706 """Test a simple binman run with debugging enabled"""
707 self._DoTestFile('005_simple.dts', debug=True)
710 """Test that we can handle creating two images
712 This also tests image padding.
714 retcode = self._DoTestFile('006_dual_image.dts')
715 self.assertEqual(0, retcode)
717 image = control.images['image1']
718 self.assertEqual(len(U_BOOT_DATA), image.size)
719 fname = tools.GetOutputFilename('image1.bin')
720 self.assertTrue(os.path.exists(fname))
721 with open(fname, 'rb') as fd:
723 self.assertEqual(U_BOOT_DATA, data)
725 image = control.images['image2']
726 self.assertEqual(3 + len(U_BOOT_DATA) + 5, image.size)
727 fname = tools.GetOutputFilename('image2.bin')
728 self.assertTrue(os.path.exists(fname))
729 with open(fname, 'rb') as fd:
731 self.assertEqual(U_BOOT_DATA, data[3:7])
732 self.assertEqual(tools.GetBytes(0, 3), data[:3])
733 self.assertEqual(tools.GetBytes(0, 5), data[7:])
735 def testBadAlign(self):
736 """Test that an invalid alignment value is detected"""
737 with self.assertRaises(ValueError) as e:
738 self._DoTestFile('007_bad_align.dts')
739 self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
740 "of two", str(e.exception))
742 def testPackSimple(self):
743 """Test that packing works as expected"""
744 retcode = self._DoTestFile('008_pack.dts')
745 self.assertEqual(0, retcode)
746 self.assertIn('image', control.images)
747 image = control.images['image']
748 entries = image.GetEntries()
749 self.assertEqual(5, len(entries))
752 self.assertIn('u-boot', entries)
753 entry = entries['u-boot']
754 self.assertEqual(0, entry.offset)
755 self.assertEqual(len(U_BOOT_DATA), entry.size)
757 # Second u-boot, aligned to 16-byte boundary
758 self.assertIn('u-boot-align', entries)
759 entry = entries['u-boot-align']
760 self.assertEqual(16, entry.offset)
761 self.assertEqual(len(U_BOOT_DATA), entry.size)
763 # Third u-boot, size 23 bytes
764 self.assertIn('u-boot-size', entries)
765 entry = entries['u-boot-size']
766 self.assertEqual(20, entry.offset)
767 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
768 self.assertEqual(23, entry.size)
770 # Fourth u-boot, placed immediate after the above
771 self.assertIn('u-boot-next', entries)
772 entry = entries['u-boot-next']
773 self.assertEqual(43, entry.offset)
774 self.assertEqual(len(U_BOOT_DATA), entry.size)
776 # Fifth u-boot, placed at a fixed offset
777 self.assertIn('u-boot-fixed', entries)
778 entry = entries['u-boot-fixed']
779 self.assertEqual(61, entry.offset)
780 self.assertEqual(len(U_BOOT_DATA), entry.size)
782 self.assertEqual(65, image.size)
784 def testPackExtra(self):
785 """Test that extra packing feature works as expected"""
786 retcode = self._DoTestFile('009_pack_extra.dts')
788 self.assertEqual(0, retcode)
789 self.assertIn('image', control.images)
790 image = control.images['image']
791 entries = image.GetEntries()
792 self.assertEqual(5, len(entries))
794 # First u-boot with padding before and after
795 self.assertIn('u-boot', entries)
796 entry = entries['u-boot']
797 self.assertEqual(0, entry.offset)
798 self.assertEqual(3, entry.pad_before)
799 self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
801 # Second u-boot has an aligned size, but it has no effect
802 self.assertIn('u-boot-align-size-nop', entries)
803 entry = entries['u-boot-align-size-nop']
804 self.assertEqual(12, entry.offset)
805 self.assertEqual(4, entry.size)
807 # Third u-boot has an aligned size too
808 self.assertIn('u-boot-align-size', entries)
809 entry = entries['u-boot-align-size']
810 self.assertEqual(16, entry.offset)
811 self.assertEqual(32, entry.size)
813 # Fourth u-boot has an aligned end
814 self.assertIn('u-boot-align-end', entries)
815 entry = entries['u-boot-align-end']
816 self.assertEqual(48, entry.offset)
817 self.assertEqual(16, entry.size)
819 # Fifth u-boot immediately afterwards
820 self.assertIn('u-boot-align-both', entries)
821 entry = entries['u-boot-align-both']
822 self.assertEqual(64, entry.offset)
823 self.assertEqual(64, entry.size)
825 self.CheckNoGaps(entries)
826 self.assertEqual(128, image.size)
828 def testPackAlignPowerOf2(self):
829 """Test that invalid entry alignment is detected"""
830 with self.assertRaises(ValueError) as e:
831 self._DoTestFile('010_pack_align_power2.dts')
832 self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
833 "of two", str(e.exception))
835 def testPackAlignSizePowerOf2(self):
836 """Test that invalid entry size alignment is detected"""
837 with self.assertRaises(ValueError) as e:
838 self._DoTestFile('011_pack_align_size_power2.dts')
839 self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
840 "power of two", str(e.exception))
842 def testPackInvalidAlign(self):
843 """Test detection of an offset that does not match its alignment"""
844 with self.assertRaises(ValueError) as e:
845 self._DoTestFile('012_pack_inv_align.dts')
846 self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
847 "align 0x4 (4)", str(e.exception))
849 def testPackInvalidSizeAlign(self):
850 """Test that invalid entry size alignment is detected"""
851 with self.assertRaises(ValueError) as e:
852 self._DoTestFile('013_pack_inv_size_align.dts')
853 self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
854 "align-size 0x4 (4)", str(e.exception))
856 def testPackOverlap(self):
857 """Test that overlapping regions are detected"""
858 with self.assertRaises(ValueError) as e:
859 self._DoTestFile('014_pack_overlap.dts')
860 self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
861 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
864 def testPackEntryOverflow(self):
865 """Test that entries that overflow their size are detected"""
866 with self.assertRaises(ValueError) as e:
867 self._DoTestFile('015_pack_overflow.dts')
868 self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
869 "but entry size is 0x3 (3)", str(e.exception))
871 def testPackImageOverflow(self):
872 """Test that entries which overflow the image size are detected"""
873 with self.assertRaises(ValueError) as e:
874 self._DoTestFile('016_pack_image_overflow.dts')
875 self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section "
876 "size 0x3 (3)", str(e.exception))
878 def testPackImageSize(self):
879 """Test that the image size can be set"""
880 retcode = self._DoTestFile('017_pack_image_size.dts')
881 self.assertEqual(0, retcode)
882 self.assertIn('image', control.images)
883 image = control.images['image']
884 self.assertEqual(7, image.size)
886 def testPackImageSizeAlign(self):
887 """Test that image size alignemnt works as expected"""
888 retcode = self._DoTestFile('018_pack_image_align.dts')
889 self.assertEqual(0, retcode)
890 self.assertIn('image', control.images)
891 image = control.images['image']
892 self.assertEqual(16, image.size)
894 def testPackInvalidImageAlign(self):
895 """Test that invalid image alignment is detected"""
896 with self.assertRaises(ValueError) as e:
897 self._DoTestFile('019_pack_inv_image_align.dts')
898 self.assertIn("Section '/binman': Size 0x7 (7) does not match "
899 "align-size 0x8 (8)", str(e.exception))
901 def testPackAlignPowerOf2(self):
902 """Test that invalid image alignment is detected"""
903 with self.assertRaises(ValueError) as e:
904 self._DoTestFile('020_pack_inv_image_align_power2.dts')
905 self.assertIn("Image '/binman': Alignment size 131 must be a power of "
906 "two", str(e.exception))
908 def testImagePadByte(self):
909 """Test that the image pad byte can be specified"""
911 data = self._DoReadFile('021_image_pad.dts')
912 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0xff, 1) +
915 def testImageName(self):
916 """Test that image files can be named"""
917 retcode = self._DoTestFile('022_image_name.dts')
918 self.assertEqual(0, retcode)
919 image = control.images['image1']
920 fname = tools.GetOutputFilename('test-name')
921 self.assertTrue(os.path.exists(fname))
923 image = control.images['image2']
924 fname = tools.GetOutputFilename('test-name.xx')
925 self.assertTrue(os.path.exists(fname))
927 def testBlobFilename(self):
928 """Test that generic blobs can be provided by filename"""
929 data = self._DoReadFile('023_blob.dts')
930 self.assertEqual(BLOB_DATA, data)
932 def testPackSorted(self):
933 """Test that entries can be sorted"""
935 data = self._DoReadFile('024_sorted.dts')
936 self.assertEqual(tools.GetBytes(0, 1) + U_BOOT_SPL_DATA +
937 tools.GetBytes(0, 2) + U_BOOT_DATA, data)
939 def testPackZeroOffset(self):
940 """Test that an entry at offset 0 is not given a new offset"""
941 with self.assertRaises(ValueError) as e:
942 self._DoTestFile('025_pack_zero_size.dts')
943 self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
944 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
947 def testPackUbootDtb(self):
948 """Test that a device tree can be added to U-Boot"""
949 data = self._DoReadFile('026_pack_u_boot_dtb.dts')
950 self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
952 def testPackX86RomNoSize(self):
953 """Test that the end-at-4gb property requires a size property"""
954 with self.assertRaises(ValueError) as e:
955 self._DoTestFile('027_pack_4gb_no_size.dts')
956 self.assertIn("Image '/binman': Section size must be provided when "
957 "using end-at-4gb", str(e.exception))
959 def test4gbAndSkipAtStartTogether(self):
960 """Test that the end-at-4gb and skip-at-size property can't be used
962 with self.assertRaises(ValueError) as e:
963 self._DoTestFile('098_4gb_and_skip_at_start_together.dts')
964 self.assertIn("Image '/binman': Provide either 'end-at-4gb' or "
965 "'skip-at-start'", str(e.exception))
967 def testPackX86RomOutside(self):
968 """Test that the end-at-4gb property checks for offset boundaries"""
969 with self.assertRaises(ValueError) as e:
970 self._DoTestFile('028_pack_4gb_outside.dts')
971 self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
972 "the section starting at 0xffffffe0 (4294967264)",
975 def testPackX86Rom(self):
976 """Test that a basic x86 ROM can be created"""
978 data = self._DoReadFile('029_x86_rom.dts')
979 self.assertEqual(U_BOOT_DATA + tools.GetBytes(0, 3) + U_BOOT_SPL_DATA +
980 tools.GetBytes(0, 2), data)
982 def testPackX86RomMeNoDesc(self):
983 """Test that an invalid Intel descriptor entry is detected"""
985 TestFunctional._MakeInputFile('descriptor-empty.bin', b'')
986 with self.assertRaises(ValueError) as e:
987 self._DoTestFile('163_x86_rom_me_empty.dts')
988 self.assertIn("Node '/binman/intel-descriptor': Cannot find Intel Flash Descriptor (FD) signature",
991 self._SetupDescriptor()
993 def testPackX86RomBadDesc(self):
994 """Test that the Intel requires a descriptor entry"""
995 with self.assertRaises(ValueError) as e:
996 self._DoTestFile('030_x86_rom_me_no_desc.dts')
997 self.assertIn("Node '/binman/intel-me': No offset set with "
998 "offset-unset: should another entry provide this correct "
999 "offset?", str(e.exception))
1001 def testPackX86RomMe(self):
1002 """Test that an x86 ROM with an ME region can be created"""
1003 data = self._DoReadFile('031_x86_rom_me.dts')
1004 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
1005 if data[:0x1000] != expected_desc:
1006 self.fail('Expected descriptor binary at start of image')
1007 self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
1009 def testPackVga(self):
1010 """Test that an image with a VGA binary can be created"""
1011 data = self._DoReadFile('032_intel_vga.dts')
1012 self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
1014 def testPackStart16(self):
1015 """Test that an image with an x86 start16 region can be created"""
1016 data = self._DoReadFile('033_x86_start16.dts')
1017 self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
1019 def testPackPowerpcMpc85xxBootpgResetvec(self):
1020 """Test that an image with powerpc-mpc85xx-bootpg-resetvec can be
1022 data = self._DoReadFile('150_powerpc_mpc85xx_bootpg_resetvec.dts')
1023 self.assertEqual(PPC_MPC85XX_BR_DATA, data[:len(PPC_MPC85XX_BR_DATA)])
1025 def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False):
1026 """Handle running a test for insertion of microcode
1029 dts_fname: Name of test .dts file
1030 nodtb_data: Data that we expect in the first section
1031 ucode_second: True if the microsecond entry is second instead of
1036 Contents of first region (U-Boot or SPL)
1037 Offset and size components of microcode pointer, as inserted
1038 in the above (two 4-byte words)
1040 data = self._DoReadFile(dts_fname, True)
1042 # Now check the device tree has no microcode
1044 ucode_content = data[len(nodtb_data):]
1045 ucode_pos = len(nodtb_data)
1046 dtb_with_ucode = ucode_content[16:]
1047 fdt_len = self.GetFdtLen(dtb_with_ucode)
1049 dtb_with_ucode = data[len(nodtb_data):]
1050 fdt_len = self.GetFdtLen(dtb_with_ucode)
1051 ucode_content = dtb_with_ucode[fdt_len:]
1052 ucode_pos = len(nodtb_data) + fdt_len
1053 fname = tools.GetOutputFilename('test.dtb')
1054 with open(fname, 'wb') as fd:
1055 fd.write(dtb_with_ucode)
1056 dtb = fdt.FdtScan(fname)
1057 ucode = dtb.GetNode('/microcode')
1058 self.assertTrue(ucode)
1059 for node in ucode.subnodes:
1060 self.assertFalse(node.props.get('data'))
1062 # Check that the microcode appears immediately after the Fdt
1063 # This matches the concatenation of the data properties in
1064 # the /microcode/update@xxx nodes in 34_x86_ucode.dts.
1065 ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
1067 self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
1069 # Check that the microcode pointer was inserted. It should match the
1070 # expected offset and size
1071 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
1073 u_boot = data[:len(nodtb_data)]
1074 return u_boot, pos_and_size
1076 def testPackUbootMicrocode(self):
1077 """Test that x86 microcode can be handled correctly
1079 We expect to see the following in the image, in order:
1080 u-boot-nodtb.bin with a microcode pointer inserted at the correct
1082 u-boot.dtb with the microcode removed
1085 first, pos_and_size = self._RunMicrocodeTest('034_x86_ucode.dts',
1087 self.assertEqual(b'nodtb with microcode' + pos_and_size +
1088 b' somewhere in here', first)
1090 def _RunPackUbootSingleMicrocode(self):
1091 """Test that x86 microcode can be handled correctly
1093 We expect to see the following in the image, in order:
1094 u-boot-nodtb.bin with a microcode pointer inserted at the correct
1096 u-boot.dtb with the microcode
1097 an empty microcode region
1099 # We need the libfdt library to run this test since only that allows
1100 # finding the offset of a property. This is required by
1101 # Entry_u_boot_dtb_with_ucode.ObtainContents().
1102 data = self._DoReadFile('035_x86_single_ucode.dts', True)
1104 second = data[len(U_BOOT_NODTB_DATA):]
1106 fdt_len = self.GetFdtLen(second)
1107 third = second[fdt_len:]
1108 second = second[:fdt_len]
1110 ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
1111 self.assertIn(ucode_data, second)
1112 ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
1114 # Check that the microcode pointer was inserted. It should match the
1115 # expected offset and size
1116 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
1118 first = data[:len(U_BOOT_NODTB_DATA)]
1119 self.assertEqual(b'nodtb with microcode' + pos_and_size +
1120 b' somewhere in here', first)
1122 def testPackUbootSingleMicrocode(self):
1123 """Test that x86 microcode can be handled correctly with fdt_normal.
1125 self._RunPackUbootSingleMicrocode()
1127 def testUBootImg(self):
1128 """Test that u-boot.img can be put in a file"""
1129 data = self._DoReadFile('036_u_boot_img.dts')
1130 self.assertEqual(U_BOOT_IMG_DATA, data)
1132 def testNoMicrocode(self):
1133 """Test that a missing microcode region is detected"""
1134 with self.assertRaises(ValueError) as e:
1135 self._DoReadFile('037_x86_no_ucode.dts', True)
1136 self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
1137 "node found in ", str(e.exception))
1139 def testMicrocodeWithoutNode(self):
1140 """Test that a missing u-boot-dtb-with-ucode node is detected"""
1141 with self.assertRaises(ValueError) as e:
1142 self._DoReadFile('038_x86_ucode_missing_node.dts', True)
1143 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1144 "microcode region u-boot-dtb-with-ucode", str(e.exception))
1146 def testMicrocodeWithoutNode2(self):
1147 """Test that a missing u-boot-ucode node is detected"""
1148 with self.assertRaises(ValueError) as e:
1149 self._DoReadFile('039_x86_ucode_missing_node2.dts', True)
1150 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1151 "microcode region u-boot-ucode", str(e.exception))
1153 def testMicrocodeWithoutPtrInElf(self):
1154 """Test that a U-Boot binary without the microcode symbol is detected"""
1155 # ELF file without a '_dt_ucode_base_size' symbol
1157 TestFunctional._MakeInputFile('u-boot',
1158 tools.ReadFile(self.ElfTestFile('u_boot_no_ucode_ptr')))
1160 with self.assertRaises(ValueError) as e:
1161 self._RunPackUbootSingleMicrocode()
1162 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
1163 "_dt_ucode_base_size symbol in u-boot", str(e.exception))
1166 # Put the original file back
1167 TestFunctional._MakeInputFile('u-boot',
1168 tools.ReadFile(self.ElfTestFile('u_boot_ucode_ptr')))
1170 def testMicrocodeNotInImage(self):
1171 """Test that microcode must be placed within the image"""
1172 with self.assertRaises(ValueError) as e:
1173 self._DoReadFile('040_x86_ucode_not_in_image.dts', True)
1174 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
1175 "pointer _dt_ucode_base_size at fffffe14 is outside the "
1176 "section ranging from 00000000 to 0000002e", str(e.exception))
1178 def testWithoutMicrocode(self):
1179 """Test that we can cope with an image without microcode (e.g. qemu)"""
1180 TestFunctional._MakeInputFile('u-boot',
1181 tools.ReadFile(self.ElfTestFile('u_boot_no_ucode_ptr')))
1182 data, dtb, _, _ = self._DoReadFileDtb('044_x86_optional_ucode.dts', True)
1184 # Now check the device tree has no microcode
1185 self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
1186 second = data[len(U_BOOT_NODTB_DATA):]
1188 fdt_len = self.GetFdtLen(second)
1189 self.assertEqual(dtb, second[:fdt_len])
1191 used_len = len(U_BOOT_NODTB_DATA) + fdt_len
1192 third = data[used_len:]
1193 self.assertEqual(tools.GetBytes(0, 0x200 - used_len), third)
1195 def testUnknownPosSize(self):
1196 """Test that microcode must be placed within the image"""
1197 with self.assertRaises(ValueError) as e:
1198 self._DoReadFile('041_unknown_pos_size.dts', True)
1199 self.assertIn("Section '/binman': Unable to set offset/size for unknown "
1200 "entry 'invalid-entry'", str(e.exception))
1202 def testPackFsp(self):
1203 """Test that an image with a FSP binary can be created"""
1204 data = self._DoReadFile('042_intel_fsp.dts')
1205 self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
1207 def testPackCmc(self):
1208 """Test that an image with a CMC binary can be created"""
1209 data = self._DoReadFile('043_intel_cmc.dts')
1210 self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
1212 def testPackVbt(self):
1213 """Test that an image with a VBT binary can be created"""
1214 data = self._DoReadFile('046_intel_vbt.dts')
1215 self.assertEqual(VBT_DATA, data[:len(VBT_DATA)])
1217 def testSplBssPad(self):
1218 """Test that we can pad SPL's BSS with zeros"""
1219 # ELF file with a '__bss_size' symbol
1221 data = self._DoReadFile('047_spl_bss_pad.dts')
1222 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0, 10) + U_BOOT_DATA,
1225 def testSplBssPadMissing(self):
1226 """Test that a missing symbol is detected"""
1227 self._SetupSplElf('u_boot_ucode_ptr')
1228 with self.assertRaises(ValueError) as e:
1229 self._DoReadFile('047_spl_bss_pad.dts')
1230 self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
1233 def testPackStart16Spl(self):
1234 """Test that an image with an x86 start16 SPL region can be created"""
1235 data = self._DoReadFile('048_x86_start16_spl.dts')
1236 self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)])
1238 def _PackUbootSplMicrocode(self, dts, ucode_second=False):
1239 """Helper function for microcode tests
1241 We expect to see the following in the image, in order:
1242 u-boot-spl-nodtb.bin with a microcode pointer inserted at the
1244 u-boot.dtb with the microcode removed
1248 dts: Device tree file to use for test
1249 ucode_second: True if the microsecond entry is second instead of
1252 self._SetupSplElf('u_boot_ucode_ptr')
1253 first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA,
1254 ucode_second=ucode_second)
1255 self.assertEqual(b'splnodtb with microc' + pos_and_size +
1256 b'ter somewhere in here', first)
1258 def testPackUbootSplMicrocode(self):
1259 """Test that x86 microcode can be handled correctly in SPL"""
1260 self._PackUbootSplMicrocode('049_x86_ucode_spl.dts')
1262 def testPackUbootSplMicrocodeReorder(self):
1263 """Test that order doesn't matter for microcode entries
1265 This is the same as testPackUbootSplMicrocode but when we process the
1266 u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode
1267 entry, so we reply on binman to try later.
1269 self._PackUbootSplMicrocode('058_x86_ucode_spl_needs_retry.dts',
1272 def testPackMrc(self):
1273 """Test that an image with an MRC binary can be created"""
1274 data = self._DoReadFile('050_intel_mrc.dts')
1275 self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
1277 def testSplDtb(self):
1278 """Test that an image with spl/u-boot-spl.dtb can be created"""
1279 data = self._DoReadFile('051_u_boot_spl_dtb.dts')
1280 self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
1282 def testSplNoDtb(self):
1283 """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
1284 data = self._DoReadFile('052_u_boot_spl_nodtb.dts')
1285 self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
1287 def testSymbols(self):
1288 """Test binman can assign symbols embedded in U-Boot"""
1289 elf_fname = self.ElfTestFile('u_boot_binman_syms')
1290 syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
1291 addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
1292 self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
1294 self._SetupSplElf('u_boot_binman_syms')
1295 data = self._DoReadFile('053_symbols.dts')
1296 sym_values = struct.pack('<LQLL', 0x00, 0x1c, 0x28, 0x04)
1297 expected = (sym_values + U_BOOT_SPL_DATA[20:] +
1298 tools.GetBytes(0xff, 1) + U_BOOT_DATA + sym_values +
1299 U_BOOT_SPL_DATA[20:])
1300 self.assertEqual(expected, data)
1302 def testPackUnitAddress(self):
1303 """Test that we support multiple binaries with the same name"""
1304 data = self._DoReadFile('054_unit_address.dts')
1305 self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
1307 def testSections(self):
1308 """Basic test of sections"""
1309 data = self._DoReadFile('055_sections.dts')
1310 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1311 U_BOOT_DATA + tools.GetBytes(ord('a'), 12) +
1312 U_BOOT_DATA + tools.GetBytes(ord('&'), 4))
1313 self.assertEqual(expected, data)
1316 """Tests outputting a map of the images"""
1317 _, _, map_data, _ = self._DoReadFileDtb('055_sections.dts', map=True)
1318 self.assertEqual('''ImagePos Offset Size Name
1319 00000000 00000000 00000028 main-section
1320 00000000 00000000 00000010 section@0
1321 00000000 00000000 00000004 u-boot
1322 00000010 00000010 00000010 section@1
1323 00000010 00000000 00000004 u-boot
1324 00000020 00000020 00000004 section@2
1325 00000020 00000000 00000004 u-boot
1328 def testNamePrefix(self):
1329 """Tests that name prefixes are used"""
1330 _, _, map_data, _ = self._DoReadFileDtb('056_name_prefix.dts', map=True)
1331 self.assertEqual('''ImagePos Offset Size Name
1332 00000000 00000000 00000028 main-section
1333 00000000 00000000 00000010 section@0
1334 00000000 00000000 00000004 ro-u-boot
1335 00000010 00000010 00000010 section@1
1336 00000010 00000000 00000004 rw-u-boot
1339 def testUnknownContents(self):
1340 """Test that obtaining the contents works as expected"""
1341 with self.assertRaises(ValueError) as e:
1342 self._DoReadFile('057_unknown_contents.dts', True)
1343 self.assertIn("Image '/binman': Internal error: Could not complete "
1344 "processing of contents: remaining ["
1345 "<binman.etype._testing.Entry__testing ", str(e.exception))
1347 def testBadChangeSize(self):
1348 """Test that trying to change the size of an entry fails"""
1350 state.SetAllowEntryExpansion(False)
1351 with self.assertRaises(ValueError) as e:
1352 self._DoReadFile('059_change_size.dts', True)
1353 self.assertIn("Node '/binman/_testing': Cannot update entry size from 2 to 3",
1356 state.SetAllowEntryExpansion(True)
1358 def testUpdateFdt(self):
1359 """Test that we can update the device tree with offset/size info"""
1360 _, _, _, out_dtb_fname = self._DoReadFileDtb('060_fdt_update.dts',
1362 dtb = fdt.Fdt(out_dtb_fname)
1364 props = self._GetPropTree(dtb, BASE_DTB_PROPS + REPACK_DTB_PROPS)
1368 '_testing:offset': 32,
1370 '_testing:image-pos': 32,
1371 'section@0/u-boot:offset': 0,
1372 'section@0/u-boot:size': len(U_BOOT_DATA),
1373 'section@0/u-boot:image-pos': 0,
1374 'section@0:offset': 0,
1375 'section@0:size': 16,
1376 'section@0:image-pos': 0,
1378 'section@1/u-boot:offset': 0,
1379 'section@1/u-boot:size': len(U_BOOT_DATA),
1380 'section@1/u-boot:image-pos': 16,
1381 'section@1:offset': 16,
1382 'section@1:size': 16,
1383 'section@1:image-pos': 16,
1387 def testUpdateFdtBad(self):
1388 """Test that we detect when ProcessFdt never completes"""
1389 with self.assertRaises(ValueError) as e:
1390 self._DoReadFileDtb('061_fdt_update_bad.dts', update_dtb=True)
1391 self.assertIn('Could not complete processing of Fdt: remaining '
1392 '[<binman.etype._testing.Entry__testing',
1395 def testEntryArgs(self):
1396 """Test passing arguments to entries from the command line"""
1398 'test-str-arg': 'test1',
1399 'test-int-arg': '456',
1401 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
1402 self.assertIn('image', control.images)
1403 entry = control.images['image'].GetEntries()['_testing']
1404 self.assertEqual('test0', entry.test_str_fdt)
1405 self.assertEqual('test1', entry.test_str_arg)
1406 self.assertEqual(123, entry.test_int_fdt)
1407 self.assertEqual(456, entry.test_int_arg)
1409 def testEntryArgsMissing(self):
1410 """Test missing arguments and properties"""
1412 'test-int-arg': '456',
1414 self._DoReadFileDtb('063_entry_args_missing.dts', entry_args=entry_args)
1415 entry = control.images['image'].GetEntries()['_testing']
1416 self.assertEqual('test0', entry.test_str_fdt)
1417 self.assertEqual(None, entry.test_str_arg)
1418 self.assertEqual(None, entry.test_int_fdt)
1419 self.assertEqual(456, entry.test_int_arg)
1421 def testEntryArgsRequired(self):
1422 """Test missing arguments and properties"""
1424 'test-int-arg': '456',
1426 with self.assertRaises(ValueError) as e:
1427 self._DoReadFileDtb('064_entry_args_required.dts')
1428 self.assertIn("Node '/binman/_testing': "
1429 'Missing required properties/entry args: test-str-arg, '
1430 'test-int-fdt, test-int-arg',
1433 def testEntryArgsInvalidFormat(self):
1434 """Test that an invalid entry-argument format is detected"""
1435 args = ['build', '-d', self.TestFile('064_entry_args_required.dts'),
1437 with self.assertRaises(ValueError) as e:
1438 self._DoBinman(*args)
1439 self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
1441 def testEntryArgsInvalidInteger(self):
1442 """Test that an invalid entry-argument integer is detected"""
1444 'test-int-arg': 'abc',
1446 with self.assertRaises(ValueError) as e:
1447 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
1448 self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
1449 "'test-int-arg' (value 'abc') to integer",
1452 def testEntryArgsInvalidDatatype(self):
1453 """Test that an invalid entry-argument datatype is detected
1455 This test could be written in entry_test.py except that it needs
1456 access to control.entry_args, which seems more than that module should
1460 'test-bad-datatype-arg': '12',
1462 with self.assertRaises(ValueError) as e:
1463 self._DoReadFileDtb('065_entry_args_unknown_datatype.dts',
1464 entry_args=entry_args)
1465 self.assertIn('GetArg() internal error: Unknown data type ',
1469 """Test for a text entry type"""
1471 'test-id': TEXT_DATA,
1472 'test-id2': TEXT_DATA2,
1473 'test-id3': TEXT_DATA3,
1475 data, _, _, _ = self._DoReadFileDtb('066_text.dts',
1476 entry_args=entry_args)
1477 expected = (tools.ToBytes(TEXT_DATA) +
1478 tools.GetBytes(0, 8 - len(TEXT_DATA)) +
1479 tools.ToBytes(TEXT_DATA2) + tools.ToBytes(TEXT_DATA3) +
1480 b'some text' + b'more text')
1481 self.assertEqual(expected, data)
1483 def testEntryDocs(self):
1484 """Test for creation of entry documentation"""
1485 with test_util.capture_sys_output() as (stdout, stderr):
1486 control.WriteEntryDocs(control.GetEntryModules())
1487 self.assertTrue(len(stdout.getvalue()) > 0)
1489 def testEntryDocsMissing(self):
1490 """Test handling of missing entry documentation"""
1491 with self.assertRaises(ValueError) as e:
1492 with test_util.capture_sys_output() as (stdout, stderr):
1493 control.WriteEntryDocs(control.GetEntryModules(), 'u_boot')
1494 self.assertIn('Documentation is missing for modules: u_boot',
1498 """Basic test of generation of a flashrom fmap"""
1499 data = self._DoReadFile('067_fmap.dts')
1500 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1501 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1502 U_BOOT_DATA + tools.GetBytes(ord('a'), 12))
1503 self.assertEqual(expected, data[:32])
1504 self.assertEqual(b'__FMAP__', fhdr.signature)
1505 self.assertEqual(1, fhdr.ver_major)
1506 self.assertEqual(0, fhdr.ver_minor)
1507 self.assertEqual(0, fhdr.base)
1508 self.assertEqual(16 + 16 +
1509 fmap_util.FMAP_HEADER_LEN +
1510 fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
1511 self.assertEqual(b'FMAP', fhdr.name)
1512 self.assertEqual(3, fhdr.nareas)
1513 for fentry in fentries:
1514 self.assertEqual(0, fentry.flags)
1516 self.assertEqual(0, fentries[0].offset)
1517 self.assertEqual(4, fentries[0].size)
1518 self.assertEqual(b'RO_U_BOOT', fentries[0].name)
1520 self.assertEqual(16, fentries[1].offset)
1521 self.assertEqual(4, fentries[1].size)
1522 self.assertEqual(b'RW_U_BOOT', fentries[1].name)
1524 self.assertEqual(32, fentries[2].offset)
1525 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1526 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1527 self.assertEqual(b'FMAP', fentries[2].name)
1529 def testBlobNamedByArg(self):
1530 """Test we can add a blob with the filename coming from an entry arg"""
1532 'cros-ec-rw-path': 'ecrw.bin',
1534 self._DoReadFileDtb('068_blob_named_by_arg.dts', entry_args=entry_args)
1537 """Test for an fill entry type"""
1538 data = self._DoReadFile('069_fill.dts')
1539 expected = tools.GetBytes(0xff, 8) + tools.GetBytes(0, 8)
1540 self.assertEqual(expected, data)
1542 def testFillNoSize(self):
1543 """Test for an fill entry type with no size"""
1544 with self.assertRaises(ValueError) as e:
1545 self._DoReadFile('070_fill_no_size.dts')
1546 self.assertIn("'fill' entry must have a size property",
1549 def _HandleGbbCommand(self, pipe_list):
1550 """Fake calls to the futility utility"""
1551 if pipe_list[0][0] == 'futility':
1552 fname = pipe_list[0][-1]
1553 # Append our GBB data to the file, which will happen every time the
1554 # futility command is called.
1555 with open(fname, 'ab') as fd:
1557 return command.CommandResult()
1560 """Test for the Chromium OS Google Binary Block"""
1561 command.test_result = self._HandleGbbCommand
1563 'keydir': 'devkeys',
1564 'bmpblk': 'bmpblk.bin',
1566 data, _, _, _ = self._DoReadFileDtb('071_gbb.dts', entry_args=entry_args)
1569 expected = (GBB_DATA + GBB_DATA + tools.GetBytes(0, 8) +
1570 tools.GetBytes(0, 0x2180 - 16))
1571 self.assertEqual(expected, data)
1573 def testGbbTooSmall(self):
1574 """Test for the Chromium OS Google Binary Block being large enough"""
1575 with self.assertRaises(ValueError) as e:
1576 self._DoReadFileDtb('072_gbb_too_small.dts')
1577 self.assertIn("Node '/binman/gbb': GBB is too small",
1580 def testGbbNoSize(self):
1581 """Test for the Chromium OS Google Binary Block having a size"""
1582 with self.assertRaises(ValueError) as e:
1583 self._DoReadFileDtb('073_gbb_no_size.dts')
1584 self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
1587 def _HandleVblockCommand(self, pipe_list):
1588 """Fake calls to the futility utility"""
1589 if pipe_list[0][0] == 'futility':
1590 fname = pipe_list[0][3]
1591 with open(fname, 'wb') as fd:
1592 fd.write(VBLOCK_DATA)
1593 return command.CommandResult()
1595 def testVblock(self):
1596 """Test for the Chromium OS Verified Boot Block"""
1597 command.test_result = self._HandleVblockCommand
1599 'keydir': 'devkeys',
1601 data, _, _, _ = self._DoReadFileDtb('074_vblock.dts',
1602 entry_args=entry_args)
1603 expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
1604 self.assertEqual(expected, data)
1606 def testVblockNoContent(self):
1607 """Test we detect a vblock which has no content to sign"""
1608 with self.assertRaises(ValueError) as e:
1609 self._DoReadFile('075_vblock_no_content.dts')
1610 self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
1611 'property', str(e.exception))
1613 def testVblockBadPhandle(self):
1614 """Test that we detect a vblock with an invalid phandle in contents"""
1615 with self.assertRaises(ValueError) as e:
1616 self._DoReadFile('076_vblock_bad_phandle.dts')
1617 self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
1618 '1000', str(e.exception))
1620 def testVblockBadEntry(self):
1621 """Test that we detect an entry that points to a non-entry"""
1622 with self.assertRaises(ValueError) as e:
1623 self._DoReadFile('077_vblock_bad_entry.dts')
1624 self.assertIn("Node '/binman/vblock': Cannot find entry for node "
1625 "'other'", str(e.exception))
1628 """Test that an image with TPL and its device tree can be created"""
1629 # ELF file with a '__bss_size' symbol
1631 data = self._DoReadFile('078_u_boot_tpl.dts')
1632 self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
1634 def testUsesPos(self):
1635 """Test that the 'pos' property cannot be used anymore"""
1636 with self.assertRaises(ValueError) as e:
1637 data = self._DoReadFile('079_uses_pos.dts')
1638 self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
1639 "'pos'", str(e.exception))
1641 def testFillZero(self):
1642 """Test for an fill entry type with a size of 0"""
1643 data = self._DoReadFile('080_fill_empty.dts')
1644 self.assertEqual(tools.GetBytes(0, 16), data)
1646 def testTextMissing(self):
1647 """Test for a text entry type where there is no text"""
1648 with self.assertRaises(ValueError) as e:
1649 self._DoReadFileDtb('066_text.dts',)
1650 self.assertIn("Node '/binman/text': No value provided for text label "
1651 "'test-id'", str(e.exception))
1653 def testPackStart16Tpl(self):
1654 """Test that an image with an x86 start16 TPL region can be created"""
1655 data = self._DoReadFile('081_x86_start16_tpl.dts')
1656 self.assertEqual(X86_START16_TPL_DATA, data[:len(X86_START16_TPL_DATA)])
1658 def testSelectImage(self):
1659 """Test that we can select which images to build"""
1660 expected = 'Skipping images: image1'
1662 # We should only get the expected message in verbose mode
1663 for verbosity in (0, 2):
1664 with test_util.capture_sys_output() as (stdout, stderr):
1665 retcode = self._DoTestFile('006_dual_image.dts',
1666 verbosity=verbosity,
1668 self.assertEqual(0, retcode)
1670 self.assertIn(expected, stdout.getvalue())
1672 self.assertNotIn(expected, stdout.getvalue())
1674 self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
1675 self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
1676 self._CleanupOutputDir()
1678 def testUpdateFdtAll(self):
1679 """Test that all device trees are updated with offset/size info"""
1680 data = self._DoReadFileRealDtb('082_fdt_update_all.dts')
1683 'section:image-pos': 0,
1684 'u-boot-tpl-dtb:size': 513,
1685 'u-boot-spl-dtb:size': 513,
1686 'u-boot-spl-dtb:offset': 493,
1688 'section/u-boot-dtb:image-pos': 0,
1689 'u-boot-spl-dtb:image-pos': 493,
1690 'section/u-boot-dtb:size': 493,
1691 'u-boot-tpl-dtb:image-pos': 1006,
1692 'section/u-boot-dtb:offset': 0,
1693 'section:size': 493,
1695 'section:offset': 0,
1696 'u-boot-tpl-dtb:offset': 1006,
1700 # We expect three device-tree files in the output, one after the other.
1701 # Read them in sequence. We look for an 'spl' property in the SPL tree,
1702 # and 'tpl' in the TPL tree, to make sure they are distinct from the
1703 # main U-Boot tree. All three should have the same postions and offset.
1705 for item in ['', 'spl', 'tpl']:
1706 dtb = fdt.Fdt.FromData(data[start:])
1708 props = self._GetPropTree(dtb, BASE_DTB_PROPS + REPACK_DTB_PROPS +
1710 expected = dict(base_expected)
1713 self.assertEqual(expected, props)
1714 start += dtb._fdt_obj.totalsize()
1716 def testUpdateFdtOutput(self):
1717 """Test that output DTB files are updated"""
1719 data, dtb_data, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
1720 use_real_dtb=True, update_dtb=True, reset_dtbs=False)
1722 # Unfortunately, compiling a source file always results in a file
1723 # called source.dtb (see fdt_util.EnsureCompiled()). The test
1724 # source file (e.g. test/075_fdt_update_all.dts) thus does not enter
1725 # binman as a file called u-boot.dtb. To fix this, copy the file
1726 # over to the expected place.
1728 for fname in ['u-boot.dtb.out', 'spl/u-boot-spl.dtb.out',
1729 'tpl/u-boot-tpl.dtb.out']:
1730 dtb = fdt.Fdt.FromData(data[start:])
1731 size = dtb._fdt_obj.totalsize()
1732 pathname = tools.GetOutputFilename(os.path.split(fname)[1])
1733 outdata = tools.ReadFile(pathname)
1734 name = os.path.split(fname)[0]
1737 orig_indata = self._GetDtbContentsForSplTpl(dtb_data, name)
1739 orig_indata = dtb_data
1740 self.assertNotEqual(outdata, orig_indata,
1741 "Expected output file '%s' be updated" % pathname)
1742 self.assertEqual(outdata, data[start:start + size],
1743 "Expected output file '%s' to match output image" %
1749 def _decompress(self, data):
1750 return tools.Decompress(data, 'lz4')
1752 def testCompress(self):
1753 """Test compression of blobs"""
1755 data, _, _, out_dtb_fname = self._DoReadFileDtb('083_compress.dts',
1756 use_real_dtb=True, update_dtb=True)
1757 dtb = fdt.Fdt(out_dtb_fname)
1759 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
1760 orig = self._decompress(data)
1761 self.assertEquals(COMPRESS_DATA, orig)
1763 'blob:uncomp-size': len(COMPRESS_DATA),
1764 'blob:size': len(data),
1767 self.assertEqual(expected, props)
1769 def testFiles(self):
1770 """Test bringing in multiple files"""
1771 data = self._DoReadFile('084_files.dts')
1772 self.assertEqual(FILES_DATA, data)
1774 def testFilesCompress(self):
1775 """Test bringing in multiple files and compressing them"""
1777 data = self._DoReadFile('085_files_compress.dts')
1779 image = control.images['image']
1780 entries = image.GetEntries()
1781 files = entries['files']
1782 entries = files._entries
1785 for i in range(1, 3):
1787 start = entries[key].image_pos
1788 len = entries[key].size
1789 chunk = data[start:start + len]
1790 orig += self._decompress(chunk)
1792 self.assertEqual(FILES_DATA, orig)
1794 def testFilesMissing(self):
1795 """Test missing files"""
1796 with self.assertRaises(ValueError) as e:
1797 data = self._DoReadFile('086_files_none.dts')
1798 self.assertIn("Node '/binman/files': Pattern \'files/*.none\' matched "
1799 'no files', str(e.exception))
1801 def testFilesNoPattern(self):
1802 """Test missing files"""
1803 with self.assertRaises(ValueError) as e:
1804 data = self._DoReadFile('087_files_no_pattern.dts')
1805 self.assertIn("Node '/binman/files': Missing 'pattern' property",
1808 def testExpandSize(self):
1809 """Test an expanding entry"""
1810 data, _, map_data, _ = self._DoReadFileDtb('088_expand_size.dts',
1812 expect = (tools.GetBytes(ord('a'), 8) + U_BOOT_DATA +
1813 MRC_DATA + tools.GetBytes(ord('b'), 1) + U_BOOT_DATA +
1814 tools.GetBytes(ord('c'), 8) + U_BOOT_DATA +
1815 tools.GetBytes(ord('d'), 8))
1816 self.assertEqual(expect, data)
1817 self.assertEqual('''ImagePos Offset Size Name
1818 00000000 00000000 00000028 main-section
1819 00000000 00000000 00000008 fill
1820 00000008 00000008 00000004 u-boot
1821 0000000c 0000000c 00000004 section
1822 0000000c 00000000 00000003 intel-mrc
1823 00000010 00000010 00000004 u-boot2
1824 00000014 00000014 0000000c section2
1825 00000014 00000000 00000008 fill
1826 0000001c 00000008 00000004 u-boot
1827 00000020 00000020 00000008 fill2
1830 def testExpandSizeBad(self):
1831 """Test an expanding entry which fails to provide contents"""
1832 with test_util.capture_sys_output() as (stdout, stderr):
1833 with self.assertRaises(ValueError) as e:
1834 self._DoReadFileDtb('089_expand_size_bad.dts', map=True)
1835 self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
1836 'expanding entry', str(e.exception))
1839 """Test hashing of the contents of an entry"""
1840 _, _, _, out_dtb_fname = self._DoReadFileDtb('090_hash.dts',
1841 use_real_dtb=True, update_dtb=True)
1842 dtb = fdt.Fdt(out_dtb_fname)
1844 hash_node = dtb.GetNode('/binman/u-boot/hash').props['value']
1845 m = hashlib.sha256()
1846 m.update(U_BOOT_DATA)
1847 self.assertEqual(m.digest(), b''.join(hash_node.value))
1849 def testHashNoAlgo(self):
1850 with self.assertRaises(ValueError) as e:
1851 self._DoReadFileDtb('091_hash_no_algo.dts', update_dtb=True)
1852 self.assertIn("Node \'/binman/u-boot\': Missing \'algo\' property for "
1853 'hash node', str(e.exception))
1855 def testHashBadAlgo(self):
1856 with self.assertRaises(ValueError) as e:
1857 self._DoReadFileDtb('092_hash_bad_algo.dts', update_dtb=True)
1858 self.assertIn("Node '/binman/u-boot': Unknown hash algorithm",
1861 def testHashSection(self):
1862 """Test hashing of the contents of an entry"""
1863 _, _, _, out_dtb_fname = self._DoReadFileDtb('099_hash_section.dts',
1864 use_real_dtb=True, update_dtb=True)
1865 dtb = fdt.Fdt(out_dtb_fname)
1867 hash_node = dtb.GetNode('/binman/section/hash').props['value']
1868 m = hashlib.sha256()
1869 m.update(U_BOOT_DATA)
1870 m.update(tools.GetBytes(ord('a'), 16))
1871 self.assertEqual(m.digest(), b''.join(hash_node.value))
1873 def testPackUBootTplMicrocode(self):
1874 """Test that x86 microcode can be handled correctly in TPL
1876 We expect to see the following in the image, in order:
1877 u-boot-tpl-nodtb.bin with a microcode pointer inserted at the correct
1879 u-boot-tpl.dtb with the microcode removed
1882 self._SetupTplElf('u_boot_ucode_ptr')
1883 first, pos_and_size = self._RunMicrocodeTest('093_x86_tpl_ucode.dts',
1884 U_BOOT_TPL_NODTB_DATA)
1885 self.assertEqual(b'tplnodtb with microc' + pos_and_size +
1886 b'ter somewhere in here', first)
1888 def testFmapX86(self):
1889 """Basic test of generation of a flashrom fmap"""
1890 data = self._DoReadFile('094_fmap_x86.dts')
1891 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1892 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('a'), 32 - 7)
1893 self.assertEqual(expected, data[:32])
1894 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1896 self.assertEqual(0x100, fhdr.image_size)
1898 self.assertEqual(0, fentries[0].offset)
1899 self.assertEqual(4, fentries[0].size)
1900 self.assertEqual(b'U_BOOT', fentries[0].name)
1902 self.assertEqual(4, fentries[1].offset)
1903 self.assertEqual(3, fentries[1].size)
1904 self.assertEqual(b'INTEL_MRC', fentries[1].name)
1906 self.assertEqual(32, fentries[2].offset)
1907 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1908 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1909 self.assertEqual(b'FMAP', fentries[2].name)
1911 def testFmapX86Section(self):
1912 """Basic test of generation of a flashrom fmap"""
1913 data = self._DoReadFile('095_fmap_x86_section.dts')
1914 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('b'), 32 - 7)
1915 self.assertEqual(expected, data[:32])
1916 fhdr, fentries = fmap_util.DecodeFmap(data[36:])
1918 self.assertEqual(0x100, fhdr.image_size)
1920 self.assertEqual(0, fentries[0].offset)
1921 self.assertEqual(4, fentries[0].size)
1922 self.assertEqual(b'U_BOOT', fentries[0].name)
1924 self.assertEqual(4, fentries[1].offset)
1925 self.assertEqual(3, fentries[1].size)
1926 self.assertEqual(b'INTEL_MRC', fentries[1].name)
1928 self.assertEqual(36, fentries[2].offset)
1929 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1930 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1931 self.assertEqual(b'FMAP', fentries[2].name)
1934 """Basic test of ELF entries"""
1937 with open(self.ElfTestFile('bss_data'), 'rb') as fd:
1938 TestFunctional._MakeInputFile('-boot', fd.read())
1939 data = self._DoReadFile('096_elf.dts')
1941 def testElfStrip(self):
1942 """Basic test of ELF entries"""
1944 with open(self.ElfTestFile('bss_data'), 'rb') as fd:
1945 TestFunctional._MakeInputFile('-boot', fd.read())
1946 data = self._DoReadFile('097_elf_strip.dts')
1948 def testPackOverlapMap(self):
1949 """Test that overlapping regions are detected"""
1950 with test_util.capture_sys_output() as (stdout, stderr):
1951 with self.assertRaises(ValueError) as e:
1952 self._DoTestFile('014_pack_overlap.dts', map=True)
1953 map_fname = tools.GetOutputFilename('image.map')
1954 self.assertEqual("Wrote map file '%s' to show errors\n" % map_fname,
1957 # We should not get an inmage, but there should be a map file
1958 self.assertFalse(os.path.exists(tools.GetOutputFilename('image.bin')))
1959 self.assertTrue(os.path.exists(map_fname))
1960 map_data = tools.ReadFile(map_fname, binary=False)
1961 self.assertEqual('''ImagePos Offset Size Name
1962 <none> 00000000 00000007 main-section
1963 <none> 00000000 00000004 u-boot
1964 <none> 00000003 00000004 u-boot-align
1967 def testPackRefCode(self):
1968 """Test that an image with an Intel Reference code binary works"""
1969 data = self._DoReadFile('100_intel_refcode.dts')
1970 self.assertEqual(REFCODE_DATA, data[:len(REFCODE_DATA)])
1972 def testSectionOffset(self):
1973 """Tests use of a section with an offset"""
1974 data, _, map_data, _ = self._DoReadFileDtb('101_sections_offset.dts',
1976 self.assertEqual('''ImagePos Offset Size Name
1977 00000000 00000000 00000038 main-section
1978 00000004 00000004 00000010 section@0
1979 00000004 00000000 00000004 u-boot
1980 00000018 00000018 00000010 section@1
1981 00000018 00000000 00000004 u-boot
1982 0000002c 0000002c 00000004 section@2
1983 0000002c 00000000 00000004 u-boot
1985 self.assertEqual(data,
1986 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1987 tools.GetBytes(0x21, 12) +
1988 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1989 tools.GetBytes(0x61, 12) +
1990 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1991 tools.GetBytes(0x26, 8))
1993 def testCbfsRaw(self):
1994 """Test base handling of a Coreboot Filesystem (CBFS)
1996 The exact contents of the CBFS is verified by similar tests in
1997 cbfs_util_test.py. The tests here merely check that the files added to
1998 the CBFS can be found in the final image.
2000 data = self._DoReadFile('102_cbfs_raw.dts')
2003 cbfs = cbfs_util.CbfsReader(data)
2004 self.assertEqual(size, cbfs.rom_size)
2006 self.assertIn('u-boot-dtb', cbfs.files)
2007 cfile = cbfs.files['u-boot-dtb']
2008 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
2010 def testCbfsArch(self):
2011 """Test on non-x86 architecture"""
2012 data = self._DoReadFile('103_cbfs_raw_ppc.dts')
2015 cbfs = cbfs_util.CbfsReader(data)
2016 self.assertEqual(size, cbfs.rom_size)
2018 self.assertIn('u-boot-dtb', cbfs.files)
2019 cfile = cbfs.files['u-boot-dtb']
2020 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
2022 def testCbfsStage(self):
2023 """Tests handling of a Coreboot Filesystem (CBFS)"""
2024 if not elf.ELF_TOOLS:
2025 self.skipTest('Python elftools not available')
2026 elf_fname = os.path.join(self._indir, 'cbfs-stage.elf')
2027 elf.MakeElf(elf_fname, U_BOOT_DATA, U_BOOT_DTB_DATA)
2030 data = self._DoReadFile('104_cbfs_stage.dts')
2031 cbfs = cbfs_util.CbfsReader(data)
2032 self.assertEqual(size, cbfs.rom_size)
2034 self.assertIn('u-boot', cbfs.files)
2035 cfile = cbfs.files['u-boot']
2036 self.assertEqual(U_BOOT_DATA + U_BOOT_DTB_DATA, cfile.data)
2038 def testCbfsRawCompress(self):
2039 """Test handling of compressing raw files"""
2041 data = self._DoReadFile('105_cbfs_raw_compress.dts')
2044 cbfs = cbfs_util.CbfsReader(data)
2045 self.assertIn('u-boot', cbfs.files)
2046 cfile = cbfs.files['u-boot']
2047 self.assertEqual(COMPRESS_DATA, cfile.data)
2049 def testCbfsBadArch(self):
2050 """Test handling of a bad architecture"""
2051 with self.assertRaises(ValueError) as e:
2052 self._DoReadFile('106_cbfs_bad_arch.dts')
2053 self.assertIn("Invalid architecture 'bad-arch'", str(e.exception))
2055 def testCbfsNoSize(self):
2056 """Test handling of a missing size property"""
2057 with self.assertRaises(ValueError) as e:
2058 self._DoReadFile('107_cbfs_no_size.dts')
2059 self.assertIn('entry must have a size property', str(e.exception))
2061 def testCbfsNoCOntents(self):
2062 """Test handling of a CBFS entry which does not provide contentsy"""
2063 with self.assertRaises(ValueError) as e:
2064 self._DoReadFile('108_cbfs_no_contents.dts')
2065 self.assertIn('Could not complete processing of contents',
2068 def testCbfsBadCompress(self):
2069 """Test handling of a bad architecture"""
2070 with self.assertRaises(ValueError) as e:
2071 self._DoReadFile('109_cbfs_bad_compress.dts')
2072 self.assertIn("Invalid compression in 'u-boot': 'invalid-algo'",
2075 def testCbfsNamedEntries(self):
2076 """Test handling of named entries"""
2077 data = self._DoReadFile('110_cbfs_name.dts')
2079 cbfs = cbfs_util.CbfsReader(data)
2080 self.assertIn('FRED', cbfs.files)
2081 cfile1 = cbfs.files['FRED']
2082 self.assertEqual(U_BOOT_DATA, cfile1.data)
2084 self.assertIn('hello', cbfs.files)
2085 cfile2 = cbfs.files['hello']
2086 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
2088 def _SetupIfwi(self, fname):
2089 """Set up to run an IFWI test
2092 fname: Filename of input file to provide (fitimage.bin or ifwi.bin)
2097 # Intel Integrated Firmware Image (IFWI) file
2098 with gzip.open(self.TestFile('%s.gz' % fname), 'rb') as fd:
2100 TestFunctional._MakeInputFile(fname,data)
2102 def _CheckIfwi(self, data):
2103 """Check that an image with an IFWI contains the correct output
2106 data: Conents of output file
2108 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
2109 if data[:0x1000] != expected_desc:
2110 self.fail('Expected descriptor binary at start of image')
2112 # We expect to find the TPL wil in subpart IBBP entry IBBL
2113 image_fname = tools.GetOutputFilename('image.bin')
2114 tpl_fname = tools.GetOutputFilename('tpl.out')
2115 tools.RunIfwiTool(image_fname, tools.CMD_EXTRACT, fname=tpl_fname,
2116 subpart='IBBP', entry_name='IBBL')
2118 tpl_data = tools.ReadFile(tpl_fname)
2119 self.assertEqual(U_BOOT_TPL_DATA, tpl_data[:len(U_BOOT_TPL_DATA)])
2121 def testPackX86RomIfwi(self):
2122 """Test that an x86 ROM with Integrated Firmware Image can be created"""
2123 self._SetupIfwi('fitimage.bin')
2124 data = self._DoReadFile('111_x86_rom_ifwi.dts')
2125 self._CheckIfwi(data)
2127 def testPackX86RomIfwiNoDesc(self):
2128 """Test that an x86 ROM with IFWI can be created from an ifwi.bin file"""
2129 self._SetupIfwi('ifwi.bin')
2130 data = self._DoReadFile('112_x86_rom_ifwi_nodesc.dts')
2131 self._CheckIfwi(data)
2133 def testPackX86RomIfwiNoData(self):
2134 """Test that an x86 ROM with IFWI handles missing data"""
2135 self._SetupIfwi('ifwi.bin')
2136 with self.assertRaises(ValueError) as e:
2137 data = self._DoReadFile('113_x86_rom_ifwi_nodata.dts')
2138 self.assertIn('Could not complete processing of contents',
2141 def testCbfsOffset(self):
2142 """Test a CBFS with files at particular offsets
2144 Like all CFBS tests, this is just checking the logic that calls
2145 cbfs_util. See cbfs_util_test for fully tests (e.g. test_cbfs_offset()).
2147 data = self._DoReadFile('114_cbfs_offset.dts')
2150 cbfs = cbfs_util.CbfsReader(data)
2151 self.assertEqual(size, cbfs.rom_size)
2153 self.assertIn('u-boot', cbfs.files)
2154 cfile = cbfs.files['u-boot']
2155 self.assertEqual(U_BOOT_DATA, cfile.data)
2156 self.assertEqual(0x40, cfile.cbfs_offset)
2158 self.assertIn('u-boot-dtb', cbfs.files)
2159 cfile2 = cbfs.files['u-boot-dtb']
2160 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
2161 self.assertEqual(0x140, cfile2.cbfs_offset)
2163 def testFdtmap(self):
2164 """Test an FDT map can be inserted in the image"""
2165 data = self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
2166 fdtmap_data = data[len(U_BOOT_DATA):]
2167 magic = fdtmap_data[:8]
2168 self.assertEqual(b'_FDTMAP_', magic)
2169 self.assertEqual(tools.GetBytes(0, 8), fdtmap_data[8:16])
2171 fdt_data = fdtmap_data[16:]
2172 dtb = fdt.Fdt.FromData(fdt_data)
2174 props = self._GetPropTree(dtb, BASE_DTB_PROPS, prefix='/')
2179 'u-boot:size': len(U_BOOT_DATA),
2180 'u-boot:image-pos': 0,
2181 'fdtmap:image-pos': 4,
2183 'fdtmap:size': len(fdtmap_data),
2187 def testFdtmapNoMatch(self):
2188 """Check handling of an FDT map when the section cannot be found"""
2189 self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
2191 # Mangle the section name, which should cause a mismatch between the
2192 # correct FDT path and the one expected by the section
2193 image = control.images['image']
2194 image._node.path += '-suffix'
2195 entries = image.GetEntries()
2196 fdtmap = entries['fdtmap']
2197 with self.assertRaises(ValueError) as e:
2199 self.assertIn("Cannot locate node for path '/binman-suffix'",
2202 def testFdtmapHeader(self):
2203 """Test an FDT map and image header can be inserted in the image"""
2204 data = self.data = self._DoReadFileRealDtb('116_fdtmap_hdr.dts')
2205 fdtmap_pos = len(U_BOOT_DATA)
2206 fdtmap_data = data[fdtmap_pos:]
2207 fdt_data = fdtmap_data[16:]
2208 dtb = fdt.Fdt.FromData(fdt_data)
2209 fdt_size = dtb.GetFdtObj().totalsize()
2210 hdr_data = data[-8:]
2211 self.assertEqual(b'BinM', hdr_data[:4])
2212 offset = struct.unpack('<I', hdr_data[4:])[0] & 0xffffffff
2213 self.assertEqual(fdtmap_pos - 0x400, offset - (1 << 32))
2215 def testFdtmapHeaderStart(self):
2216 """Test an image header can be inserted at the image start"""
2217 data = self.data = self._DoReadFileRealDtb('117_fdtmap_hdr_start.dts')
2218 fdtmap_pos = 0x100 + len(U_BOOT_DATA)
2220 self.assertEqual(b'BinM', hdr_data[:4])
2221 offset = struct.unpack('<I', hdr_data[4:])[0]
2222 self.assertEqual(fdtmap_pos, offset)
2224 def testFdtmapHeaderPos(self):
2225 """Test an image header can be inserted at a chosen position"""
2226 data = self.data = self._DoReadFileRealDtb('118_fdtmap_hdr_pos.dts')
2227 fdtmap_pos = 0x100 + len(U_BOOT_DATA)
2228 hdr_data = data[0x80:0x88]
2229 self.assertEqual(b'BinM', hdr_data[:4])
2230 offset = struct.unpack('<I', hdr_data[4:])[0]
2231 self.assertEqual(fdtmap_pos, offset)
2233 def testHeaderMissingFdtmap(self):
2234 """Test an image header requires an fdtmap"""
2235 with self.assertRaises(ValueError) as e:
2236 self.data = self._DoReadFileRealDtb('119_fdtmap_hdr_missing.dts')
2237 self.assertIn("'image_header' section must have an 'fdtmap' sibling",
2240 def testHeaderNoLocation(self):
2241 """Test an image header with a no specified location is detected"""
2242 with self.assertRaises(ValueError) as e:
2243 self.data = self._DoReadFileRealDtb('120_hdr_no_location.dts')
2244 self.assertIn("Invalid location 'None', expected 'start' or 'end'",
2247 def testEntryExpand(self):
2248 """Test expanding an entry after it is packed"""
2249 data = self._DoReadFile('121_entry_expand.dts')
2250 self.assertEqual(b'aaa', data[:3])
2251 self.assertEqual(U_BOOT_DATA, data[3:3 + len(U_BOOT_DATA)])
2252 self.assertEqual(b'aaa', data[-3:])
2254 def testEntryExpandBad(self):
2255 """Test expanding an entry after it is packed, twice"""
2256 with self.assertRaises(ValueError) as e:
2257 self._DoReadFile('122_entry_expand_twice.dts')
2258 self.assertIn("Image '/binman': Entries changed size after packing",
2261 def testEntryExpandSection(self):
2262 """Test expanding an entry within a section after it is packed"""
2263 data = self._DoReadFile('123_entry_expand_section.dts')
2264 self.assertEqual(b'aaa', data[:3])
2265 self.assertEqual(U_BOOT_DATA, data[3:3 + len(U_BOOT_DATA)])
2266 self.assertEqual(b'aaa', data[-3:])
2268 def testCompressDtb(self):
2269 """Test that compress of device-tree files is supported"""
2271 data = self.data = self._DoReadFileRealDtb('124_compress_dtb.dts')
2272 self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
2273 comp_data = data[len(U_BOOT_DATA):]
2274 orig = self._decompress(comp_data)
2275 dtb = fdt.Fdt.FromData(orig)
2277 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
2279 'u-boot:size': len(U_BOOT_DATA),
2280 'u-boot-dtb:uncomp-size': len(orig),
2281 'u-boot-dtb:size': len(comp_data),
2284 self.assertEqual(expected, props)
2286 def testCbfsUpdateFdt(self):
2287 """Test that we can update the device tree with CBFS offset/size info"""
2289 data, _, _, out_dtb_fname = self._DoReadFileDtb('125_cbfs_update.dts',
2291 dtb = fdt.Fdt(out_dtb_fname)
2293 props = self._GetPropTree(dtb, BASE_DTB_PROPS + ['uncomp-size'])
2294 del props['cbfs/u-boot:size']
2300 'cbfs:size': len(data),
2301 'cbfs:image-pos': 0,
2302 'cbfs/u-boot:offset': 0x38,
2303 'cbfs/u-boot:uncomp-size': len(U_BOOT_DATA),
2304 'cbfs/u-boot:image-pos': 0x38,
2305 'cbfs/u-boot-dtb:offset': 0xb8,
2306 'cbfs/u-boot-dtb:size': len(U_BOOT_DATA),
2307 'cbfs/u-boot-dtb:image-pos': 0xb8,
2310 def testCbfsBadType(self):
2311 """Test an image header with a no specified location is detected"""
2312 with self.assertRaises(ValueError) as e:
2313 self._DoReadFile('126_cbfs_bad_type.dts')
2314 self.assertIn("Unknown cbfs-type 'badtype'", str(e.exception))
2317 """Test listing the files in an image"""
2319 data = self._DoReadFile('127_list.dts')
2320 image = control.images['image']
2321 entries = image.BuildEntryList()
2322 self.assertEqual(7, len(entries))
2325 self.assertEqual(0, ent.indent)
2326 self.assertEqual('main-section', ent.name)
2327 self.assertEqual('section', ent.etype)
2328 self.assertEqual(len(data), ent.size)
2329 self.assertEqual(0, ent.image_pos)
2330 self.assertEqual(None, ent.uncomp_size)
2331 self.assertEqual(0, ent.offset)
2334 self.assertEqual(1, ent.indent)
2335 self.assertEqual('u-boot', ent.name)
2336 self.assertEqual('u-boot', ent.etype)
2337 self.assertEqual(len(U_BOOT_DATA), ent.size)
2338 self.assertEqual(0, ent.image_pos)
2339 self.assertEqual(None, ent.uncomp_size)
2340 self.assertEqual(0, ent.offset)
2343 self.assertEqual(1, ent.indent)
2344 self.assertEqual('section', ent.name)
2345 self.assertEqual('section', ent.etype)
2346 section_size = ent.size
2347 self.assertEqual(0x100, ent.image_pos)
2348 self.assertEqual(None, ent.uncomp_size)
2349 self.assertEqual(0x100, ent.offset)
2352 self.assertEqual(2, ent.indent)
2353 self.assertEqual('cbfs', ent.name)
2354 self.assertEqual('cbfs', ent.etype)
2355 self.assertEqual(0x400, ent.size)
2356 self.assertEqual(0x100, ent.image_pos)
2357 self.assertEqual(None, ent.uncomp_size)
2358 self.assertEqual(0, ent.offset)
2361 self.assertEqual(3, ent.indent)
2362 self.assertEqual('u-boot', ent.name)
2363 self.assertEqual('u-boot', ent.etype)
2364 self.assertEqual(len(U_BOOT_DATA), ent.size)
2365 self.assertEqual(0x138, ent.image_pos)
2366 self.assertEqual(None, ent.uncomp_size)
2367 self.assertEqual(0x38, ent.offset)
2370 self.assertEqual(3, ent.indent)
2371 self.assertEqual('u-boot-dtb', ent.name)
2372 self.assertEqual('text', ent.etype)
2373 self.assertGreater(len(COMPRESS_DATA), ent.size)
2374 self.assertEqual(0x178, ent.image_pos)
2375 self.assertEqual(len(COMPRESS_DATA), ent.uncomp_size)
2376 self.assertEqual(0x78, ent.offset)
2379 self.assertEqual(2, ent.indent)
2380 self.assertEqual('u-boot-dtb', ent.name)
2381 self.assertEqual('u-boot-dtb', ent.etype)
2382 self.assertEqual(0x500, ent.image_pos)
2383 self.assertEqual(len(U_BOOT_DTB_DATA), ent.uncomp_size)
2385 # Compressing this data expands it since headers are added
2386 self.assertGreater(dtb_size, len(U_BOOT_DTB_DATA))
2387 self.assertEqual(0x400, ent.offset)
2389 self.assertEqual(len(data), 0x100 + section_size)
2390 self.assertEqual(section_size, 0x400 + dtb_size)
2392 def testFindFdtmap(self):
2393 """Test locating an FDT map in an image"""
2395 data = self.data = self._DoReadFileRealDtb('128_decode_image.dts')
2396 image = control.images['image']
2397 entries = image.GetEntries()
2398 entry = entries['fdtmap']
2399 self.assertEqual(entry.image_pos, fdtmap.LocateFdtmap(data))
2401 def testFindFdtmapMissing(self):
2402 """Test failing to locate an FDP map"""
2403 data = self._DoReadFile('005_simple.dts')
2404 self.assertEqual(None, fdtmap.LocateFdtmap(data))
2406 def testFindImageHeader(self):
2407 """Test locating a image header"""
2409 data = self.data = self._DoReadFileRealDtb('128_decode_image.dts')
2410 image = control.images['image']
2411 entries = image.GetEntries()
2412 entry = entries['fdtmap']
2413 # The header should point to the FDT map
2414 self.assertEqual(entry.image_pos, image_header.LocateHeaderOffset(data))
2416 def testFindImageHeaderStart(self):
2417 """Test locating a image header located at the start of an image"""
2418 data = self.data = self._DoReadFileRealDtb('117_fdtmap_hdr_start.dts')
2419 image = control.images['image']
2420 entries = image.GetEntries()
2421 entry = entries['fdtmap']
2422 # The header should point to the FDT map
2423 self.assertEqual(entry.image_pos, image_header.LocateHeaderOffset(data))
2425 def testFindImageHeaderMissing(self):
2426 """Test failing to locate an image header"""
2427 data = self._DoReadFile('005_simple.dts')
2428 self.assertEqual(None, image_header.LocateHeaderOffset(data))
2430 def testReadImage(self):
2431 """Test reading an image and accessing its FDT map"""
2433 data = self.data = self._DoReadFileRealDtb('128_decode_image.dts')
2434 image_fname = tools.GetOutputFilename('image.bin')
2435 orig_image = control.images['image']
2436 image = Image.FromFile(image_fname)
2437 self.assertEqual(orig_image.GetEntries().keys(),
2438 image.GetEntries().keys())
2440 orig_entry = orig_image.GetEntries()['fdtmap']
2441 entry = image.GetEntries()['fdtmap']
2442 self.assertEquals(orig_entry.offset, entry.offset)
2443 self.assertEquals(orig_entry.size, entry.size)
2444 self.assertEquals(orig_entry.image_pos, entry.image_pos)
2446 def testReadImageNoHeader(self):
2447 """Test accessing an image's FDT map without an image header"""
2449 data = self._DoReadFileRealDtb('129_decode_image_nohdr.dts')
2450 image_fname = tools.GetOutputFilename('image.bin')
2451 image = Image.FromFile(image_fname)
2452 self.assertTrue(isinstance(image, Image))
2453 self.assertEqual('image', image.image_name[-5:])
2455 def testReadImageFail(self):
2456 """Test failing to read an image image's FDT map"""
2457 self._DoReadFile('005_simple.dts')
2458 image_fname = tools.GetOutputFilename('image.bin')
2459 with self.assertRaises(ValueError) as e:
2460 image = Image.FromFile(image_fname)
2461 self.assertIn("Cannot find FDT map in image", str(e.exception))
2463 def testListCmd(self):
2464 """Test listing the files in an image using an Fdtmap"""
2466 data = self._DoReadFileRealDtb('130_list_fdtmap.dts')
2468 # lz4 compression size differs depending on the version
2469 image = control.images['image']
2470 entries = image.GetEntries()
2471 section_size = entries['section'].size
2472 fdt_size = entries['section'].GetEntries()['u-boot-dtb'].size
2473 fdtmap_offset = entries['fdtmap'].offset
2476 tmpdir, updated_fname = self._SetupImageInTmpdir()
2477 with test_util.capture_sys_output() as (stdout, stderr):
2478 self._DoBinman('ls', '-i', updated_fname)
2480 shutil.rmtree(tmpdir)
2481 lines = stdout.getvalue().splitlines()
2483 'Name Image-pos Size Entry-type Offset Uncomp-size',
2484 '----------------------------------------------------------------------',
2485 'main-section 0 c00 section 0',
2486 ' u-boot 0 4 u-boot 0',
2487 ' section 100 %x section 100' % section_size,
2488 ' cbfs 100 400 cbfs 0',
2489 ' u-boot 138 4 u-boot 38',
2490 ' u-boot-dtb 180 105 u-boot-dtb 80 3c9',
2491 ' u-boot-dtb 500 %x u-boot-dtb 400 3c9' % fdt_size,
2492 ' fdtmap %x 3bd fdtmap %x' %
2493 (fdtmap_offset, fdtmap_offset),
2494 ' image-header bf8 8 image-header bf8',
2496 self.assertEqual(expected, lines)
2498 def testListCmdFail(self):
2499 """Test failing to list an image"""
2500 self._DoReadFile('005_simple.dts')
2502 tmpdir, updated_fname = self._SetupImageInTmpdir()
2503 with self.assertRaises(ValueError) as e:
2504 self._DoBinman('ls', '-i', updated_fname)
2506 shutil.rmtree(tmpdir)
2507 self.assertIn("Cannot find FDT map in image", str(e.exception))
2509 def _RunListCmd(self, paths, expected):
2510 """List out entries and check the result
2513 paths: List of paths to pass to the list command
2514 expected: Expected list of filenames to be returned, in order
2517 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2518 image_fname = tools.GetOutputFilename('image.bin')
2519 image = Image.FromFile(image_fname)
2520 lines = image.GetListEntries(paths)[1]
2521 files = [line[0].strip() for line in lines[1:]]
2522 self.assertEqual(expected, files)
2524 def testListCmdSection(self):
2525 """Test listing the files in a section"""
2526 self._RunListCmd(['section'],
2527 ['section', 'cbfs', 'u-boot', 'u-boot-dtb', 'u-boot-dtb'])
2529 def testListCmdFile(self):
2530 """Test listing a particular file"""
2531 self._RunListCmd(['*u-boot-dtb'], ['u-boot-dtb', 'u-boot-dtb'])
2533 def testListCmdWildcard(self):
2534 """Test listing a wildcarded file"""
2535 self._RunListCmd(['*boot*'],
2536 ['u-boot', 'u-boot', 'u-boot-dtb', 'u-boot-dtb'])
2538 def testListCmdWildcardMulti(self):
2539 """Test listing a wildcarded file"""
2540 self._RunListCmd(['*cb*', '*head*'],
2541 ['cbfs', 'u-boot', 'u-boot-dtb', 'image-header'])
2543 def testListCmdEmpty(self):
2544 """Test listing a wildcarded file"""
2545 self._RunListCmd(['nothing'], [])
2547 def testListCmdPath(self):
2548 """Test listing the files in a sub-entry of a section"""
2549 self._RunListCmd(['section/cbfs'], ['cbfs', 'u-boot', 'u-boot-dtb'])
2551 def _RunExtractCmd(self, entry_name, decomp=True):
2552 """Extract an entry from an image
2555 entry_name: Entry name to extract
2556 decomp: True to decompress the data if compressed, False to leave
2557 it in its raw uncompressed format
2563 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2564 image_fname = tools.GetOutputFilename('image.bin')
2565 return control.ReadEntry(image_fname, entry_name, decomp)
2567 def testExtractSimple(self):
2568 """Test extracting a single file"""
2569 data = self._RunExtractCmd('u-boot')
2570 self.assertEqual(U_BOOT_DATA, data)
2572 def testExtractSection(self):
2573 """Test extracting the files in a section"""
2574 data = self._RunExtractCmd('section')
2575 cbfs_data = data[:0x400]
2576 cbfs = cbfs_util.CbfsReader(cbfs_data)
2577 self.assertEqual(['u-boot', 'u-boot-dtb', ''], list(cbfs.files.keys()))
2578 dtb_data = data[0x400:]
2579 dtb = self._decompress(dtb_data)
2580 self.assertEqual(EXTRACT_DTB_SIZE, len(dtb))
2582 def testExtractCompressed(self):
2583 """Test extracting compressed data"""
2584 data = self._RunExtractCmd('section/u-boot-dtb')
2585 self.assertEqual(EXTRACT_DTB_SIZE, len(data))
2587 def testExtractRaw(self):
2588 """Test extracting compressed data without decompressing it"""
2589 data = self._RunExtractCmd('section/u-boot-dtb', decomp=False)
2590 dtb = self._decompress(data)
2591 self.assertEqual(EXTRACT_DTB_SIZE, len(dtb))
2593 def testExtractCbfs(self):
2594 """Test extracting CBFS data"""
2595 data = self._RunExtractCmd('section/cbfs/u-boot')
2596 self.assertEqual(U_BOOT_DATA, data)
2598 def testExtractCbfsCompressed(self):
2599 """Test extracting CBFS compressed data"""
2600 data = self._RunExtractCmd('section/cbfs/u-boot-dtb')
2601 self.assertEqual(EXTRACT_DTB_SIZE, len(data))
2603 def testExtractCbfsRaw(self):
2604 """Test extracting CBFS compressed data without decompressing it"""
2605 data = self._RunExtractCmd('section/cbfs/u-boot-dtb', decomp=False)
2606 dtb = tools.Decompress(data, 'lzma', with_header=False)
2607 self.assertEqual(EXTRACT_DTB_SIZE, len(dtb))
2609 def testExtractBadEntry(self):
2610 """Test extracting a bad section path"""
2611 with self.assertRaises(ValueError) as e:
2612 self._RunExtractCmd('section/does-not-exist')
2613 self.assertIn("Entry 'does-not-exist' not found in '/section'",
2616 def testExtractMissingFile(self):
2617 """Test extracting file that does not exist"""
2618 with self.assertRaises(IOError) as e:
2619 control.ReadEntry('missing-file', 'name')
2621 def testExtractBadFile(self):
2622 """Test extracting an invalid file"""
2623 fname = os.path.join(self._indir, 'badfile')
2624 tools.WriteFile(fname, b'')
2625 with self.assertRaises(ValueError) as e:
2626 control.ReadEntry(fname, 'name')
2628 def testExtractCmd(self):
2629 """Test extracting a file fron an image on the command line"""
2631 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2632 fname = os.path.join(self._indir, 'output.extact')
2634 tmpdir, updated_fname = self._SetupImageInTmpdir()
2635 with test_util.capture_sys_output() as (stdout, stderr):
2636 self._DoBinman('extract', '-i', updated_fname, 'u-boot',
2639 shutil.rmtree(tmpdir)
2640 data = tools.ReadFile(fname)
2641 self.assertEqual(U_BOOT_DATA, data)
2643 def testExtractOneEntry(self):
2644 """Test extracting a single entry fron an image """
2646 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2647 image_fname = tools.GetOutputFilename('image.bin')
2648 fname = os.path.join(self._indir, 'output.extact')
2649 control.ExtractEntries(image_fname, fname, None, ['u-boot'])
2650 data = tools.ReadFile(fname)
2651 self.assertEqual(U_BOOT_DATA, data)
2653 def _CheckExtractOutput(self, decomp):
2654 """Helper to test file output with and without decompression
2657 decomp: True to decompress entry data, False to output it raw
2659 def _CheckPresent(entry_path, expect_data, expect_size=None):
2660 """Check and remove expected file
2662 This checks the data/size of a file and removes the file both from
2663 the outfiles set and from the output directory. Once all files are
2664 processed, both the set and directory should be empty.
2667 entry_path: Entry path
2668 expect_data: Data to expect in file, or None to skip check
2669 expect_size: Size of data to expect in file, or None to skip
2671 path = os.path.join(outdir, entry_path)
2672 data = tools.ReadFile(path)
2675 self.assertEqual(expect_data, data)
2677 self.assertEqual(expect_size, len(data))
2678 outfiles.remove(path)
2680 def _CheckDirPresent(name):
2681 """Remove expected directory
2683 This gives an error if the directory does not exist as expected
2686 name: Name of directory to remove
2688 path = os.path.join(outdir, name)
2691 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2692 image_fname = tools.GetOutputFilename('image.bin')
2693 outdir = os.path.join(self._indir, 'extract')
2694 einfos = control.ExtractEntries(image_fname, None, outdir, [], decomp)
2696 # Create a set of all file that were output (should be 9)
2698 for root, dirs, files in os.walk(outdir):
2699 outfiles |= set([os.path.join(root, fname) for fname in files])
2700 self.assertEqual(9, len(outfiles))
2701 self.assertEqual(9, len(einfos))
2703 image = control.images['image']
2704 entries = image.GetEntries()
2706 # Check the 9 files in various ways
2707 section = entries['section']
2708 section_entries = section.GetEntries()
2709 cbfs_entries = section_entries['cbfs'].GetEntries()
2710 _CheckPresent('u-boot', U_BOOT_DATA)
2711 _CheckPresent('section/cbfs/u-boot', U_BOOT_DATA)
2712 dtb_len = EXTRACT_DTB_SIZE
2714 dtb_len = cbfs_entries['u-boot-dtb'].size
2715 _CheckPresent('section/cbfs/u-boot-dtb', None, dtb_len)
2717 dtb_len = section_entries['u-boot-dtb'].size
2718 _CheckPresent('section/u-boot-dtb', None, dtb_len)
2720 fdtmap = entries['fdtmap']
2721 _CheckPresent('fdtmap', fdtmap.data)
2722 hdr = entries['image-header']
2723 _CheckPresent('image-header', hdr.data)
2725 _CheckPresent('section/root', section.data)
2726 cbfs = section_entries['cbfs']
2727 _CheckPresent('section/cbfs/root', cbfs.data)
2728 data = tools.ReadFile(image_fname)
2729 _CheckPresent('root', data)
2731 # There should be no files left. Remove all the directories to check.
2732 # If there are any files/dirs remaining, one of these checks will fail.
2733 self.assertEqual(0, len(outfiles))
2734 _CheckDirPresent('section/cbfs')
2735 _CheckDirPresent('section')
2736 _CheckDirPresent('')
2737 self.assertFalse(os.path.exists(outdir))
2739 def testExtractAllEntries(self):
2740 """Test extracting all entries"""
2742 self._CheckExtractOutput(decomp=True)
2744 def testExtractAllEntriesRaw(self):
2745 """Test extracting all entries without decompressing them"""
2747 self._CheckExtractOutput(decomp=False)
2749 def testExtractSelectedEntries(self):
2750 """Test extracting some entries"""
2752 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2753 image_fname = tools.GetOutputFilename('image.bin')
2754 outdir = os.path.join(self._indir, 'extract')
2755 einfos = control.ExtractEntries(image_fname, None, outdir,
2758 # File output is tested by testExtractAllEntries(), so just check that
2759 # the expected entries are selected
2760 names = [einfo.name for einfo in einfos]
2761 self.assertEqual(names,
2762 ['cbfs', 'u-boot', 'u-boot-dtb', 'image-header'])
2764 def testExtractNoEntryPaths(self):
2765 """Test extracting some entries"""
2767 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2768 image_fname = tools.GetOutputFilename('image.bin')
2769 with self.assertRaises(ValueError) as e:
2770 control.ExtractEntries(image_fname, 'fname', None, [])
2771 self.assertIn('Must specify an entry path to write with -f',
2774 def testExtractTooManyEntryPaths(self):
2775 """Test extracting some entries"""
2777 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2778 image_fname = tools.GetOutputFilename('image.bin')
2779 with self.assertRaises(ValueError) as e:
2780 control.ExtractEntries(image_fname, 'fname', None, ['a', 'b'])
2781 self.assertIn('Must specify exactly one entry path to write with -f',
2784 def testPackAlignSection(self):
2785 """Test that sections can have alignment"""
2786 self._DoReadFile('131_pack_align_section.dts')
2788 self.assertIn('image', control.images)
2789 image = control.images['image']
2790 entries = image.GetEntries()
2791 self.assertEqual(3, len(entries))
2794 self.assertIn('u-boot', entries)
2795 entry = entries['u-boot']
2796 self.assertEqual(0, entry.offset)
2797 self.assertEqual(0, entry.image_pos)
2798 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2799 self.assertEqual(len(U_BOOT_DATA), entry.size)
2802 self.assertIn('section0', entries)
2803 section0 = entries['section0']
2804 self.assertEqual(0x10, section0.offset)
2805 self.assertEqual(0x10, section0.image_pos)
2806 self.assertEqual(len(U_BOOT_DATA), section0.size)
2809 section_entries = section0.GetEntries()
2810 self.assertIn('u-boot', section_entries)
2811 entry = section_entries['u-boot']
2812 self.assertEqual(0, entry.offset)
2813 self.assertEqual(0x10, entry.image_pos)
2814 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2815 self.assertEqual(len(U_BOOT_DATA), entry.size)
2818 self.assertIn('section1', entries)
2819 section1 = entries['section1']
2820 self.assertEqual(0x14, section1.offset)
2821 self.assertEqual(0x14, section1.image_pos)
2822 self.assertEqual(0x20, section1.size)
2825 section_entries = section1.GetEntries()
2826 self.assertIn('u-boot', section_entries)
2827 entry = section_entries['u-boot']
2828 self.assertEqual(0, entry.offset)
2829 self.assertEqual(0x14, entry.image_pos)
2830 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2831 self.assertEqual(len(U_BOOT_DATA), entry.size)
2834 self.assertIn('section2', section_entries)
2835 section2 = section_entries['section2']
2836 self.assertEqual(0x4, section2.offset)
2837 self.assertEqual(0x18, section2.image_pos)
2838 self.assertEqual(4, section2.size)
2841 section_entries = section2.GetEntries()
2842 self.assertIn('u-boot', section_entries)
2843 entry = section_entries['u-boot']
2844 self.assertEqual(0, entry.offset)
2845 self.assertEqual(0x18, entry.image_pos)
2846 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2847 self.assertEqual(len(U_BOOT_DATA), entry.size)
2849 def _RunReplaceCmd(self, entry_name, data, decomp=True, allow_resize=True,
2850 dts='132_replace.dts'):
2851 """Replace an entry in an image
2853 This writes the entry data to update it, then opens the updated file and
2854 returns the value that it now finds there.
2857 entry_name: Entry name to replace
2858 data: Data to replace it with
2859 decomp: True to compress the data if needed, False if data is
2860 already compressed so should be used as is
2861 allow_resize: True to allow entries to change size, False to raise
2867 data from fdtmap (excluding header)
2868 Image object that was modified
2870 dtb_data = self._DoReadFileDtb(dts, use_real_dtb=True,
2873 self.assertIn('image', control.images)
2874 image = control.images['image']
2875 entries = image.GetEntries()
2876 orig_dtb_data = entries['u-boot-dtb'].data
2877 orig_fdtmap_data = entries['fdtmap'].data
2879 image_fname = tools.GetOutputFilename('image.bin')
2880 updated_fname = tools.GetOutputFilename('image-updated.bin')
2881 tools.WriteFile(updated_fname, tools.ReadFile(image_fname))
2882 image = control.WriteEntry(updated_fname, entry_name, data, decomp,
2884 data = control.ReadEntry(updated_fname, entry_name, decomp)
2886 # The DT data should not change unless resized:
2887 if not allow_resize:
2888 new_dtb_data = entries['u-boot-dtb'].data
2889 self.assertEqual(new_dtb_data, orig_dtb_data)
2890 new_fdtmap_data = entries['fdtmap'].data
2891 self.assertEqual(new_fdtmap_data, orig_fdtmap_data)
2893 return data, orig_fdtmap_data[fdtmap.FDTMAP_HDR_LEN:], image
2895 def testReplaceSimple(self):
2896 """Test replacing a single file"""
2897 expected = b'x' * len(U_BOOT_DATA)
2898 data, expected_fdtmap, _ = self._RunReplaceCmd('u-boot', expected,
2900 self.assertEqual(expected, data)
2902 # Test that the state looks right. There should be an FDT for the fdtmap
2903 # that we jsut read back in, and it should match what we find in the
2904 # 'control' tables. Checking for an FDT that does not exist should
2906 path, fdtmap = state.GetFdtContents('fdtmap')
2907 self.assertIsNotNone(path)
2908 self.assertEqual(expected_fdtmap, fdtmap)
2910 dtb = state.GetFdtForEtype('fdtmap')
2911 self.assertEqual(dtb.GetContents(), fdtmap)
2913 missing_path, missing_fdtmap = state.GetFdtContents('missing')
2914 self.assertIsNone(missing_path)
2915 self.assertIsNone(missing_fdtmap)
2917 missing_dtb = state.GetFdtForEtype('missing')
2918 self.assertIsNone(missing_dtb)
2920 self.assertEqual('/binman', state.fdt_path_prefix)
2922 def testReplaceResizeFail(self):
2923 """Test replacing a file by something larger"""
2924 expected = U_BOOT_DATA + b'x'
2925 with self.assertRaises(ValueError) as e:
2926 self._RunReplaceCmd('u-boot', expected, allow_resize=False,
2927 dts='139_replace_repack.dts')
2928 self.assertIn("Node '/u-boot': Entry data size does not match, but resize is disabled",
2931 def testReplaceMulti(self):
2932 """Test replacing entry data where multiple images are generated"""
2933 data = self._DoReadFileDtb('133_replace_multi.dts', use_real_dtb=True,
2935 expected = b'x' * len(U_BOOT_DATA)
2936 updated_fname = tools.GetOutputFilename('image-updated.bin')
2937 tools.WriteFile(updated_fname, data)
2938 entry_name = 'u-boot'
2939 control.WriteEntry(updated_fname, entry_name, expected,
2941 data = control.ReadEntry(updated_fname, entry_name)
2942 self.assertEqual(expected, data)
2944 # Check the state looks right.
2945 self.assertEqual('/binman/image', state.fdt_path_prefix)
2947 # Now check we can write the first image
2948 image_fname = tools.GetOutputFilename('first-image.bin')
2949 updated_fname = tools.GetOutputFilename('first-updated.bin')
2950 tools.WriteFile(updated_fname, tools.ReadFile(image_fname))
2951 entry_name = 'u-boot'
2952 control.WriteEntry(updated_fname, entry_name, expected,
2954 data = control.ReadEntry(updated_fname, entry_name)
2955 self.assertEqual(expected, data)
2957 # Check the state looks right.
2958 self.assertEqual('/binman/first-image', state.fdt_path_prefix)
2960 def testUpdateFdtAllRepack(self):
2961 """Test that all device trees are updated with offset/size info"""
2962 data = self._DoReadFileRealDtb('134_fdt_update_all_repack.dts')
2963 SECTION_SIZE = 0x300
2968 'size': SECTION_SIZE + DTB_SIZE * 2 + FDTMAP_SIZE,
2970 'section:offset': 0,
2971 'section:size': SECTION_SIZE,
2972 'section:image-pos': 0,
2973 'section/u-boot-dtb:offset': 4,
2974 'section/u-boot-dtb:size': 636,
2975 'section/u-boot-dtb:image-pos': 4,
2976 'u-boot-spl-dtb:offset': SECTION_SIZE,
2977 'u-boot-spl-dtb:size': DTB_SIZE,
2978 'u-boot-spl-dtb:image-pos': SECTION_SIZE,
2979 'u-boot-tpl-dtb:offset': SECTION_SIZE + DTB_SIZE,
2980 'u-boot-tpl-dtb:image-pos': SECTION_SIZE + DTB_SIZE,
2981 'u-boot-tpl-dtb:size': DTB_SIZE,
2982 'fdtmap:offset': SECTION_SIZE + DTB_SIZE * 2,
2983 'fdtmap:size': FDTMAP_SIZE,
2984 'fdtmap:image-pos': SECTION_SIZE + DTB_SIZE * 2,
2987 'section:orig-size': SECTION_SIZE,
2988 'section/u-boot-dtb:orig-offset': 4,
2991 # We expect three device-tree files in the output, with the first one
2992 # within a fixed-size section.
2993 # Read them in sequence. We look for an 'spl' property in the SPL tree,
2994 # and 'tpl' in the TPL tree, to make sure they are distinct from the
2995 # main U-Boot tree. All three should have the same positions and offset
2996 # except that the main tree should include the main_expected properties
2998 for item in ['', 'spl', 'tpl', None]:
3000 start += 16 # Move past fdtmap header
3001 dtb = fdt.Fdt.FromData(data[start:])
3003 props = self._GetPropTree(dtb,
3004 BASE_DTB_PROPS + REPACK_DTB_PROPS + ['spl', 'tpl'],
3005 prefix='/' if item is None else '/binman/')
3006 expected = dict(base_expected)
3010 # Main DTB and fdtdec should include the 'orig-' properties
3011 expected.update(main_expected)
3012 # Helpful for debugging:
3013 #for prop in sorted(props):
3014 #print('prop %s %s %s' % (prop, props[prop], expected[prop]))
3015 self.assertEqual(expected, props)
3017 start = SECTION_SIZE
3019 start += dtb._fdt_obj.totalsize()
3021 def testFdtmapHeaderMiddle(self):
3022 """Test an FDT map in the middle of an image when it should be at end"""
3023 with self.assertRaises(ValueError) as e:
3024 self._DoReadFileRealDtb('135_fdtmap_hdr_middle.dts')
3025 self.assertIn("Invalid sibling order 'middle' for image-header: Must be at 'end' to match location",
3028 def testFdtmapHeaderStartBad(self):
3029 """Test an FDT map in middle of an image when it should be at start"""
3030 with self.assertRaises(ValueError) as e:
3031 self._DoReadFileRealDtb('136_fdtmap_hdr_startbad.dts')
3032 self.assertIn("Invalid sibling order 'end' for image-header: Must be at 'start' to match location",
3035 def testFdtmapHeaderEndBad(self):
3036 """Test an FDT map at the start of an image when it should be at end"""
3037 with self.assertRaises(ValueError) as e:
3038 self._DoReadFileRealDtb('137_fdtmap_hdr_endbad.dts')
3039 self.assertIn("Invalid sibling order 'start' for image-header: Must be at 'end' to match location",
3042 def testFdtmapHeaderNoSize(self):
3043 """Test an image header at the end of an image with undefined size"""
3044 self._DoReadFileRealDtb('138_fdtmap_hdr_nosize.dts')
3046 def testReplaceResize(self):
3047 """Test replacing a single file in an entry with a larger file"""
3048 expected = U_BOOT_DATA + b'x'
3049 data, _, image = self._RunReplaceCmd('u-boot', expected,
3050 dts='139_replace_repack.dts')
3051 self.assertEqual(expected, data)
3053 entries = image.GetEntries()
3054 dtb_data = entries['u-boot-dtb'].data
3055 dtb = fdt.Fdt.FromData(dtb_data)
3058 # The u-boot section should now be larger in the dtb
3059 node = dtb.GetNode('/binman/u-boot')
3060 self.assertEqual(len(expected), fdt_util.GetInt(node, 'size'))
3062 # Same for the fdtmap
3063 fdata = entries['fdtmap'].data
3064 fdtb = fdt.Fdt.FromData(fdata[fdtmap.FDTMAP_HDR_LEN:])
3066 fnode = fdtb.GetNode('/u-boot')
3067 self.assertEqual(len(expected), fdt_util.GetInt(fnode, 'size'))
3069 def testReplaceResizeNoRepack(self):
3070 """Test replacing an entry with a larger file when not allowed"""
3071 expected = U_BOOT_DATA + b'x'
3072 with self.assertRaises(ValueError) as e:
3073 self._RunReplaceCmd('u-boot', expected)
3074 self.assertIn('Entry data size does not match, but allow-repack is not present for this image',
3077 def testEntryShrink(self):
3078 """Test contracting an entry after it is packed"""
3080 state.SetAllowEntryContraction(True)
3081 data = self._DoReadFileDtb('140_entry_shrink.dts',
3084 state.SetAllowEntryContraction(False)
3085 self.assertEqual(b'a', data[:1])
3086 self.assertEqual(U_BOOT_DATA, data[1:1 + len(U_BOOT_DATA)])
3087 self.assertEqual(b'a', data[-1:])
3089 def testEntryShrinkFail(self):
3090 """Test not being allowed to contract an entry after it is packed"""
3091 data = self._DoReadFileDtb('140_entry_shrink.dts', update_dtb=True)[0]
3093 # In this case there is a spare byte at the end of the data. The size of
3094 # the contents is only 1 byte but we still have the size before it
3096 self.assertEqual(b'a\0', data[:2])
3097 self.assertEqual(U_BOOT_DATA, data[2:2 + len(U_BOOT_DATA)])
3098 self.assertEqual(b'a\0', data[-2:])
3100 def testDescriptorOffset(self):
3101 """Test that the Intel descriptor is always placed at at the start"""
3102 data = self._DoReadFileDtb('141_descriptor_offset.dts')
3103 image = control.images['image']
3104 entries = image.GetEntries()
3105 desc = entries['intel-descriptor']
3106 self.assertEqual(0xff800000, desc.offset);
3107 self.assertEqual(0xff800000, desc.image_pos);
3109 def testReplaceCbfs(self):
3110 """Test replacing a single file in CBFS without changing the size"""
3112 expected = b'x' * len(U_BOOT_DATA)
3113 data = self._DoReadFileRealDtb('142_replace_cbfs.dts')
3114 updated_fname = tools.GetOutputFilename('image-updated.bin')
3115 tools.WriteFile(updated_fname, data)
3116 entry_name = 'section/cbfs/u-boot'
3117 control.WriteEntry(updated_fname, entry_name, expected,
3119 data = control.ReadEntry(updated_fname, entry_name)
3120 self.assertEqual(expected, data)
3122 def testReplaceResizeCbfs(self):
3123 """Test replacing a single file in CBFS with one of a different size"""
3125 expected = U_BOOT_DATA + b'x'
3126 data = self._DoReadFileRealDtb('142_replace_cbfs.dts')
3127 updated_fname = tools.GetOutputFilename('image-updated.bin')
3128 tools.WriteFile(updated_fname, data)
3129 entry_name = 'section/cbfs/u-boot'
3130 control.WriteEntry(updated_fname, entry_name, expected,
3132 data = control.ReadEntry(updated_fname, entry_name)
3133 self.assertEqual(expected, data)
3135 def _SetupForReplace(self):
3136 """Set up some files to use to replace entries
3138 This generates an image, copies it to a new file, extracts all the files
3139 in it and updates some of them
3145 Expected values for updated entries, each a string
3147 data = self._DoReadFileRealDtb('143_replace_all.dts')
3149 updated_fname = tools.GetOutputFilename('image-updated.bin')
3150 tools.WriteFile(updated_fname, data)
3152 outdir = os.path.join(self._indir, 'extract')
3153 einfos = control.ExtractEntries(updated_fname, None, outdir, [])
3155 expected1 = b'x' + U_BOOT_DATA + b'y'
3156 u_boot_fname1 = os.path.join(outdir, 'u-boot')
3157 tools.WriteFile(u_boot_fname1, expected1)
3159 expected2 = b'a' + U_BOOT_DATA + b'b'
3160 u_boot_fname2 = os.path.join(outdir, 'u-boot2')
3161 tools.WriteFile(u_boot_fname2, expected2)
3163 expected_text = b'not the same text'
3164 text_fname = os.path.join(outdir, 'text')
3165 tools.WriteFile(text_fname, expected_text)
3167 dtb_fname = os.path.join(outdir, 'u-boot-dtb')
3168 dtb = fdt.FdtScan(dtb_fname)
3169 node = dtb.GetNode('/binman/text')
3170 node.AddString('my-property', 'the value')
3171 dtb.Sync(auto_resize=True)
3174 return updated_fname, outdir, expected1, expected2, expected_text
3176 def _CheckReplaceMultiple(self, entry_paths):
3177 """Handle replacing the contents of multiple entries
3180 entry_paths: List of entry paths to replace
3184 Dict of entries in the image:
3187 Expected values for updated entries, each a string
3189 updated_fname, outdir, expected1, expected2, expected_text = (
3190 self._SetupForReplace())
3191 control.ReplaceEntries(updated_fname, None, outdir, entry_paths)
3193 image = Image.FromFile(updated_fname)
3195 return image.GetEntries(), expected1, expected2, expected_text
3197 def testReplaceAll(self):
3198 """Test replacing the contents of all entries"""
3199 entries, expected1, expected2, expected_text = (
3200 self._CheckReplaceMultiple([]))
3201 data = entries['u-boot'].data
3202 self.assertEqual(expected1, data)
3204 data = entries['u-boot2'].data
3205 self.assertEqual(expected2, data)
3207 data = entries['text'].data
3208 self.assertEqual(expected_text, data)
3210 # Check that the device tree is updated
3211 data = entries['u-boot-dtb'].data
3212 dtb = fdt.Fdt.FromData(data)
3214 node = dtb.GetNode('/binman/text')
3215 self.assertEqual('the value', node.props['my-property'].value)
3217 def testReplaceSome(self):
3218 """Test replacing the contents of a few entries"""
3219 entries, expected1, expected2, expected_text = (
3220 self._CheckReplaceMultiple(['u-boot2', 'text']))
3222 # This one should not change
3223 data = entries['u-boot'].data
3224 self.assertEqual(U_BOOT_DATA, data)
3226 data = entries['u-boot2'].data
3227 self.assertEqual(expected2, data)
3229 data = entries['text'].data
3230 self.assertEqual(expected_text, data)
3232 def testReplaceCmd(self):
3233 """Test replacing a file fron an image on the command line"""
3234 self._DoReadFileRealDtb('143_replace_all.dts')
3237 tmpdir, updated_fname = self._SetupImageInTmpdir()
3239 fname = os.path.join(tmpdir, 'update-u-boot.bin')
3240 expected = b'x' * len(U_BOOT_DATA)
3241 tools.WriteFile(fname, expected)
3243 self._DoBinman('replace', '-i', updated_fname, 'u-boot', '-f', fname)
3244 data = tools.ReadFile(updated_fname)
3245 self.assertEqual(expected, data[:len(expected)])
3246 map_fname = os.path.join(tmpdir, 'image-updated.map')
3247 self.assertFalse(os.path.exists(map_fname))
3249 shutil.rmtree(tmpdir)
3251 def testReplaceCmdSome(self):
3252 """Test replacing some files fron an image on the command line"""
3253 updated_fname, outdir, expected1, expected2, expected_text = (
3254 self._SetupForReplace())
3256 self._DoBinman('replace', '-i', updated_fname, '-I', outdir,
3259 tools.PrepareOutputDir(None)
3260 image = Image.FromFile(updated_fname)
3262 entries = image.GetEntries()
3264 # This one should not change
3265 data = entries['u-boot'].data
3266 self.assertEqual(U_BOOT_DATA, data)
3268 data = entries['u-boot2'].data
3269 self.assertEqual(expected2, data)
3271 data = entries['text'].data
3272 self.assertEqual(expected_text, data)
3274 def testReplaceMissing(self):
3275 """Test replacing entries where the file is missing"""
3276 updated_fname, outdir, expected1, expected2, expected_text = (
3277 self._SetupForReplace())
3279 # Remove one of the files, to generate a warning
3280 u_boot_fname1 = os.path.join(outdir, 'u-boot')
3281 os.remove(u_boot_fname1)
3283 with test_util.capture_sys_output() as (stdout, stderr):
3284 control.ReplaceEntries(updated_fname, None, outdir, [])
3285 self.assertIn("Skipping entry '/u-boot' from missing file",
3288 def testReplaceCmdMap(self):
3289 """Test replacing a file fron an image on the command line"""
3290 self._DoReadFileRealDtb('143_replace_all.dts')
3293 tmpdir, updated_fname = self._SetupImageInTmpdir()
3295 fname = os.path.join(self._indir, 'update-u-boot.bin')
3296 expected = b'x' * len(U_BOOT_DATA)
3297 tools.WriteFile(fname, expected)
3299 self._DoBinman('replace', '-i', updated_fname, 'u-boot',
3301 map_fname = os.path.join(tmpdir, 'image-updated.map')
3302 self.assertTrue(os.path.exists(map_fname))
3304 shutil.rmtree(tmpdir)
3306 def testReplaceNoEntryPaths(self):
3307 """Test replacing an entry without an entry path"""
3308 self._DoReadFileRealDtb('143_replace_all.dts')
3309 image_fname = tools.GetOutputFilename('image.bin')
3310 with self.assertRaises(ValueError) as e:
3311 control.ReplaceEntries(image_fname, 'fname', None, [])
3312 self.assertIn('Must specify an entry path to read with -f',
3315 def testReplaceTooManyEntryPaths(self):
3316 """Test extracting some entries"""
3317 self._DoReadFileRealDtb('143_replace_all.dts')
3318 image_fname = tools.GetOutputFilename('image.bin')
3319 with self.assertRaises(ValueError) as e:
3320 control.ReplaceEntries(image_fname, 'fname', None, ['a', 'b'])
3321 self.assertIn('Must specify exactly one entry path to write with -f',
3324 def testPackReset16(self):
3325 """Test that an image with an x86 reset16 region can be created"""
3326 data = self._DoReadFile('144_x86_reset16.dts')
3327 self.assertEqual(X86_RESET16_DATA, data[:len(X86_RESET16_DATA)])
3329 def testPackReset16Spl(self):
3330 """Test that an image with an x86 reset16-spl region can be created"""
3331 data = self._DoReadFile('145_x86_reset16_spl.dts')
3332 self.assertEqual(X86_RESET16_SPL_DATA, data[:len(X86_RESET16_SPL_DATA)])
3334 def testPackReset16Tpl(self):
3335 """Test that an image with an x86 reset16-tpl region can be created"""
3336 data = self._DoReadFile('146_x86_reset16_tpl.dts')
3337 self.assertEqual(X86_RESET16_TPL_DATA, data[:len(X86_RESET16_TPL_DATA)])
3339 def testPackIntelFit(self):
3340 """Test that an image with an Intel FIT and pointer can be created"""
3341 data = self._DoReadFile('147_intel_fit.dts')
3342 self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
3344 self.assertEqual(b'_FIT_ \x01\x00\x00\x00\x00\x01\x80}' , fit)
3345 ptr = struct.unpack('<i', data[0x40:0x44])[0]
3347 image = control.images['image']
3348 entries = image.GetEntries()
3349 expected_ptr = entries['intel-fit'].image_pos - (1 << 32)
3350 self.assertEqual(expected_ptr, ptr)
3352 def testPackIntelFitMissing(self):
3353 """Test detection of a FIT pointer with not FIT region"""
3354 with self.assertRaises(ValueError) as e:
3355 self._DoReadFile('148_intel_fit_missing.dts')
3356 self.assertIn("'intel-fit-ptr' section must have an 'intel-fit' sibling",
3359 def _CheckSymbolsTplSection(self, dts, expected_vals):
3360 data = self._DoReadFile(dts)
3361 sym_values = struct.pack('<LQLL', *expected_vals)
3362 upto1 = 4 + len(U_BOOT_SPL_DATA)
3363 expected1 = tools.GetBytes(0xff, 4) + sym_values + U_BOOT_SPL_DATA[20:]
3364 self.assertEqual(expected1, data[:upto1])
3366 upto2 = upto1 + 1 + len(U_BOOT_SPL_DATA)
3367 expected2 = tools.GetBytes(0xff, 1) + sym_values + U_BOOT_SPL_DATA[20:]
3368 self.assertEqual(expected2, data[upto1:upto2])
3370 upto3 = 0x34 + len(U_BOOT_DATA)
3371 expected3 = tools.GetBytes(0xff, 1) + U_BOOT_DATA
3372 self.assertEqual(expected3, data[upto2:upto3])
3374 expected4 = sym_values + U_BOOT_TPL_DATA[20:]
3375 self.assertEqual(expected4, data[upto3:upto3 + len(U_BOOT_TPL_DATA)])
3377 def testSymbolsTplSection(self):
3378 """Test binman can assign symbols embedded in U-Boot TPL in a section"""
3379 self._SetupSplElf('u_boot_binman_syms')
3380 self._SetupTplElf('u_boot_binman_syms')
3381 self._CheckSymbolsTplSection('149_symbols_tpl.dts',
3382 [0x04, 0x1c, 0x10 + 0x34, 0x04])
3384 def testSymbolsTplSectionX86(self):
3385 """Test binman can assign symbols in a section with end-at-4gb"""
3386 self._SetupSplElf('u_boot_binman_syms_x86')
3387 self._SetupTplElf('u_boot_binman_syms_x86')
3388 self._CheckSymbolsTplSection('155_symbols_tpl_x86.dts',
3389 [0xffffff04, 0xffffff1c, 0xffffff34,
3392 def testPackX86RomIfwiSectiom(self):
3393 """Test that a section can be placed in an IFWI region"""
3394 self._SetupIfwi('fitimage.bin')
3395 data = self._DoReadFile('151_x86_rom_ifwi_section.dts')
3396 self._CheckIfwi(data)
3398 def testPackFspM(self):
3399 """Test that an image with a FSP memory-init binary can be created"""
3400 data = self._DoReadFile('152_intel_fsp_m.dts')
3401 self.assertEqual(FSP_M_DATA, data[:len(FSP_M_DATA)])
3403 def testPackFspS(self):
3404 """Test that an image with a FSP silicon-init binary can be created"""
3405 data = self._DoReadFile('153_intel_fsp_s.dts')
3406 self.assertEqual(FSP_S_DATA, data[:len(FSP_S_DATA)])
3408 def testPackFspT(self):
3409 """Test that an image with a FSP temp-ram-init binary can be created"""
3410 data = self._DoReadFile('154_intel_fsp_t.dts')
3411 self.assertEqual(FSP_T_DATA, data[:len(FSP_T_DATA)])
3413 def testMkimage(self):
3414 """Test using mkimage to build an image"""
3415 data = self._DoReadFile('156_mkimage.dts')
3417 # Just check that the data appears in the file somewhere
3418 self.assertIn(U_BOOT_SPL_DATA, data)
3420 def testExtblob(self):
3421 """Test an image with an external blob"""
3422 data = self._DoReadFile('157_blob_ext.dts')
3423 self.assertEqual(REFCODE_DATA, data)
3425 def testExtblobMissing(self):
3426 """Test an image with a missing external blob"""
3427 with self.assertRaises(ValueError) as e:
3428 self._DoReadFile('158_blob_ext_missing.dts')
3429 self.assertIn("Filename 'missing-file' not found in input path",
3432 def testExtblobMissingOk(self):
3433 """Test an image with an missing external blob that is allowed"""
3434 with test_util.capture_sys_output() as (stdout, stderr):
3435 self._DoTestFile('158_blob_ext_missing.dts', allow_missing=True)
3436 err = stderr.getvalue()
3437 self.assertRegex(err, "Image 'main-section'.*missing.*: blob-ext")
3439 def testExtblobMissingOkSect(self):
3440 """Test an image with an missing external blob that is allowed"""
3441 with test_util.capture_sys_output() as (stdout, stderr):
3442 self._DoTestFile('159_blob_ext_missing_sect.dts',
3444 err = stderr.getvalue()
3445 self.assertRegex(err, "Image 'main-section'.*missing.*: "
3446 "blob-ext blob-ext2")
3448 def testPackX86RomMeMissingDesc(self):
3449 """Test that an missing Intel descriptor entry is allowed"""
3450 with test_util.capture_sys_output() as (stdout, stderr):
3451 self._DoTestFile('164_x86_rom_me_missing.dts', allow_missing=True)
3452 err = stderr.getvalue()
3453 self.assertRegex(err,
3454 "Image 'main-section'.*missing.*: intel-descriptor")
3456 def testPackX86RomMissingIfwi(self):
3457 """Test that an x86 ROM with Integrated Firmware Image can be created"""
3458 self._SetupIfwi('fitimage.bin')
3459 pathname = os.path.join(self._indir, 'fitimage.bin')
3461 with test_util.capture_sys_output() as (stdout, stderr):
3462 self._DoTestFile('111_x86_rom_ifwi.dts', allow_missing=True)
3463 err = stderr.getvalue()
3464 self.assertRegex(err, "Image 'main-section'.*missing.*: intel-ifwi")
3466 def testPackOverlap(self):
3467 """Test that zero-size overlapping regions are ignored"""
3468 self._DoTestFile('160_pack_overlap_zero.dts')
3470 def testSimpleFit(self):
3471 """Test an image with a FIT inside"""
3472 data = self._DoReadFile('161_fit.dts')
3473 self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
3474 self.assertEqual(U_BOOT_NODTB_DATA, data[-len(U_BOOT_NODTB_DATA):])
3475 fit_data = data[len(U_BOOT_DATA):-len(U_BOOT_NODTB_DATA)]
3477 # The data should be inside the FIT
3478 dtb = fdt.Fdt.FromData(fit_data)
3480 fnode = dtb.GetNode('/images/kernel')
3481 self.assertIn('data', fnode.props)
3483 fname = os.path.join(self._indir, 'fit_data.fit')
3484 tools.WriteFile(fname, fit_data)
3485 out = tools.Run('dumpimage', '-l', fname)
3487 # Check a few features to make sure the plumbing works. We don't need
3488 # to test the operation of mkimage or dumpimage here. First convert the
3489 # output into a dict where the keys are the fields printed by dumpimage
3490 # and the values are a list of values for each field
3491 lines = out.splitlines()
3493 # Converts "Compression: gzip compressed" into two groups:
3494 # 'Compression' and 'gzip compressed'
3495 re_line = re.compile(r'^ *([^:]*)(?:: *(.*))?$')
3496 vals = collections.defaultdict(list)
3498 mat = re_line.match(line)
3499 vals[mat.group(1)].append(mat.group(2))
3501 self.assertEquals('FIT description: test-desc', lines[0])
3502 self.assertIn('Created:', lines[1])
3503 self.assertIn('Image 0 (kernel)', vals)
3504 self.assertIn('Hash value', vals)
3505 data_sizes = vals.get('Data Size')
3506 self.assertIsNotNone(data_sizes)
3507 self.assertEqual(2, len(data_sizes))
3508 # Format is "4 Bytes = 0.00 KiB = 0.00 MiB" so take the first word
3509 self.assertEqual(len(U_BOOT_DATA), int(data_sizes[0].split()[0]))
3510 self.assertEqual(len(U_BOOT_SPL_DTB_DATA), int(data_sizes[1].split()[0]))
3512 def testFitExternal(self):
3513 """Test an image with an FIT with external images"""
3514 data = self._DoReadFile('162_fit_external.dts')
3515 fit_data = data[len(U_BOOT_DATA):-2] # _testing is 2 bytes
3517 # The data should be outside the FIT
3518 dtb = fdt.Fdt.FromData(fit_data)
3520 fnode = dtb.GetNode('/images/kernel')
3521 self.assertNotIn('data', fnode.props)
3523 def testSectionIgnoreHashSignature(self):
3524 """Test that sections ignore hash, signature nodes for its data"""
3525 data = self._DoReadFile('165_section_ignore_hash_signature.dts')
3526 expected = (U_BOOT_DATA + U_BOOT_DATA)
3527 self.assertEqual(expected, data)
3529 def testPadInSections(self):
3530 """Test pad-before, pad-after for entries in sections"""
3531 data = self._DoReadFile('166_pad_in_sections.dts')
3532 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
3533 U_BOOT_DATA + tools.GetBytes(ord('!'), 6) +
3535 self.assertEqual(expected, data)
3537 def testFitImageSubentryAlignment(self):
3538 """Test relative alignability of FIT image subentries"""
3540 'test-id': TEXT_DATA,
3542 data, _, _, _ = self._DoReadFileDtb('167_fit_image_subentry_alignment.dts',
3543 entry_args=entry_args)
3544 dtb = fdt.Fdt.FromData(data)
3547 node = dtb.GetNode('/images/kernel')
3548 data = dtb.GetProps(node)["data"].bytes
3549 align_pad = 0x10 - (len(U_BOOT_SPL_DATA) % 0x10)
3550 expected = (tools.GetBytes(0, 0x20) + U_BOOT_SPL_DATA +
3551 tools.GetBytes(0, align_pad) + U_BOOT_DATA)
3552 self.assertEqual(expected, data)
3554 node = dtb.GetNode('/images/fdt-1')
3555 data = dtb.GetProps(node)["data"].bytes
3556 expected = (U_BOOT_SPL_DTB_DATA + tools.GetBytes(0, 20) +
3557 tools.ToBytes(TEXT_DATA) + tools.GetBytes(0, 30) +
3559 self.assertEqual(expected, data)
3561 def testFitExtblobMissingOk(self):
3562 """Test a FIT with a missing external blob that is allowed"""
3563 with test_util.capture_sys_output() as (stdout, stderr):
3564 self._DoTestFile('168_fit_missing_blob.dts',
3566 err = stderr.getvalue()
3567 self.assertRegex(err, "Image 'main-section'.*missing.*: atf-bl31")
3569 def testBlobNamedByArgMissing(self):
3570 """Test handling of a missing entry arg"""
3571 with self.assertRaises(ValueError) as e:
3572 self._DoReadFile('068_blob_named_by_arg.dts')
3573 self.assertIn("Missing required properties/entry args: cros-ec-rw-path",
3576 def testPackBl31(self):
3577 """Test that an image with an ATF BL31 binary can be created"""
3578 data = self._DoReadFile('169_atf_bl31.dts')
3579 self.assertEqual(ATF_BL31_DATA, data[:len(ATF_BL31_DATA)])
3581 def testFitFdt(self):
3582 """Test an image with an FIT with multiple FDT images"""
3583 def _CheckFdt(seq, expected_data):
3584 """Check the FDT nodes
3587 seq: Sequence number to check (0 or 1)
3588 expected_data: Expected contents of 'data' property
3590 name = 'fdt-%d' % seq
3591 fnode = dtb.GetNode('/images/%s' % name)
3592 self.assertIsNotNone(fnode)
3593 self.assertEqual({'description','type', 'compression', 'data'},
3594 set(fnode.props.keys()))
3595 self.assertEqual(expected_data, fnode.props['data'].bytes)
3596 self.assertEqual('fdt-test-fdt%d.dtb' % seq,
3597 fnode.props['description'].value)
3599 def _CheckConfig(seq, expected_data):
3600 """Check the configuration nodes
3603 seq: Sequence number to check (0 or 1)
3604 expected_data: Expected contents of 'data' property
3606 cnode = dtb.GetNode('/configurations')
3607 self.assertIn('default', cnode.props)
3608 self.assertEqual('config-2', cnode.props['default'].value)
3610 name = 'config-%d' % seq
3611 fnode = dtb.GetNode('/configurations/%s' % name)
3612 self.assertIsNotNone(fnode)
3613 self.assertEqual({'description','firmware', 'loadables', 'fdt'},
3614 set(fnode.props.keys()))
3615 self.assertEqual('conf-test-fdt%d.dtb' % seq,
3616 fnode.props['description'].value)
3617 self.assertEqual('fdt-%d' % seq, fnode.props['fdt'].value)
3620 'of-list': 'test-fdt1 test-fdt2',
3621 'default-dt': 'test-fdt2',
3623 data = self._DoReadFileDtb(
3625 entry_args=entry_args,
3626 extra_indirs=[os.path.join(self._indir, TEST_FDT_SUBDIR)])[0]
3627 self.assertEqual(U_BOOT_NODTB_DATA, data[-len(U_BOOT_NODTB_DATA):])
3628 fit_data = data[len(U_BOOT_DATA):-len(U_BOOT_NODTB_DATA)]
3630 dtb = fdt.Fdt.FromData(fit_data)
3632 fnode = dtb.GetNode('/images/kernel')
3633 self.assertIn('data', fnode.props)
3635 # Check all the properties in fdt-1 and fdt-2
3636 _CheckFdt(1, TEST_FDT1_DATA)
3637 _CheckFdt(2, TEST_FDT2_DATA)
3639 # Check configurations
3640 _CheckConfig(1, TEST_FDT1_DATA)
3641 _CheckConfig(2, TEST_FDT2_DATA)
3643 def testFitFdtMissingList(self):
3644 """Test handling of a missing 'of-list' entry arg"""
3645 with self.assertRaises(ValueError) as e:
3646 self._DoReadFile('172_fit_fdt.dts')
3647 self.assertIn("Generator node requires 'of-list' entry argument",
3650 def testFitFdtEmptyList(self):
3651 """Test handling of an empty 'of-list' entry arg"""
3655 data = self._DoReadFileDtb('170_fit_fdt.dts', entry_args=entry_args)[0]
3657 def testFitFdtMissingProp(self):
3658 """Test handling of a missing 'fit,fdt-list' property"""
3659 with self.assertRaises(ValueError) as e:
3660 self._DoReadFile('171_fit_fdt_missing_prop.dts')
3661 self.assertIn("Generator node requires 'fit,fdt-list' property",
3664 def testFitFdtEmptyList(self):
3665 """Test handling of an empty 'of-list' entry arg"""
3669 data = self._DoReadFileDtb('172_fit_fdt.dts', entry_args=entry_args)[0]
3671 def testFitFdtMissing(self):
3672 """Test handling of a missing 'default-dt' entry arg"""
3674 'of-list': 'test-fdt1 test-fdt2',
3676 with self.assertRaises(ValueError) as e:
3677 self._DoReadFileDtb(
3679 entry_args=entry_args,
3680 extra_indirs=[os.path.join(self._indir, TEST_FDT_SUBDIR)])[0]
3681 self.assertIn("Generated 'default' node requires default-dt entry argument",
3684 def testFitFdtNotInList(self):
3685 """Test handling of a default-dt that is not in the of-list"""
3687 'of-list': 'test-fdt1 test-fdt2',
3688 'default-dt': 'test-fdt3',
3690 with self.assertRaises(ValueError) as e:
3691 self._DoReadFileDtb(
3693 entry_args=entry_args,
3694 extra_indirs=[os.path.join(self._indir, TEST_FDT_SUBDIR)])[0]
3695 self.assertIn("default-dt entry argument 'test-fdt3' not found in fdt list: test-fdt1, test-fdt2",
3698 def testFitExtblobMissingHelp(self):
3699 """Test display of help messages when an external blob is missing"""
3700 control.missing_blob_help = control._ReadMissingBlobHelp()
3701 control.missing_blob_help['wibble'] = 'Wibble test'
3702 control.missing_blob_help['another'] = 'Another test'
3703 with test_util.capture_sys_output() as (stdout, stderr):
3704 self._DoTestFile('168_fit_missing_blob.dts',
3706 err = stderr.getvalue()
3708 # We can get the tag from the name, the type or the missing-msg
3709 # property. Check all three.
3710 self.assertIn('You may need to build ARM Trusted', err)
3711 self.assertIn('Wibble test', err)
3712 self.assertIn('Another test', err)
3714 def testMissingBlob(self):
3715 """Test handling of a blob containing a missing file"""
3716 with self.assertRaises(ValueError) as e:
3717 self._DoTestFile('173_missing_blob.dts', allow_missing=True)
3718 self.assertIn("Filename 'missing' not found in input path",
3721 def testEnvironment(self):
3722 """Test adding a U-Boot environment"""
3723 data = self._DoReadFile('174_env.dts')
3724 self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
3725 self.assertEqual(U_BOOT_NODTB_DATA, data[-len(U_BOOT_NODTB_DATA):])
3726 env = data[len(U_BOOT_DATA):-len(U_BOOT_NODTB_DATA)]
3727 self.assertEqual(b'\x1b\x97\x22\x7c\x01var1=1\0var2="2"\0\0\xff\xff',
3730 def testEnvironmentNoSize(self):
3731 """Test that a missing 'size' property is detected"""
3732 with self.assertRaises(ValueError) as e:
3733 data = self._DoTestFile('175_env_no_size.dts')
3734 self.assertIn("'u-boot-env' entry must have a size property",
3737 def testEnvironmentTooSmall(self):
3738 """Test handling of an environment that does not fit"""
3739 with self.assertRaises(ValueError) as e:
3740 data = self._DoTestFile('176_env_too_small.dts')
3742 # checksum, start byte, environment with \0 terminator, final \0
3743 need = 4 + 1 + len(ENV_DATA) + 1 + 1
3745 self.assertIn("too small to hold data (need %#x more bytes)" % short,
3749 if __name__ == "__main__":