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'
81 # Subdirectory of the input dir to use to put test FDTs
82 TEST_FDT_SUBDIR = 'fdts'
84 # The expected size for the device tree in some tests
85 EXTRACT_DTB_SIZE = 0x3c9
87 # Properties expected to be in the device tree when update_dtb is used
88 BASE_DTB_PROPS = ['offset', 'size', 'image-pos']
90 # Extra properties expected to be in the device tree when allow-repack is used
91 REPACK_DTB_PROPS = ['orig-offset', 'orig-size']
94 class TestFunctional(unittest.TestCase):
95 """Functional tests for binman
97 Most of these use a sample .dts file to build an image and then check
98 that it looks correct. The sample files are in the test/ subdirectory
101 For each entry type a very small test file is created using fixed
102 string contents. This makes it easy to test that things look right, and
105 In some cases a 'real' file must be used - these are also supplied in
106 the test/ diurectory.
111 from binman import entry
113 # Handle the case where argv[0] is 'python'
114 cls._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
115 cls._binman_pathname = os.path.join(cls._binman_dir, 'binman')
117 # Create a temporary directory for input files
118 cls._indir = tempfile.mkdtemp(prefix='binmant.')
120 # Create some test files
121 TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
122 TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
123 TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
124 TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
125 TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
126 TestFunctional._MakeInputFile('me.bin', ME_DATA)
127 TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
130 TestFunctional._MakeInputFile('u-boot-br.bin', PPC_MPC85XX_BR_DATA)
132 TestFunctional._MakeInputFile('u-boot-x86-start16.bin', X86_START16_DATA)
133 TestFunctional._MakeInputFile('spl/u-boot-x86-start16-spl.bin',
134 X86_START16_SPL_DATA)
135 TestFunctional._MakeInputFile('tpl/u-boot-x86-start16-tpl.bin',
136 X86_START16_TPL_DATA)
138 TestFunctional._MakeInputFile('u-boot-x86-reset16.bin',
140 TestFunctional._MakeInputFile('spl/u-boot-x86-reset16-spl.bin',
141 X86_RESET16_SPL_DATA)
142 TestFunctional._MakeInputFile('tpl/u-boot-x86-reset16-tpl.bin',
143 X86_RESET16_TPL_DATA)
145 TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
146 TestFunctional._MakeInputFile('spl/u-boot-spl-nodtb.bin',
147 U_BOOT_SPL_NODTB_DATA)
148 TestFunctional._MakeInputFile('tpl/u-boot-tpl-nodtb.bin',
149 U_BOOT_TPL_NODTB_DATA)
150 TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
151 TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
152 TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
153 TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
154 TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
155 TestFunctional._MakeInputDir('devkeys')
156 TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
157 TestFunctional._MakeInputFile('refcode.bin', REFCODE_DATA)
158 TestFunctional._MakeInputFile('fsp_m.bin', FSP_M_DATA)
159 TestFunctional._MakeInputFile('fsp_s.bin', FSP_S_DATA)
160 TestFunctional._MakeInputFile('fsp_t.bin', FSP_T_DATA)
162 cls._elf_testdir = os.path.join(cls._indir, 'elftest')
163 elf_test.BuildElfTestFiles(cls._elf_testdir)
165 # ELF file with a '_dt_ucode_base_size' symbol
166 TestFunctional._MakeInputFile('u-boot',
167 tools.ReadFile(cls.ElfTestFile('u_boot_ucode_ptr')))
169 # Intel flash descriptor file
170 cls._SetupDescriptor()
172 shutil.copytree(cls.TestFile('files'),
173 os.path.join(cls._indir, 'files'))
175 TestFunctional._MakeInputFile('compress', COMPRESS_DATA)
176 TestFunctional._MakeInputFile('bl31.bin', ATF_BL31_DATA)
178 # Add a few .dtb files for testing
179 TestFunctional._MakeInputFile('%s/test-fdt1.dtb' % TEST_FDT_SUBDIR,
181 TestFunctional._MakeInputFile('%s/test-fdt2.dtb' % TEST_FDT_SUBDIR,
184 # Travis-CI may have an old lz4
187 tools.Run('lz4', '--no-frame-crc', '-c',
188 os.path.join(cls._indir, 'u-boot.bin'), binary=True)
193 def tearDownClass(cls):
194 """Remove the temporary input directory and its contents"""
195 if cls.preserve_indir:
196 print('Preserving input dir: %s' % cls._indir)
199 shutil.rmtree(cls._indir)
203 def setup_test_args(cls, preserve_indir=False, preserve_outdirs=False,
204 toolpath=None, verbosity=None):
205 """Accept arguments controlling test execution
208 preserve_indir: Preserve the shared input directory used by all
210 preserve_outdir: Preserve the output directories used by tests. Each
211 test has its own, so this is normally only useful when running a
213 toolpath: ist of paths to use for tools
215 cls.preserve_indir = preserve_indir
216 cls.preserve_outdirs = preserve_outdirs
217 cls.toolpath = toolpath
218 cls.verbosity = verbosity
221 if not self.have_lz4:
222 self.skipTest('lz4 --no-frame-crc not available')
224 def _CleanupOutputDir(self):
225 """Remove the temporary output directory"""
226 if self.preserve_outdirs:
227 print('Preserving output dir: %s' % tools.outdir)
229 tools._FinaliseForTest()
232 # Enable this to turn on debugging output
233 # tout.Init(tout.DEBUG)
234 command.test_result = None
237 """Remove the temporary output directory"""
238 self._CleanupOutputDir()
240 def _SetupImageInTmpdir(self):
241 """Set up the output image in a new temporary directory
243 This is used when an image has been generated in the output directory,
244 but we want to run binman again. This will create a new output
245 directory and fail to delete the original one.
247 This creates a new temporary directory, copies the image to it (with a
248 new name) and removes the old output directory.
252 Temporary directory to use
255 image_fname = tools.GetOutputFilename('image.bin')
256 tmpdir = tempfile.mkdtemp(prefix='binman.')
257 updated_fname = os.path.join(tmpdir, 'image-updated.bin')
258 tools.WriteFile(updated_fname, tools.ReadFile(image_fname))
259 self._CleanupOutputDir()
260 return tmpdir, updated_fname
264 TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
265 TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
266 TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
268 def _RunBinman(self, *args, **kwargs):
269 """Run binman using the command line
272 Arguments to pass, as a list of strings
273 kwargs: Arguments to pass to Command.RunPipe()
275 result = command.RunPipe([[self._binman_pathname] + list(args)],
276 capture=True, capture_stderr=True, raise_on_error=False)
277 if result.return_code and kwargs.get('raise_on_error', True):
278 raise Exception("Error running '%s': %s" % (' '.join(args),
279 result.stdout + result.stderr))
282 def _DoBinman(self, *argv):
283 """Run binman using directly (in the same process)
286 Arguments to pass, as a list of strings
288 Return value (0 for success)
291 args = cmdline.ParseArgs(argv)
292 args.pager = 'binman-invalid-pager'
293 args.build_dir = self._indir
295 # For testing, you can force an increase in verbosity here
296 # args.verbosity = tout.DEBUG
297 return control.Binman(args)
299 def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
300 entry_args=None, images=None, use_real_dtb=False,
301 verbosity=None, allow_missing=False, extra_indirs=None):
302 """Run binman with a given test file
305 fname: Device-tree source filename to use (e.g. 005_simple.dts)
306 debug: True to enable debugging output
307 map: True to output map files for the images
308 update_dtb: Update the offset and size of each entry in the device
309 tree before packing it into the image
310 entry_args: Dict of entry args to supply to binman
312 value: value of that arg
313 images: List of image names to build
314 use_real_dtb: True to use the test file as the contents of
315 the u-boot-dtb entry. Normally this is not needed and the
316 test contents (the U_BOOT_DTB_DATA string) can be used.
317 But in some test we need the real contents.
318 verbosity: Verbosity level to use (0-3, None=don't set it)
319 allow_missing: Set the '--allow-missing' flag so that missing
320 external binaries just produce a warning instead of an error
321 extra_indirs: Extra input directories to add using -I
326 if verbosity is not None:
327 args.append('-v%d' % verbosity)
329 args.append('-v%d' % self.verbosity)
331 for path in self.toolpath:
332 args += ['--toolpath', path]
333 args += ['build', '-p', '-I', self._indir, '-d', self.TestFile(fname)]
339 args.append('--fake-dtb')
341 for arg, value in entry_args.items():
342 args.append('-a%s=%s' % (arg, value))
347 args += ['-i', image]
349 for indir in extra_indirs:
350 args += ['-I', indir]
351 return self._DoBinman(*args)
353 def _SetupDtb(self, fname, outfile='u-boot.dtb'):
354 """Set up a new test device-tree file
356 The given file is compiled and set up as the device tree to be used
360 fname: Filename of .dts file to read
361 outfile: Output filename for compiled device-tree binary
364 Contents of device-tree binary
366 tmpdir = tempfile.mkdtemp(prefix='binmant.')
367 dtb = fdt_util.EnsureCompiled(self.TestFile(fname), tmpdir)
368 with open(dtb, 'rb') as fd:
370 TestFunctional._MakeInputFile(outfile, data)
371 shutil.rmtree(tmpdir)
374 def _GetDtbContentsForSplTpl(self, dtb_data, name):
375 """Create a version of the main DTB for SPL or SPL
377 For testing we don't actually have different versions of the DTB. With
378 U-Boot we normally run fdtgrep to remove unwanted nodes, but for tests
379 we don't normally have any unwanted nodes.
381 We still want the DTBs for SPL and TPL to be different though, since
382 otherwise it is confusing to know which one we are looking at. So add
383 an 'spl' or 'tpl' property to the top-level node.
386 dtb_data: dtb data to modify (this should be a value devicetree)
387 name: Name of a new property to add
390 New dtb data with the property added
392 dtb = fdt.Fdt.FromData(dtb_data)
394 dtb.GetNode('/binman').AddZeroProp(name)
395 dtb.Sync(auto_resize=True)
397 return dtb.GetContents()
399 def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
400 update_dtb=False, entry_args=None, reset_dtbs=True,
402 """Run binman and return the resulting image
404 This runs binman with a given test file and then reads the resulting
405 output file. It is a shortcut function since most tests need to do
408 Raises an assertion failure if binman returns a non-zero exit code.
411 fname: Device-tree source filename to use (e.g. 005_simple.dts)
412 use_real_dtb: True to use the test file as the contents of
413 the u-boot-dtb entry. Normally this is not needed and the
414 test contents (the U_BOOT_DTB_DATA string) can be used.
415 But in some test we need the real contents.
416 map: True to output map files for the images
417 update_dtb: Update the offset and size of each entry in the device
418 tree before packing it into the image
419 entry_args: Dict of entry args to supply to binman
421 value: value of that arg
422 reset_dtbs: With use_real_dtb the test dtb is overwritten by this
423 function. If reset_dtbs is True, then the original test dtb
424 is written back before this function finishes
425 extra_indirs: Extra input directories to add using -I
429 Resulting image contents
431 Map data showing contents of image (or None if none)
432 Output device tree binary filename ('u-boot.dtb' path)
435 # Use the compiled test file as the u-boot-dtb input
437 dtb_data = self._SetupDtb(fname)
439 # For testing purposes, make a copy of the DT for SPL and TPL. Add
440 # a node indicating which it is, so aid verification.
441 for name in ['spl', 'tpl']:
442 dtb_fname = '%s/u-boot-%s.dtb' % (name, name)
443 outfile = os.path.join(self._indir, dtb_fname)
444 TestFunctional._MakeInputFile(dtb_fname,
445 self._GetDtbContentsForSplTpl(dtb_data, name))
448 retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
449 entry_args=entry_args, use_real_dtb=use_real_dtb,
450 extra_indirs=extra_indirs)
451 self.assertEqual(0, retcode)
452 out_dtb_fname = tools.GetOutputFilename('u-boot.dtb.out')
454 # Find the (only) image, read it and return its contents
455 image = control.images['image']
456 image_fname = tools.GetOutputFilename('image.bin')
457 self.assertTrue(os.path.exists(image_fname))
459 map_fname = tools.GetOutputFilename('image.map')
460 with open(map_fname) as fd:
464 with open(image_fname, 'rb') as fd:
465 return fd.read(), dtb_data, map_data, out_dtb_fname
467 # Put the test file back
468 if reset_dtbs and use_real_dtb:
471 def _DoReadFileRealDtb(self, fname):
472 """Run binman with a real .dtb file and return the resulting data
475 fname: DT source filename to use (e.g. 082_fdt_update_all.dts)
478 Resulting image contents
480 return self._DoReadFileDtb(fname, use_real_dtb=True, update_dtb=True)[0]
482 def _DoReadFile(self, fname, use_real_dtb=False):
483 """Helper function which discards the device-tree binary
486 fname: Device-tree source filename to use (e.g. 005_simple.dts)
487 use_real_dtb: True to use the test file as the contents of
488 the u-boot-dtb entry. Normally this is not needed and the
489 test contents (the U_BOOT_DTB_DATA string) can be used.
490 But in some test we need the real contents.
493 Resulting image contents
495 return self._DoReadFileDtb(fname, use_real_dtb)[0]
498 def _MakeInputFile(cls, fname, contents):
499 """Create a new test input file, creating directories as needed
502 fname: Filename to create
503 contents: File contents to write in to the file
505 Full pathname of file created
507 pathname = os.path.join(cls._indir, fname)
508 dirname = os.path.dirname(pathname)
509 if dirname and not os.path.exists(dirname):
511 with open(pathname, 'wb') as fd:
516 def _MakeInputDir(cls, dirname):
517 """Create a new test input directory, creating directories as needed
520 dirname: Directory name to create
523 Full pathname of directory created
525 pathname = os.path.join(cls._indir, dirname)
526 if not os.path.exists(pathname):
527 os.makedirs(pathname)
531 def _SetupSplElf(cls, src_fname='bss_data'):
532 """Set up an ELF file with a '_dt_ucode_base_size' symbol
535 Filename of ELF file to use as SPL
537 TestFunctional._MakeInputFile('spl/u-boot-spl',
538 tools.ReadFile(cls.ElfTestFile(src_fname)))
541 def _SetupTplElf(cls, src_fname='bss_data'):
542 """Set up an ELF file with a '_dt_ucode_base_size' symbol
545 Filename of ELF file to use as TPL
547 TestFunctional._MakeInputFile('tpl/u-boot-tpl',
548 tools.ReadFile(cls.ElfTestFile(src_fname)))
551 def _SetupDescriptor(cls):
552 with open(cls.TestFile('descriptor.bin'), 'rb') as fd:
553 TestFunctional._MakeInputFile('descriptor.bin', fd.read())
556 def TestFile(cls, fname):
557 return os.path.join(cls._binman_dir, 'test', fname)
560 def ElfTestFile(cls, fname):
561 return os.path.join(cls._elf_testdir, fname)
563 def AssertInList(self, grep_list, target):
564 """Assert that at least one of a list of things is in a target
567 grep_list: List of strings to check
568 target: Target string
570 for grep in grep_list:
573 self.fail("Error: '%s' not found in '%s'" % (grep_list, target))
575 def CheckNoGaps(self, entries):
576 """Check that all entries fit together without gaps
579 entries: List of entries to check
582 for entry in entries.values():
583 self.assertEqual(offset, entry.offset)
586 def GetFdtLen(self, dtb):
587 """Get the totalsize field from a device-tree binary
590 dtb: Device-tree binary contents
593 Total size of device-tree binary, from the header
595 return struct.unpack('>L', dtb[4:8])[0]
597 def _GetPropTree(self, dtb, prop_names, prefix='/binman/'):
598 def AddNode(node, path):
600 path += '/' + node.name
601 for prop in node.props.values():
602 if prop.name in prop_names:
603 prop_path = path + ':' + prop.name
604 tree[prop_path[len(prefix):]] = fdt_util.fdt32_to_cpu(
606 for subnode in node.subnodes:
607 AddNode(subnode, path)
610 AddNode(dtb.GetRoot(), '')
614 """Test a basic run with valid args"""
615 result = self._RunBinman('-h')
617 def testFullHelp(self):
618 """Test that the full help is displayed with -H"""
619 result = self._RunBinman('-H')
620 help_file = os.path.join(self._binman_dir, 'README')
621 # Remove possible extraneous strings
622 extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
623 gothelp = result.stdout.replace(extra, '')
624 self.assertEqual(len(gothelp), os.path.getsize(help_file))
625 self.assertEqual(0, len(result.stderr))
626 self.assertEqual(0, result.return_code)
628 def testFullHelpInternal(self):
629 """Test that the full help is displayed with -H"""
631 command.test_result = command.CommandResult()
632 result = self._DoBinman('-H')
633 help_file = os.path.join(self._binman_dir, 'README')
635 command.test_result = None
638 """Test that the basic help is displayed with -h"""
639 result = self._RunBinman('-h')
640 self.assertTrue(len(result.stdout) > 200)
641 self.assertEqual(0, len(result.stderr))
642 self.assertEqual(0, result.return_code)
645 """Test that we can run it with a specific board"""
646 self._SetupDtb('005_simple.dts', 'sandbox/u-boot.dtb')
647 TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
648 result = self._DoBinman('build', '-b', 'sandbox')
649 self.assertEqual(0, result)
651 def testNeedBoard(self):
652 """Test that we get an error when no board ius supplied"""
653 with self.assertRaises(ValueError) as e:
654 result = self._DoBinman('build')
655 self.assertIn("Must provide a board to process (use -b <board>)",
658 def testMissingDt(self):
659 """Test that an invalid device-tree file generates an error"""
660 with self.assertRaises(Exception) as e:
661 self._RunBinman('build', '-d', 'missing_file')
662 # We get one error from libfdt, and a different one from fdtget.
663 self.AssertInList(["Couldn't open blob from 'missing_file'",
664 'No such file or directory'], str(e.exception))
666 def testBrokenDt(self):
667 """Test that an invalid device-tree source file generates an error
669 Since this is a source file it should be compiled and the error
670 will come from the device-tree compiler (dtc).
672 with self.assertRaises(Exception) as e:
673 self._RunBinman('build', '-d', self.TestFile('001_invalid.dts'))
674 self.assertIn("FATAL ERROR: Unable to parse input tree",
677 def testMissingNode(self):
678 """Test that a device tree without a 'binman' node generates an error"""
679 with self.assertRaises(Exception) as e:
680 self._DoBinman('build', '-d', self.TestFile('002_missing_node.dts'))
681 self.assertIn("does not have a 'binman' node", str(e.exception))
684 """Test that an empty binman node works OK (i.e. does nothing)"""
685 result = self._RunBinman('build', '-d', self.TestFile('003_empty.dts'))
686 self.assertEqual(0, len(result.stderr))
687 self.assertEqual(0, result.return_code)
689 def testInvalidEntry(self):
690 """Test that an invalid entry is flagged"""
691 with self.assertRaises(Exception) as e:
692 result = self._RunBinman('build', '-d',
693 self.TestFile('004_invalid_entry.dts'))
694 self.assertIn("Unknown entry type 'not-a-valid-type' in node "
695 "'/binman/not-a-valid-type'", str(e.exception))
697 def testSimple(self):
698 """Test a simple binman with a single file"""
699 data = self._DoReadFile('005_simple.dts')
700 self.assertEqual(U_BOOT_DATA, data)
702 def testSimpleDebug(self):
703 """Test a simple binman run with debugging enabled"""
704 self._DoTestFile('005_simple.dts', debug=True)
707 """Test that we can handle creating two images
709 This also tests image padding.
711 retcode = self._DoTestFile('006_dual_image.dts')
712 self.assertEqual(0, retcode)
714 image = control.images['image1']
715 self.assertEqual(len(U_BOOT_DATA), image.size)
716 fname = tools.GetOutputFilename('image1.bin')
717 self.assertTrue(os.path.exists(fname))
718 with open(fname, 'rb') as fd:
720 self.assertEqual(U_BOOT_DATA, data)
722 image = control.images['image2']
723 self.assertEqual(3 + len(U_BOOT_DATA) + 5, image.size)
724 fname = tools.GetOutputFilename('image2.bin')
725 self.assertTrue(os.path.exists(fname))
726 with open(fname, 'rb') as fd:
728 self.assertEqual(U_BOOT_DATA, data[3:7])
729 self.assertEqual(tools.GetBytes(0, 3), data[:3])
730 self.assertEqual(tools.GetBytes(0, 5), data[7:])
732 def testBadAlign(self):
733 """Test that an invalid alignment value is detected"""
734 with self.assertRaises(ValueError) as e:
735 self._DoTestFile('007_bad_align.dts')
736 self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
737 "of two", str(e.exception))
739 def testPackSimple(self):
740 """Test that packing works as expected"""
741 retcode = self._DoTestFile('008_pack.dts')
742 self.assertEqual(0, retcode)
743 self.assertIn('image', control.images)
744 image = control.images['image']
745 entries = image.GetEntries()
746 self.assertEqual(5, len(entries))
749 self.assertIn('u-boot', entries)
750 entry = entries['u-boot']
751 self.assertEqual(0, entry.offset)
752 self.assertEqual(len(U_BOOT_DATA), entry.size)
754 # Second u-boot, aligned to 16-byte boundary
755 self.assertIn('u-boot-align', entries)
756 entry = entries['u-boot-align']
757 self.assertEqual(16, entry.offset)
758 self.assertEqual(len(U_BOOT_DATA), entry.size)
760 # Third u-boot, size 23 bytes
761 self.assertIn('u-boot-size', entries)
762 entry = entries['u-boot-size']
763 self.assertEqual(20, entry.offset)
764 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
765 self.assertEqual(23, entry.size)
767 # Fourth u-boot, placed immediate after the above
768 self.assertIn('u-boot-next', entries)
769 entry = entries['u-boot-next']
770 self.assertEqual(43, entry.offset)
771 self.assertEqual(len(U_BOOT_DATA), entry.size)
773 # Fifth u-boot, placed at a fixed offset
774 self.assertIn('u-boot-fixed', entries)
775 entry = entries['u-boot-fixed']
776 self.assertEqual(61, entry.offset)
777 self.assertEqual(len(U_BOOT_DATA), entry.size)
779 self.assertEqual(65, image.size)
781 def testPackExtra(self):
782 """Test that extra packing feature works as expected"""
783 retcode = self._DoTestFile('009_pack_extra.dts')
785 self.assertEqual(0, retcode)
786 self.assertIn('image', control.images)
787 image = control.images['image']
788 entries = image.GetEntries()
789 self.assertEqual(5, len(entries))
791 # First u-boot with padding before and after
792 self.assertIn('u-boot', entries)
793 entry = entries['u-boot']
794 self.assertEqual(0, entry.offset)
795 self.assertEqual(3, entry.pad_before)
796 self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
798 # Second u-boot has an aligned size, but it has no effect
799 self.assertIn('u-boot-align-size-nop', entries)
800 entry = entries['u-boot-align-size-nop']
801 self.assertEqual(12, entry.offset)
802 self.assertEqual(4, entry.size)
804 # Third u-boot has an aligned size too
805 self.assertIn('u-boot-align-size', entries)
806 entry = entries['u-boot-align-size']
807 self.assertEqual(16, entry.offset)
808 self.assertEqual(32, entry.size)
810 # Fourth u-boot has an aligned end
811 self.assertIn('u-boot-align-end', entries)
812 entry = entries['u-boot-align-end']
813 self.assertEqual(48, entry.offset)
814 self.assertEqual(16, entry.size)
816 # Fifth u-boot immediately afterwards
817 self.assertIn('u-boot-align-both', entries)
818 entry = entries['u-boot-align-both']
819 self.assertEqual(64, entry.offset)
820 self.assertEqual(64, entry.size)
822 self.CheckNoGaps(entries)
823 self.assertEqual(128, image.size)
825 def testPackAlignPowerOf2(self):
826 """Test that invalid entry alignment is detected"""
827 with self.assertRaises(ValueError) as e:
828 self._DoTestFile('010_pack_align_power2.dts')
829 self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
830 "of two", str(e.exception))
832 def testPackAlignSizePowerOf2(self):
833 """Test that invalid entry size alignment is detected"""
834 with self.assertRaises(ValueError) as e:
835 self._DoTestFile('011_pack_align_size_power2.dts')
836 self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
837 "power of two", str(e.exception))
839 def testPackInvalidAlign(self):
840 """Test detection of an offset that does not match its alignment"""
841 with self.assertRaises(ValueError) as e:
842 self._DoTestFile('012_pack_inv_align.dts')
843 self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
844 "align 0x4 (4)", str(e.exception))
846 def testPackInvalidSizeAlign(self):
847 """Test that invalid entry size alignment is detected"""
848 with self.assertRaises(ValueError) as e:
849 self._DoTestFile('013_pack_inv_size_align.dts')
850 self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
851 "align-size 0x4 (4)", str(e.exception))
853 def testPackOverlap(self):
854 """Test that overlapping regions are detected"""
855 with self.assertRaises(ValueError) as e:
856 self._DoTestFile('014_pack_overlap.dts')
857 self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
858 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
861 def testPackEntryOverflow(self):
862 """Test that entries that overflow their size are detected"""
863 with self.assertRaises(ValueError) as e:
864 self._DoTestFile('015_pack_overflow.dts')
865 self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
866 "but entry size is 0x3 (3)", str(e.exception))
868 def testPackImageOverflow(self):
869 """Test that entries which overflow the image size are detected"""
870 with self.assertRaises(ValueError) as e:
871 self._DoTestFile('016_pack_image_overflow.dts')
872 self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section "
873 "size 0x3 (3)", str(e.exception))
875 def testPackImageSize(self):
876 """Test that the image size can be set"""
877 retcode = self._DoTestFile('017_pack_image_size.dts')
878 self.assertEqual(0, retcode)
879 self.assertIn('image', control.images)
880 image = control.images['image']
881 self.assertEqual(7, image.size)
883 def testPackImageSizeAlign(self):
884 """Test that image size alignemnt works as expected"""
885 retcode = self._DoTestFile('018_pack_image_align.dts')
886 self.assertEqual(0, retcode)
887 self.assertIn('image', control.images)
888 image = control.images['image']
889 self.assertEqual(16, image.size)
891 def testPackInvalidImageAlign(self):
892 """Test that invalid image alignment is detected"""
893 with self.assertRaises(ValueError) as e:
894 self._DoTestFile('019_pack_inv_image_align.dts')
895 self.assertIn("Section '/binman': Size 0x7 (7) does not match "
896 "align-size 0x8 (8)", str(e.exception))
898 def testPackAlignPowerOf2(self):
899 """Test that invalid image alignment is detected"""
900 with self.assertRaises(ValueError) as e:
901 self._DoTestFile('020_pack_inv_image_align_power2.dts')
902 self.assertIn("Image '/binman': Alignment size 131 must be a power of "
903 "two", str(e.exception))
905 def testImagePadByte(self):
906 """Test that the image pad byte can be specified"""
908 data = self._DoReadFile('021_image_pad.dts')
909 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0xff, 1) +
912 def testImageName(self):
913 """Test that image files can be named"""
914 retcode = self._DoTestFile('022_image_name.dts')
915 self.assertEqual(0, retcode)
916 image = control.images['image1']
917 fname = tools.GetOutputFilename('test-name')
918 self.assertTrue(os.path.exists(fname))
920 image = control.images['image2']
921 fname = tools.GetOutputFilename('test-name.xx')
922 self.assertTrue(os.path.exists(fname))
924 def testBlobFilename(self):
925 """Test that generic blobs can be provided by filename"""
926 data = self._DoReadFile('023_blob.dts')
927 self.assertEqual(BLOB_DATA, data)
929 def testPackSorted(self):
930 """Test that entries can be sorted"""
932 data = self._DoReadFile('024_sorted.dts')
933 self.assertEqual(tools.GetBytes(0, 1) + U_BOOT_SPL_DATA +
934 tools.GetBytes(0, 2) + U_BOOT_DATA, data)
936 def testPackZeroOffset(self):
937 """Test that an entry at offset 0 is not given a new offset"""
938 with self.assertRaises(ValueError) as e:
939 self._DoTestFile('025_pack_zero_size.dts')
940 self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
941 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
944 def testPackUbootDtb(self):
945 """Test that a device tree can be added to U-Boot"""
946 data = self._DoReadFile('026_pack_u_boot_dtb.dts')
947 self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
949 def testPackX86RomNoSize(self):
950 """Test that the end-at-4gb property requires a size property"""
951 with self.assertRaises(ValueError) as e:
952 self._DoTestFile('027_pack_4gb_no_size.dts')
953 self.assertIn("Image '/binman': Section size must be provided when "
954 "using end-at-4gb", str(e.exception))
956 def test4gbAndSkipAtStartTogether(self):
957 """Test that the end-at-4gb and skip-at-size property can't be used
959 with self.assertRaises(ValueError) as e:
960 self._DoTestFile('098_4gb_and_skip_at_start_together.dts')
961 self.assertIn("Image '/binman': Provide either 'end-at-4gb' or "
962 "'skip-at-start'", str(e.exception))
964 def testPackX86RomOutside(self):
965 """Test that the end-at-4gb property checks for offset boundaries"""
966 with self.assertRaises(ValueError) as e:
967 self._DoTestFile('028_pack_4gb_outside.dts')
968 self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
969 "the section starting at 0xffffffe0 (4294967264)",
972 def testPackX86Rom(self):
973 """Test that a basic x86 ROM can be created"""
975 data = self._DoReadFile('029_x86_rom.dts')
976 self.assertEqual(U_BOOT_DATA + tools.GetBytes(0, 3) + U_BOOT_SPL_DATA +
977 tools.GetBytes(0, 2), data)
979 def testPackX86RomMeNoDesc(self):
980 """Test that an invalid Intel descriptor entry is detected"""
982 TestFunctional._MakeInputFile('descriptor-empty.bin', b'')
983 with self.assertRaises(ValueError) as e:
984 self._DoTestFile('163_x86_rom_me_empty.dts')
985 self.assertIn("Node '/binman/intel-descriptor': Cannot find Intel Flash Descriptor (FD) signature",
988 self._SetupDescriptor()
990 def testPackX86RomBadDesc(self):
991 """Test that the Intel requires a descriptor entry"""
992 with self.assertRaises(ValueError) as e:
993 self._DoTestFile('030_x86_rom_me_no_desc.dts')
994 self.assertIn("Node '/binman/intel-me': No offset set with "
995 "offset-unset: should another entry provide this correct "
996 "offset?", str(e.exception))
998 def testPackX86RomMe(self):
999 """Test that an x86 ROM with an ME region can be created"""
1000 data = self._DoReadFile('031_x86_rom_me.dts')
1001 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
1002 if data[:0x1000] != expected_desc:
1003 self.fail('Expected descriptor binary at start of image')
1004 self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
1006 def testPackVga(self):
1007 """Test that an image with a VGA binary can be created"""
1008 data = self._DoReadFile('032_intel_vga.dts')
1009 self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
1011 def testPackStart16(self):
1012 """Test that an image with an x86 start16 region can be created"""
1013 data = self._DoReadFile('033_x86_start16.dts')
1014 self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
1016 def testPackPowerpcMpc85xxBootpgResetvec(self):
1017 """Test that an image with powerpc-mpc85xx-bootpg-resetvec can be
1019 data = self._DoReadFile('150_powerpc_mpc85xx_bootpg_resetvec.dts')
1020 self.assertEqual(PPC_MPC85XX_BR_DATA, data[:len(PPC_MPC85XX_BR_DATA)])
1022 def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False):
1023 """Handle running a test for insertion of microcode
1026 dts_fname: Name of test .dts file
1027 nodtb_data: Data that we expect in the first section
1028 ucode_second: True if the microsecond entry is second instead of
1033 Contents of first region (U-Boot or SPL)
1034 Offset and size components of microcode pointer, as inserted
1035 in the above (two 4-byte words)
1037 data = self._DoReadFile(dts_fname, True)
1039 # Now check the device tree has no microcode
1041 ucode_content = data[len(nodtb_data):]
1042 ucode_pos = len(nodtb_data)
1043 dtb_with_ucode = ucode_content[16:]
1044 fdt_len = self.GetFdtLen(dtb_with_ucode)
1046 dtb_with_ucode = data[len(nodtb_data):]
1047 fdt_len = self.GetFdtLen(dtb_with_ucode)
1048 ucode_content = dtb_with_ucode[fdt_len:]
1049 ucode_pos = len(nodtb_data) + fdt_len
1050 fname = tools.GetOutputFilename('test.dtb')
1051 with open(fname, 'wb') as fd:
1052 fd.write(dtb_with_ucode)
1053 dtb = fdt.FdtScan(fname)
1054 ucode = dtb.GetNode('/microcode')
1055 self.assertTrue(ucode)
1056 for node in ucode.subnodes:
1057 self.assertFalse(node.props.get('data'))
1059 # Check that the microcode appears immediately after the Fdt
1060 # This matches the concatenation of the data properties in
1061 # the /microcode/update@xxx nodes in 34_x86_ucode.dts.
1062 ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
1064 self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
1066 # Check that the microcode pointer was inserted. It should match the
1067 # expected offset and size
1068 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
1070 u_boot = data[:len(nodtb_data)]
1071 return u_boot, pos_and_size
1073 def testPackUbootMicrocode(self):
1074 """Test that x86 microcode can be handled correctly
1076 We expect to see the following in the image, in order:
1077 u-boot-nodtb.bin with a microcode pointer inserted at the correct
1079 u-boot.dtb with the microcode removed
1082 first, pos_and_size = self._RunMicrocodeTest('034_x86_ucode.dts',
1084 self.assertEqual(b'nodtb with microcode' + pos_and_size +
1085 b' somewhere in here', first)
1087 def _RunPackUbootSingleMicrocode(self):
1088 """Test that x86 microcode can be handled correctly
1090 We expect to see the following in the image, in order:
1091 u-boot-nodtb.bin with a microcode pointer inserted at the correct
1093 u-boot.dtb with the microcode
1094 an empty microcode region
1096 # We need the libfdt library to run this test since only that allows
1097 # finding the offset of a property. This is required by
1098 # Entry_u_boot_dtb_with_ucode.ObtainContents().
1099 data = self._DoReadFile('035_x86_single_ucode.dts', True)
1101 second = data[len(U_BOOT_NODTB_DATA):]
1103 fdt_len = self.GetFdtLen(second)
1104 third = second[fdt_len:]
1105 second = second[:fdt_len]
1107 ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
1108 self.assertIn(ucode_data, second)
1109 ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
1111 # Check that the microcode pointer was inserted. It should match the
1112 # expected offset and size
1113 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
1115 first = data[:len(U_BOOT_NODTB_DATA)]
1116 self.assertEqual(b'nodtb with microcode' + pos_and_size +
1117 b' somewhere in here', first)
1119 def testPackUbootSingleMicrocode(self):
1120 """Test that x86 microcode can be handled correctly with fdt_normal.
1122 self._RunPackUbootSingleMicrocode()
1124 def testUBootImg(self):
1125 """Test that u-boot.img can be put in a file"""
1126 data = self._DoReadFile('036_u_boot_img.dts')
1127 self.assertEqual(U_BOOT_IMG_DATA, data)
1129 def testNoMicrocode(self):
1130 """Test that a missing microcode region is detected"""
1131 with self.assertRaises(ValueError) as e:
1132 self._DoReadFile('037_x86_no_ucode.dts', True)
1133 self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
1134 "node found in ", str(e.exception))
1136 def testMicrocodeWithoutNode(self):
1137 """Test that a missing u-boot-dtb-with-ucode node is detected"""
1138 with self.assertRaises(ValueError) as e:
1139 self._DoReadFile('038_x86_ucode_missing_node.dts', True)
1140 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1141 "microcode region u-boot-dtb-with-ucode", str(e.exception))
1143 def testMicrocodeWithoutNode2(self):
1144 """Test that a missing u-boot-ucode node is detected"""
1145 with self.assertRaises(ValueError) as e:
1146 self._DoReadFile('039_x86_ucode_missing_node2.dts', True)
1147 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1148 "microcode region u-boot-ucode", str(e.exception))
1150 def testMicrocodeWithoutPtrInElf(self):
1151 """Test that a U-Boot binary without the microcode symbol is detected"""
1152 # ELF file without a '_dt_ucode_base_size' symbol
1154 TestFunctional._MakeInputFile('u-boot',
1155 tools.ReadFile(self.ElfTestFile('u_boot_no_ucode_ptr')))
1157 with self.assertRaises(ValueError) as e:
1158 self._RunPackUbootSingleMicrocode()
1159 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
1160 "_dt_ucode_base_size symbol in u-boot", str(e.exception))
1163 # Put the original file back
1164 TestFunctional._MakeInputFile('u-boot',
1165 tools.ReadFile(self.ElfTestFile('u_boot_ucode_ptr')))
1167 def testMicrocodeNotInImage(self):
1168 """Test that microcode must be placed within the image"""
1169 with self.assertRaises(ValueError) as e:
1170 self._DoReadFile('040_x86_ucode_not_in_image.dts', True)
1171 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
1172 "pointer _dt_ucode_base_size at fffffe14 is outside the "
1173 "section ranging from 00000000 to 0000002e", str(e.exception))
1175 def testWithoutMicrocode(self):
1176 """Test that we can cope with an image without microcode (e.g. qemu)"""
1177 TestFunctional._MakeInputFile('u-boot',
1178 tools.ReadFile(self.ElfTestFile('u_boot_no_ucode_ptr')))
1179 data, dtb, _, _ = self._DoReadFileDtb('044_x86_optional_ucode.dts', True)
1181 # Now check the device tree has no microcode
1182 self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
1183 second = data[len(U_BOOT_NODTB_DATA):]
1185 fdt_len = self.GetFdtLen(second)
1186 self.assertEqual(dtb, second[:fdt_len])
1188 used_len = len(U_BOOT_NODTB_DATA) + fdt_len
1189 third = data[used_len:]
1190 self.assertEqual(tools.GetBytes(0, 0x200 - used_len), third)
1192 def testUnknownPosSize(self):
1193 """Test that microcode must be placed within the image"""
1194 with self.assertRaises(ValueError) as e:
1195 self._DoReadFile('041_unknown_pos_size.dts', True)
1196 self.assertIn("Section '/binman': Unable to set offset/size for unknown "
1197 "entry 'invalid-entry'", str(e.exception))
1199 def testPackFsp(self):
1200 """Test that an image with a FSP binary can be created"""
1201 data = self._DoReadFile('042_intel_fsp.dts')
1202 self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
1204 def testPackCmc(self):
1205 """Test that an image with a CMC binary can be created"""
1206 data = self._DoReadFile('043_intel_cmc.dts')
1207 self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
1209 def testPackVbt(self):
1210 """Test that an image with a VBT binary can be created"""
1211 data = self._DoReadFile('046_intel_vbt.dts')
1212 self.assertEqual(VBT_DATA, data[:len(VBT_DATA)])
1214 def testSplBssPad(self):
1215 """Test that we can pad SPL's BSS with zeros"""
1216 # ELF file with a '__bss_size' symbol
1218 data = self._DoReadFile('047_spl_bss_pad.dts')
1219 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0, 10) + U_BOOT_DATA,
1222 def testSplBssPadMissing(self):
1223 """Test that a missing symbol is detected"""
1224 self._SetupSplElf('u_boot_ucode_ptr')
1225 with self.assertRaises(ValueError) as e:
1226 self._DoReadFile('047_spl_bss_pad.dts')
1227 self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
1230 def testPackStart16Spl(self):
1231 """Test that an image with an x86 start16 SPL region can be created"""
1232 data = self._DoReadFile('048_x86_start16_spl.dts')
1233 self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)])
1235 def _PackUbootSplMicrocode(self, dts, ucode_second=False):
1236 """Helper function for microcode tests
1238 We expect to see the following in the image, in order:
1239 u-boot-spl-nodtb.bin with a microcode pointer inserted at the
1241 u-boot.dtb with the microcode removed
1245 dts: Device tree file to use for test
1246 ucode_second: True if the microsecond entry is second instead of
1249 self._SetupSplElf('u_boot_ucode_ptr')
1250 first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA,
1251 ucode_second=ucode_second)
1252 self.assertEqual(b'splnodtb with microc' + pos_and_size +
1253 b'ter somewhere in here', first)
1255 def testPackUbootSplMicrocode(self):
1256 """Test that x86 microcode can be handled correctly in SPL"""
1257 self._PackUbootSplMicrocode('049_x86_ucode_spl.dts')
1259 def testPackUbootSplMicrocodeReorder(self):
1260 """Test that order doesn't matter for microcode entries
1262 This is the same as testPackUbootSplMicrocode but when we process the
1263 u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode
1264 entry, so we reply on binman to try later.
1266 self._PackUbootSplMicrocode('058_x86_ucode_spl_needs_retry.dts',
1269 def testPackMrc(self):
1270 """Test that an image with an MRC binary can be created"""
1271 data = self._DoReadFile('050_intel_mrc.dts')
1272 self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
1274 def testSplDtb(self):
1275 """Test that an image with spl/u-boot-spl.dtb can be created"""
1276 data = self._DoReadFile('051_u_boot_spl_dtb.dts')
1277 self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
1279 def testSplNoDtb(self):
1280 """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
1281 data = self._DoReadFile('052_u_boot_spl_nodtb.dts')
1282 self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
1284 def testSymbols(self):
1285 """Test binman can assign symbols embedded in U-Boot"""
1286 elf_fname = self.ElfTestFile('u_boot_binman_syms')
1287 syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
1288 addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
1289 self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
1291 self._SetupSplElf('u_boot_binman_syms')
1292 data = self._DoReadFile('053_symbols.dts')
1293 sym_values = struct.pack('<LQLL', 0x00, 0x1c, 0x28, 0x04)
1294 expected = (sym_values + U_BOOT_SPL_DATA[20:] +
1295 tools.GetBytes(0xff, 1) + U_BOOT_DATA + sym_values +
1296 U_BOOT_SPL_DATA[20:])
1297 self.assertEqual(expected, data)
1299 def testPackUnitAddress(self):
1300 """Test that we support multiple binaries with the same name"""
1301 data = self._DoReadFile('054_unit_address.dts')
1302 self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
1304 def testSections(self):
1305 """Basic test of sections"""
1306 data = self._DoReadFile('055_sections.dts')
1307 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1308 U_BOOT_DATA + tools.GetBytes(ord('a'), 12) +
1309 U_BOOT_DATA + tools.GetBytes(ord('&'), 4))
1310 self.assertEqual(expected, data)
1313 """Tests outputting a map of the images"""
1314 _, _, map_data, _ = self._DoReadFileDtb('055_sections.dts', map=True)
1315 self.assertEqual('''ImagePos Offset Size Name
1316 00000000 00000000 00000028 main-section
1317 00000000 00000000 00000010 section@0
1318 00000000 00000000 00000004 u-boot
1319 00000010 00000010 00000010 section@1
1320 00000010 00000000 00000004 u-boot
1321 00000020 00000020 00000004 section@2
1322 00000020 00000000 00000004 u-boot
1325 def testNamePrefix(self):
1326 """Tests that name prefixes are used"""
1327 _, _, map_data, _ = self._DoReadFileDtb('056_name_prefix.dts', map=True)
1328 self.assertEqual('''ImagePos Offset Size Name
1329 00000000 00000000 00000028 main-section
1330 00000000 00000000 00000010 section@0
1331 00000000 00000000 00000004 ro-u-boot
1332 00000010 00000010 00000010 section@1
1333 00000010 00000000 00000004 rw-u-boot
1336 def testUnknownContents(self):
1337 """Test that obtaining the contents works as expected"""
1338 with self.assertRaises(ValueError) as e:
1339 self._DoReadFile('057_unknown_contents.dts', True)
1340 self.assertIn("Image '/binman': Internal error: Could not complete "
1341 "processing of contents: remaining ["
1342 "<binman.etype._testing.Entry__testing ", str(e.exception))
1344 def testBadChangeSize(self):
1345 """Test that trying to change the size of an entry fails"""
1347 state.SetAllowEntryExpansion(False)
1348 with self.assertRaises(ValueError) as e:
1349 self._DoReadFile('059_change_size.dts', True)
1350 self.assertIn("Node '/binman/_testing': Cannot update entry size from 2 to 3",
1353 state.SetAllowEntryExpansion(True)
1355 def testUpdateFdt(self):
1356 """Test that we can update the device tree with offset/size info"""
1357 _, _, _, out_dtb_fname = self._DoReadFileDtb('060_fdt_update.dts',
1359 dtb = fdt.Fdt(out_dtb_fname)
1361 props = self._GetPropTree(dtb, BASE_DTB_PROPS + REPACK_DTB_PROPS)
1365 '_testing:offset': 32,
1367 '_testing:image-pos': 32,
1368 'section@0/u-boot:offset': 0,
1369 'section@0/u-boot:size': len(U_BOOT_DATA),
1370 'section@0/u-boot:image-pos': 0,
1371 'section@0:offset': 0,
1372 'section@0:size': 16,
1373 'section@0:image-pos': 0,
1375 'section@1/u-boot:offset': 0,
1376 'section@1/u-boot:size': len(U_BOOT_DATA),
1377 'section@1/u-boot:image-pos': 16,
1378 'section@1:offset': 16,
1379 'section@1:size': 16,
1380 'section@1:image-pos': 16,
1384 def testUpdateFdtBad(self):
1385 """Test that we detect when ProcessFdt never completes"""
1386 with self.assertRaises(ValueError) as e:
1387 self._DoReadFileDtb('061_fdt_update_bad.dts', update_dtb=True)
1388 self.assertIn('Could not complete processing of Fdt: remaining '
1389 '[<binman.etype._testing.Entry__testing',
1392 def testEntryArgs(self):
1393 """Test passing arguments to entries from the command line"""
1395 'test-str-arg': 'test1',
1396 'test-int-arg': '456',
1398 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
1399 self.assertIn('image', control.images)
1400 entry = control.images['image'].GetEntries()['_testing']
1401 self.assertEqual('test0', entry.test_str_fdt)
1402 self.assertEqual('test1', entry.test_str_arg)
1403 self.assertEqual(123, entry.test_int_fdt)
1404 self.assertEqual(456, entry.test_int_arg)
1406 def testEntryArgsMissing(self):
1407 """Test missing arguments and properties"""
1409 'test-int-arg': '456',
1411 self._DoReadFileDtb('063_entry_args_missing.dts', entry_args=entry_args)
1412 entry = control.images['image'].GetEntries()['_testing']
1413 self.assertEqual('test0', entry.test_str_fdt)
1414 self.assertEqual(None, entry.test_str_arg)
1415 self.assertEqual(None, entry.test_int_fdt)
1416 self.assertEqual(456, entry.test_int_arg)
1418 def testEntryArgsRequired(self):
1419 """Test missing arguments and properties"""
1421 'test-int-arg': '456',
1423 with self.assertRaises(ValueError) as e:
1424 self._DoReadFileDtb('064_entry_args_required.dts')
1425 self.assertIn("Node '/binman/_testing': "
1426 'Missing required properties/entry args: test-str-arg, '
1427 'test-int-fdt, test-int-arg',
1430 def testEntryArgsInvalidFormat(self):
1431 """Test that an invalid entry-argument format is detected"""
1432 args = ['build', '-d', self.TestFile('064_entry_args_required.dts'),
1434 with self.assertRaises(ValueError) as e:
1435 self._DoBinman(*args)
1436 self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
1438 def testEntryArgsInvalidInteger(self):
1439 """Test that an invalid entry-argument integer is detected"""
1441 'test-int-arg': 'abc',
1443 with self.assertRaises(ValueError) as e:
1444 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
1445 self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
1446 "'test-int-arg' (value 'abc') to integer",
1449 def testEntryArgsInvalidDatatype(self):
1450 """Test that an invalid entry-argument datatype is detected
1452 This test could be written in entry_test.py except that it needs
1453 access to control.entry_args, which seems more than that module should
1457 'test-bad-datatype-arg': '12',
1459 with self.assertRaises(ValueError) as e:
1460 self._DoReadFileDtb('065_entry_args_unknown_datatype.dts',
1461 entry_args=entry_args)
1462 self.assertIn('GetArg() internal error: Unknown data type ',
1466 """Test for a text entry type"""
1468 'test-id': TEXT_DATA,
1469 'test-id2': TEXT_DATA2,
1470 'test-id3': TEXT_DATA3,
1472 data, _, _, _ = self._DoReadFileDtb('066_text.dts',
1473 entry_args=entry_args)
1474 expected = (tools.ToBytes(TEXT_DATA) +
1475 tools.GetBytes(0, 8 - len(TEXT_DATA)) +
1476 tools.ToBytes(TEXT_DATA2) + tools.ToBytes(TEXT_DATA3) +
1477 b'some text' + b'more text')
1478 self.assertEqual(expected, data)
1480 def testEntryDocs(self):
1481 """Test for creation of entry documentation"""
1482 with test_util.capture_sys_output() as (stdout, stderr):
1483 control.WriteEntryDocs(control.GetEntryModules())
1484 self.assertTrue(len(stdout.getvalue()) > 0)
1486 def testEntryDocsMissing(self):
1487 """Test handling of missing entry documentation"""
1488 with self.assertRaises(ValueError) as e:
1489 with test_util.capture_sys_output() as (stdout, stderr):
1490 control.WriteEntryDocs(control.GetEntryModules(), 'u_boot')
1491 self.assertIn('Documentation is missing for modules: u_boot',
1495 """Basic test of generation of a flashrom fmap"""
1496 data = self._DoReadFile('067_fmap.dts')
1497 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1498 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1499 U_BOOT_DATA + tools.GetBytes(ord('a'), 12))
1500 self.assertEqual(expected, data[:32])
1501 self.assertEqual(b'__FMAP__', fhdr.signature)
1502 self.assertEqual(1, fhdr.ver_major)
1503 self.assertEqual(0, fhdr.ver_minor)
1504 self.assertEqual(0, fhdr.base)
1505 self.assertEqual(16 + 16 +
1506 fmap_util.FMAP_HEADER_LEN +
1507 fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
1508 self.assertEqual(b'FMAP', fhdr.name)
1509 self.assertEqual(3, fhdr.nareas)
1510 for fentry in fentries:
1511 self.assertEqual(0, fentry.flags)
1513 self.assertEqual(0, fentries[0].offset)
1514 self.assertEqual(4, fentries[0].size)
1515 self.assertEqual(b'RO_U_BOOT', fentries[0].name)
1517 self.assertEqual(16, fentries[1].offset)
1518 self.assertEqual(4, fentries[1].size)
1519 self.assertEqual(b'RW_U_BOOT', fentries[1].name)
1521 self.assertEqual(32, fentries[2].offset)
1522 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1523 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1524 self.assertEqual(b'FMAP', fentries[2].name)
1526 def testBlobNamedByArg(self):
1527 """Test we can add a blob with the filename coming from an entry arg"""
1529 'cros-ec-rw-path': 'ecrw.bin',
1531 self._DoReadFileDtb('068_blob_named_by_arg.dts', entry_args=entry_args)
1534 """Test for an fill entry type"""
1535 data = self._DoReadFile('069_fill.dts')
1536 expected = tools.GetBytes(0xff, 8) + tools.GetBytes(0, 8)
1537 self.assertEqual(expected, data)
1539 def testFillNoSize(self):
1540 """Test for an fill entry type with no size"""
1541 with self.assertRaises(ValueError) as e:
1542 self._DoReadFile('070_fill_no_size.dts')
1543 self.assertIn("'fill' entry must have a size property",
1546 def _HandleGbbCommand(self, pipe_list):
1547 """Fake calls to the futility utility"""
1548 if pipe_list[0][0] == 'futility':
1549 fname = pipe_list[0][-1]
1550 # Append our GBB data to the file, which will happen every time the
1551 # futility command is called.
1552 with open(fname, 'ab') as fd:
1554 return command.CommandResult()
1557 """Test for the Chromium OS Google Binary Block"""
1558 command.test_result = self._HandleGbbCommand
1560 'keydir': 'devkeys',
1561 'bmpblk': 'bmpblk.bin',
1563 data, _, _, _ = self._DoReadFileDtb('071_gbb.dts', entry_args=entry_args)
1566 expected = (GBB_DATA + GBB_DATA + tools.GetBytes(0, 8) +
1567 tools.GetBytes(0, 0x2180 - 16))
1568 self.assertEqual(expected, data)
1570 def testGbbTooSmall(self):
1571 """Test for the Chromium OS Google Binary Block being large enough"""
1572 with self.assertRaises(ValueError) as e:
1573 self._DoReadFileDtb('072_gbb_too_small.dts')
1574 self.assertIn("Node '/binman/gbb': GBB is too small",
1577 def testGbbNoSize(self):
1578 """Test for the Chromium OS Google Binary Block having a size"""
1579 with self.assertRaises(ValueError) as e:
1580 self._DoReadFileDtb('073_gbb_no_size.dts')
1581 self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
1584 def _HandleVblockCommand(self, pipe_list):
1585 """Fake calls to the futility utility"""
1586 if pipe_list[0][0] == 'futility':
1587 fname = pipe_list[0][3]
1588 with open(fname, 'wb') as fd:
1589 fd.write(VBLOCK_DATA)
1590 return command.CommandResult()
1592 def testVblock(self):
1593 """Test for the Chromium OS Verified Boot Block"""
1594 command.test_result = self._HandleVblockCommand
1596 'keydir': 'devkeys',
1598 data, _, _, _ = self._DoReadFileDtb('074_vblock.dts',
1599 entry_args=entry_args)
1600 expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
1601 self.assertEqual(expected, data)
1603 def testVblockNoContent(self):
1604 """Test we detect a vblock which has no content to sign"""
1605 with self.assertRaises(ValueError) as e:
1606 self._DoReadFile('075_vblock_no_content.dts')
1607 self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
1608 'property', str(e.exception))
1610 def testVblockBadPhandle(self):
1611 """Test that we detect a vblock with an invalid phandle in contents"""
1612 with self.assertRaises(ValueError) as e:
1613 self._DoReadFile('076_vblock_bad_phandle.dts')
1614 self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
1615 '1000', str(e.exception))
1617 def testVblockBadEntry(self):
1618 """Test that we detect an entry that points to a non-entry"""
1619 with self.assertRaises(ValueError) as e:
1620 self._DoReadFile('077_vblock_bad_entry.dts')
1621 self.assertIn("Node '/binman/vblock': Cannot find entry for node "
1622 "'other'", str(e.exception))
1625 """Test that an image with TPL and its device tree can be created"""
1626 # ELF file with a '__bss_size' symbol
1628 data = self._DoReadFile('078_u_boot_tpl.dts')
1629 self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
1631 def testUsesPos(self):
1632 """Test that the 'pos' property cannot be used anymore"""
1633 with self.assertRaises(ValueError) as e:
1634 data = self._DoReadFile('079_uses_pos.dts')
1635 self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
1636 "'pos'", str(e.exception))
1638 def testFillZero(self):
1639 """Test for an fill entry type with a size of 0"""
1640 data = self._DoReadFile('080_fill_empty.dts')
1641 self.assertEqual(tools.GetBytes(0, 16), data)
1643 def testTextMissing(self):
1644 """Test for a text entry type where there is no text"""
1645 with self.assertRaises(ValueError) as e:
1646 self._DoReadFileDtb('066_text.dts',)
1647 self.assertIn("Node '/binman/text': No value provided for text label "
1648 "'test-id'", str(e.exception))
1650 def testPackStart16Tpl(self):
1651 """Test that an image with an x86 start16 TPL region can be created"""
1652 data = self._DoReadFile('081_x86_start16_tpl.dts')
1653 self.assertEqual(X86_START16_TPL_DATA, data[:len(X86_START16_TPL_DATA)])
1655 def testSelectImage(self):
1656 """Test that we can select which images to build"""
1657 expected = 'Skipping images: image1'
1659 # We should only get the expected message in verbose mode
1660 for verbosity in (0, 2):
1661 with test_util.capture_sys_output() as (stdout, stderr):
1662 retcode = self._DoTestFile('006_dual_image.dts',
1663 verbosity=verbosity,
1665 self.assertEqual(0, retcode)
1667 self.assertIn(expected, stdout.getvalue())
1669 self.assertNotIn(expected, stdout.getvalue())
1671 self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
1672 self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
1673 self._CleanupOutputDir()
1675 def testUpdateFdtAll(self):
1676 """Test that all device trees are updated with offset/size info"""
1677 data = self._DoReadFileRealDtb('082_fdt_update_all.dts')
1680 'section:image-pos': 0,
1681 'u-boot-tpl-dtb:size': 513,
1682 'u-boot-spl-dtb:size': 513,
1683 'u-boot-spl-dtb:offset': 493,
1685 'section/u-boot-dtb:image-pos': 0,
1686 'u-boot-spl-dtb:image-pos': 493,
1687 'section/u-boot-dtb:size': 493,
1688 'u-boot-tpl-dtb:image-pos': 1006,
1689 'section/u-boot-dtb:offset': 0,
1690 'section:size': 493,
1692 'section:offset': 0,
1693 'u-boot-tpl-dtb:offset': 1006,
1697 # We expect three device-tree files in the output, one after the other.
1698 # Read them in sequence. We look for an 'spl' property in the SPL tree,
1699 # and 'tpl' in the TPL tree, to make sure they are distinct from the
1700 # main U-Boot tree. All three should have the same postions and offset.
1702 for item in ['', 'spl', 'tpl']:
1703 dtb = fdt.Fdt.FromData(data[start:])
1705 props = self._GetPropTree(dtb, BASE_DTB_PROPS + REPACK_DTB_PROPS +
1707 expected = dict(base_expected)
1710 self.assertEqual(expected, props)
1711 start += dtb._fdt_obj.totalsize()
1713 def testUpdateFdtOutput(self):
1714 """Test that output DTB files are updated"""
1716 data, dtb_data, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
1717 use_real_dtb=True, update_dtb=True, reset_dtbs=False)
1719 # Unfortunately, compiling a source file always results in a file
1720 # called source.dtb (see fdt_util.EnsureCompiled()). The test
1721 # source file (e.g. test/075_fdt_update_all.dts) thus does not enter
1722 # binman as a file called u-boot.dtb. To fix this, copy the file
1723 # over to the expected place.
1725 for fname in ['u-boot.dtb.out', 'spl/u-boot-spl.dtb.out',
1726 'tpl/u-boot-tpl.dtb.out']:
1727 dtb = fdt.Fdt.FromData(data[start:])
1728 size = dtb._fdt_obj.totalsize()
1729 pathname = tools.GetOutputFilename(os.path.split(fname)[1])
1730 outdata = tools.ReadFile(pathname)
1731 name = os.path.split(fname)[0]
1734 orig_indata = self._GetDtbContentsForSplTpl(dtb_data, name)
1736 orig_indata = dtb_data
1737 self.assertNotEqual(outdata, orig_indata,
1738 "Expected output file '%s' be updated" % pathname)
1739 self.assertEqual(outdata, data[start:start + size],
1740 "Expected output file '%s' to match output image" %
1746 def _decompress(self, data):
1747 return tools.Decompress(data, 'lz4')
1749 def testCompress(self):
1750 """Test compression of blobs"""
1752 data, _, _, out_dtb_fname = self._DoReadFileDtb('083_compress.dts',
1753 use_real_dtb=True, update_dtb=True)
1754 dtb = fdt.Fdt(out_dtb_fname)
1756 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
1757 orig = self._decompress(data)
1758 self.assertEquals(COMPRESS_DATA, orig)
1760 'blob:uncomp-size': len(COMPRESS_DATA),
1761 'blob:size': len(data),
1764 self.assertEqual(expected, props)
1766 def testFiles(self):
1767 """Test bringing in multiple files"""
1768 data = self._DoReadFile('084_files.dts')
1769 self.assertEqual(FILES_DATA, data)
1771 def testFilesCompress(self):
1772 """Test bringing in multiple files and compressing them"""
1774 data = self._DoReadFile('085_files_compress.dts')
1776 image = control.images['image']
1777 entries = image.GetEntries()
1778 files = entries['files']
1779 entries = files._entries
1782 for i in range(1, 3):
1784 start = entries[key].image_pos
1785 len = entries[key].size
1786 chunk = data[start:start + len]
1787 orig += self._decompress(chunk)
1789 self.assertEqual(FILES_DATA, orig)
1791 def testFilesMissing(self):
1792 """Test missing files"""
1793 with self.assertRaises(ValueError) as e:
1794 data = self._DoReadFile('086_files_none.dts')
1795 self.assertIn("Node '/binman/files': Pattern \'files/*.none\' matched "
1796 'no files', str(e.exception))
1798 def testFilesNoPattern(self):
1799 """Test missing files"""
1800 with self.assertRaises(ValueError) as e:
1801 data = self._DoReadFile('087_files_no_pattern.dts')
1802 self.assertIn("Node '/binman/files': Missing 'pattern' property",
1805 def testExpandSize(self):
1806 """Test an expanding entry"""
1807 data, _, map_data, _ = self._DoReadFileDtb('088_expand_size.dts',
1809 expect = (tools.GetBytes(ord('a'), 8) + U_BOOT_DATA +
1810 MRC_DATA + tools.GetBytes(ord('b'), 1) + U_BOOT_DATA +
1811 tools.GetBytes(ord('c'), 8) + U_BOOT_DATA +
1812 tools.GetBytes(ord('d'), 8))
1813 self.assertEqual(expect, data)
1814 self.assertEqual('''ImagePos Offset Size Name
1815 00000000 00000000 00000028 main-section
1816 00000000 00000000 00000008 fill
1817 00000008 00000008 00000004 u-boot
1818 0000000c 0000000c 00000004 section
1819 0000000c 00000000 00000003 intel-mrc
1820 00000010 00000010 00000004 u-boot2
1821 00000014 00000014 0000000c section2
1822 00000014 00000000 00000008 fill
1823 0000001c 00000008 00000004 u-boot
1824 00000020 00000020 00000008 fill2
1827 def testExpandSizeBad(self):
1828 """Test an expanding entry which fails to provide contents"""
1829 with test_util.capture_sys_output() as (stdout, stderr):
1830 with self.assertRaises(ValueError) as e:
1831 self._DoReadFileDtb('089_expand_size_bad.dts', map=True)
1832 self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
1833 'expanding entry', str(e.exception))
1836 """Test hashing of the contents of an entry"""
1837 _, _, _, out_dtb_fname = self._DoReadFileDtb('090_hash.dts',
1838 use_real_dtb=True, update_dtb=True)
1839 dtb = fdt.Fdt(out_dtb_fname)
1841 hash_node = dtb.GetNode('/binman/u-boot/hash').props['value']
1842 m = hashlib.sha256()
1843 m.update(U_BOOT_DATA)
1844 self.assertEqual(m.digest(), b''.join(hash_node.value))
1846 def testHashNoAlgo(self):
1847 with self.assertRaises(ValueError) as e:
1848 self._DoReadFileDtb('091_hash_no_algo.dts', update_dtb=True)
1849 self.assertIn("Node \'/binman/u-boot\': Missing \'algo\' property for "
1850 'hash node', str(e.exception))
1852 def testHashBadAlgo(self):
1853 with self.assertRaises(ValueError) as e:
1854 self._DoReadFileDtb('092_hash_bad_algo.dts', update_dtb=True)
1855 self.assertIn("Node '/binman/u-boot': Unknown hash algorithm",
1858 def testHashSection(self):
1859 """Test hashing of the contents of an entry"""
1860 _, _, _, out_dtb_fname = self._DoReadFileDtb('099_hash_section.dts',
1861 use_real_dtb=True, update_dtb=True)
1862 dtb = fdt.Fdt(out_dtb_fname)
1864 hash_node = dtb.GetNode('/binman/section/hash').props['value']
1865 m = hashlib.sha256()
1866 m.update(U_BOOT_DATA)
1867 m.update(tools.GetBytes(ord('a'), 16))
1868 self.assertEqual(m.digest(), b''.join(hash_node.value))
1870 def testPackUBootTplMicrocode(self):
1871 """Test that x86 microcode can be handled correctly in TPL
1873 We expect to see the following in the image, in order:
1874 u-boot-tpl-nodtb.bin with a microcode pointer inserted at the correct
1876 u-boot-tpl.dtb with the microcode removed
1879 self._SetupTplElf('u_boot_ucode_ptr')
1880 first, pos_and_size = self._RunMicrocodeTest('093_x86_tpl_ucode.dts',
1881 U_BOOT_TPL_NODTB_DATA)
1882 self.assertEqual(b'tplnodtb with microc' + pos_and_size +
1883 b'ter somewhere in here', first)
1885 def testFmapX86(self):
1886 """Basic test of generation of a flashrom fmap"""
1887 data = self._DoReadFile('094_fmap_x86.dts')
1888 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1889 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('a'), 32 - 7)
1890 self.assertEqual(expected, data[:32])
1891 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1893 self.assertEqual(0x100, fhdr.image_size)
1895 self.assertEqual(0, fentries[0].offset)
1896 self.assertEqual(4, fentries[0].size)
1897 self.assertEqual(b'U_BOOT', fentries[0].name)
1899 self.assertEqual(4, fentries[1].offset)
1900 self.assertEqual(3, fentries[1].size)
1901 self.assertEqual(b'INTEL_MRC', fentries[1].name)
1903 self.assertEqual(32, fentries[2].offset)
1904 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1905 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1906 self.assertEqual(b'FMAP', fentries[2].name)
1908 def testFmapX86Section(self):
1909 """Basic test of generation of a flashrom fmap"""
1910 data = self._DoReadFile('095_fmap_x86_section.dts')
1911 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('b'), 32 - 7)
1912 self.assertEqual(expected, data[:32])
1913 fhdr, fentries = fmap_util.DecodeFmap(data[36:])
1915 self.assertEqual(0x100, fhdr.image_size)
1917 self.assertEqual(0, fentries[0].offset)
1918 self.assertEqual(4, fentries[0].size)
1919 self.assertEqual(b'U_BOOT', fentries[0].name)
1921 self.assertEqual(4, fentries[1].offset)
1922 self.assertEqual(3, fentries[1].size)
1923 self.assertEqual(b'INTEL_MRC', fentries[1].name)
1925 self.assertEqual(36, fentries[2].offset)
1926 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1927 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1928 self.assertEqual(b'FMAP', fentries[2].name)
1931 """Basic test of ELF entries"""
1934 with open(self.ElfTestFile('bss_data'), 'rb') as fd:
1935 TestFunctional._MakeInputFile('-boot', fd.read())
1936 data = self._DoReadFile('096_elf.dts')
1938 def testElfStrip(self):
1939 """Basic test of ELF entries"""
1941 with open(self.ElfTestFile('bss_data'), 'rb') as fd:
1942 TestFunctional._MakeInputFile('-boot', fd.read())
1943 data = self._DoReadFile('097_elf_strip.dts')
1945 def testPackOverlapMap(self):
1946 """Test that overlapping regions are detected"""
1947 with test_util.capture_sys_output() as (stdout, stderr):
1948 with self.assertRaises(ValueError) as e:
1949 self._DoTestFile('014_pack_overlap.dts', map=True)
1950 map_fname = tools.GetOutputFilename('image.map')
1951 self.assertEqual("Wrote map file '%s' to show errors\n" % map_fname,
1954 # We should not get an inmage, but there should be a map file
1955 self.assertFalse(os.path.exists(tools.GetOutputFilename('image.bin')))
1956 self.assertTrue(os.path.exists(map_fname))
1957 map_data = tools.ReadFile(map_fname, binary=False)
1958 self.assertEqual('''ImagePos Offset Size Name
1959 <none> 00000000 00000007 main-section
1960 <none> 00000000 00000004 u-boot
1961 <none> 00000003 00000004 u-boot-align
1964 def testPackRefCode(self):
1965 """Test that an image with an Intel Reference code binary works"""
1966 data = self._DoReadFile('100_intel_refcode.dts')
1967 self.assertEqual(REFCODE_DATA, data[:len(REFCODE_DATA)])
1969 def testSectionOffset(self):
1970 """Tests use of a section with an offset"""
1971 data, _, map_data, _ = self._DoReadFileDtb('101_sections_offset.dts',
1973 self.assertEqual('''ImagePos Offset Size Name
1974 00000000 00000000 00000038 main-section
1975 00000004 00000004 00000010 section@0
1976 00000004 00000000 00000004 u-boot
1977 00000018 00000018 00000010 section@1
1978 00000018 00000000 00000004 u-boot
1979 0000002c 0000002c 00000004 section@2
1980 0000002c 00000000 00000004 u-boot
1982 self.assertEqual(data,
1983 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1984 tools.GetBytes(0x21, 12) +
1985 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1986 tools.GetBytes(0x61, 12) +
1987 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1988 tools.GetBytes(0x26, 8))
1990 def testCbfsRaw(self):
1991 """Test base handling of a Coreboot Filesystem (CBFS)
1993 The exact contents of the CBFS is verified by similar tests in
1994 cbfs_util_test.py. The tests here merely check that the files added to
1995 the CBFS can be found in the final image.
1997 data = self._DoReadFile('102_cbfs_raw.dts')
2000 cbfs = cbfs_util.CbfsReader(data)
2001 self.assertEqual(size, cbfs.rom_size)
2003 self.assertIn('u-boot-dtb', cbfs.files)
2004 cfile = cbfs.files['u-boot-dtb']
2005 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
2007 def testCbfsArch(self):
2008 """Test on non-x86 architecture"""
2009 data = self._DoReadFile('103_cbfs_raw_ppc.dts')
2012 cbfs = cbfs_util.CbfsReader(data)
2013 self.assertEqual(size, cbfs.rom_size)
2015 self.assertIn('u-boot-dtb', cbfs.files)
2016 cfile = cbfs.files['u-boot-dtb']
2017 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
2019 def testCbfsStage(self):
2020 """Tests handling of a Coreboot Filesystem (CBFS)"""
2021 if not elf.ELF_TOOLS:
2022 self.skipTest('Python elftools not available')
2023 elf_fname = os.path.join(self._indir, 'cbfs-stage.elf')
2024 elf.MakeElf(elf_fname, U_BOOT_DATA, U_BOOT_DTB_DATA)
2027 data = self._DoReadFile('104_cbfs_stage.dts')
2028 cbfs = cbfs_util.CbfsReader(data)
2029 self.assertEqual(size, cbfs.rom_size)
2031 self.assertIn('u-boot', cbfs.files)
2032 cfile = cbfs.files['u-boot']
2033 self.assertEqual(U_BOOT_DATA + U_BOOT_DTB_DATA, cfile.data)
2035 def testCbfsRawCompress(self):
2036 """Test handling of compressing raw files"""
2038 data = self._DoReadFile('105_cbfs_raw_compress.dts')
2041 cbfs = cbfs_util.CbfsReader(data)
2042 self.assertIn('u-boot', cbfs.files)
2043 cfile = cbfs.files['u-boot']
2044 self.assertEqual(COMPRESS_DATA, cfile.data)
2046 def testCbfsBadArch(self):
2047 """Test handling of a bad architecture"""
2048 with self.assertRaises(ValueError) as e:
2049 self._DoReadFile('106_cbfs_bad_arch.dts')
2050 self.assertIn("Invalid architecture 'bad-arch'", str(e.exception))
2052 def testCbfsNoSize(self):
2053 """Test handling of a missing size property"""
2054 with self.assertRaises(ValueError) as e:
2055 self._DoReadFile('107_cbfs_no_size.dts')
2056 self.assertIn('entry must have a size property', str(e.exception))
2058 def testCbfsNoCOntents(self):
2059 """Test handling of a CBFS entry which does not provide contentsy"""
2060 with self.assertRaises(ValueError) as e:
2061 self._DoReadFile('108_cbfs_no_contents.dts')
2062 self.assertIn('Could not complete processing of contents',
2065 def testCbfsBadCompress(self):
2066 """Test handling of a bad architecture"""
2067 with self.assertRaises(ValueError) as e:
2068 self._DoReadFile('109_cbfs_bad_compress.dts')
2069 self.assertIn("Invalid compression in 'u-boot': 'invalid-algo'",
2072 def testCbfsNamedEntries(self):
2073 """Test handling of named entries"""
2074 data = self._DoReadFile('110_cbfs_name.dts')
2076 cbfs = cbfs_util.CbfsReader(data)
2077 self.assertIn('FRED', cbfs.files)
2078 cfile1 = cbfs.files['FRED']
2079 self.assertEqual(U_BOOT_DATA, cfile1.data)
2081 self.assertIn('hello', cbfs.files)
2082 cfile2 = cbfs.files['hello']
2083 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
2085 def _SetupIfwi(self, fname):
2086 """Set up to run an IFWI test
2089 fname: Filename of input file to provide (fitimage.bin or ifwi.bin)
2094 # Intel Integrated Firmware Image (IFWI) file
2095 with gzip.open(self.TestFile('%s.gz' % fname), 'rb') as fd:
2097 TestFunctional._MakeInputFile(fname,data)
2099 def _CheckIfwi(self, data):
2100 """Check that an image with an IFWI contains the correct output
2103 data: Conents of output file
2105 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
2106 if data[:0x1000] != expected_desc:
2107 self.fail('Expected descriptor binary at start of image')
2109 # We expect to find the TPL wil in subpart IBBP entry IBBL
2110 image_fname = tools.GetOutputFilename('image.bin')
2111 tpl_fname = tools.GetOutputFilename('tpl.out')
2112 tools.RunIfwiTool(image_fname, tools.CMD_EXTRACT, fname=tpl_fname,
2113 subpart='IBBP', entry_name='IBBL')
2115 tpl_data = tools.ReadFile(tpl_fname)
2116 self.assertEqual(U_BOOT_TPL_DATA, tpl_data[:len(U_BOOT_TPL_DATA)])
2118 def testPackX86RomIfwi(self):
2119 """Test that an x86 ROM with Integrated Firmware Image can be created"""
2120 self._SetupIfwi('fitimage.bin')
2121 data = self._DoReadFile('111_x86_rom_ifwi.dts')
2122 self._CheckIfwi(data)
2124 def testPackX86RomIfwiNoDesc(self):
2125 """Test that an x86 ROM with IFWI can be created from an ifwi.bin file"""
2126 self._SetupIfwi('ifwi.bin')
2127 data = self._DoReadFile('112_x86_rom_ifwi_nodesc.dts')
2128 self._CheckIfwi(data)
2130 def testPackX86RomIfwiNoData(self):
2131 """Test that an x86 ROM with IFWI handles missing data"""
2132 self._SetupIfwi('ifwi.bin')
2133 with self.assertRaises(ValueError) as e:
2134 data = self._DoReadFile('113_x86_rom_ifwi_nodata.dts')
2135 self.assertIn('Could not complete processing of contents',
2138 def testCbfsOffset(self):
2139 """Test a CBFS with files at particular offsets
2141 Like all CFBS tests, this is just checking the logic that calls
2142 cbfs_util. See cbfs_util_test for fully tests (e.g. test_cbfs_offset()).
2144 data = self._DoReadFile('114_cbfs_offset.dts')
2147 cbfs = cbfs_util.CbfsReader(data)
2148 self.assertEqual(size, cbfs.rom_size)
2150 self.assertIn('u-boot', cbfs.files)
2151 cfile = cbfs.files['u-boot']
2152 self.assertEqual(U_BOOT_DATA, cfile.data)
2153 self.assertEqual(0x40, cfile.cbfs_offset)
2155 self.assertIn('u-boot-dtb', cbfs.files)
2156 cfile2 = cbfs.files['u-boot-dtb']
2157 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
2158 self.assertEqual(0x140, cfile2.cbfs_offset)
2160 def testFdtmap(self):
2161 """Test an FDT map can be inserted in the image"""
2162 data = self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
2163 fdtmap_data = data[len(U_BOOT_DATA):]
2164 magic = fdtmap_data[:8]
2165 self.assertEqual(b'_FDTMAP_', magic)
2166 self.assertEqual(tools.GetBytes(0, 8), fdtmap_data[8:16])
2168 fdt_data = fdtmap_data[16:]
2169 dtb = fdt.Fdt.FromData(fdt_data)
2171 props = self._GetPropTree(dtb, BASE_DTB_PROPS, prefix='/')
2176 'u-boot:size': len(U_BOOT_DATA),
2177 'u-boot:image-pos': 0,
2178 'fdtmap:image-pos': 4,
2180 'fdtmap:size': len(fdtmap_data),
2184 def testFdtmapNoMatch(self):
2185 """Check handling of an FDT map when the section cannot be found"""
2186 self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
2188 # Mangle the section name, which should cause a mismatch between the
2189 # correct FDT path and the one expected by the section
2190 image = control.images['image']
2191 image._node.path += '-suffix'
2192 entries = image.GetEntries()
2193 fdtmap = entries['fdtmap']
2194 with self.assertRaises(ValueError) as e:
2196 self.assertIn("Cannot locate node for path '/binman-suffix'",
2199 def testFdtmapHeader(self):
2200 """Test an FDT map and image header can be inserted in the image"""
2201 data = self.data = self._DoReadFileRealDtb('116_fdtmap_hdr.dts')
2202 fdtmap_pos = len(U_BOOT_DATA)
2203 fdtmap_data = data[fdtmap_pos:]
2204 fdt_data = fdtmap_data[16:]
2205 dtb = fdt.Fdt.FromData(fdt_data)
2206 fdt_size = dtb.GetFdtObj().totalsize()
2207 hdr_data = data[-8:]
2208 self.assertEqual(b'BinM', hdr_data[:4])
2209 offset = struct.unpack('<I', hdr_data[4:])[0] & 0xffffffff
2210 self.assertEqual(fdtmap_pos - 0x400, offset - (1 << 32))
2212 def testFdtmapHeaderStart(self):
2213 """Test an image header can be inserted at the image start"""
2214 data = self.data = self._DoReadFileRealDtb('117_fdtmap_hdr_start.dts')
2215 fdtmap_pos = 0x100 + len(U_BOOT_DATA)
2217 self.assertEqual(b'BinM', hdr_data[:4])
2218 offset = struct.unpack('<I', hdr_data[4:])[0]
2219 self.assertEqual(fdtmap_pos, offset)
2221 def testFdtmapHeaderPos(self):
2222 """Test an image header can be inserted at a chosen position"""
2223 data = self.data = self._DoReadFileRealDtb('118_fdtmap_hdr_pos.dts')
2224 fdtmap_pos = 0x100 + len(U_BOOT_DATA)
2225 hdr_data = data[0x80:0x88]
2226 self.assertEqual(b'BinM', hdr_data[:4])
2227 offset = struct.unpack('<I', hdr_data[4:])[0]
2228 self.assertEqual(fdtmap_pos, offset)
2230 def testHeaderMissingFdtmap(self):
2231 """Test an image header requires an fdtmap"""
2232 with self.assertRaises(ValueError) as e:
2233 self.data = self._DoReadFileRealDtb('119_fdtmap_hdr_missing.dts')
2234 self.assertIn("'image_header' section must have an 'fdtmap' sibling",
2237 def testHeaderNoLocation(self):
2238 """Test an image header with a no specified location is detected"""
2239 with self.assertRaises(ValueError) as e:
2240 self.data = self._DoReadFileRealDtb('120_hdr_no_location.dts')
2241 self.assertIn("Invalid location 'None', expected 'start' or 'end'",
2244 def testEntryExpand(self):
2245 """Test expanding an entry after it is packed"""
2246 data = self._DoReadFile('121_entry_expand.dts')
2247 self.assertEqual(b'aaa', data[:3])
2248 self.assertEqual(U_BOOT_DATA, data[3:3 + len(U_BOOT_DATA)])
2249 self.assertEqual(b'aaa', data[-3:])
2251 def testEntryExpandBad(self):
2252 """Test expanding an entry after it is packed, twice"""
2253 with self.assertRaises(ValueError) as e:
2254 self._DoReadFile('122_entry_expand_twice.dts')
2255 self.assertIn("Image '/binman': Entries changed size after packing",
2258 def testEntryExpandSection(self):
2259 """Test expanding an entry within a section after it is packed"""
2260 data = self._DoReadFile('123_entry_expand_section.dts')
2261 self.assertEqual(b'aaa', data[:3])
2262 self.assertEqual(U_BOOT_DATA, data[3:3 + len(U_BOOT_DATA)])
2263 self.assertEqual(b'aaa', data[-3:])
2265 def testCompressDtb(self):
2266 """Test that compress of device-tree files is supported"""
2268 data = self.data = self._DoReadFileRealDtb('124_compress_dtb.dts')
2269 self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
2270 comp_data = data[len(U_BOOT_DATA):]
2271 orig = self._decompress(comp_data)
2272 dtb = fdt.Fdt.FromData(orig)
2274 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
2276 'u-boot:size': len(U_BOOT_DATA),
2277 'u-boot-dtb:uncomp-size': len(orig),
2278 'u-boot-dtb:size': len(comp_data),
2281 self.assertEqual(expected, props)
2283 def testCbfsUpdateFdt(self):
2284 """Test that we can update the device tree with CBFS offset/size info"""
2286 data, _, _, out_dtb_fname = self._DoReadFileDtb('125_cbfs_update.dts',
2288 dtb = fdt.Fdt(out_dtb_fname)
2290 props = self._GetPropTree(dtb, BASE_DTB_PROPS + ['uncomp-size'])
2291 del props['cbfs/u-boot:size']
2297 'cbfs:size': len(data),
2298 'cbfs:image-pos': 0,
2299 'cbfs/u-boot:offset': 0x38,
2300 'cbfs/u-boot:uncomp-size': len(U_BOOT_DATA),
2301 'cbfs/u-boot:image-pos': 0x38,
2302 'cbfs/u-boot-dtb:offset': 0xb8,
2303 'cbfs/u-boot-dtb:size': len(U_BOOT_DATA),
2304 'cbfs/u-boot-dtb:image-pos': 0xb8,
2307 def testCbfsBadType(self):
2308 """Test an image header with a no specified location is detected"""
2309 with self.assertRaises(ValueError) as e:
2310 self._DoReadFile('126_cbfs_bad_type.dts')
2311 self.assertIn("Unknown cbfs-type 'badtype'", str(e.exception))
2314 """Test listing the files in an image"""
2316 data = self._DoReadFile('127_list.dts')
2317 image = control.images['image']
2318 entries = image.BuildEntryList()
2319 self.assertEqual(7, len(entries))
2322 self.assertEqual(0, ent.indent)
2323 self.assertEqual('main-section', ent.name)
2324 self.assertEqual('section', ent.etype)
2325 self.assertEqual(len(data), ent.size)
2326 self.assertEqual(0, ent.image_pos)
2327 self.assertEqual(None, ent.uncomp_size)
2328 self.assertEqual(0, ent.offset)
2331 self.assertEqual(1, ent.indent)
2332 self.assertEqual('u-boot', ent.name)
2333 self.assertEqual('u-boot', ent.etype)
2334 self.assertEqual(len(U_BOOT_DATA), ent.size)
2335 self.assertEqual(0, ent.image_pos)
2336 self.assertEqual(None, ent.uncomp_size)
2337 self.assertEqual(0, ent.offset)
2340 self.assertEqual(1, ent.indent)
2341 self.assertEqual('section', ent.name)
2342 self.assertEqual('section', ent.etype)
2343 section_size = ent.size
2344 self.assertEqual(0x100, ent.image_pos)
2345 self.assertEqual(None, ent.uncomp_size)
2346 self.assertEqual(0x100, ent.offset)
2349 self.assertEqual(2, ent.indent)
2350 self.assertEqual('cbfs', ent.name)
2351 self.assertEqual('cbfs', ent.etype)
2352 self.assertEqual(0x400, ent.size)
2353 self.assertEqual(0x100, ent.image_pos)
2354 self.assertEqual(None, ent.uncomp_size)
2355 self.assertEqual(0, ent.offset)
2358 self.assertEqual(3, ent.indent)
2359 self.assertEqual('u-boot', ent.name)
2360 self.assertEqual('u-boot', ent.etype)
2361 self.assertEqual(len(U_BOOT_DATA), ent.size)
2362 self.assertEqual(0x138, ent.image_pos)
2363 self.assertEqual(None, ent.uncomp_size)
2364 self.assertEqual(0x38, ent.offset)
2367 self.assertEqual(3, ent.indent)
2368 self.assertEqual('u-boot-dtb', ent.name)
2369 self.assertEqual('text', ent.etype)
2370 self.assertGreater(len(COMPRESS_DATA), ent.size)
2371 self.assertEqual(0x178, ent.image_pos)
2372 self.assertEqual(len(COMPRESS_DATA), ent.uncomp_size)
2373 self.assertEqual(0x78, ent.offset)
2376 self.assertEqual(2, ent.indent)
2377 self.assertEqual('u-boot-dtb', ent.name)
2378 self.assertEqual('u-boot-dtb', ent.etype)
2379 self.assertEqual(0x500, ent.image_pos)
2380 self.assertEqual(len(U_BOOT_DTB_DATA), ent.uncomp_size)
2382 # Compressing this data expands it since headers are added
2383 self.assertGreater(dtb_size, len(U_BOOT_DTB_DATA))
2384 self.assertEqual(0x400, ent.offset)
2386 self.assertEqual(len(data), 0x100 + section_size)
2387 self.assertEqual(section_size, 0x400 + dtb_size)
2389 def testFindFdtmap(self):
2390 """Test locating an FDT map in an image"""
2392 data = self.data = self._DoReadFileRealDtb('128_decode_image.dts')
2393 image = control.images['image']
2394 entries = image.GetEntries()
2395 entry = entries['fdtmap']
2396 self.assertEqual(entry.image_pos, fdtmap.LocateFdtmap(data))
2398 def testFindFdtmapMissing(self):
2399 """Test failing to locate an FDP map"""
2400 data = self._DoReadFile('005_simple.dts')
2401 self.assertEqual(None, fdtmap.LocateFdtmap(data))
2403 def testFindImageHeader(self):
2404 """Test locating a image header"""
2406 data = self.data = self._DoReadFileRealDtb('128_decode_image.dts')
2407 image = control.images['image']
2408 entries = image.GetEntries()
2409 entry = entries['fdtmap']
2410 # The header should point to the FDT map
2411 self.assertEqual(entry.image_pos, image_header.LocateHeaderOffset(data))
2413 def testFindImageHeaderStart(self):
2414 """Test locating a image header located at the start of an image"""
2415 data = self.data = self._DoReadFileRealDtb('117_fdtmap_hdr_start.dts')
2416 image = control.images['image']
2417 entries = image.GetEntries()
2418 entry = entries['fdtmap']
2419 # The header should point to the FDT map
2420 self.assertEqual(entry.image_pos, image_header.LocateHeaderOffset(data))
2422 def testFindImageHeaderMissing(self):
2423 """Test failing to locate an image header"""
2424 data = self._DoReadFile('005_simple.dts')
2425 self.assertEqual(None, image_header.LocateHeaderOffset(data))
2427 def testReadImage(self):
2428 """Test reading an image and accessing its FDT map"""
2430 data = self.data = self._DoReadFileRealDtb('128_decode_image.dts')
2431 image_fname = tools.GetOutputFilename('image.bin')
2432 orig_image = control.images['image']
2433 image = Image.FromFile(image_fname)
2434 self.assertEqual(orig_image.GetEntries().keys(),
2435 image.GetEntries().keys())
2437 orig_entry = orig_image.GetEntries()['fdtmap']
2438 entry = image.GetEntries()['fdtmap']
2439 self.assertEquals(orig_entry.offset, entry.offset)
2440 self.assertEquals(orig_entry.size, entry.size)
2441 self.assertEquals(orig_entry.image_pos, entry.image_pos)
2443 def testReadImageNoHeader(self):
2444 """Test accessing an image's FDT map without an image header"""
2446 data = self._DoReadFileRealDtb('129_decode_image_nohdr.dts')
2447 image_fname = tools.GetOutputFilename('image.bin')
2448 image = Image.FromFile(image_fname)
2449 self.assertTrue(isinstance(image, Image))
2450 self.assertEqual('image', image.image_name[-5:])
2452 def testReadImageFail(self):
2453 """Test failing to read an image image's FDT map"""
2454 self._DoReadFile('005_simple.dts')
2455 image_fname = tools.GetOutputFilename('image.bin')
2456 with self.assertRaises(ValueError) as e:
2457 image = Image.FromFile(image_fname)
2458 self.assertIn("Cannot find FDT map in image", str(e.exception))
2460 def testListCmd(self):
2461 """Test listing the files in an image using an Fdtmap"""
2463 data = self._DoReadFileRealDtb('130_list_fdtmap.dts')
2465 # lz4 compression size differs depending on the version
2466 image = control.images['image']
2467 entries = image.GetEntries()
2468 section_size = entries['section'].size
2469 fdt_size = entries['section'].GetEntries()['u-boot-dtb'].size
2470 fdtmap_offset = entries['fdtmap'].offset
2473 tmpdir, updated_fname = self._SetupImageInTmpdir()
2474 with test_util.capture_sys_output() as (stdout, stderr):
2475 self._DoBinman('ls', '-i', updated_fname)
2477 shutil.rmtree(tmpdir)
2478 lines = stdout.getvalue().splitlines()
2480 'Name Image-pos Size Entry-type Offset Uncomp-size',
2481 '----------------------------------------------------------------------',
2482 'main-section 0 c00 section 0',
2483 ' u-boot 0 4 u-boot 0',
2484 ' section 100 %x section 100' % section_size,
2485 ' cbfs 100 400 cbfs 0',
2486 ' u-boot 138 4 u-boot 38',
2487 ' u-boot-dtb 180 105 u-boot-dtb 80 3c9',
2488 ' u-boot-dtb 500 %x u-boot-dtb 400 3c9' % fdt_size,
2489 ' fdtmap %x 3bd fdtmap %x' %
2490 (fdtmap_offset, fdtmap_offset),
2491 ' image-header bf8 8 image-header bf8',
2493 self.assertEqual(expected, lines)
2495 def testListCmdFail(self):
2496 """Test failing to list an image"""
2497 self._DoReadFile('005_simple.dts')
2499 tmpdir, updated_fname = self._SetupImageInTmpdir()
2500 with self.assertRaises(ValueError) as e:
2501 self._DoBinman('ls', '-i', updated_fname)
2503 shutil.rmtree(tmpdir)
2504 self.assertIn("Cannot find FDT map in image", str(e.exception))
2506 def _RunListCmd(self, paths, expected):
2507 """List out entries and check the result
2510 paths: List of paths to pass to the list command
2511 expected: Expected list of filenames to be returned, in order
2514 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2515 image_fname = tools.GetOutputFilename('image.bin')
2516 image = Image.FromFile(image_fname)
2517 lines = image.GetListEntries(paths)[1]
2518 files = [line[0].strip() for line in lines[1:]]
2519 self.assertEqual(expected, files)
2521 def testListCmdSection(self):
2522 """Test listing the files in a section"""
2523 self._RunListCmd(['section'],
2524 ['section', 'cbfs', 'u-boot', 'u-boot-dtb', 'u-boot-dtb'])
2526 def testListCmdFile(self):
2527 """Test listing a particular file"""
2528 self._RunListCmd(['*u-boot-dtb'], ['u-boot-dtb', 'u-boot-dtb'])
2530 def testListCmdWildcard(self):
2531 """Test listing a wildcarded file"""
2532 self._RunListCmd(['*boot*'],
2533 ['u-boot', 'u-boot', 'u-boot-dtb', 'u-boot-dtb'])
2535 def testListCmdWildcardMulti(self):
2536 """Test listing a wildcarded file"""
2537 self._RunListCmd(['*cb*', '*head*'],
2538 ['cbfs', 'u-boot', 'u-boot-dtb', 'image-header'])
2540 def testListCmdEmpty(self):
2541 """Test listing a wildcarded file"""
2542 self._RunListCmd(['nothing'], [])
2544 def testListCmdPath(self):
2545 """Test listing the files in a sub-entry of a section"""
2546 self._RunListCmd(['section/cbfs'], ['cbfs', 'u-boot', 'u-boot-dtb'])
2548 def _RunExtractCmd(self, entry_name, decomp=True):
2549 """Extract an entry from an image
2552 entry_name: Entry name to extract
2553 decomp: True to decompress the data if compressed, False to leave
2554 it in its raw uncompressed format
2560 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2561 image_fname = tools.GetOutputFilename('image.bin')
2562 return control.ReadEntry(image_fname, entry_name, decomp)
2564 def testExtractSimple(self):
2565 """Test extracting a single file"""
2566 data = self._RunExtractCmd('u-boot')
2567 self.assertEqual(U_BOOT_DATA, data)
2569 def testExtractSection(self):
2570 """Test extracting the files in a section"""
2571 data = self._RunExtractCmd('section')
2572 cbfs_data = data[:0x400]
2573 cbfs = cbfs_util.CbfsReader(cbfs_data)
2574 self.assertEqual(['u-boot', 'u-boot-dtb', ''], list(cbfs.files.keys()))
2575 dtb_data = data[0x400:]
2576 dtb = self._decompress(dtb_data)
2577 self.assertEqual(EXTRACT_DTB_SIZE, len(dtb))
2579 def testExtractCompressed(self):
2580 """Test extracting compressed data"""
2581 data = self._RunExtractCmd('section/u-boot-dtb')
2582 self.assertEqual(EXTRACT_DTB_SIZE, len(data))
2584 def testExtractRaw(self):
2585 """Test extracting compressed data without decompressing it"""
2586 data = self._RunExtractCmd('section/u-boot-dtb', decomp=False)
2587 dtb = self._decompress(data)
2588 self.assertEqual(EXTRACT_DTB_SIZE, len(dtb))
2590 def testExtractCbfs(self):
2591 """Test extracting CBFS data"""
2592 data = self._RunExtractCmd('section/cbfs/u-boot')
2593 self.assertEqual(U_BOOT_DATA, data)
2595 def testExtractCbfsCompressed(self):
2596 """Test extracting CBFS compressed data"""
2597 data = self._RunExtractCmd('section/cbfs/u-boot-dtb')
2598 self.assertEqual(EXTRACT_DTB_SIZE, len(data))
2600 def testExtractCbfsRaw(self):
2601 """Test extracting CBFS compressed data without decompressing it"""
2602 data = self._RunExtractCmd('section/cbfs/u-boot-dtb', decomp=False)
2603 dtb = tools.Decompress(data, 'lzma', with_header=False)
2604 self.assertEqual(EXTRACT_DTB_SIZE, len(dtb))
2606 def testExtractBadEntry(self):
2607 """Test extracting a bad section path"""
2608 with self.assertRaises(ValueError) as e:
2609 self._RunExtractCmd('section/does-not-exist')
2610 self.assertIn("Entry 'does-not-exist' not found in '/section'",
2613 def testExtractMissingFile(self):
2614 """Test extracting file that does not exist"""
2615 with self.assertRaises(IOError) as e:
2616 control.ReadEntry('missing-file', 'name')
2618 def testExtractBadFile(self):
2619 """Test extracting an invalid file"""
2620 fname = os.path.join(self._indir, 'badfile')
2621 tools.WriteFile(fname, b'')
2622 with self.assertRaises(ValueError) as e:
2623 control.ReadEntry(fname, 'name')
2625 def testExtractCmd(self):
2626 """Test extracting a file fron an image on the command line"""
2628 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2629 fname = os.path.join(self._indir, 'output.extact')
2631 tmpdir, updated_fname = self._SetupImageInTmpdir()
2632 with test_util.capture_sys_output() as (stdout, stderr):
2633 self._DoBinman('extract', '-i', updated_fname, 'u-boot',
2636 shutil.rmtree(tmpdir)
2637 data = tools.ReadFile(fname)
2638 self.assertEqual(U_BOOT_DATA, data)
2640 def testExtractOneEntry(self):
2641 """Test extracting a single entry fron an image """
2643 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2644 image_fname = tools.GetOutputFilename('image.bin')
2645 fname = os.path.join(self._indir, 'output.extact')
2646 control.ExtractEntries(image_fname, fname, None, ['u-boot'])
2647 data = tools.ReadFile(fname)
2648 self.assertEqual(U_BOOT_DATA, data)
2650 def _CheckExtractOutput(self, decomp):
2651 """Helper to test file output with and without decompression
2654 decomp: True to decompress entry data, False to output it raw
2656 def _CheckPresent(entry_path, expect_data, expect_size=None):
2657 """Check and remove expected file
2659 This checks the data/size of a file and removes the file both from
2660 the outfiles set and from the output directory. Once all files are
2661 processed, both the set and directory should be empty.
2664 entry_path: Entry path
2665 expect_data: Data to expect in file, or None to skip check
2666 expect_size: Size of data to expect in file, or None to skip
2668 path = os.path.join(outdir, entry_path)
2669 data = tools.ReadFile(path)
2672 self.assertEqual(expect_data, data)
2674 self.assertEqual(expect_size, len(data))
2675 outfiles.remove(path)
2677 def _CheckDirPresent(name):
2678 """Remove expected directory
2680 This gives an error if the directory does not exist as expected
2683 name: Name of directory to remove
2685 path = os.path.join(outdir, name)
2688 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2689 image_fname = tools.GetOutputFilename('image.bin')
2690 outdir = os.path.join(self._indir, 'extract')
2691 einfos = control.ExtractEntries(image_fname, None, outdir, [], decomp)
2693 # Create a set of all file that were output (should be 9)
2695 for root, dirs, files in os.walk(outdir):
2696 outfiles |= set([os.path.join(root, fname) for fname in files])
2697 self.assertEqual(9, len(outfiles))
2698 self.assertEqual(9, len(einfos))
2700 image = control.images['image']
2701 entries = image.GetEntries()
2703 # Check the 9 files in various ways
2704 section = entries['section']
2705 section_entries = section.GetEntries()
2706 cbfs_entries = section_entries['cbfs'].GetEntries()
2707 _CheckPresent('u-boot', U_BOOT_DATA)
2708 _CheckPresent('section/cbfs/u-boot', U_BOOT_DATA)
2709 dtb_len = EXTRACT_DTB_SIZE
2711 dtb_len = cbfs_entries['u-boot-dtb'].size
2712 _CheckPresent('section/cbfs/u-boot-dtb', None, dtb_len)
2714 dtb_len = section_entries['u-boot-dtb'].size
2715 _CheckPresent('section/u-boot-dtb', None, dtb_len)
2717 fdtmap = entries['fdtmap']
2718 _CheckPresent('fdtmap', fdtmap.data)
2719 hdr = entries['image-header']
2720 _CheckPresent('image-header', hdr.data)
2722 _CheckPresent('section/root', section.data)
2723 cbfs = section_entries['cbfs']
2724 _CheckPresent('section/cbfs/root', cbfs.data)
2725 data = tools.ReadFile(image_fname)
2726 _CheckPresent('root', data)
2728 # There should be no files left. Remove all the directories to check.
2729 # If there are any files/dirs remaining, one of these checks will fail.
2730 self.assertEqual(0, len(outfiles))
2731 _CheckDirPresent('section/cbfs')
2732 _CheckDirPresent('section')
2733 _CheckDirPresent('')
2734 self.assertFalse(os.path.exists(outdir))
2736 def testExtractAllEntries(self):
2737 """Test extracting all entries"""
2739 self._CheckExtractOutput(decomp=True)
2741 def testExtractAllEntriesRaw(self):
2742 """Test extracting all entries without decompressing them"""
2744 self._CheckExtractOutput(decomp=False)
2746 def testExtractSelectedEntries(self):
2747 """Test extracting some entries"""
2749 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2750 image_fname = tools.GetOutputFilename('image.bin')
2751 outdir = os.path.join(self._indir, 'extract')
2752 einfos = control.ExtractEntries(image_fname, None, outdir,
2755 # File output is tested by testExtractAllEntries(), so just check that
2756 # the expected entries are selected
2757 names = [einfo.name for einfo in einfos]
2758 self.assertEqual(names,
2759 ['cbfs', 'u-boot', 'u-boot-dtb', 'image-header'])
2761 def testExtractNoEntryPaths(self):
2762 """Test extracting some entries"""
2764 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2765 image_fname = tools.GetOutputFilename('image.bin')
2766 with self.assertRaises(ValueError) as e:
2767 control.ExtractEntries(image_fname, 'fname', None, [])
2768 self.assertIn('Must specify an entry path to write with -f',
2771 def testExtractTooManyEntryPaths(self):
2772 """Test extracting some entries"""
2774 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2775 image_fname = tools.GetOutputFilename('image.bin')
2776 with self.assertRaises(ValueError) as e:
2777 control.ExtractEntries(image_fname, 'fname', None, ['a', 'b'])
2778 self.assertIn('Must specify exactly one entry path to write with -f',
2781 def testPackAlignSection(self):
2782 """Test that sections can have alignment"""
2783 self._DoReadFile('131_pack_align_section.dts')
2785 self.assertIn('image', control.images)
2786 image = control.images['image']
2787 entries = image.GetEntries()
2788 self.assertEqual(3, len(entries))
2791 self.assertIn('u-boot', entries)
2792 entry = entries['u-boot']
2793 self.assertEqual(0, entry.offset)
2794 self.assertEqual(0, entry.image_pos)
2795 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2796 self.assertEqual(len(U_BOOT_DATA), entry.size)
2799 self.assertIn('section0', entries)
2800 section0 = entries['section0']
2801 self.assertEqual(0x10, section0.offset)
2802 self.assertEqual(0x10, section0.image_pos)
2803 self.assertEqual(len(U_BOOT_DATA), section0.size)
2806 section_entries = section0.GetEntries()
2807 self.assertIn('u-boot', section_entries)
2808 entry = section_entries['u-boot']
2809 self.assertEqual(0, entry.offset)
2810 self.assertEqual(0x10, entry.image_pos)
2811 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2812 self.assertEqual(len(U_BOOT_DATA), entry.size)
2815 self.assertIn('section1', entries)
2816 section1 = entries['section1']
2817 self.assertEqual(0x14, section1.offset)
2818 self.assertEqual(0x14, section1.image_pos)
2819 self.assertEqual(0x20, section1.size)
2822 section_entries = section1.GetEntries()
2823 self.assertIn('u-boot', section_entries)
2824 entry = section_entries['u-boot']
2825 self.assertEqual(0, entry.offset)
2826 self.assertEqual(0x14, entry.image_pos)
2827 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2828 self.assertEqual(len(U_BOOT_DATA), entry.size)
2831 self.assertIn('section2', section_entries)
2832 section2 = section_entries['section2']
2833 self.assertEqual(0x4, section2.offset)
2834 self.assertEqual(0x18, section2.image_pos)
2835 self.assertEqual(4, section2.size)
2838 section_entries = section2.GetEntries()
2839 self.assertIn('u-boot', section_entries)
2840 entry = section_entries['u-boot']
2841 self.assertEqual(0, entry.offset)
2842 self.assertEqual(0x18, entry.image_pos)
2843 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2844 self.assertEqual(len(U_BOOT_DATA), entry.size)
2846 def _RunReplaceCmd(self, entry_name, data, decomp=True, allow_resize=True,
2847 dts='132_replace.dts'):
2848 """Replace an entry in an image
2850 This writes the entry data to update it, then opens the updated file and
2851 returns the value that it now finds there.
2854 entry_name: Entry name to replace
2855 data: Data to replace it with
2856 decomp: True to compress the data if needed, False if data is
2857 already compressed so should be used as is
2858 allow_resize: True to allow entries to change size, False to raise
2864 data from fdtmap (excluding header)
2865 Image object that was modified
2867 dtb_data = self._DoReadFileDtb(dts, use_real_dtb=True,
2870 self.assertIn('image', control.images)
2871 image = control.images['image']
2872 entries = image.GetEntries()
2873 orig_dtb_data = entries['u-boot-dtb'].data
2874 orig_fdtmap_data = entries['fdtmap'].data
2876 image_fname = tools.GetOutputFilename('image.bin')
2877 updated_fname = tools.GetOutputFilename('image-updated.bin')
2878 tools.WriteFile(updated_fname, tools.ReadFile(image_fname))
2879 image = control.WriteEntry(updated_fname, entry_name, data, decomp,
2881 data = control.ReadEntry(updated_fname, entry_name, decomp)
2883 # The DT data should not change unless resized:
2884 if not allow_resize:
2885 new_dtb_data = entries['u-boot-dtb'].data
2886 self.assertEqual(new_dtb_data, orig_dtb_data)
2887 new_fdtmap_data = entries['fdtmap'].data
2888 self.assertEqual(new_fdtmap_data, orig_fdtmap_data)
2890 return data, orig_fdtmap_data[fdtmap.FDTMAP_HDR_LEN:], image
2892 def testReplaceSimple(self):
2893 """Test replacing a single file"""
2894 expected = b'x' * len(U_BOOT_DATA)
2895 data, expected_fdtmap, _ = self._RunReplaceCmd('u-boot', expected,
2897 self.assertEqual(expected, data)
2899 # Test that the state looks right. There should be an FDT for the fdtmap
2900 # that we jsut read back in, and it should match what we find in the
2901 # 'control' tables. Checking for an FDT that does not exist should
2903 path, fdtmap = state.GetFdtContents('fdtmap')
2904 self.assertIsNotNone(path)
2905 self.assertEqual(expected_fdtmap, fdtmap)
2907 dtb = state.GetFdtForEtype('fdtmap')
2908 self.assertEqual(dtb.GetContents(), fdtmap)
2910 missing_path, missing_fdtmap = state.GetFdtContents('missing')
2911 self.assertIsNone(missing_path)
2912 self.assertIsNone(missing_fdtmap)
2914 missing_dtb = state.GetFdtForEtype('missing')
2915 self.assertIsNone(missing_dtb)
2917 self.assertEqual('/binman', state.fdt_path_prefix)
2919 def testReplaceResizeFail(self):
2920 """Test replacing a file by something larger"""
2921 expected = U_BOOT_DATA + b'x'
2922 with self.assertRaises(ValueError) as e:
2923 self._RunReplaceCmd('u-boot', expected, allow_resize=False,
2924 dts='139_replace_repack.dts')
2925 self.assertIn("Node '/u-boot': Entry data size does not match, but resize is disabled",
2928 def testReplaceMulti(self):
2929 """Test replacing entry data where multiple images are generated"""
2930 data = self._DoReadFileDtb('133_replace_multi.dts', use_real_dtb=True,
2932 expected = b'x' * len(U_BOOT_DATA)
2933 updated_fname = tools.GetOutputFilename('image-updated.bin')
2934 tools.WriteFile(updated_fname, data)
2935 entry_name = 'u-boot'
2936 control.WriteEntry(updated_fname, entry_name, expected,
2938 data = control.ReadEntry(updated_fname, entry_name)
2939 self.assertEqual(expected, data)
2941 # Check the state looks right.
2942 self.assertEqual('/binman/image', state.fdt_path_prefix)
2944 # Now check we can write the first image
2945 image_fname = tools.GetOutputFilename('first-image.bin')
2946 updated_fname = tools.GetOutputFilename('first-updated.bin')
2947 tools.WriteFile(updated_fname, tools.ReadFile(image_fname))
2948 entry_name = 'u-boot'
2949 control.WriteEntry(updated_fname, entry_name, expected,
2951 data = control.ReadEntry(updated_fname, entry_name)
2952 self.assertEqual(expected, data)
2954 # Check the state looks right.
2955 self.assertEqual('/binman/first-image', state.fdt_path_prefix)
2957 def testUpdateFdtAllRepack(self):
2958 """Test that all device trees are updated with offset/size info"""
2959 data = self._DoReadFileRealDtb('134_fdt_update_all_repack.dts')
2960 SECTION_SIZE = 0x300
2965 'size': SECTION_SIZE + DTB_SIZE * 2 + FDTMAP_SIZE,
2967 'section:offset': 0,
2968 'section:size': SECTION_SIZE,
2969 'section:image-pos': 0,
2970 'section/u-boot-dtb:offset': 4,
2971 'section/u-boot-dtb:size': 636,
2972 'section/u-boot-dtb:image-pos': 4,
2973 'u-boot-spl-dtb:offset': SECTION_SIZE,
2974 'u-boot-spl-dtb:size': DTB_SIZE,
2975 'u-boot-spl-dtb:image-pos': SECTION_SIZE,
2976 'u-boot-tpl-dtb:offset': SECTION_SIZE + DTB_SIZE,
2977 'u-boot-tpl-dtb:image-pos': SECTION_SIZE + DTB_SIZE,
2978 'u-boot-tpl-dtb:size': DTB_SIZE,
2979 'fdtmap:offset': SECTION_SIZE + DTB_SIZE * 2,
2980 'fdtmap:size': FDTMAP_SIZE,
2981 'fdtmap:image-pos': SECTION_SIZE + DTB_SIZE * 2,
2984 'section:orig-size': SECTION_SIZE,
2985 'section/u-boot-dtb:orig-offset': 4,
2988 # We expect three device-tree files in the output, with the first one
2989 # within a fixed-size section.
2990 # Read them in sequence. We look for an 'spl' property in the SPL tree,
2991 # and 'tpl' in the TPL tree, to make sure they are distinct from the
2992 # main U-Boot tree. All three should have the same positions and offset
2993 # except that the main tree should include the main_expected properties
2995 for item in ['', 'spl', 'tpl', None]:
2997 start += 16 # Move past fdtmap header
2998 dtb = fdt.Fdt.FromData(data[start:])
3000 props = self._GetPropTree(dtb,
3001 BASE_DTB_PROPS + REPACK_DTB_PROPS + ['spl', 'tpl'],
3002 prefix='/' if item is None else '/binman/')
3003 expected = dict(base_expected)
3007 # Main DTB and fdtdec should include the 'orig-' properties
3008 expected.update(main_expected)
3009 # Helpful for debugging:
3010 #for prop in sorted(props):
3011 #print('prop %s %s %s' % (prop, props[prop], expected[prop]))
3012 self.assertEqual(expected, props)
3014 start = SECTION_SIZE
3016 start += dtb._fdt_obj.totalsize()
3018 def testFdtmapHeaderMiddle(self):
3019 """Test an FDT map in the middle of an image when it should be at end"""
3020 with self.assertRaises(ValueError) as e:
3021 self._DoReadFileRealDtb('135_fdtmap_hdr_middle.dts')
3022 self.assertIn("Invalid sibling order 'middle' for image-header: Must be at 'end' to match location",
3025 def testFdtmapHeaderStartBad(self):
3026 """Test an FDT map in middle of an image when it should be at start"""
3027 with self.assertRaises(ValueError) as e:
3028 self._DoReadFileRealDtb('136_fdtmap_hdr_startbad.dts')
3029 self.assertIn("Invalid sibling order 'end' for image-header: Must be at 'start' to match location",
3032 def testFdtmapHeaderEndBad(self):
3033 """Test an FDT map at the start of an image when it should be at end"""
3034 with self.assertRaises(ValueError) as e:
3035 self._DoReadFileRealDtb('137_fdtmap_hdr_endbad.dts')
3036 self.assertIn("Invalid sibling order 'start' for image-header: Must be at 'end' to match location",
3039 def testFdtmapHeaderNoSize(self):
3040 """Test an image header at the end of an image with undefined size"""
3041 self._DoReadFileRealDtb('138_fdtmap_hdr_nosize.dts')
3043 def testReplaceResize(self):
3044 """Test replacing a single file in an entry with a larger file"""
3045 expected = U_BOOT_DATA + b'x'
3046 data, _, image = self._RunReplaceCmd('u-boot', expected,
3047 dts='139_replace_repack.dts')
3048 self.assertEqual(expected, data)
3050 entries = image.GetEntries()
3051 dtb_data = entries['u-boot-dtb'].data
3052 dtb = fdt.Fdt.FromData(dtb_data)
3055 # The u-boot section should now be larger in the dtb
3056 node = dtb.GetNode('/binman/u-boot')
3057 self.assertEqual(len(expected), fdt_util.GetInt(node, 'size'))
3059 # Same for the fdtmap
3060 fdata = entries['fdtmap'].data
3061 fdtb = fdt.Fdt.FromData(fdata[fdtmap.FDTMAP_HDR_LEN:])
3063 fnode = fdtb.GetNode('/u-boot')
3064 self.assertEqual(len(expected), fdt_util.GetInt(fnode, 'size'))
3066 def testReplaceResizeNoRepack(self):
3067 """Test replacing an entry with a larger file when not allowed"""
3068 expected = U_BOOT_DATA + b'x'
3069 with self.assertRaises(ValueError) as e:
3070 self._RunReplaceCmd('u-boot', expected)
3071 self.assertIn('Entry data size does not match, but allow-repack is not present for this image',
3074 def testEntryShrink(self):
3075 """Test contracting an entry after it is packed"""
3077 state.SetAllowEntryContraction(True)
3078 data = self._DoReadFileDtb('140_entry_shrink.dts',
3081 state.SetAllowEntryContraction(False)
3082 self.assertEqual(b'a', data[:1])
3083 self.assertEqual(U_BOOT_DATA, data[1:1 + len(U_BOOT_DATA)])
3084 self.assertEqual(b'a', data[-1:])
3086 def testEntryShrinkFail(self):
3087 """Test not being allowed to contract an entry after it is packed"""
3088 data = self._DoReadFileDtb('140_entry_shrink.dts', update_dtb=True)[0]
3090 # In this case there is a spare byte at the end of the data. The size of
3091 # the contents is only 1 byte but we still have the size before it
3093 self.assertEqual(b'a\0', data[:2])
3094 self.assertEqual(U_BOOT_DATA, data[2:2 + len(U_BOOT_DATA)])
3095 self.assertEqual(b'a\0', data[-2:])
3097 def testDescriptorOffset(self):
3098 """Test that the Intel descriptor is always placed at at the start"""
3099 data = self._DoReadFileDtb('141_descriptor_offset.dts')
3100 image = control.images['image']
3101 entries = image.GetEntries()
3102 desc = entries['intel-descriptor']
3103 self.assertEqual(0xff800000, desc.offset);
3104 self.assertEqual(0xff800000, desc.image_pos);
3106 def testReplaceCbfs(self):
3107 """Test replacing a single file in CBFS without changing the size"""
3109 expected = b'x' * len(U_BOOT_DATA)
3110 data = self._DoReadFileRealDtb('142_replace_cbfs.dts')
3111 updated_fname = tools.GetOutputFilename('image-updated.bin')
3112 tools.WriteFile(updated_fname, data)
3113 entry_name = 'section/cbfs/u-boot'
3114 control.WriteEntry(updated_fname, entry_name, expected,
3116 data = control.ReadEntry(updated_fname, entry_name)
3117 self.assertEqual(expected, data)
3119 def testReplaceResizeCbfs(self):
3120 """Test replacing a single file in CBFS with one of a different size"""
3122 expected = U_BOOT_DATA + b'x'
3123 data = self._DoReadFileRealDtb('142_replace_cbfs.dts')
3124 updated_fname = tools.GetOutputFilename('image-updated.bin')
3125 tools.WriteFile(updated_fname, data)
3126 entry_name = 'section/cbfs/u-boot'
3127 control.WriteEntry(updated_fname, entry_name, expected,
3129 data = control.ReadEntry(updated_fname, entry_name)
3130 self.assertEqual(expected, data)
3132 def _SetupForReplace(self):
3133 """Set up some files to use to replace entries
3135 This generates an image, copies it to a new file, extracts all the files
3136 in it and updates some of them
3142 Expected values for updated entries, each a string
3144 data = self._DoReadFileRealDtb('143_replace_all.dts')
3146 updated_fname = tools.GetOutputFilename('image-updated.bin')
3147 tools.WriteFile(updated_fname, data)
3149 outdir = os.path.join(self._indir, 'extract')
3150 einfos = control.ExtractEntries(updated_fname, None, outdir, [])
3152 expected1 = b'x' + U_BOOT_DATA + b'y'
3153 u_boot_fname1 = os.path.join(outdir, 'u-boot')
3154 tools.WriteFile(u_boot_fname1, expected1)
3156 expected2 = b'a' + U_BOOT_DATA + b'b'
3157 u_boot_fname2 = os.path.join(outdir, 'u-boot2')
3158 tools.WriteFile(u_boot_fname2, expected2)
3160 expected_text = b'not the same text'
3161 text_fname = os.path.join(outdir, 'text')
3162 tools.WriteFile(text_fname, expected_text)
3164 dtb_fname = os.path.join(outdir, 'u-boot-dtb')
3165 dtb = fdt.FdtScan(dtb_fname)
3166 node = dtb.GetNode('/binman/text')
3167 node.AddString('my-property', 'the value')
3168 dtb.Sync(auto_resize=True)
3171 return updated_fname, outdir, expected1, expected2, expected_text
3173 def _CheckReplaceMultiple(self, entry_paths):
3174 """Handle replacing the contents of multiple entries
3177 entry_paths: List of entry paths to replace
3181 Dict of entries in the image:
3184 Expected values for updated entries, each a string
3186 updated_fname, outdir, expected1, expected2, expected_text = (
3187 self._SetupForReplace())
3188 control.ReplaceEntries(updated_fname, None, outdir, entry_paths)
3190 image = Image.FromFile(updated_fname)
3192 return image.GetEntries(), expected1, expected2, expected_text
3194 def testReplaceAll(self):
3195 """Test replacing the contents of all entries"""
3196 entries, expected1, expected2, expected_text = (
3197 self._CheckReplaceMultiple([]))
3198 data = entries['u-boot'].data
3199 self.assertEqual(expected1, data)
3201 data = entries['u-boot2'].data
3202 self.assertEqual(expected2, data)
3204 data = entries['text'].data
3205 self.assertEqual(expected_text, data)
3207 # Check that the device tree is updated
3208 data = entries['u-boot-dtb'].data
3209 dtb = fdt.Fdt.FromData(data)
3211 node = dtb.GetNode('/binman/text')
3212 self.assertEqual('the value', node.props['my-property'].value)
3214 def testReplaceSome(self):
3215 """Test replacing the contents of a few entries"""
3216 entries, expected1, expected2, expected_text = (
3217 self._CheckReplaceMultiple(['u-boot2', 'text']))
3219 # This one should not change
3220 data = entries['u-boot'].data
3221 self.assertEqual(U_BOOT_DATA, data)
3223 data = entries['u-boot2'].data
3224 self.assertEqual(expected2, data)
3226 data = entries['text'].data
3227 self.assertEqual(expected_text, data)
3229 def testReplaceCmd(self):
3230 """Test replacing a file fron an image on the command line"""
3231 self._DoReadFileRealDtb('143_replace_all.dts')
3234 tmpdir, updated_fname = self._SetupImageInTmpdir()
3236 fname = os.path.join(tmpdir, 'update-u-boot.bin')
3237 expected = b'x' * len(U_BOOT_DATA)
3238 tools.WriteFile(fname, expected)
3240 self._DoBinman('replace', '-i', updated_fname, 'u-boot', '-f', fname)
3241 data = tools.ReadFile(updated_fname)
3242 self.assertEqual(expected, data[:len(expected)])
3243 map_fname = os.path.join(tmpdir, 'image-updated.map')
3244 self.assertFalse(os.path.exists(map_fname))
3246 shutil.rmtree(tmpdir)
3248 def testReplaceCmdSome(self):
3249 """Test replacing some files fron an image on the command line"""
3250 updated_fname, outdir, expected1, expected2, expected_text = (
3251 self._SetupForReplace())
3253 self._DoBinman('replace', '-i', updated_fname, '-I', outdir,
3256 tools.PrepareOutputDir(None)
3257 image = Image.FromFile(updated_fname)
3259 entries = image.GetEntries()
3261 # This one should not change
3262 data = entries['u-boot'].data
3263 self.assertEqual(U_BOOT_DATA, data)
3265 data = entries['u-boot2'].data
3266 self.assertEqual(expected2, data)
3268 data = entries['text'].data
3269 self.assertEqual(expected_text, data)
3271 def testReplaceMissing(self):
3272 """Test replacing entries where the file is missing"""
3273 updated_fname, outdir, expected1, expected2, expected_text = (
3274 self._SetupForReplace())
3276 # Remove one of the files, to generate a warning
3277 u_boot_fname1 = os.path.join(outdir, 'u-boot')
3278 os.remove(u_boot_fname1)
3280 with test_util.capture_sys_output() as (stdout, stderr):
3281 control.ReplaceEntries(updated_fname, None, outdir, [])
3282 self.assertIn("Skipping entry '/u-boot' from missing file",
3285 def testReplaceCmdMap(self):
3286 """Test replacing a file fron an image on the command line"""
3287 self._DoReadFileRealDtb('143_replace_all.dts')
3290 tmpdir, updated_fname = self._SetupImageInTmpdir()
3292 fname = os.path.join(self._indir, 'update-u-boot.bin')
3293 expected = b'x' * len(U_BOOT_DATA)
3294 tools.WriteFile(fname, expected)
3296 self._DoBinman('replace', '-i', updated_fname, 'u-boot',
3298 map_fname = os.path.join(tmpdir, 'image-updated.map')
3299 self.assertTrue(os.path.exists(map_fname))
3301 shutil.rmtree(tmpdir)
3303 def testReplaceNoEntryPaths(self):
3304 """Test replacing an entry without an entry path"""
3305 self._DoReadFileRealDtb('143_replace_all.dts')
3306 image_fname = tools.GetOutputFilename('image.bin')
3307 with self.assertRaises(ValueError) as e:
3308 control.ReplaceEntries(image_fname, 'fname', None, [])
3309 self.assertIn('Must specify an entry path to read with -f',
3312 def testReplaceTooManyEntryPaths(self):
3313 """Test extracting some entries"""
3314 self._DoReadFileRealDtb('143_replace_all.dts')
3315 image_fname = tools.GetOutputFilename('image.bin')
3316 with self.assertRaises(ValueError) as e:
3317 control.ReplaceEntries(image_fname, 'fname', None, ['a', 'b'])
3318 self.assertIn('Must specify exactly one entry path to write with -f',
3321 def testPackReset16(self):
3322 """Test that an image with an x86 reset16 region can be created"""
3323 data = self._DoReadFile('144_x86_reset16.dts')
3324 self.assertEqual(X86_RESET16_DATA, data[:len(X86_RESET16_DATA)])
3326 def testPackReset16Spl(self):
3327 """Test that an image with an x86 reset16-spl region can be created"""
3328 data = self._DoReadFile('145_x86_reset16_spl.dts')
3329 self.assertEqual(X86_RESET16_SPL_DATA, data[:len(X86_RESET16_SPL_DATA)])
3331 def testPackReset16Tpl(self):
3332 """Test that an image with an x86 reset16-tpl region can be created"""
3333 data = self._DoReadFile('146_x86_reset16_tpl.dts')
3334 self.assertEqual(X86_RESET16_TPL_DATA, data[:len(X86_RESET16_TPL_DATA)])
3336 def testPackIntelFit(self):
3337 """Test that an image with an Intel FIT and pointer can be created"""
3338 data = self._DoReadFile('147_intel_fit.dts')
3339 self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
3341 self.assertEqual(b'_FIT_ \x01\x00\x00\x00\x00\x01\x80}' , fit)
3342 ptr = struct.unpack('<i', data[0x40:0x44])[0]
3344 image = control.images['image']
3345 entries = image.GetEntries()
3346 expected_ptr = entries['intel-fit'].image_pos - (1 << 32)
3347 self.assertEqual(expected_ptr, ptr)
3349 def testPackIntelFitMissing(self):
3350 """Test detection of a FIT pointer with not FIT region"""
3351 with self.assertRaises(ValueError) as e:
3352 self._DoReadFile('148_intel_fit_missing.dts')
3353 self.assertIn("'intel-fit-ptr' section must have an 'intel-fit' sibling",
3356 def _CheckSymbolsTplSection(self, dts, expected_vals):
3357 data = self._DoReadFile(dts)
3358 sym_values = struct.pack('<LQLL', *expected_vals)
3359 upto1 = 4 + len(U_BOOT_SPL_DATA)
3360 expected1 = tools.GetBytes(0xff, 4) + sym_values + U_BOOT_SPL_DATA[20:]
3361 self.assertEqual(expected1, data[:upto1])
3363 upto2 = upto1 + 1 + len(U_BOOT_SPL_DATA)
3364 expected2 = tools.GetBytes(0xff, 1) + sym_values + U_BOOT_SPL_DATA[20:]
3365 self.assertEqual(expected2, data[upto1:upto2])
3367 upto3 = 0x34 + len(U_BOOT_DATA)
3368 expected3 = tools.GetBytes(0xff, 1) + U_BOOT_DATA
3369 self.assertEqual(expected3, data[upto2:upto3])
3371 expected4 = sym_values + U_BOOT_TPL_DATA[20:]
3372 self.assertEqual(expected4, data[upto3:upto3 + len(U_BOOT_TPL_DATA)])
3374 def testSymbolsTplSection(self):
3375 """Test binman can assign symbols embedded in U-Boot TPL in a section"""
3376 self._SetupSplElf('u_boot_binman_syms')
3377 self._SetupTplElf('u_boot_binman_syms')
3378 self._CheckSymbolsTplSection('149_symbols_tpl.dts',
3379 [0x04, 0x1c, 0x10 + 0x34, 0x04])
3381 def testSymbolsTplSectionX86(self):
3382 """Test binman can assign symbols in a section with end-at-4gb"""
3383 self._SetupSplElf('u_boot_binman_syms_x86')
3384 self._SetupTplElf('u_boot_binman_syms_x86')
3385 self._CheckSymbolsTplSection('155_symbols_tpl_x86.dts',
3386 [0xffffff04, 0xffffff1c, 0xffffff34,
3389 def testPackX86RomIfwiSectiom(self):
3390 """Test that a section can be placed in an IFWI region"""
3391 self._SetupIfwi('fitimage.bin')
3392 data = self._DoReadFile('151_x86_rom_ifwi_section.dts')
3393 self._CheckIfwi(data)
3395 def testPackFspM(self):
3396 """Test that an image with a FSP memory-init binary can be created"""
3397 data = self._DoReadFile('152_intel_fsp_m.dts')
3398 self.assertEqual(FSP_M_DATA, data[:len(FSP_M_DATA)])
3400 def testPackFspS(self):
3401 """Test that an image with a FSP silicon-init binary can be created"""
3402 data = self._DoReadFile('153_intel_fsp_s.dts')
3403 self.assertEqual(FSP_S_DATA, data[:len(FSP_S_DATA)])
3405 def testPackFspT(self):
3406 """Test that an image with a FSP temp-ram-init binary can be created"""
3407 data = self._DoReadFile('154_intel_fsp_t.dts')
3408 self.assertEqual(FSP_T_DATA, data[:len(FSP_T_DATA)])
3410 def testMkimage(self):
3411 """Test using mkimage to build an image"""
3412 data = self._DoReadFile('156_mkimage.dts')
3414 # Just check that the data appears in the file somewhere
3415 self.assertIn(U_BOOT_SPL_DATA, data)
3417 def testExtblob(self):
3418 """Test an image with an external blob"""
3419 data = self._DoReadFile('157_blob_ext.dts')
3420 self.assertEqual(REFCODE_DATA, data)
3422 def testExtblobMissing(self):
3423 """Test an image with a missing external blob"""
3424 with self.assertRaises(ValueError) as e:
3425 self._DoReadFile('158_blob_ext_missing.dts')
3426 self.assertIn("Filename 'missing-file' not found in input path",
3429 def testExtblobMissingOk(self):
3430 """Test an image with an missing external blob that is allowed"""
3431 with test_util.capture_sys_output() as (stdout, stderr):
3432 self._DoTestFile('158_blob_ext_missing.dts', allow_missing=True)
3433 err = stderr.getvalue()
3434 self.assertRegex(err, "Image 'main-section'.*missing.*: blob-ext")
3436 def testExtblobMissingOkSect(self):
3437 """Test an image with an missing external blob that is allowed"""
3438 with test_util.capture_sys_output() as (stdout, stderr):
3439 self._DoTestFile('159_blob_ext_missing_sect.dts',
3441 err = stderr.getvalue()
3442 self.assertRegex(err, "Image 'main-section'.*missing.*: "
3443 "blob-ext blob-ext2")
3445 def testPackX86RomMeMissingDesc(self):
3446 """Test that an missing Intel descriptor entry is allowed"""
3447 with test_util.capture_sys_output() as (stdout, stderr):
3448 self._DoTestFile('164_x86_rom_me_missing.dts', allow_missing=True)
3449 err = stderr.getvalue()
3450 self.assertRegex(err,
3451 "Image 'main-section'.*missing.*: intel-descriptor")
3453 def testPackX86RomMissingIfwi(self):
3454 """Test that an x86 ROM with Integrated Firmware Image can be created"""
3455 self._SetupIfwi('fitimage.bin')
3456 pathname = os.path.join(self._indir, 'fitimage.bin')
3458 with test_util.capture_sys_output() as (stdout, stderr):
3459 self._DoTestFile('111_x86_rom_ifwi.dts', allow_missing=True)
3460 err = stderr.getvalue()
3461 self.assertRegex(err, "Image 'main-section'.*missing.*: intel-ifwi")
3463 def testPackOverlap(self):
3464 """Test that zero-size overlapping regions are ignored"""
3465 self._DoTestFile('160_pack_overlap_zero.dts')
3467 def testSimpleFit(self):
3468 """Test an image with a FIT inside"""
3469 data = self._DoReadFile('161_fit.dts')
3470 self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
3471 self.assertEqual(U_BOOT_NODTB_DATA, data[-len(U_BOOT_NODTB_DATA):])
3472 fit_data = data[len(U_BOOT_DATA):-len(U_BOOT_NODTB_DATA)]
3474 # The data should be inside the FIT
3475 dtb = fdt.Fdt.FromData(fit_data)
3477 fnode = dtb.GetNode('/images/kernel')
3478 self.assertIn('data', fnode.props)
3480 fname = os.path.join(self._indir, 'fit_data.fit')
3481 tools.WriteFile(fname, fit_data)
3482 out = tools.Run('dumpimage', '-l', fname)
3484 # Check a few features to make sure the plumbing works. We don't need
3485 # to test the operation of mkimage or dumpimage here. First convert the
3486 # output into a dict where the keys are the fields printed by dumpimage
3487 # and the values are a list of values for each field
3488 lines = out.splitlines()
3490 # Converts "Compression: gzip compressed" into two groups:
3491 # 'Compression' and 'gzip compressed'
3492 re_line = re.compile(r'^ *([^:]*)(?:: *(.*))?$')
3493 vals = collections.defaultdict(list)
3495 mat = re_line.match(line)
3496 vals[mat.group(1)].append(mat.group(2))
3498 self.assertEquals('FIT description: test-desc', lines[0])
3499 self.assertIn('Created:', lines[1])
3500 self.assertIn('Image 0 (kernel)', vals)
3501 self.assertIn('Hash value', vals)
3502 data_sizes = vals.get('Data Size')
3503 self.assertIsNotNone(data_sizes)
3504 self.assertEqual(2, len(data_sizes))
3505 # Format is "4 Bytes = 0.00 KiB = 0.00 MiB" so take the first word
3506 self.assertEqual(len(U_BOOT_DATA), int(data_sizes[0].split()[0]))
3507 self.assertEqual(len(U_BOOT_SPL_DTB_DATA), int(data_sizes[1].split()[0]))
3509 def testFitExternal(self):
3510 """Test an image with an FIT with external images"""
3511 data = self._DoReadFile('162_fit_external.dts')
3512 fit_data = data[len(U_BOOT_DATA):-2] # _testing is 2 bytes
3514 # The data should be outside the FIT
3515 dtb = fdt.Fdt.FromData(fit_data)
3517 fnode = dtb.GetNode('/images/kernel')
3518 self.assertNotIn('data', fnode.props)
3520 def testSectionIgnoreHashSignature(self):
3521 """Test that sections ignore hash, signature nodes for its data"""
3522 data = self._DoReadFile('165_section_ignore_hash_signature.dts')
3523 expected = (U_BOOT_DATA + U_BOOT_DATA)
3524 self.assertEqual(expected, data)
3526 def testPadInSections(self):
3527 """Test pad-before, pad-after for entries in sections"""
3528 data = self._DoReadFile('166_pad_in_sections.dts')
3529 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
3530 U_BOOT_DATA + tools.GetBytes(ord('!'), 6) +
3532 self.assertEqual(expected, data)
3534 def testFitImageSubentryAlignment(self):
3535 """Test relative alignability of FIT image subentries"""
3537 'test-id': TEXT_DATA,
3539 data, _, _, _ = self._DoReadFileDtb('167_fit_image_subentry_alignment.dts',
3540 entry_args=entry_args)
3541 dtb = fdt.Fdt.FromData(data)
3544 node = dtb.GetNode('/images/kernel')
3545 data = dtb.GetProps(node)["data"].bytes
3546 align_pad = 0x10 - (len(U_BOOT_SPL_DATA) % 0x10)
3547 expected = (tools.GetBytes(0, 0x20) + U_BOOT_SPL_DATA +
3548 tools.GetBytes(0, align_pad) + U_BOOT_DATA)
3549 self.assertEqual(expected, data)
3551 node = dtb.GetNode('/images/fdt-1')
3552 data = dtb.GetProps(node)["data"].bytes
3553 expected = (U_BOOT_SPL_DTB_DATA + tools.GetBytes(0, 20) +
3554 tools.ToBytes(TEXT_DATA) + tools.GetBytes(0, 30) +
3556 self.assertEqual(expected, data)
3558 def testFitExtblobMissingOk(self):
3559 """Test a FIT with a missing external blob that is allowed"""
3560 with test_util.capture_sys_output() as (stdout, stderr):
3561 self._DoTestFile('168_fit_missing_blob.dts',
3563 err = stderr.getvalue()
3564 self.assertRegex(err, "Image 'main-section'.*missing.*: blob-ext")
3566 def testBlobNamedByArgMissing(self):
3567 """Test handling of a missing entry arg"""
3568 with self.assertRaises(ValueError) as e:
3569 self._DoReadFile('068_blob_named_by_arg.dts')
3570 self.assertIn("Missing required properties/entry args: cros-ec-rw-path",
3573 def testPackBl31(self):
3574 """Test that an image with an ATF BL31 binary can be created"""
3575 data = self._DoReadFile('169_atf_bl31.dts')
3576 self.assertEqual(ATF_BL31_DATA, data[:len(ATF_BL31_DATA)])
3578 def testFitFdt(self):
3579 """Test an image with an FIT with multiple FDT images"""
3580 def _CheckFdt(seq, expected_data):
3581 """Check the FDT nodes
3584 seq: Sequence number to check (0 or 1)
3585 expected_data: Expected contents of 'data' property
3587 name = 'fdt-%d' % seq
3588 fnode = dtb.GetNode('/images/%s' % name)
3589 self.assertIsNotNone(fnode)
3590 self.assertEqual({'description','type', 'compression', 'data'},
3591 set(fnode.props.keys()))
3592 self.assertEqual(expected_data, fnode.props['data'].bytes)
3593 self.assertEqual('fdt-test-fdt%d.dtb' % seq,
3594 fnode.props['description'].value)
3596 def _CheckConfig(seq, expected_data):
3597 """Check the configuration nodes
3600 seq: Sequence number to check (0 or 1)
3601 expected_data: Expected contents of 'data' property
3603 cnode = dtb.GetNode('/configurations')
3604 self.assertIn('default', cnode.props)
3605 self.assertEqual('config-1', cnode.props['default'].value)
3607 name = 'config-%d' % seq
3608 fnode = dtb.GetNode('/configurations/%s' % name)
3609 self.assertIsNotNone(fnode)
3610 self.assertEqual({'description','firmware', 'loadables', 'fdt'},
3611 set(fnode.props.keys()))
3612 self.assertEqual('conf-test-fdt%d.dtb' % seq,
3613 fnode.props['description'].value)
3614 self.assertEqual('fdt-%d' % seq, fnode.props['fdt'].value)
3617 'of-list': 'test-fdt1 test-fdt2',
3619 data = self._DoReadFileDtb(
3621 entry_args=entry_args,
3622 extra_indirs=[os.path.join(self._indir, TEST_FDT_SUBDIR)])[0]
3623 self.assertEqual(U_BOOT_NODTB_DATA, data[-len(U_BOOT_NODTB_DATA):])
3624 fit_data = data[len(U_BOOT_DATA):-len(U_BOOT_NODTB_DATA)]
3626 dtb = fdt.Fdt.FromData(fit_data)
3628 fnode = dtb.GetNode('/images/kernel')
3629 self.assertIn('data', fnode.props)
3631 # Check all the properties in fdt-1 and fdt-2
3632 _CheckFdt(1, TEST_FDT1_DATA)
3633 _CheckFdt(2, TEST_FDT2_DATA)
3635 # Check configurations
3636 _CheckConfig(1, TEST_FDT1_DATA)
3637 _CheckConfig(2, TEST_FDT2_DATA)
3639 def testFitFdtMissingList(self):
3640 """Test handling of a missing 'of-list' entry arg"""
3641 with self.assertRaises(ValueError) as e:
3642 self._DoReadFile('170_fit_fdt.dts')
3643 self.assertIn("Generator node requires 'of-list' entry argument",
3646 def testFitFdtEmptyList(self):
3647 """Test handling of an empty 'of-list' entry arg"""
3651 data = self._DoReadFileDtb('170_fit_fdt.dts', entry_args=entry_args)[0]
3653 def testFitFdtMissingProp(self):
3654 """Test handling of a missing 'fit,fdt-list' property"""
3655 with self.assertRaises(ValueError) as e:
3656 self._DoReadFile('171_fit_fdt_missing_prop.dts')
3657 self.assertIn("Generator node requires 'fit,fdt-list' property",
3660 if __name__ == "__main__":