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'
79 TEST_FDT1_DATA = b'fdt1'
80 TEST_FDT2_DATA = b'test-fdt2'
81 ENV_DATA = b'var1=1\nvar2="2"'
83 # Subdirectory of the input dir to use to put test FDTs
84 TEST_FDT_SUBDIR = 'fdts'
86 # The expected size for the device tree in some tests
87 EXTRACT_DTB_SIZE = 0x3c9
89 # Properties expected to be in the device tree when update_dtb is used
90 BASE_DTB_PROPS = ['offset', 'size', 'image-pos']
92 # Extra properties expected to be in the device tree when allow-repack is used
93 REPACK_DTB_PROPS = ['orig-offset', 'orig-size']
96 class TestFunctional(unittest.TestCase):
97 """Functional tests for binman
99 Most of these use a sample .dts file to build an image and then check
100 that it looks correct. The sample files are in the test/ subdirectory
103 For each entry type a very small test file is created using fixed
104 string contents. This makes it easy to test that things look right, and
107 In some cases a 'real' file must be used - these are also supplied in
108 the test/ diurectory.
113 from binman import entry
115 # Handle the case where argv[0] is 'python'
116 cls._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
117 cls._binman_pathname = os.path.join(cls._binman_dir, 'binman')
119 # Create a temporary directory for input files
120 cls._indir = tempfile.mkdtemp(prefix='binmant.')
122 # Create some test files
123 TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
124 TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
125 TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
126 TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
127 TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
128 TestFunctional._MakeInputFile('me.bin', ME_DATA)
129 TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
132 TestFunctional._MakeInputFile('u-boot-br.bin', PPC_MPC85XX_BR_DATA)
134 TestFunctional._MakeInputFile('u-boot-x86-start16.bin', X86_START16_DATA)
135 TestFunctional._MakeInputFile('spl/u-boot-x86-start16-spl.bin',
136 X86_START16_SPL_DATA)
137 TestFunctional._MakeInputFile('tpl/u-boot-x86-start16-tpl.bin',
138 X86_START16_TPL_DATA)
140 TestFunctional._MakeInputFile('u-boot-x86-reset16.bin',
142 TestFunctional._MakeInputFile('spl/u-boot-x86-reset16-spl.bin',
143 X86_RESET16_SPL_DATA)
144 TestFunctional._MakeInputFile('tpl/u-boot-x86-reset16-tpl.bin',
145 X86_RESET16_TPL_DATA)
147 TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
148 TestFunctional._MakeInputFile('spl/u-boot-spl-nodtb.bin',
149 U_BOOT_SPL_NODTB_DATA)
150 TestFunctional._MakeInputFile('tpl/u-boot-tpl-nodtb.bin',
151 U_BOOT_TPL_NODTB_DATA)
152 TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
153 TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
154 TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
155 TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
156 TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
157 TestFunctional._MakeInputDir('devkeys')
158 TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
159 TestFunctional._MakeInputFile('refcode.bin', REFCODE_DATA)
160 TestFunctional._MakeInputFile('fsp_m.bin', FSP_M_DATA)
161 TestFunctional._MakeInputFile('fsp_s.bin', FSP_S_DATA)
162 TestFunctional._MakeInputFile('fsp_t.bin', FSP_T_DATA)
164 cls._elf_testdir = os.path.join(cls._indir, 'elftest')
165 elf_test.BuildElfTestFiles(cls._elf_testdir)
167 # ELF file with a '_dt_ucode_base_size' symbol
168 TestFunctional._MakeInputFile('u-boot',
169 tools.ReadFile(cls.ElfTestFile('u_boot_ucode_ptr')))
171 # Intel flash descriptor file
172 cls._SetupDescriptor()
174 shutil.copytree(cls.TestFile('files'),
175 os.path.join(cls._indir, 'files'))
177 TestFunctional._MakeInputFile('compress', COMPRESS_DATA)
178 TestFunctional._MakeInputFile('bl31.bin', ATF_BL31_DATA)
179 TestFunctional._MakeInputFile('scp.bin', SCP_DATA)
181 # Add a few .dtb files for testing
182 TestFunctional._MakeInputFile('%s/test-fdt1.dtb' % TEST_FDT_SUBDIR,
184 TestFunctional._MakeInputFile('%s/test-fdt2.dtb' % TEST_FDT_SUBDIR,
187 TestFunctional._MakeInputFile('env.txt', ENV_DATA)
189 # Travis-CI may have an old lz4
192 tools.Run('lz4', '--no-frame-crc', '-c',
193 os.path.join(cls._indir, 'u-boot.bin'), binary=True)
198 def tearDownClass(cls):
199 """Remove the temporary input directory and its contents"""
200 if cls.preserve_indir:
201 print('Preserving input dir: %s' % cls._indir)
204 shutil.rmtree(cls._indir)
208 def setup_test_args(cls, preserve_indir=False, preserve_outdirs=False,
209 toolpath=None, verbosity=None):
210 """Accept arguments controlling test execution
213 preserve_indir: Preserve the shared input directory used by all
215 preserve_outdir: Preserve the output directories used by tests. Each
216 test has its own, so this is normally only useful when running a
218 toolpath: ist of paths to use for tools
220 cls.preserve_indir = preserve_indir
221 cls.preserve_outdirs = preserve_outdirs
222 cls.toolpath = toolpath
223 cls.verbosity = verbosity
226 if not self.have_lz4:
227 self.skipTest('lz4 --no-frame-crc not available')
229 def _CleanupOutputDir(self):
230 """Remove the temporary output directory"""
231 if self.preserve_outdirs:
232 print('Preserving output dir: %s' % tools.outdir)
234 tools._FinaliseForTest()
237 # Enable this to turn on debugging output
238 # tout.Init(tout.DEBUG)
239 command.test_result = None
242 """Remove the temporary output directory"""
243 self._CleanupOutputDir()
245 def _SetupImageInTmpdir(self):
246 """Set up the output image in a new temporary directory
248 This is used when an image has been generated in the output directory,
249 but we want to run binman again. This will create a new output
250 directory and fail to delete the original one.
252 This creates a new temporary directory, copies the image to it (with a
253 new name) and removes the old output directory.
257 Temporary directory to use
260 image_fname = tools.GetOutputFilename('image.bin')
261 tmpdir = tempfile.mkdtemp(prefix='binman.')
262 updated_fname = os.path.join(tmpdir, 'image-updated.bin')
263 tools.WriteFile(updated_fname, tools.ReadFile(image_fname))
264 self._CleanupOutputDir()
265 return tmpdir, updated_fname
269 TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
270 TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
271 TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
273 def _RunBinman(self, *args, **kwargs):
274 """Run binman using the command line
277 Arguments to pass, as a list of strings
278 kwargs: Arguments to pass to Command.RunPipe()
280 result = command.RunPipe([[self._binman_pathname] + list(args)],
281 capture=True, capture_stderr=True, raise_on_error=False)
282 if result.return_code and kwargs.get('raise_on_error', True):
283 raise Exception("Error running '%s': %s" % (' '.join(args),
284 result.stdout + result.stderr))
287 def _DoBinman(self, *argv):
288 """Run binman using directly (in the same process)
291 Arguments to pass, as a list of strings
293 Return value (0 for success)
296 args = cmdline.ParseArgs(argv)
297 args.pager = 'binman-invalid-pager'
298 args.build_dir = self._indir
300 # For testing, you can force an increase in verbosity here
301 # args.verbosity = tout.DEBUG
302 return control.Binman(args)
304 def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
305 entry_args=None, images=None, use_real_dtb=False,
306 verbosity=None, allow_missing=False, extra_indirs=None):
307 """Run binman with a given test file
310 fname: Device-tree source filename to use (e.g. 005_simple.dts)
311 debug: True to enable debugging output
312 map: True to output map files for the images
313 update_dtb: Update the offset and size of each entry in the device
314 tree before packing it into the image
315 entry_args: Dict of entry args to supply to binman
317 value: value of that arg
318 images: List of image names to build
319 use_real_dtb: True to use the test file as the contents of
320 the u-boot-dtb entry. Normally this is not needed and the
321 test contents (the U_BOOT_DTB_DATA string) can be used.
322 But in some test we need the real contents.
323 verbosity: Verbosity level to use (0-3, None=don't set it)
324 allow_missing: Set the '--allow-missing' flag so that missing
325 external binaries just produce a warning instead of an error
326 extra_indirs: Extra input directories to add using -I
331 if verbosity is not None:
332 args.append('-v%d' % verbosity)
334 args.append('-v%d' % self.verbosity)
336 for path in self.toolpath:
337 args += ['--toolpath', path]
338 args += ['build', '-p', '-I', self._indir, '-d', self.TestFile(fname)]
344 args.append('--fake-dtb')
346 for arg, value in entry_args.items():
347 args.append('-a%s=%s' % (arg, value))
352 args += ['-i', image]
354 for indir in extra_indirs:
355 args += ['-I', indir]
356 return self._DoBinman(*args)
358 def _SetupDtb(self, fname, outfile='u-boot.dtb'):
359 """Set up a new test device-tree file
361 The given file is compiled and set up as the device tree to be used
365 fname: Filename of .dts file to read
366 outfile: Output filename for compiled device-tree binary
369 Contents of device-tree binary
371 tmpdir = tempfile.mkdtemp(prefix='binmant.')
372 dtb = fdt_util.EnsureCompiled(self.TestFile(fname), tmpdir)
373 with open(dtb, 'rb') as fd:
375 TestFunctional._MakeInputFile(outfile, data)
376 shutil.rmtree(tmpdir)
379 def _GetDtbContentsForSplTpl(self, dtb_data, name):
380 """Create a version of the main DTB for SPL or SPL
382 For testing we don't actually have different versions of the DTB. With
383 U-Boot we normally run fdtgrep to remove unwanted nodes, but for tests
384 we don't normally have any unwanted nodes.
386 We still want the DTBs for SPL and TPL to be different though, since
387 otherwise it is confusing to know which one we are looking at. So add
388 an 'spl' or 'tpl' property to the top-level node.
391 dtb_data: dtb data to modify (this should be a value devicetree)
392 name: Name of a new property to add
395 New dtb data with the property added
397 dtb = fdt.Fdt.FromData(dtb_data)
399 dtb.GetNode('/binman').AddZeroProp(name)
400 dtb.Sync(auto_resize=True)
402 return dtb.GetContents()
404 def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
405 update_dtb=False, entry_args=None, reset_dtbs=True,
407 """Run binman and return the resulting image
409 This runs binman with a given test file and then reads the resulting
410 output file. It is a shortcut function since most tests need to do
413 Raises an assertion failure if binman returns a non-zero exit code.
416 fname: Device-tree source filename to use (e.g. 005_simple.dts)
417 use_real_dtb: True to use the test file as the contents of
418 the u-boot-dtb entry. Normally this is not needed and the
419 test contents (the U_BOOT_DTB_DATA string) can be used.
420 But in some test we need the real contents.
421 map: True to output map files for the images
422 update_dtb: Update the offset and size of each entry in the device
423 tree before packing it into the image
424 entry_args: Dict of entry args to supply to binman
426 value: value of that arg
427 reset_dtbs: With use_real_dtb the test dtb is overwritten by this
428 function. If reset_dtbs is True, then the original test dtb
429 is written back before this function finishes
430 extra_indirs: Extra input directories to add using -I
434 Resulting image contents
436 Map data showing contents of image (or None if none)
437 Output device tree binary filename ('u-boot.dtb' path)
440 # Use the compiled test file as the u-boot-dtb input
442 dtb_data = self._SetupDtb(fname)
444 # For testing purposes, make a copy of the DT for SPL and TPL. Add
445 # a node indicating which it is, so aid verification.
446 for name in ['spl', 'tpl']:
447 dtb_fname = '%s/u-boot-%s.dtb' % (name, name)
448 outfile = os.path.join(self._indir, dtb_fname)
449 TestFunctional._MakeInputFile(dtb_fname,
450 self._GetDtbContentsForSplTpl(dtb_data, name))
453 retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
454 entry_args=entry_args, use_real_dtb=use_real_dtb,
455 extra_indirs=extra_indirs)
456 self.assertEqual(0, retcode)
457 out_dtb_fname = tools.GetOutputFilename('u-boot.dtb.out')
459 # Find the (only) image, read it and return its contents
460 image = control.images['image']
461 image_fname = tools.GetOutputFilename('image.bin')
462 self.assertTrue(os.path.exists(image_fname))
464 map_fname = tools.GetOutputFilename('image.map')
465 with open(map_fname) as fd:
469 with open(image_fname, 'rb') as fd:
470 return fd.read(), dtb_data, map_data, out_dtb_fname
472 # Put the test file back
473 if reset_dtbs and use_real_dtb:
476 def _DoReadFileRealDtb(self, fname):
477 """Run binman with a real .dtb file and return the resulting data
480 fname: DT source filename to use (e.g. 082_fdt_update_all.dts)
483 Resulting image contents
485 return self._DoReadFileDtb(fname, use_real_dtb=True, update_dtb=True)[0]
487 def _DoReadFile(self, fname, use_real_dtb=False):
488 """Helper function which discards the device-tree binary
491 fname: Device-tree source filename to use (e.g. 005_simple.dts)
492 use_real_dtb: True to use the test file as the contents of
493 the u-boot-dtb entry. Normally this is not needed and the
494 test contents (the U_BOOT_DTB_DATA string) can be used.
495 But in some test we need the real contents.
498 Resulting image contents
500 return self._DoReadFileDtb(fname, use_real_dtb)[0]
503 def _MakeInputFile(cls, fname, contents):
504 """Create a new test input file, creating directories as needed
507 fname: Filename to create
508 contents: File contents to write in to the file
510 Full pathname of file created
512 pathname = os.path.join(cls._indir, fname)
513 dirname = os.path.dirname(pathname)
514 if dirname and not os.path.exists(dirname):
516 with open(pathname, 'wb') as fd:
521 def _MakeInputDir(cls, dirname):
522 """Create a new test input directory, creating directories as needed
525 dirname: Directory name to create
528 Full pathname of directory created
530 pathname = os.path.join(cls._indir, dirname)
531 if not os.path.exists(pathname):
532 os.makedirs(pathname)
536 def _SetupSplElf(cls, src_fname='bss_data'):
537 """Set up an ELF file with a '_dt_ucode_base_size' symbol
540 Filename of ELF file to use as SPL
542 TestFunctional._MakeInputFile('spl/u-boot-spl',
543 tools.ReadFile(cls.ElfTestFile(src_fname)))
546 def _SetupTplElf(cls, src_fname='bss_data'):
547 """Set up an ELF file with a '_dt_ucode_base_size' symbol
550 Filename of ELF file to use as TPL
552 TestFunctional._MakeInputFile('tpl/u-boot-tpl',
553 tools.ReadFile(cls.ElfTestFile(src_fname)))
556 def _SetupDescriptor(cls):
557 with open(cls.TestFile('descriptor.bin'), 'rb') as fd:
558 TestFunctional._MakeInputFile('descriptor.bin', fd.read())
561 def TestFile(cls, fname):
562 return os.path.join(cls._binman_dir, 'test', fname)
565 def ElfTestFile(cls, fname):
566 return os.path.join(cls._elf_testdir, fname)
568 def AssertInList(self, grep_list, target):
569 """Assert that at least one of a list of things is in a target
572 grep_list: List of strings to check
573 target: Target string
575 for grep in grep_list:
578 self.fail("Error: '%s' not found in '%s'" % (grep_list, target))
580 def CheckNoGaps(self, entries):
581 """Check that all entries fit together without gaps
584 entries: List of entries to check
587 for entry in entries.values():
588 self.assertEqual(offset, entry.offset)
591 def GetFdtLen(self, dtb):
592 """Get the totalsize field from a device-tree binary
595 dtb: Device-tree binary contents
598 Total size of device-tree binary, from the header
600 return struct.unpack('>L', dtb[4:8])[0]
602 def _GetPropTree(self, dtb, prop_names, prefix='/binman/'):
603 def AddNode(node, path):
605 path += '/' + node.name
606 for prop in node.props.values():
607 if prop.name in prop_names:
608 prop_path = path + ':' + prop.name
609 tree[prop_path[len(prefix):]] = fdt_util.fdt32_to_cpu(
611 for subnode in node.subnodes:
612 AddNode(subnode, path)
615 AddNode(dtb.GetRoot(), '')
619 """Test a basic run with valid args"""
620 result = self._RunBinman('-h')
622 def testFullHelp(self):
623 """Test that the full help is displayed with -H"""
624 result = self._RunBinman('-H')
625 help_file = os.path.join(self._binman_dir, 'README')
626 # Remove possible extraneous strings
627 extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
628 gothelp = result.stdout.replace(extra, '')
629 self.assertEqual(len(gothelp), os.path.getsize(help_file))
630 self.assertEqual(0, len(result.stderr))
631 self.assertEqual(0, result.return_code)
633 def testFullHelpInternal(self):
634 """Test that the full help is displayed with -H"""
636 command.test_result = command.CommandResult()
637 result = self._DoBinman('-H')
638 help_file = os.path.join(self._binman_dir, 'README')
640 command.test_result = None
643 """Test that the basic help is displayed with -h"""
644 result = self._RunBinman('-h')
645 self.assertTrue(len(result.stdout) > 200)
646 self.assertEqual(0, len(result.stderr))
647 self.assertEqual(0, result.return_code)
650 """Test that we can run it with a specific board"""
651 self._SetupDtb('005_simple.dts', 'sandbox/u-boot.dtb')
652 TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
653 result = self._DoBinman('build', '-b', 'sandbox')
654 self.assertEqual(0, result)
656 def testNeedBoard(self):
657 """Test that we get an error when no board ius supplied"""
658 with self.assertRaises(ValueError) as e:
659 result = self._DoBinman('build')
660 self.assertIn("Must provide a board to process (use -b <board>)",
663 def testMissingDt(self):
664 """Test that an invalid device-tree file generates an error"""
665 with self.assertRaises(Exception) as e:
666 self._RunBinman('build', '-d', 'missing_file')
667 # We get one error from libfdt, and a different one from fdtget.
668 self.AssertInList(["Couldn't open blob from 'missing_file'",
669 'No such file or directory'], str(e.exception))
671 def testBrokenDt(self):
672 """Test that an invalid device-tree source file generates an error
674 Since this is a source file it should be compiled and the error
675 will come from the device-tree compiler (dtc).
677 with self.assertRaises(Exception) as e:
678 self._RunBinman('build', '-d', self.TestFile('001_invalid.dts'))
679 self.assertIn("FATAL ERROR: Unable to parse input tree",
682 def testMissingNode(self):
683 """Test that a device tree without a 'binman' node generates an error"""
684 with self.assertRaises(Exception) as e:
685 self._DoBinman('build', '-d', self.TestFile('002_missing_node.dts'))
686 self.assertIn("does not have a 'binman' node", str(e.exception))
689 """Test that an empty binman node works OK (i.e. does nothing)"""
690 result = self._RunBinman('build', '-d', self.TestFile('003_empty.dts'))
691 self.assertEqual(0, len(result.stderr))
692 self.assertEqual(0, result.return_code)
694 def testInvalidEntry(self):
695 """Test that an invalid entry is flagged"""
696 with self.assertRaises(Exception) as e:
697 result = self._RunBinman('build', '-d',
698 self.TestFile('004_invalid_entry.dts'))
699 self.assertIn("Unknown entry type 'not-a-valid-type' in node "
700 "'/binman/not-a-valid-type'", str(e.exception))
702 def testSimple(self):
703 """Test a simple binman with a single file"""
704 data = self._DoReadFile('005_simple.dts')
705 self.assertEqual(U_BOOT_DATA, data)
707 def testSimpleDebug(self):
708 """Test a simple binman run with debugging enabled"""
709 self._DoTestFile('005_simple.dts', debug=True)
712 """Test that we can handle creating two images
714 This also tests image padding.
716 retcode = self._DoTestFile('006_dual_image.dts')
717 self.assertEqual(0, retcode)
719 image = control.images['image1']
720 self.assertEqual(len(U_BOOT_DATA), image.size)
721 fname = tools.GetOutputFilename('image1.bin')
722 self.assertTrue(os.path.exists(fname))
723 with open(fname, 'rb') as fd:
725 self.assertEqual(U_BOOT_DATA, data)
727 image = control.images['image2']
728 self.assertEqual(3 + len(U_BOOT_DATA) + 5, image.size)
729 fname = tools.GetOutputFilename('image2.bin')
730 self.assertTrue(os.path.exists(fname))
731 with open(fname, 'rb') as fd:
733 self.assertEqual(U_BOOT_DATA, data[3:7])
734 self.assertEqual(tools.GetBytes(0, 3), data[:3])
735 self.assertEqual(tools.GetBytes(0, 5), data[7:])
737 def testBadAlign(self):
738 """Test that an invalid alignment value is detected"""
739 with self.assertRaises(ValueError) as e:
740 self._DoTestFile('007_bad_align.dts')
741 self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
742 "of two", str(e.exception))
744 def testPackSimple(self):
745 """Test that packing works as expected"""
746 retcode = self._DoTestFile('008_pack.dts')
747 self.assertEqual(0, retcode)
748 self.assertIn('image', control.images)
749 image = control.images['image']
750 entries = image.GetEntries()
751 self.assertEqual(5, len(entries))
754 self.assertIn('u-boot', entries)
755 entry = entries['u-boot']
756 self.assertEqual(0, entry.offset)
757 self.assertEqual(len(U_BOOT_DATA), entry.size)
759 # Second u-boot, aligned to 16-byte boundary
760 self.assertIn('u-boot-align', entries)
761 entry = entries['u-boot-align']
762 self.assertEqual(16, entry.offset)
763 self.assertEqual(len(U_BOOT_DATA), entry.size)
765 # Third u-boot, size 23 bytes
766 self.assertIn('u-boot-size', entries)
767 entry = entries['u-boot-size']
768 self.assertEqual(20, entry.offset)
769 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
770 self.assertEqual(23, entry.size)
772 # Fourth u-boot, placed immediate after the above
773 self.assertIn('u-boot-next', entries)
774 entry = entries['u-boot-next']
775 self.assertEqual(43, entry.offset)
776 self.assertEqual(len(U_BOOT_DATA), entry.size)
778 # Fifth u-boot, placed at a fixed offset
779 self.assertIn('u-boot-fixed', entries)
780 entry = entries['u-boot-fixed']
781 self.assertEqual(61, entry.offset)
782 self.assertEqual(len(U_BOOT_DATA), entry.size)
784 self.assertEqual(65, image.size)
786 def testPackExtra(self):
787 """Test that extra packing feature works as expected"""
788 retcode = self._DoTestFile('009_pack_extra.dts')
790 self.assertEqual(0, retcode)
791 self.assertIn('image', control.images)
792 image = control.images['image']
793 entries = image.GetEntries()
794 self.assertEqual(5, len(entries))
796 # First u-boot with padding before and after
797 self.assertIn('u-boot', entries)
798 entry = entries['u-boot']
799 self.assertEqual(0, entry.offset)
800 self.assertEqual(3, entry.pad_before)
801 self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
803 # Second u-boot has an aligned size, but it has no effect
804 self.assertIn('u-boot-align-size-nop', entries)
805 entry = entries['u-boot-align-size-nop']
806 self.assertEqual(12, entry.offset)
807 self.assertEqual(4, entry.size)
809 # Third u-boot has an aligned size too
810 self.assertIn('u-boot-align-size', entries)
811 entry = entries['u-boot-align-size']
812 self.assertEqual(16, entry.offset)
813 self.assertEqual(32, entry.size)
815 # Fourth u-boot has an aligned end
816 self.assertIn('u-boot-align-end', entries)
817 entry = entries['u-boot-align-end']
818 self.assertEqual(48, entry.offset)
819 self.assertEqual(16, entry.size)
821 # Fifth u-boot immediately afterwards
822 self.assertIn('u-boot-align-both', entries)
823 entry = entries['u-boot-align-both']
824 self.assertEqual(64, entry.offset)
825 self.assertEqual(64, entry.size)
827 self.CheckNoGaps(entries)
828 self.assertEqual(128, image.size)
830 def testPackAlignPowerOf2(self):
831 """Test that invalid entry alignment is detected"""
832 with self.assertRaises(ValueError) as e:
833 self._DoTestFile('010_pack_align_power2.dts')
834 self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
835 "of two", str(e.exception))
837 def testPackAlignSizePowerOf2(self):
838 """Test that invalid entry size alignment is detected"""
839 with self.assertRaises(ValueError) as e:
840 self._DoTestFile('011_pack_align_size_power2.dts')
841 self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
842 "power of two", str(e.exception))
844 def testPackInvalidAlign(self):
845 """Test detection of an offset that does not match its alignment"""
846 with self.assertRaises(ValueError) as e:
847 self._DoTestFile('012_pack_inv_align.dts')
848 self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
849 "align 0x4 (4)", str(e.exception))
851 def testPackInvalidSizeAlign(self):
852 """Test that invalid entry size alignment is detected"""
853 with self.assertRaises(ValueError) as e:
854 self._DoTestFile('013_pack_inv_size_align.dts')
855 self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
856 "align-size 0x4 (4)", str(e.exception))
858 def testPackOverlap(self):
859 """Test that overlapping regions are detected"""
860 with self.assertRaises(ValueError) as e:
861 self._DoTestFile('014_pack_overlap.dts')
862 self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
863 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
866 def testPackEntryOverflow(self):
867 """Test that entries that overflow their size are detected"""
868 with self.assertRaises(ValueError) as e:
869 self._DoTestFile('015_pack_overflow.dts')
870 self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
871 "but entry size is 0x3 (3)", str(e.exception))
873 def testPackImageOverflow(self):
874 """Test that entries which overflow the image size are detected"""
875 with self.assertRaises(ValueError) as e:
876 self._DoTestFile('016_pack_image_overflow.dts')
877 self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section "
878 "size 0x3 (3)", str(e.exception))
880 def testPackImageSize(self):
881 """Test that the image size can be set"""
882 retcode = self._DoTestFile('017_pack_image_size.dts')
883 self.assertEqual(0, retcode)
884 self.assertIn('image', control.images)
885 image = control.images['image']
886 self.assertEqual(7, image.size)
888 def testPackImageSizeAlign(self):
889 """Test that image size alignemnt works as expected"""
890 retcode = self._DoTestFile('018_pack_image_align.dts')
891 self.assertEqual(0, retcode)
892 self.assertIn('image', control.images)
893 image = control.images['image']
894 self.assertEqual(16, image.size)
896 def testPackInvalidImageAlign(self):
897 """Test that invalid image alignment is detected"""
898 with self.assertRaises(ValueError) as e:
899 self._DoTestFile('019_pack_inv_image_align.dts')
900 self.assertIn("Section '/binman': Size 0x7 (7) does not match "
901 "align-size 0x8 (8)", str(e.exception))
903 def testPackAlignPowerOf2(self):
904 """Test that invalid image alignment is detected"""
905 with self.assertRaises(ValueError) as e:
906 self._DoTestFile('020_pack_inv_image_align_power2.dts')
907 self.assertIn("Image '/binman': Alignment size 131 must be a power of "
908 "two", str(e.exception))
910 def testImagePadByte(self):
911 """Test that the image pad byte can be specified"""
913 data = self._DoReadFile('021_image_pad.dts')
914 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0xff, 1) +
917 def testImageName(self):
918 """Test that image files can be named"""
919 retcode = self._DoTestFile('022_image_name.dts')
920 self.assertEqual(0, retcode)
921 image = control.images['image1']
922 fname = tools.GetOutputFilename('test-name')
923 self.assertTrue(os.path.exists(fname))
925 image = control.images['image2']
926 fname = tools.GetOutputFilename('test-name.xx')
927 self.assertTrue(os.path.exists(fname))
929 def testBlobFilename(self):
930 """Test that generic blobs can be provided by filename"""
931 data = self._DoReadFile('023_blob.dts')
932 self.assertEqual(BLOB_DATA, data)
934 def testPackSorted(self):
935 """Test that entries can be sorted"""
937 data = self._DoReadFile('024_sorted.dts')
938 self.assertEqual(tools.GetBytes(0, 1) + U_BOOT_SPL_DATA +
939 tools.GetBytes(0, 2) + U_BOOT_DATA, data)
941 def testPackZeroOffset(self):
942 """Test that an entry at offset 0 is not given a new offset"""
943 with self.assertRaises(ValueError) as e:
944 self._DoTestFile('025_pack_zero_size.dts')
945 self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
946 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
949 def testPackUbootDtb(self):
950 """Test that a device tree can be added to U-Boot"""
951 data = self._DoReadFile('026_pack_u_boot_dtb.dts')
952 self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
954 def testPackX86RomNoSize(self):
955 """Test that the end-at-4gb property requires a size property"""
956 with self.assertRaises(ValueError) as e:
957 self._DoTestFile('027_pack_4gb_no_size.dts')
958 self.assertIn("Image '/binman': Section size must be provided when "
959 "using end-at-4gb", str(e.exception))
961 def test4gbAndSkipAtStartTogether(self):
962 """Test that the end-at-4gb and skip-at-size property can't be used
964 with self.assertRaises(ValueError) as e:
965 self._DoTestFile('098_4gb_and_skip_at_start_together.dts')
966 self.assertIn("Image '/binman': Provide either 'end-at-4gb' or "
967 "'skip-at-start'", str(e.exception))
969 def testPackX86RomOutside(self):
970 """Test that the end-at-4gb property checks for offset boundaries"""
971 with self.assertRaises(ValueError) as e:
972 self._DoTestFile('028_pack_4gb_outside.dts')
973 self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
974 "the section starting at 0xffffffe0 (4294967264)",
977 def testPackX86Rom(self):
978 """Test that a basic x86 ROM can be created"""
980 data = self._DoReadFile('029_x86_rom.dts')
981 self.assertEqual(U_BOOT_DATA + tools.GetBytes(0, 3) + U_BOOT_SPL_DATA +
982 tools.GetBytes(0, 2), data)
984 def testPackX86RomMeNoDesc(self):
985 """Test that an invalid Intel descriptor entry is detected"""
987 TestFunctional._MakeInputFile('descriptor-empty.bin', b'')
988 with self.assertRaises(ValueError) as e:
989 self._DoTestFile('163_x86_rom_me_empty.dts')
990 self.assertIn("Node '/binman/intel-descriptor': Cannot find Intel Flash Descriptor (FD) signature",
993 self._SetupDescriptor()
995 def testPackX86RomBadDesc(self):
996 """Test that the Intel requires a descriptor entry"""
997 with self.assertRaises(ValueError) as e:
998 self._DoTestFile('030_x86_rom_me_no_desc.dts')
999 self.assertIn("Node '/binman/intel-me': No offset set with "
1000 "offset-unset: should another entry provide this correct "
1001 "offset?", str(e.exception))
1003 def testPackX86RomMe(self):
1004 """Test that an x86 ROM with an ME region can be created"""
1005 data = self._DoReadFile('031_x86_rom_me.dts')
1006 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
1007 if data[:0x1000] != expected_desc:
1008 self.fail('Expected descriptor binary at start of image')
1009 self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
1011 def testPackVga(self):
1012 """Test that an image with a VGA binary can be created"""
1013 data = self._DoReadFile('032_intel_vga.dts')
1014 self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
1016 def testPackStart16(self):
1017 """Test that an image with an x86 start16 region can be created"""
1018 data = self._DoReadFile('033_x86_start16.dts')
1019 self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
1021 def testPackPowerpcMpc85xxBootpgResetvec(self):
1022 """Test that an image with powerpc-mpc85xx-bootpg-resetvec can be
1024 data = self._DoReadFile('150_powerpc_mpc85xx_bootpg_resetvec.dts')
1025 self.assertEqual(PPC_MPC85XX_BR_DATA, data[:len(PPC_MPC85XX_BR_DATA)])
1027 def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False):
1028 """Handle running a test for insertion of microcode
1031 dts_fname: Name of test .dts file
1032 nodtb_data: Data that we expect in the first section
1033 ucode_second: True if the microsecond entry is second instead of
1038 Contents of first region (U-Boot or SPL)
1039 Offset and size components of microcode pointer, as inserted
1040 in the above (two 4-byte words)
1042 data = self._DoReadFile(dts_fname, True)
1044 # Now check the device tree has no microcode
1046 ucode_content = data[len(nodtb_data):]
1047 ucode_pos = len(nodtb_data)
1048 dtb_with_ucode = ucode_content[16:]
1049 fdt_len = self.GetFdtLen(dtb_with_ucode)
1051 dtb_with_ucode = data[len(nodtb_data):]
1052 fdt_len = self.GetFdtLen(dtb_with_ucode)
1053 ucode_content = dtb_with_ucode[fdt_len:]
1054 ucode_pos = len(nodtb_data) + fdt_len
1055 fname = tools.GetOutputFilename('test.dtb')
1056 with open(fname, 'wb') as fd:
1057 fd.write(dtb_with_ucode)
1058 dtb = fdt.FdtScan(fname)
1059 ucode = dtb.GetNode('/microcode')
1060 self.assertTrue(ucode)
1061 for node in ucode.subnodes:
1062 self.assertFalse(node.props.get('data'))
1064 # Check that the microcode appears immediately after the Fdt
1065 # This matches the concatenation of the data properties in
1066 # the /microcode/update@xxx nodes in 34_x86_ucode.dts.
1067 ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
1069 self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
1071 # Check that the microcode pointer was inserted. It should match the
1072 # expected offset and size
1073 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
1075 u_boot = data[:len(nodtb_data)]
1076 return u_boot, pos_and_size
1078 def testPackUbootMicrocode(self):
1079 """Test that x86 microcode can be handled correctly
1081 We expect to see the following in the image, in order:
1082 u-boot-nodtb.bin with a microcode pointer inserted at the correct
1084 u-boot.dtb with the microcode removed
1087 first, pos_and_size = self._RunMicrocodeTest('034_x86_ucode.dts',
1089 self.assertEqual(b'nodtb with microcode' + pos_and_size +
1090 b' somewhere in here', first)
1092 def _RunPackUbootSingleMicrocode(self):
1093 """Test that x86 microcode can be handled correctly
1095 We expect to see the following in the image, in order:
1096 u-boot-nodtb.bin with a microcode pointer inserted at the correct
1098 u-boot.dtb with the microcode
1099 an empty microcode region
1101 # We need the libfdt library to run this test since only that allows
1102 # finding the offset of a property. This is required by
1103 # Entry_u_boot_dtb_with_ucode.ObtainContents().
1104 data = self._DoReadFile('035_x86_single_ucode.dts', True)
1106 second = data[len(U_BOOT_NODTB_DATA):]
1108 fdt_len = self.GetFdtLen(second)
1109 third = second[fdt_len:]
1110 second = second[:fdt_len]
1112 ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
1113 self.assertIn(ucode_data, second)
1114 ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
1116 # Check that the microcode pointer was inserted. It should match the
1117 # expected offset and size
1118 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
1120 first = data[:len(U_BOOT_NODTB_DATA)]
1121 self.assertEqual(b'nodtb with microcode' + pos_and_size +
1122 b' somewhere in here', first)
1124 def testPackUbootSingleMicrocode(self):
1125 """Test that x86 microcode can be handled correctly with fdt_normal.
1127 self._RunPackUbootSingleMicrocode()
1129 def testUBootImg(self):
1130 """Test that u-boot.img can be put in a file"""
1131 data = self._DoReadFile('036_u_boot_img.dts')
1132 self.assertEqual(U_BOOT_IMG_DATA, data)
1134 def testNoMicrocode(self):
1135 """Test that a missing microcode region is detected"""
1136 with self.assertRaises(ValueError) as e:
1137 self._DoReadFile('037_x86_no_ucode.dts', True)
1138 self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
1139 "node found in ", str(e.exception))
1141 def testMicrocodeWithoutNode(self):
1142 """Test that a missing u-boot-dtb-with-ucode node is detected"""
1143 with self.assertRaises(ValueError) as e:
1144 self._DoReadFile('038_x86_ucode_missing_node.dts', True)
1145 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1146 "microcode region u-boot-dtb-with-ucode", str(e.exception))
1148 def testMicrocodeWithoutNode2(self):
1149 """Test that a missing u-boot-ucode node is detected"""
1150 with self.assertRaises(ValueError) as e:
1151 self._DoReadFile('039_x86_ucode_missing_node2.dts', True)
1152 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1153 "microcode region u-boot-ucode", str(e.exception))
1155 def testMicrocodeWithoutPtrInElf(self):
1156 """Test that a U-Boot binary without the microcode symbol is detected"""
1157 # ELF file without a '_dt_ucode_base_size' symbol
1159 TestFunctional._MakeInputFile('u-boot',
1160 tools.ReadFile(self.ElfTestFile('u_boot_no_ucode_ptr')))
1162 with self.assertRaises(ValueError) as e:
1163 self._RunPackUbootSingleMicrocode()
1164 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
1165 "_dt_ucode_base_size symbol in u-boot", str(e.exception))
1168 # Put the original file back
1169 TestFunctional._MakeInputFile('u-boot',
1170 tools.ReadFile(self.ElfTestFile('u_boot_ucode_ptr')))
1172 def testMicrocodeNotInImage(self):
1173 """Test that microcode must be placed within the image"""
1174 with self.assertRaises(ValueError) as e:
1175 self._DoReadFile('040_x86_ucode_not_in_image.dts', True)
1176 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
1177 "pointer _dt_ucode_base_size at fffffe14 is outside the "
1178 "section ranging from 00000000 to 0000002e", str(e.exception))
1180 def testWithoutMicrocode(self):
1181 """Test that we can cope with an image without microcode (e.g. qemu)"""
1182 TestFunctional._MakeInputFile('u-boot',
1183 tools.ReadFile(self.ElfTestFile('u_boot_no_ucode_ptr')))
1184 data, dtb, _, _ = self._DoReadFileDtb('044_x86_optional_ucode.dts', True)
1186 # Now check the device tree has no microcode
1187 self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
1188 second = data[len(U_BOOT_NODTB_DATA):]
1190 fdt_len = self.GetFdtLen(second)
1191 self.assertEqual(dtb, second[:fdt_len])
1193 used_len = len(U_BOOT_NODTB_DATA) + fdt_len
1194 third = data[used_len:]
1195 self.assertEqual(tools.GetBytes(0, 0x200 - used_len), third)
1197 def testUnknownPosSize(self):
1198 """Test that microcode must be placed within the image"""
1199 with self.assertRaises(ValueError) as e:
1200 self._DoReadFile('041_unknown_pos_size.dts', True)
1201 self.assertIn("Section '/binman': Unable to set offset/size for unknown "
1202 "entry 'invalid-entry'", str(e.exception))
1204 def testPackFsp(self):
1205 """Test that an image with a FSP binary can be created"""
1206 data = self._DoReadFile('042_intel_fsp.dts')
1207 self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
1209 def testPackCmc(self):
1210 """Test that an image with a CMC binary can be created"""
1211 data = self._DoReadFile('043_intel_cmc.dts')
1212 self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
1214 def testPackVbt(self):
1215 """Test that an image with a VBT binary can be created"""
1216 data = self._DoReadFile('046_intel_vbt.dts')
1217 self.assertEqual(VBT_DATA, data[:len(VBT_DATA)])
1219 def testSplBssPad(self):
1220 """Test that we can pad SPL's BSS with zeros"""
1221 # ELF file with a '__bss_size' symbol
1223 data = self._DoReadFile('047_spl_bss_pad.dts')
1224 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0, 10) + U_BOOT_DATA,
1227 def testSplBssPadMissing(self):
1228 """Test that a missing symbol is detected"""
1229 self._SetupSplElf('u_boot_ucode_ptr')
1230 with self.assertRaises(ValueError) as e:
1231 self._DoReadFile('047_spl_bss_pad.dts')
1232 self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
1235 def testPackStart16Spl(self):
1236 """Test that an image with an x86 start16 SPL region can be created"""
1237 data = self._DoReadFile('048_x86_start16_spl.dts')
1238 self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)])
1240 def _PackUbootSplMicrocode(self, dts, ucode_second=False):
1241 """Helper function for microcode tests
1243 We expect to see the following in the image, in order:
1244 u-boot-spl-nodtb.bin with a microcode pointer inserted at the
1246 u-boot.dtb with the microcode removed
1250 dts: Device tree file to use for test
1251 ucode_second: True if the microsecond entry is second instead of
1254 self._SetupSplElf('u_boot_ucode_ptr')
1255 first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA,
1256 ucode_second=ucode_second)
1257 self.assertEqual(b'splnodtb with microc' + pos_and_size +
1258 b'ter somewhere in here', first)
1260 def testPackUbootSplMicrocode(self):
1261 """Test that x86 microcode can be handled correctly in SPL"""
1262 self._PackUbootSplMicrocode('049_x86_ucode_spl.dts')
1264 def testPackUbootSplMicrocodeReorder(self):
1265 """Test that order doesn't matter for microcode entries
1267 This is the same as testPackUbootSplMicrocode but when we process the
1268 u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode
1269 entry, so we reply on binman to try later.
1271 self._PackUbootSplMicrocode('058_x86_ucode_spl_needs_retry.dts',
1274 def testPackMrc(self):
1275 """Test that an image with an MRC binary can be created"""
1276 data = self._DoReadFile('050_intel_mrc.dts')
1277 self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
1279 def testSplDtb(self):
1280 """Test that an image with spl/u-boot-spl.dtb can be created"""
1281 data = self._DoReadFile('051_u_boot_spl_dtb.dts')
1282 self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
1284 def testSplNoDtb(self):
1285 """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
1286 data = self._DoReadFile('052_u_boot_spl_nodtb.dts')
1287 self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
1289 def testSymbols(self):
1290 """Test binman can assign symbols embedded in U-Boot"""
1291 elf_fname = self.ElfTestFile('u_boot_binman_syms')
1292 syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
1293 addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
1294 self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
1296 self._SetupSplElf('u_boot_binman_syms')
1297 data = self._DoReadFile('053_symbols.dts')
1298 sym_values = struct.pack('<LQLL', 0x00, 0x1c, 0x28, 0x04)
1299 expected = (sym_values + U_BOOT_SPL_DATA[20:] +
1300 tools.GetBytes(0xff, 1) + U_BOOT_DATA + sym_values +
1301 U_BOOT_SPL_DATA[20:])
1302 self.assertEqual(expected, data)
1304 def testPackUnitAddress(self):
1305 """Test that we support multiple binaries with the same name"""
1306 data = self._DoReadFile('054_unit_address.dts')
1307 self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
1309 def testSections(self):
1310 """Basic test of sections"""
1311 data = self._DoReadFile('055_sections.dts')
1312 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1313 U_BOOT_DATA + tools.GetBytes(ord('a'), 12) +
1314 U_BOOT_DATA + tools.GetBytes(ord('&'), 4))
1315 self.assertEqual(expected, data)
1318 """Tests outputting a map of the images"""
1319 _, _, map_data, _ = self._DoReadFileDtb('055_sections.dts', map=True)
1320 self.assertEqual('''ImagePos Offset Size Name
1321 00000000 00000000 00000028 main-section
1322 00000000 00000000 00000010 section@0
1323 00000000 00000000 00000004 u-boot
1324 00000010 00000010 00000010 section@1
1325 00000010 00000000 00000004 u-boot
1326 00000020 00000020 00000004 section@2
1327 00000020 00000000 00000004 u-boot
1330 def testNamePrefix(self):
1331 """Tests that name prefixes are used"""
1332 _, _, map_data, _ = self._DoReadFileDtb('056_name_prefix.dts', map=True)
1333 self.assertEqual('''ImagePos Offset Size Name
1334 00000000 00000000 00000028 main-section
1335 00000000 00000000 00000010 section@0
1336 00000000 00000000 00000004 ro-u-boot
1337 00000010 00000010 00000010 section@1
1338 00000010 00000000 00000004 rw-u-boot
1341 def testUnknownContents(self):
1342 """Test that obtaining the contents works as expected"""
1343 with self.assertRaises(ValueError) as e:
1344 self._DoReadFile('057_unknown_contents.dts', True)
1345 self.assertIn("Image '/binman': Internal error: Could not complete "
1346 "processing of contents: remaining ["
1347 "<binman.etype._testing.Entry__testing ", str(e.exception))
1349 def testBadChangeSize(self):
1350 """Test that trying to change the size of an entry fails"""
1352 state.SetAllowEntryExpansion(False)
1353 with self.assertRaises(ValueError) as e:
1354 self._DoReadFile('059_change_size.dts', True)
1355 self.assertIn("Node '/binman/_testing': Cannot update entry size from 2 to 3",
1358 state.SetAllowEntryExpansion(True)
1360 def testUpdateFdt(self):
1361 """Test that we can update the device tree with offset/size info"""
1362 _, _, _, out_dtb_fname = self._DoReadFileDtb('060_fdt_update.dts',
1364 dtb = fdt.Fdt(out_dtb_fname)
1366 props = self._GetPropTree(dtb, BASE_DTB_PROPS + REPACK_DTB_PROPS)
1370 '_testing:offset': 32,
1372 '_testing:image-pos': 32,
1373 'section@0/u-boot:offset': 0,
1374 'section@0/u-boot:size': len(U_BOOT_DATA),
1375 'section@0/u-boot:image-pos': 0,
1376 'section@0:offset': 0,
1377 'section@0:size': 16,
1378 'section@0:image-pos': 0,
1380 'section@1/u-boot:offset': 0,
1381 'section@1/u-boot:size': len(U_BOOT_DATA),
1382 'section@1/u-boot:image-pos': 16,
1383 'section@1:offset': 16,
1384 'section@1:size': 16,
1385 'section@1:image-pos': 16,
1389 def testUpdateFdtBad(self):
1390 """Test that we detect when ProcessFdt never completes"""
1391 with self.assertRaises(ValueError) as e:
1392 self._DoReadFileDtb('061_fdt_update_bad.dts', update_dtb=True)
1393 self.assertIn('Could not complete processing of Fdt: remaining '
1394 '[<binman.etype._testing.Entry__testing',
1397 def testEntryArgs(self):
1398 """Test passing arguments to entries from the command line"""
1400 'test-str-arg': 'test1',
1401 'test-int-arg': '456',
1403 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
1404 self.assertIn('image', control.images)
1405 entry = control.images['image'].GetEntries()['_testing']
1406 self.assertEqual('test0', entry.test_str_fdt)
1407 self.assertEqual('test1', entry.test_str_arg)
1408 self.assertEqual(123, entry.test_int_fdt)
1409 self.assertEqual(456, entry.test_int_arg)
1411 def testEntryArgsMissing(self):
1412 """Test missing arguments and properties"""
1414 'test-int-arg': '456',
1416 self._DoReadFileDtb('063_entry_args_missing.dts', entry_args=entry_args)
1417 entry = control.images['image'].GetEntries()['_testing']
1418 self.assertEqual('test0', entry.test_str_fdt)
1419 self.assertEqual(None, entry.test_str_arg)
1420 self.assertEqual(None, entry.test_int_fdt)
1421 self.assertEqual(456, entry.test_int_arg)
1423 def testEntryArgsRequired(self):
1424 """Test missing arguments and properties"""
1426 'test-int-arg': '456',
1428 with self.assertRaises(ValueError) as e:
1429 self._DoReadFileDtb('064_entry_args_required.dts')
1430 self.assertIn("Node '/binman/_testing': "
1431 'Missing required properties/entry args: test-str-arg, '
1432 'test-int-fdt, test-int-arg',
1435 def testEntryArgsInvalidFormat(self):
1436 """Test that an invalid entry-argument format is detected"""
1437 args = ['build', '-d', self.TestFile('064_entry_args_required.dts'),
1439 with self.assertRaises(ValueError) as e:
1440 self._DoBinman(*args)
1441 self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
1443 def testEntryArgsInvalidInteger(self):
1444 """Test that an invalid entry-argument integer is detected"""
1446 'test-int-arg': 'abc',
1448 with self.assertRaises(ValueError) as e:
1449 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
1450 self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
1451 "'test-int-arg' (value 'abc') to integer",
1454 def testEntryArgsInvalidDatatype(self):
1455 """Test that an invalid entry-argument datatype is detected
1457 This test could be written in entry_test.py except that it needs
1458 access to control.entry_args, which seems more than that module should
1462 'test-bad-datatype-arg': '12',
1464 with self.assertRaises(ValueError) as e:
1465 self._DoReadFileDtb('065_entry_args_unknown_datatype.dts',
1466 entry_args=entry_args)
1467 self.assertIn('GetArg() internal error: Unknown data type ',
1471 """Test for a text entry type"""
1473 'test-id': TEXT_DATA,
1474 'test-id2': TEXT_DATA2,
1475 'test-id3': TEXT_DATA3,
1477 data, _, _, _ = self._DoReadFileDtb('066_text.dts',
1478 entry_args=entry_args)
1479 expected = (tools.ToBytes(TEXT_DATA) +
1480 tools.GetBytes(0, 8 - len(TEXT_DATA)) +
1481 tools.ToBytes(TEXT_DATA2) + tools.ToBytes(TEXT_DATA3) +
1482 b'some text' + b'more text')
1483 self.assertEqual(expected, data)
1485 def testEntryDocs(self):
1486 """Test for creation of entry documentation"""
1487 with test_util.capture_sys_output() as (stdout, stderr):
1488 control.WriteEntryDocs(control.GetEntryModules())
1489 self.assertTrue(len(stdout.getvalue()) > 0)
1491 def testEntryDocsMissing(self):
1492 """Test handling of missing entry documentation"""
1493 with self.assertRaises(ValueError) as e:
1494 with test_util.capture_sys_output() as (stdout, stderr):
1495 control.WriteEntryDocs(control.GetEntryModules(), 'u_boot')
1496 self.assertIn('Documentation is missing for modules: u_boot',
1500 """Basic test of generation of a flashrom fmap"""
1501 data = self._DoReadFile('067_fmap.dts')
1502 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1503 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1504 U_BOOT_DATA + tools.GetBytes(ord('a'), 12))
1505 self.assertEqual(expected, data[:32])
1506 self.assertEqual(b'__FMAP__', fhdr.signature)
1507 self.assertEqual(1, fhdr.ver_major)
1508 self.assertEqual(0, fhdr.ver_minor)
1509 self.assertEqual(0, fhdr.base)
1510 self.assertEqual(16 + 16 +
1511 fmap_util.FMAP_HEADER_LEN +
1512 fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
1513 self.assertEqual(b'FMAP', fhdr.name)
1514 self.assertEqual(3, fhdr.nareas)
1515 for fentry in fentries:
1516 self.assertEqual(0, fentry.flags)
1518 self.assertEqual(0, fentries[0].offset)
1519 self.assertEqual(4, fentries[0].size)
1520 self.assertEqual(b'RO_U_BOOT', fentries[0].name)
1522 self.assertEqual(16, fentries[1].offset)
1523 self.assertEqual(4, fentries[1].size)
1524 self.assertEqual(b'RW_U_BOOT', fentries[1].name)
1526 self.assertEqual(32, fentries[2].offset)
1527 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1528 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1529 self.assertEqual(b'FMAP', fentries[2].name)
1531 def testBlobNamedByArg(self):
1532 """Test we can add a blob with the filename coming from an entry arg"""
1534 'cros-ec-rw-path': 'ecrw.bin',
1536 self._DoReadFileDtb('068_blob_named_by_arg.dts', entry_args=entry_args)
1539 """Test for an fill entry type"""
1540 data = self._DoReadFile('069_fill.dts')
1541 expected = tools.GetBytes(0xff, 8) + tools.GetBytes(0, 8)
1542 self.assertEqual(expected, data)
1544 def testFillNoSize(self):
1545 """Test for an fill entry type with no size"""
1546 with self.assertRaises(ValueError) as e:
1547 self._DoReadFile('070_fill_no_size.dts')
1548 self.assertIn("'fill' entry must have a size property",
1551 def _HandleGbbCommand(self, pipe_list):
1552 """Fake calls to the futility utility"""
1553 if pipe_list[0][0] == 'futility':
1554 fname = pipe_list[0][-1]
1555 # Append our GBB data to the file, which will happen every time the
1556 # futility command is called.
1557 with open(fname, 'ab') as fd:
1559 return command.CommandResult()
1562 """Test for the Chromium OS Google Binary Block"""
1563 command.test_result = self._HandleGbbCommand
1565 'keydir': 'devkeys',
1566 'bmpblk': 'bmpblk.bin',
1568 data, _, _, _ = self._DoReadFileDtb('071_gbb.dts', entry_args=entry_args)
1571 expected = (GBB_DATA + GBB_DATA + tools.GetBytes(0, 8) +
1572 tools.GetBytes(0, 0x2180 - 16))
1573 self.assertEqual(expected, data)
1575 def testGbbTooSmall(self):
1576 """Test for the Chromium OS Google Binary Block being large enough"""
1577 with self.assertRaises(ValueError) as e:
1578 self._DoReadFileDtb('072_gbb_too_small.dts')
1579 self.assertIn("Node '/binman/gbb': GBB is too small",
1582 def testGbbNoSize(self):
1583 """Test for the Chromium OS Google Binary Block having a size"""
1584 with self.assertRaises(ValueError) as e:
1585 self._DoReadFileDtb('073_gbb_no_size.dts')
1586 self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
1589 def _HandleVblockCommand(self, pipe_list):
1590 """Fake calls to the futility utility"""
1591 if pipe_list[0][0] == 'futility':
1592 fname = pipe_list[0][3]
1593 with open(fname, 'wb') as fd:
1594 fd.write(VBLOCK_DATA)
1595 return command.CommandResult()
1597 def testVblock(self):
1598 """Test for the Chromium OS Verified Boot Block"""
1599 command.test_result = self._HandleVblockCommand
1601 'keydir': 'devkeys',
1603 data, _, _, _ = self._DoReadFileDtb('074_vblock.dts',
1604 entry_args=entry_args)
1605 expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
1606 self.assertEqual(expected, data)
1608 def testVblockNoContent(self):
1609 """Test we detect a vblock which has no content to sign"""
1610 with self.assertRaises(ValueError) as e:
1611 self._DoReadFile('075_vblock_no_content.dts')
1612 self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
1613 'property', str(e.exception))
1615 def testVblockBadPhandle(self):
1616 """Test that we detect a vblock with an invalid phandle in contents"""
1617 with self.assertRaises(ValueError) as e:
1618 self._DoReadFile('076_vblock_bad_phandle.dts')
1619 self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
1620 '1000', str(e.exception))
1622 def testVblockBadEntry(self):
1623 """Test that we detect an entry that points to a non-entry"""
1624 with self.assertRaises(ValueError) as e:
1625 self._DoReadFile('077_vblock_bad_entry.dts')
1626 self.assertIn("Node '/binman/vblock': Cannot find entry for node "
1627 "'other'", str(e.exception))
1630 """Test that an image with TPL and its device tree can be created"""
1631 # ELF file with a '__bss_size' symbol
1633 data = self._DoReadFile('078_u_boot_tpl.dts')
1634 self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
1636 def testUsesPos(self):
1637 """Test that the 'pos' property cannot be used anymore"""
1638 with self.assertRaises(ValueError) as e:
1639 data = self._DoReadFile('079_uses_pos.dts')
1640 self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
1641 "'pos'", str(e.exception))
1643 def testFillZero(self):
1644 """Test for an fill entry type with a size of 0"""
1645 data = self._DoReadFile('080_fill_empty.dts')
1646 self.assertEqual(tools.GetBytes(0, 16), data)
1648 def testTextMissing(self):
1649 """Test for a text entry type where there is no text"""
1650 with self.assertRaises(ValueError) as e:
1651 self._DoReadFileDtb('066_text.dts',)
1652 self.assertIn("Node '/binman/text': No value provided for text label "
1653 "'test-id'", str(e.exception))
1655 def testPackStart16Tpl(self):
1656 """Test that an image with an x86 start16 TPL region can be created"""
1657 data = self._DoReadFile('081_x86_start16_tpl.dts')
1658 self.assertEqual(X86_START16_TPL_DATA, data[:len(X86_START16_TPL_DATA)])
1660 def testSelectImage(self):
1661 """Test that we can select which images to build"""
1662 expected = 'Skipping images: image1'
1664 # We should only get the expected message in verbose mode
1665 for verbosity in (0, 2):
1666 with test_util.capture_sys_output() as (stdout, stderr):
1667 retcode = self._DoTestFile('006_dual_image.dts',
1668 verbosity=verbosity,
1670 self.assertEqual(0, retcode)
1672 self.assertIn(expected, stdout.getvalue())
1674 self.assertNotIn(expected, stdout.getvalue())
1676 self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
1677 self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
1678 self._CleanupOutputDir()
1680 def testUpdateFdtAll(self):
1681 """Test that all device trees are updated with offset/size info"""
1682 data = self._DoReadFileRealDtb('082_fdt_update_all.dts')
1685 'section:image-pos': 0,
1686 'u-boot-tpl-dtb:size': 513,
1687 'u-boot-spl-dtb:size': 513,
1688 'u-boot-spl-dtb:offset': 493,
1690 'section/u-boot-dtb:image-pos': 0,
1691 'u-boot-spl-dtb:image-pos': 493,
1692 'section/u-boot-dtb:size': 493,
1693 'u-boot-tpl-dtb:image-pos': 1006,
1694 'section/u-boot-dtb:offset': 0,
1695 'section:size': 493,
1697 'section:offset': 0,
1698 'u-boot-tpl-dtb:offset': 1006,
1702 # We expect three device-tree files in the output, one after the other.
1703 # Read them in sequence. We look for an 'spl' property in the SPL tree,
1704 # and 'tpl' in the TPL tree, to make sure they are distinct from the
1705 # main U-Boot tree. All three should have the same postions and offset.
1707 for item in ['', 'spl', 'tpl']:
1708 dtb = fdt.Fdt.FromData(data[start:])
1710 props = self._GetPropTree(dtb, BASE_DTB_PROPS + REPACK_DTB_PROPS +
1712 expected = dict(base_expected)
1715 self.assertEqual(expected, props)
1716 start += dtb._fdt_obj.totalsize()
1718 def testUpdateFdtOutput(self):
1719 """Test that output DTB files are updated"""
1721 data, dtb_data, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
1722 use_real_dtb=True, update_dtb=True, reset_dtbs=False)
1724 # Unfortunately, compiling a source file always results in a file
1725 # called source.dtb (see fdt_util.EnsureCompiled()). The test
1726 # source file (e.g. test/075_fdt_update_all.dts) thus does not enter
1727 # binman as a file called u-boot.dtb. To fix this, copy the file
1728 # over to the expected place.
1730 for fname in ['u-boot.dtb.out', 'spl/u-boot-spl.dtb.out',
1731 'tpl/u-boot-tpl.dtb.out']:
1732 dtb = fdt.Fdt.FromData(data[start:])
1733 size = dtb._fdt_obj.totalsize()
1734 pathname = tools.GetOutputFilename(os.path.split(fname)[1])
1735 outdata = tools.ReadFile(pathname)
1736 name = os.path.split(fname)[0]
1739 orig_indata = self._GetDtbContentsForSplTpl(dtb_data, name)
1741 orig_indata = dtb_data
1742 self.assertNotEqual(outdata, orig_indata,
1743 "Expected output file '%s' be updated" % pathname)
1744 self.assertEqual(outdata, data[start:start + size],
1745 "Expected output file '%s' to match output image" %
1751 def _decompress(self, data):
1752 return tools.Decompress(data, 'lz4')
1754 def testCompress(self):
1755 """Test compression of blobs"""
1757 data, _, _, out_dtb_fname = self._DoReadFileDtb('083_compress.dts',
1758 use_real_dtb=True, update_dtb=True)
1759 dtb = fdt.Fdt(out_dtb_fname)
1761 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
1762 orig = self._decompress(data)
1763 self.assertEquals(COMPRESS_DATA, orig)
1765 'blob:uncomp-size': len(COMPRESS_DATA),
1766 'blob:size': len(data),
1769 self.assertEqual(expected, props)
1771 def testFiles(self):
1772 """Test bringing in multiple files"""
1773 data = self._DoReadFile('084_files.dts')
1774 self.assertEqual(FILES_DATA, data)
1776 def testFilesCompress(self):
1777 """Test bringing in multiple files and compressing them"""
1779 data = self._DoReadFile('085_files_compress.dts')
1781 image = control.images['image']
1782 entries = image.GetEntries()
1783 files = entries['files']
1784 entries = files._entries
1787 for i in range(1, 3):
1789 start = entries[key].image_pos
1790 len = entries[key].size
1791 chunk = data[start:start + len]
1792 orig += self._decompress(chunk)
1794 self.assertEqual(FILES_DATA, orig)
1796 def testFilesMissing(self):
1797 """Test missing files"""
1798 with self.assertRaises(ValueError) as e:
1799 data = self._DoReadFile('086_files_none.dts')
1800 self.assertIn("Node '/binman/files': Pattern \'files/*.none\' matched "
1801 'no files', str(e.exception))
1803 def testFilesNoPattern(self):
1804 """Test missing files"""
1805 with self.assertRaises(ValueError) as e:
1806 data = self._DoReadFile('087_files_no_pattern.dts')
1807 self.assertIn("Node '/binman/files': Missing 'pattern' property",
1810 def testExpandSize(self):
1811 """Test an expanding entry"""
1812 data, _, map_data, _ = self._DoReadFileDtb('088_expand_size.dts',
1814 expect = (tools.GetBytes(ord('a'), 8) + U_BOOT_DATA +
1815 MRC_DATA + tools.GetBytes(ord('b'), 1) + U_BOOT_DATA +
1816 tools.GetBytes(ord('c'), 8) + U_BOOT_DATA +
1817 tools.GetBytes(ord('d'), 8))
1818 self.assertEqual(expect, data)
1819 self.assertEqual('''ImagePos Offset Size Name
1820 00000000 00000000 00000028 main-section
1821 00000000 00000000 00000008 fill
1822 00000008 00000008 00000004 u-boot
1823 0000000c 0000000c 00000004 section
1824 0000000c 00000000 00000003 intel-mrc
1825 00000010 00000010 00000004 u-boot2
1826 00000014 00000014 0000000c section2
1827 00000014 00000000 00000008 fill
1828 0000001c 00000008 00000004 u-boot
1829 00000020 00000020 00000008 fill2
1832 def testExpandSizeBad(self):
1833 """Test an expanding entry which fails to provide contents"""
1834 with test_util.capture_sys_output() as (stdout, stderr):
1835 with self.assertRaises(ValueError) as e:
1836 self._DoReadFileDtb('089_expand_size_bad.dts', map=True)
1837 self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
1838 'expanding entry', str(e.exception))
1841 """Test hashing of the contents of an entry"""
1842 _, _, _, out_dtb_fname = self._DoReadFileDtb('090_hash.dts',
1843 use_real_dtb=True, update_dtb=True)
1844 dtb = fdt.Fdt(out_dtb_fname)
1846 hash_node = dtb.GetNode('/binman/u-boot/hash').props['value']
1847 m = hashlib.sha256()
1848 m.update(U_BOOT_DATA)
1849 self.assertEqual(m.digest(), b''.join(hash_node.value))
1851 def testHashNoAlgo(self):
1852 with self.assertRaises(ValueError) as e:
1853 self._DoReadFileDtb('091_hash_no_algo.dts', update_dtb=True)
1854 self.assertIn("Node \'/binman/u-boot\': Missing \'algo\' property for "
1855 'hash node', str(e.exception))
1857 def testHashBadAlgo(self):
1858 with self.assertRaises(ValueError) as e:
1859 self._DoReadFileDtb('092_hash_bad_algo.dts', update_dtb=True)
1860 self.assertIn("Node '/binman/u-boot': Unknown hash algorithm",
1863 def testHashSection(self):
1864 """Test hashing of the contents of an entry"""
1865 _, _, _, out_dtb_fname = self._DoReadFileDtb('099_hash_section.dts',
1866 use_real_dtb=True, update_dtb=True)
1867 dtb = fdt.Fdt(out_dtb_fname)
1869 hash_node = dtb.GetNode('/binman/section/hash').props['value']
1870 m = hashlib.sha256()
1871 m.update(U_BOOT_DATA)
1872 m.update(tools.GetBytes(ord('a'), 16))
1873 self.assertEqual(m.digest(), b''.join(hash_node.value))
1875 def testPackUBootTplMicrocode(self):
1876 """Test that x86 microcode can be handled correctly in TPL
1878 We expect to see the following in the image, in order:
1879 u-boot-tpl-nodtb.bin with a microcode pointer inserted at the correct
1881 u-boot-tpl.dtb with the microcode removed
1884 self._SetupTplElf('u_boot_ucode_ptr')
1885 first, pos_and_size = self._RunMicrocodeTest('093_x86_tpl_ucode.dts',
1886 U_BOOT_TPL_NODTB_DATA)
1887 self.assertEqual(b'tplnodtb with microc' + pos_and_size +
1888 b'ter somewhere in here', first)
1890 def testFmapX86(self):
1891 """Basic test of generation of a flashrom fmap"""
1892 data = self._DoReadFile('094_fmap_x86.dts')
1893 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1894 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('a'), 32 - 7)
1895 self.assertEqual(expected, data[:32])
1896 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1898 self.assertEqual(0x100, fhdr.image_size)
1900 self.assertEqual(0, fentries[0].offset)
1901 self.assertEqual(4, fentries[0].size)
1902 self.assertEqual(b'U_BOOT', fentries[0].name)
1904 self.assertEqual(4, fentries[1].offset)
1905 self.assertEqual(3, fentries[1].size)
1906 self.assertEqual(b'INTEL_MRC', fentries[1].name)
1908 self.assertEqual(32, fentries[2].offset)
1909 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1910 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1911 self.assertEqual(b'FMAP', fentries[2].name)
1913 def testFmapX86Section(self):
1914 """Basic test of generation of a flashrom fmap"""
1915 data = self._DoReadFile('095_fmap_x86_section.dts')
1916 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('b'), 32 - 7)
1917 self.assertEqual(expected, data[:32])
1918 fhdr, fentries = fmap_util.DecodeFmap(data[36:])
1920 self.assertEqual(0x100, fhdr.image_size)
1922 self.assertEqual(0, fentries[0].offset)
1923 self.assertEqual(4, fentries[0].size)
1924 self.assertEqual(b'U_BOOT', fentries[0].name)
1926 self.assertEqual(4, fentries[1].offset)
1927 self.assertEqual(3, fentries[1].size)
1928 self.assertEqual(b'INTEL_MRC', fentries[1].name)
1930 self.assertEqual(36, fentries[2].offset)
1931 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1932 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1933 self.assertEqual(b'FMAP', fentries[2].name)
1936 """Basic test of ELF entries"""
1939 with open(self.ElfTestFile('bss_data'), 'rb') as fd:
1940 TestFunctional._MakeInputFile('-boot', fd.read())
1941 data = self._DoReadFile('096_elf.dts')
1943 def testElfStrip(self):
1944 """Basic test of ELF entries"""
1946 with open(self.ElfTestFile('bss_data'), 'rb') as fd:
1947 TestFunctional._MakeInputFile('-boot', fd.read())
1948 data = self._DoReadFile('097_elf_strip.dts')
1950 def testPackOverlapMap(self):
1951 """Test that overlapping regions are detected"""
1952 with test_util.capture_sys_output() as (stdout, stderr):
1953 with self.assertRaises(ValueError) as e:
1954 self._DoTestFile('014_pack_overlap.dts', map=True)
1955 map_fname = tools.GetOutputFilename('image.map')
1956 self.assertEqual("Wrote map file '%s' to show errors\n" % map_fname,
1959 # We should not get an inmage, but there should be a map file
1960 self.assertFalse(os.path.exists(tools.GetOutputFilename('image.bin')))
1961 self.assertTrue(os.path.exists(map_fname))
1962 map_data = tools.ReadFile(map_fname, binary=False)
1963 self.assertEqual('''ImagePos Offset Size Name
1964 <none> 00000000 00000007 main-section
1965 <none> 00000000 00000004 u-boot
1966 <none> 00000003 00000004 u-boot-align
1969 def testPackRefCode(self):
1970 """Test that an image with an Intel Reference code binary works"""
1971 data = self._DoReadFile('100_intel_refcode.dts')
1972 self.assertEqual(REFCODE_DATA, data[:len(REFCODE_DATA)])
1974 def testSectionOffset(self):
1975 """Tests use of a section with an offset"""
1976 data, _, map_data, _ = self._DoReadFileDtb('101_sections_offset.dts',
1978 self.assertEqual('''ImagePos Offset Size Name
1979 00000000 00000000 00000038 main-section
1980 00000004 00000004 00000010 section@0
1981 00000004 00000000 00000004 u-boot
1982 00000018 00000018 00000010 section@1
1983 00000018 00000000 00000004 u-boot
1984 0000002c 0000002c 00000004 section@2
1985 0000002c 00000000 00000004 u-boot
1987 self.assertEqual(data,
1988 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1989 tools.GetBytes(0x21, 12) +
1990 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1991 tools.GetBytes(0x61, 12) +
1992 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1993 tools.GetBytes(0x26, 8))
1995 def testCbfsRaw(self):
1996 """Test base handling of a Coreboot Filesystem (CBFS)
1998 The exact contents of the CBFS is verified by similar tests in
1999 cbfs_util_test.py. The tests here merely check that the files added to
2000 the CBFS can be found in the final image.
2002 data = self._DoReadFile('102_cbfs_raw.dts')
2005 cbfs = cbfs_util.CbfsReader(data)
2006 self.assertEqual(size, cbfs.rom_size)
2008 self.assertIn('u-boot-dtb', cbfs.files)
2009 cfile = cbfs.files['u-boot-dtb']
2010 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
2012 def testCbfsArch(self):
2013 """Test on non-x86 architecture"""
2014 data = self._DoReadFile('103_cbfs_raw_ppc.dts')
2017 cbfs = cbfs_util.CbfsReader(data)
2018 self.assertEqual(size, cbfs.rom_size)
2020 self.assertIn('u-boot-dtb', cbfs.files)
2021 cfile = cbfs.files['u-boot-dtb']
2022 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
2024 def testCbfsStage(self):
2025 """Tests handling of a Coreboot Filesystem (CBFS)"""
2026 if not elf.ELF_TOOLS:
2027 self.skipTest('Python elftools not available')
2028 elf_fname = os.path.join(self._indir, 'cbfs-stage.elf')
2029 elf.MakeElf(elf_fname, U_BOOT_DATA, U_BOOT_DTB_DATA)
2032 data = self._DoReadFile('104_cbfs_stage.dts')
2033 cbfs = cbfs_util.CbfsReader(data)
2034 self.assertEqual(size, cbfs.rom_size)
2036 self.assertIn('u-boot', cbfs.files)
2037 cfile = cbfs.files['u-boot']
2038 self.assertEqual(U_BOOT_DATA + U_BOOT_DTB_DATA, cfile.data)
2040 def testCbfsRawCompress(self):
2041 """Test handling of compressing raw files"""
2043 data = self._DoReadFile('105_cbfs_raw_compress.dts')
2046 cbfs = cbfs_util.CbfsReader(data)
2047 self.assertIn('u-boot', cbfs.files)
2048 cfile = cbfs.files['u-boot']
2049 self.assertEqual(COMPRESS_DATA, cfile.data)
2051 def testCbfsBadArch(self):
2052 """Test handling of a bad architecture"""
2053 with self.assertRaises(ValueError) as e:
2054 self._DoReadFile('106_cbfs_bad_arch.dts')
2055 self.assertIn("Invalid architecture 'bad-arch'", str(e.exception))
2057 def testCbfsNoSize(self):
2058 """Test handling of a missing size property"""
2059 with self.assertRaises(ValueError) as e:
2060 self._DoReadFile('107_cbfs_no_size.dts')
2061 self.assertIn('entry must have a size property', str(e.exception))
2063 def testCbfsNoCOntents(self):
2064 """Test handling of a CBFS entry which does not provide contentsy"""
2065 with self.assertRaises(ValueError) as e:
2066 self._DoReadFile('108_cbfs_no_contents.dts')
2067 self.assertIn('Could not complete processing of contents',
2070 def testCbfsBadCompress(self):
2071 """Test handling of a bad architecture"""
2072 with self.assertRaises(ValueError) as e:
2073 self._DoReadFile('109_cbfs_bad_compress.dts')
2074 self.assertIn("Invalid compression in 'u-boot': 'invalid-algo'",
2077 def testCbfsNamedEntries(self):
2078 """Test handling of named entries"""
2079 data = self._DoReadFile('110_cbfs_name.dts')
2081 cbfs = cbfs_util.CbfsReader(data)
2082 self.assertIn('FRED', cbfs.files)
2083 cfile1 = cbfs.files['FRED']
2084 self.assertEqual(U_BOOT_DATA, cfile1.data)
2086 self.assertIn('hello', cbfs.files)
2087 cfile2 = cbfs.files['hello']
2088 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
2090 def _SetupIfwi(self, fname):
2091 """Set up to run an IFWI test
2094 fname: Filename of input file to provide (fitimage.bin or ifwi.bin)
2099 # Intel Integrated Firmware Image (IFWI) file
2100 with gzip.open(self.TestFile('%s.gz' % fname), 'rb') as fd:
2102 TestFunctional._MakeInputFile(fname,data)
2104 def _CheckIfwi(self, data):
2105 """Check that an image with an IFWI contains the correct output
2108 data: Conents of output file
2110 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
2111 if data[:0x1000] != expected_desc:
2112 self.fail('Expected descriptor binary at start of image')
2114 # We expect to find the TPL wil in subpart IBBP entry IBBL
2115 image_fname = tools.GetOutputFilename('image.bin')
2116 tpl_fname = tools.GetOutputFilename('tpl.out')
2117 tools.RunIfwiTool(image_fname, tools.CMD_EXTRACT, fname=tpl_fname,
2118 subpart='IBBP', entry_name='IBBL')
2120 tpl_data = tools.ReadFile(tpl_fname)
2121 self.assertEqual(U_BOOT_TPL_DATA, tpl_data[:len(U_BOOT_TPL_DATA)])
2123 def testPackX86RomIfwi(self):
2124 """Test that an x86 ROM with Integrated Firmware Image can be created"""
2125 self._SetupIfwi('fitimage.bin')
2126 data = self._DoReadFile('111_x86_rom_ifwi.dts')
2127 self._CheckIfwi(data)
2129 def testPackX86RomIfwiNoDesc(self):
2130 """Test that an x86 ROM with IFWI can be created from an ifwi.bin file"""
2131 self._SetupIfwi('ifwi.bin')
2132 data = self._DoReadFile('112_x86_rom_ifwi_nodesc.dts')
2133 self._CheckIfwi(data)
2135 def testPackX86RomIfwiNoData(self):
2136 """Test that an x86 ROM with IFWI handles missing data"""
2137 self._SetupIfwi('ifwi.bin')
2138 with self.assertRaises(ValueError) as e:
2139 data = self._DoReadFile('113_x86_rom_ifwi_nodata.dts')
2140 self.assertIn('Could not complete processing of contents',
2143 def testCbfsOffset(self):
2144 """Test a CBFS with files at particular offsets
2146 Like all CFBS tests, this is just checking the logic that calls
2147 cbfs_util. See cbfs_util_test for fully tests (e.g. test_cbfs_offset()).
2149 data = self._DoReadFile('114_cbfs_offset.dts')
2152 cbfs = cbfs_util.CbfsReader(data)
2153 self.assertEqual(size, cbfs.rom_size)
2155 self.assertIn('u-boot', cbfs.files)
2156 cfile = cbfs.files['u-boot']
2157 self.assertEqual(U_BOOT_DATA, cfile.data)
2158 self.assertEqual(0x40, cfile.cbfs_offset)
2160 self.assertIn('u-boot-dtb', cbfs.files)
2161 cfile2 = cbfs.files['u-boot-dtb']
2162 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
2163 self.assertEqual(0x140, cfile2.cbfs_offset)
2165 def testFdtmap(self):
2166 """Test an FDT map can be inserted in the image"""
2167 data = self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
2168 fdtmap_data = data[len(U_BOOT_DATA):]
2169 magic = fdtmap_data[:8]
2170 self.assertEqual(b'_FDTMAP_', magic)
2171 self.assertEqual(tools.GetBytes(0, 8), fdtmap_data[8:16])
2173 fdt_data = fdtmap_data[16:]
2174 dtb = fdt.Fdt.FromData(fdt_data)
2176 props = self._GetPropTree(dtb, BASE_DTB_PROPS, prefix='/')
2181 'u-boot:size': len(U_BOOT_DATA),
2182 'u-boot:image-pos': 0,
2183 'fdtmap:image-pos': 4,
2185 'fdtmap:size': len(fdtmap_data),
2189 def testFdtmapNoMatch(self):
2190 """Check handling of an FDT map when the section cannot be found"""
2191 self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
2193 # Mangle the section name, which should cause a mismatch between the
2194 # correct FDT path and the one expected by the section
2195 image = control.images['image']
2196 image._node.path += '-suffix'
2197 entries = image.GetEntries()
2198 fdtmap = entries['fdtmap']
2199 with self.assertRaises(ValueError) as e:
2201 self.assertIn("Cannot locate node for path '/binman-suffix'",
2204 def testFdtmapHeader(self):
2205 """Test an FDT map and image header can be inserted in the image"""
2206 data = self.data = self._DoReadFileRealDtb('116_fdtmap_hdr.dts')
2207 fdtmap_pos = len(U_BOOT_DATA)
2208 fdtmap_data = data[fdtmap_pos:]
2209 fdt_data = fdtmap_data[16:]
2210 dtb = fdt.Fdt.FromData(fdt_data)
2211 fdt_size = dtb.GetFdtObj().totalsize()
2212 hdr_data = data[-8:]
2213 self.assertEqual(b'BinM', hdr_data[:4])
2214 offset = struct.unpack('<I', hdr_data[4:])[0] & 0xffffffff
2215 self.assertEqual(fdtmap_pos - 0x400, offset - (1 << 32))
2217 def testFdtmapHeaderStart(self):
2218 """Test an image header can be inserted at the image start"""
2219 data = self.data = self._DoReadFileRealDtb('117_fdtmap_hdr_start.dts')
2220 fdtmap_pos = 0x100 + len(U_BOOT_DATA)
2222 self.assertEqual(b'BinM', hdr_data[:4])
2223 offset = struct.unpack('<I', hdr_data[4:])[0]
2224 self.assertEqual(fdtmap_pos, offset)
2226 def testFdtmapHeaderPos(self):
2227 """Test an image header can be inserted at a chosen position"""
2228 data = self.data = self._DoReadFileRealDtb('118_fdtmap_hdr_pos.dts')
2229 fdtmap_pos = 0x100 + len(U_BOOT_DATA)
2230 hdr_data = data[0x80:0x88]
2231 self.assertEqual(b'BinM', hdr_data[:4])
2232 offset = struct.unpack('<I', hdr_data[4:])[0]
2233 self.assertEqual(fdtmap_pos, offset)
2235 def testHeaderMissingFdtmap(self):
2236 """Test an image header requires an fdtmap"""
2237 with self.assertRaises(ValueError) as e:
2238 self.data = self._DoReadFileRealDtb('119_fdtmap_hdr_missing.dts')
2239 self.assertIn("'image_header' section must have an 'fdtmap' sibling",
2242 def testHeaderNoLocation(self):
2243 """Test an image header with a no specified location is detected"""
2244 with self.assertRaises(ValueError) as e:
2245 self.data = self._DoReadFileRealDtb('120_hdr_no_location.dts')
2246 self.assertIn("Invalid location 'None', expected 'start' or 'end'",
2249 def testEntryExpand(self):
2250 """Test expanding an entry after it is packed"""
2251 data = self._DoReadFile('121_entry_expand.dts')
2252 self.assertEqual(b'aaa', data[:3])
2253 self.assertEqual(U_BOOT_DATA, data[3:3 + len(U_BOOT_DATA)])
2254 self.assertEqual(b'aaa', data[-3:])
2256 def testEntryExpandBad(self):
2257 """Test expanding an entry after it is packed, twice"""
2258 with self.assertRaises(ValueError) as e:
2259 self._DoReadFile('122_entry_expand_twice.dts')
2260 self.assertIn("Image '/binman': Entries changed size after packing",
2263 def testEntryExpandSection(self):
2264 """Test expanding an entry within a section after it is packed"""
2265 data = self._DoReadFile('123_entry_expand_section.dts')
2266 self.assertEqual(b'aaa', data[:3])
2267 self.assertEqual(U_BOOT_DATA, data[3:3 + len(U_BOOT_DATA)])
2268 self.assertEqual(b'aaa', data[-3:])
2270 def testCompressDtb(self):
2271 """Test that compress of device-tree files is supported"""
2273 data = self.data = self._DoReadFileRealDtb('124_compress_dtb.dts')
2274 self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
2275 comp_data = data[len(U_BOOT_DATA):]
2276 orig = self._decompress(comp_data)
2277 dtb = fdt.Fdt.FromData(orig)
2279 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
2281 'u-boot:size': len(U_BOOT_DATA),
2282 'u-boot-dtb:uncomp-size': len(orig),
2283 'u-boot-dtb:size': len(comp_data),
2286 self.assertEqual(expected, props)
2288 def testCbfsUpdateFdt(self):
2289 """Test that we can update the device tree with CBFS offset/size info"""
2291 data, _, _, out_dtb_fname = self._DoReadFileDtb('125_cbfs_update.dts',
2293 dtb = fdt.Fdt(out_dtb_fname)
2295 props = self._GetPropTree(dtb, BASE_DTB_PROPS + ['uncomp-size'])
2296 del props['cbfs/u-boot:size']
2302 'cbfs:size': len(data),
2303 'cbfs:image-pos': 0,
2304 'cbfs/u-boot:offset': 0x38,
2305 'cbfs/u-boot:uncomp-size': len(U_BOOT_DATA),
2306 'cbfs/u-boot:image-pos': 0x38,
2307 'cbfs/u-boot-dtb:offset': 0xb8,
2308 'cbfs/u-boot-dtb:size': len(U_BOOT_DATA),
2309 'cbfs/u-boot-dtb:image-pos': 0xb8,
2312 def testCbfsBadType(self):
2313 """Test an image header with a no specified location is detected"""
2314 with self.assertRaises(ValueError) as e:
2315 self._DoReadFile('126_cbfs_bad_type.dts')
2316 self.assertIn("Unknown cbfs-type 'badtype'", str(e.exception))
2319 """Test listing the files in an image"""
2321 data = self._DoReadFile('127_list.dts')
2322 image = control.images['image']
2323 entries = image.BuildEntryList()
2324 self.assertEqual(7, len(entries))
2327 self.assertEqual(0, ent.indent)
2328 self.assertEqual('main-section', ent.name)
2329 self.assertEqual('section', ent.etype)
2330 self.assertEqual(len(data), ent.size)
2331 self.assertEqual(0, ent.image_pos)
2332 self.assertEqual(None, ent.uncomp_size)
2333 self.assertEqual(0, ent.offset)
2336 self.assertEqual(1, ent.indent)
2337 self.assertEqual('u-boot', ent.name)
2338 self.assertEqual('u-boot', ent.etype)
2339 self.assertEqual(len(U_BOOT_DATA), ent.size)
2340 self.assertEqual(0, ent.image_pos)
2341 self.assertEqual(None, ent.uncomp_size)
2342 self.assertEqual(0, ent.offset)
2345 self.assertEqual(1, ent.indent)
2346 self.assertEqual('section', ent.name)
2347 self.assertEqual('section', ent.etype)
2348 section_size = ent.size
2349 self.assertEqual(0x100, ent.image_pos)
2350 self.assertEqual(None, ent.uncomp_size)
2351 self.assertEqual(0x100, ent.offset)
2354 self.assertEqual(2, ent.indent)
2355 self.assertEqual('cbfs', ent.name)
2356 self.assertEqual('cbfs', ent.etype)
2357 self.assertEqual(0x400, ent.size)
2358 self.assertEqual(0x100, ent.image_pos)
2359 self.assertEqual(None, ent.uncomp_size)
2360 self.assertEqual(0, ent.offset)
2363 self.assertEqual(3, ent.indent)
2364 self.assertEqual('u-boot', ent.name)
2365 self.assertEqual('u-boot', ent.etype)
2366 self.assertEqual(len(U_BOOT_DATA), ent.size)
2367 self.assertEqual(0x138, ent.image_pos)
2368 self.assertEqual(None, ent.uncomp_size)
2369 self.assertEqual(0x38, ent.offset)
2372 self.assertEqual(3, ent.indent)
2373 self.assertEqual('u-boot-dtb', ent.name)
2374 self.assertEqual('text', ent.etype)
2375 self.assertGreater(len(COMPRESS_DATA), ent.size)
2376 self.assertEqual(0x178, ent.image_pos)
2377 self.assertEqual(len(COMPRESS_DATA), ent.uncomp_size)
2378 self.assertEqual(0x78, ent.offset)
2381 self.assertEqual(2, ent.indent)
2382 self.assertEqual('u-boot-dtb', ent.name)
2383 self.assertEqual('u-boot-dtb', ent.etype)
2384 self.assertEqual(0x500, ent.image_pos)
2385 self.assertEqual(len(U_BOOT_DTB_DATA), ent.uncomp_size)
2387 # Compressing this data expands it since headers are added
2388 self.assertGreater(dtb_size, len(U_BOOT_DTB_DATA))
2389 self.assertEqual(0x400, ent.offset)
2391 self.assertEqual(len(data), 0x100 + section_size)
2392 self.assertEqual(section_size, 0x400 + dtb_size)
2394 def testFindFdtmap(self):
2395 """Test locating an FDT map in an image"""
2397 data = self.data = self._DoReadFileRealDtb('128_decode_image.dts')
2398 image = control.images['image']
2399 entries = image.GetEntries()
2400 entry = entries['fdtmap']
2401 self.assertEqual(entry.image_pos, fdtmap.LocateFdtmap(data))
2403 def testFindFdtmapMissing(self):
2404 """Test failing to locate an FDP map"""
2405 data = self._DoReadFile('005_simple.dts')
2406 self.assertEqual(None, fdtmap.LocateFdtmap(data))
2408 def testFindImageHeader(self):
2409 """Test locating a image header"""
2411 data = self.data = self._DoReadFileRealDtb('128_decode_image.dts')
2412 image = control.images['image']
2413 entries = image.GetEntries()
2414 entry = entries['fdtmap']
2415 # The header should point to the FDT map
2416 self.assertEqual(entry.image_pos, image_header.LocateHeaderOffset(data))
2418 def testFindImageHeaderStart(self):
2419 """Test locating a image header located at the start of an image"""
2420 data = self.data = self._DoReadFileRealDtb('117_fdtmap_hdr_start.dts')
2421 image = control.images['image']
2422 entries = image.GetEntries()
2423 entry = entries['fdtmap']
2424 # The header should point to the FDT map
2425 self.assertEqual(entry.image_pos, image_header.LocateHeaderOffset(data))
2427 def testFindImageHeaderMissing(self):
2428 """Test failing to locate an image header"""
2429 data = self._DoReadFile('005_simple.dts')
2430 self.assertEqual(None, image_header.LocateHeaderOffset(data))
2432 def testReadImage(self):
2433 """Test reading an image and accessing its FDT map"""
2435 data = self.data = self._DoReadFileRealDtb('128_decode_image.dts')
2436 image_fname = tools.GetOutputFilename('image.bin')
2437 orig_image = control.images['image']
2438 image = Image.FromFile(image_fname)
2439 self.assertEqual(orig_image.GetEntries().keys(),
2440 image.GetEntries().keys())
2442 orig_entry = orig_image.GetEntries()['fdtmap']
2443 entry = image.GetEntries()['fdtmap']
2444 self.assertEquals(orig_entry.offset, entry.offset)
2445 self.assertEquals(orig_entry.size, entry.size)
2446 self.assertEquals(orig_entry.image_pos, entry.image_pos)
2448 def testReadImageNoHeader(self):
2449 """Test accessing an image's FDT map without an image header"""
2451 data = self._DoReadFileRealDtb('129_decode_image_nohdr.dts')
2452 image_fname = tools.GetOutputFilename('image.bin')
2453 image = Image.FromFile(image_fname)
2454 self.assertTrue(isinstance(image, Image))
2455 self.assertEqual('image', image.image_name[-5:])
2457 def testReadImageFail(self):
2458 """Test failing to read an image image's FDT map"""
2459 self._DoReadFile('005_simple.dts')
2460 image_fname = tools.GetOutputFilename('image.bin')
2461 with self.assertRaises(ValueError) as e:
2462 image = Image.FromFile(image_fname)
2463 self.assertIn("Cannot find FDT map in image", str(e.exception))
2465 def testListCmd(self):
2466 """Test listing the files in an image using an Fdtmap"""
2468 data = self._DoReadFileRealDtb('130_list_fdtmap.dts')
2470 # lz4 compression size differs depending on the version
2471 image = control.images['image']
2472 entries = image.GetEntries()
2473 section_size = entries['section'].size
2474 fdt_size = entries['section'].GetEntries()['u-boot-dtb'].size
2475 fdtmap_offset = entries['fdtmap'].offset
2478 tmpdir, updated_fname = self._SetupImageInTmpdir()
2479 with test_util.capture_sys_output() as (stdout, stderr):
2480 self._DoBinman('ls', '-i', updated_fname)
2482 shutil.rmtree(tmpdir)
2483 lines = stdout.getvalue().splitlines()
2485 'Name Image-pos Size Entry-type Offset Uncomp-size',
2486 '----------------------------------------------------------------------',
2487 'main-section 0 c00 section 0',
2488 ' u-boot 0 4 u-boot 0',
2489 ' section 100 %x section 100' % section_size,
2490 ' cbfs 100 400 cbfs 0',
2491 ' u-boot 138 4 u-boot 38',
2492 ' u-boot-dtb 180 105 u-boot-dtb 80 3c9',
2493 ' u-boot-dtb 500 %x u-boot-dtb 400 3c9' % fdt_size,
2494 ' fdtmap %x 3bd fdtmap %x' %
2495 (fdtmap_offset, fdtmap_offset),
2496 ' image-header bf8 8 image-header bf8',
2498 self.assertEqual(expected, lines)
2500 def testListCmdFail(self):
2501 """Test failing to list an image"""
2502 self._DoReadFile('005_simple.dts')
2504 tmpdir, updated_fname = self._SetupImageInTmpdir()
2505 with self.assertRaises(ValueError) as e:
2506 self._DoBinman('ls', '-i', updated_fname)
2508 shutil.rmtree(tmpdir)
2509 self.assertIn("Cannot find FDT map in image", str(e.exception))
2511 def _RunListCmd(self, paths, expected):
2512 """List out entries and check the result
2515 paths: List of paths to pass to the list command
2516 expected: Expected list of filenames to be returned, in order
2519 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2520 image_fname = tools.GetOutputFilename('image.bin')
2521 image = Image.FromFile(image_fname)
2522 lines = image.GetListEntries(paths)[1]
2523 files = [line[0].strip() for line in lines[1:]]
2524 self.assertEqual(expected, files)
2526 def testListCmdSection(self):
2527 """Test listing the files in a section"""
2528 self._RunListCmd(['section'],
2529 ['section', 'cbfs', 'u-boot', 'u-boot-dtb', 'u-boot-dtb'])
2531 def testListCmdFile(self):
2532 """Test listing a particular file"""
2533 self._RunListCmd(['*u-boot-dtb'], ['u-boot-dtb', 'u-boot-dtb'])
2535 def testListCmdWildcard(self):
2536 """Test listing a wildcarded file"""
2537 self._RunListCmd(['*boot*'],
2538 ['u-boot', 'u-boot', 'u-boot-dtb', 'u-boot-dtb'])
2540 def testListCmdWildcardMulti(self):
2541 """Test listing a wildcarded file"""
2542 self._RunListCmd(['*cb*', '*head*'],
2543 ['cbfs', 'u-boot', 'u-boot-dtb', 'image-header'])
2545 def testListCmdEmpty(self):
2546 """Test listing a wildcarded file"""
2547 self._RunListCmd(['nothing'], [])
2549 def testListCmdPath(self):
2550 """Test listing the files in a sub-entry of a section"""
2551 self._RunListCmd(['section/cbfs'], ['cbfs', 'u-boot', 'u-boot-dtb'])
2553 def _RunExtractCmd(self, entry_name, decomp=True):
2554 """Extract an entry from an image
2557 entry_name: Entry name to extract
2558 decomp: True to decompress the data if compressed, False to leave
2559 it in its raw uncompressed format
2565 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2566 image_fname = tools.GetOutputFilename('image.bin')
2567 return control.ReadEntry(image_fname, entry_name, decomp)
2569 def testExtractSimple(self):
2570 """Test extracting a single file"""
2571 data = self._RunExtractCmd('u-boot')
2572 self.assertEqual(U_BOOT_DATA, data)
2574 def testExtractSection(self):
2575 """Test extracting the files in a section"""
2576 data = self._RunExtractCmd('section')
2577 cbfs_data = data[:0x400]
2578 cbfs = cbfs_util.CbfsReader(cbfs_data)
2579 self.assertEqual(['u-boot', 'u-boot-dtb', ''], list(cbfs.files.keys()))
2580 dtb_data = data[0x400:]
2581 dtb = self._decompress(dtb_data)
2582 self.assertEqual(EXTRACT_DTB_SIZE, len(dtb))
2584 def testExtractCompressed(self):
2585 """Test extracting compressed data"""
2586 data = self._RunExtractCmd('section/u-boot-dtb')
2587 self.assertEqual(EXTRACT_DTB_SIZE, len(data))
2589 def testExtractRaw(self):
2590 """Test extracting compressed data without decompressing it"""
2591 data = self._RunExtractCmd('section/u-boot-dtb', decomp=False)
2592 dtb = self._decompress(data)
2593 self.assertEqual(EXTRACT_DTB_SIZE, len(dtb))
2595 def testExtractCbfs(self):
2596 """Test extracting CBFS data"""
2597 data = self._RunExtractCmd('section/cbfs/u-boot')
2598 self.assertEqual(U_BOOT_DATA, data)
2600 def testExtractCbfsCompressed(self):
2601 """Test extracting CBFS compressed data"""
2602 data = self._RunExtractCmd('section/cbfs/u-boot-dtb')
2603 self.assertEqual(EXTRACT_DTB_SIZE, len(data))
2605 def testExtractCbfsRaw(self):
2606 """Test extracting CBFS compressed data without decompressing it"""
2607 data = self._RunExtractCmd('section/cbfs/u-boot-dtb', decomp=False)
2608 dtb = tools.Decompress(data, 'lzma', with_header=False)
2609 self.assertEqual(EXTRACT_DTB_SIZE, len(dtb))
2611 def testExtractBadEntry(self):
2612 """Test extracting a bad section path"""
2613 with self.assertRaises(ValueError) as e:
2614 self._RunExtractCmd('section/does-not-exist')
2615 self.assertIn("Entry 'does-not-exist' not found in '/section'",
2618 def testExtractMissingFile(self):
2619 """Test extracting file that does not exist"""
2620 with self.assertRaises(IOError) as e:
2621 control.ReadEntry('missing-file', 'name')
2623 def testExtractBadFile(self):
2624 """Test extracting an invalid file"""
2625 fname = os.path.join(self._indir, 'badfile')
2626 tools.WriteFile(fname, b'')
2627 with self.assertRaises(ValueError) as e:
2628 control.ReadEntry(fname, 'name')
2630 def testExtractCmd(self):
2631 """Test extracting a file fron an image on the command line"""
2633 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2634 fname = os.path.join(self._indir, 'output.extact')
2636 tmpdir, updated_fname = self._SetupImageInTmpdir()
2637 with test_util.capture_sys_output() as (stdout, stderr):
2638 self._DoBinman('extract', '-i', updated_fname, 'u-boot',
2641 shutil.rmtree(tmpdir)
2642 data = tools.ReadFile(fname)
2643 self.assertEqual(U_BOOT_DATA, data)
2645 def testExtractOneEntry(self):
2646 """Test extracting a single entry fron an image """
2648 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2649 image_fname = tools.GetOutputFilename('image.bin')
2650 fname = os.path.join(self._indir, 'output.extact')
2651 control.ExtractEntries(image_fname, fname, None, ['u-boot'])
2652 data = tools.ReadFile(fname)
2653 self.assertEqual(U_BOOT_DATA, data)
2655 def _CheckExtractOutput(self, decomp):
2656 """Helper to test file output with and without decompression
2659 decomp: True to decompress entry data, False to output it raw
2661 def _CheckPresent(entry_path, expect_data, expect_size=None):
2662 """Check and remove expected file
2664 This checks the data/size of a file and removes the file both from
2665 the outfiles set and from the output directory. Once all files are
2666 processed, both the set and directory should be empty.
2669 entry_path: Entry path
2670 expect_data: Data to expect in file, or None to skip check
2671 expect_size: Size of data to expect in file, or None to skip
2673 path = os.path.join(outdir, entry_path)
2674 data = tools.ReadFile(path)
2677 self.assertEqual(expect_data, data)
2679 self.assertEqual(expect_size, len(data))
2680 outfiles.remove(path)
2682 def _CheckDirPresent(name):
2683 """Remove expected directory
2685 This gives an error if the directory does not exist as expected
2688 name: Name of directory to remove
2690 path = os.path.join(outdir, name)
2693 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2694 image_fname = tools.GetOutputFilename('image.bin')
2695 outdir = os.path.join(self._indir, 'extract')
2696 einfos = control.ExtractEntries(image_fname, None, outdir, [], decomp)
2698 # Create a set of all file that were output (should be 9)
2700 for root, dirs, files in os.walk(outdir):
2701 outfiles |= set([os.path.join(root, fname) for fname in files])
2702 self.assertEqual(9, len(outfiles))
2703 self.assertEqual(9, len(einfos))
2705 image = control.images['image']
2706 entries = image.GetEntries()
2708 # Check the 9 files in various ways
2709 section = entries['section']
2710 section_entries = section.GetEntries()
2711 cbfs_entries = section_entries['cbfs'].GetEntries()
2712 _CheckPresent('u-boot', U_BOOT_DATA)
2713 _CheckPresent('section/cbfs/u-boot', U_BOOT_DATA)
2714 dtb_len = EXTRACT_DTB_SIZE
2716 dtb_len = cbfs_entries['u-boot-dtb'].size
2717 _CheckPresent('section/cbfs/u-boot-dtb', None, dtb_len)
2719 dtb_len = section_entries['u-boot-dtb'].size
2720 _CheckPresent('section/u-boot-dtb', None, dtb_len)
2722 fdtmap = entries['fdtmap']
2723 _CheckPresent('fdtmap', fdtmap.data)
2724 hdr = entries['image-header']
2725 _CheckPresent('image-header', hdr.data)
2727 _CheckPresent('section/root', section.data)
2728 cbfs = section_entries['cbfs']
2729 _CheckPresent('section/cbfs/root', cbfs.data)
2730 data = tools.ReadFile(image_fname)
2731 _CheckPresent('root', data)
2733 # There should be no files left. Remove all the directories to check.
2734 # If there are any files/dirs remaining, one of these checks will fail.
2735 self.assertEqual(0, len(outfiles))
2736 _CheckDirPresent('section/cbfs')
2737 _CheckDirPresent('section')
2738 _CheckDirPresent('')
2739 self.assertFalse(os.path.exists(outdir))
2741 def testExtractAllEntries(self):
2742 """Test extracting all entries"""
2744 self._CheckExtractOutput(decomp=True)
2746 def testExtractAllEntriesRaw(self):
2747 """Test extracting all entries without decompressing them"""
2749 self._CheckExtractOutput(decomp=False)
2751 def testExtractSelectedEntries(self):
2752 """Test extracting some entries"""
2754 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2755 image_fname = tools.GetOutputFilename('image.bin')
2756 outdir = os.path.join(self._indir, 'extract')
2757 einfos = control.ExtractEntries(image_fname, None, outdir,
2760 # File output is tested by testExtractAllEntries(), so just check that
2761 # the expected entries are selected
2762 names = [einfo.name for einfo in einfos]
2763 self.assertEqual(names,
2764 ['cbfs', 'u-boot', 'u-boot-dtb', 'image-header'])
2766 def testExtractNoEntryPaths(self):
2767 """Test extracting some entries"""
2769 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2770 image_fname = tools.GetOutputFilename('image.bin')
2771 with self.assertRaises(ValueError) as e:
2772 control.ExtractEntries(image_fname, 'fname', None, [])
2773 self.assertIn('Must specify an entry path to write with -f',
2776 def testExtractTooManyEntryPaths(self):
2777 """Test extracting some entries"""
2779 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2780 image_fname = tools.GetOutputFilename('image.bin')
2781 with self.assertRaises(ValueError) as e:
2782 control.ExtractEntries(image_fname, 'fname', None, ['a', 'b'])
2783 self.assertIn('Must specify exactly one entry path to write with -f',
2786 def testPackAlignSection(self):
2787 """Test that sections can have alignment"""
2788 self._DoReadFile('131_pack_align_section.dts')
2790 self.assertIn('image', control.images)
2791 image = control.images['image']
2792 entries = image.GetEntries()
2793 self.assertEqual(3, len(entries))
2796 self.assertIn('u-boot', entries)
2797 entry = entries['u-boot']
2798 self.assertEqual(0, entry.offset)
2799 self.assertEqual(0, entry.image_pos)
2800 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2801 self.assertEqual(len(U_BOOT_DATA), entry.size)
2804 self.assertIn('section0', entries)
2805 section0 = entries['section0']
2806 self.assertEqual(0x10, section0.offset)
2807 self.assertEqual(0x10, section0.image_pos)
2808 self.assertEqual(len(U_BOOT_DATA), section0.size)
2811 section_entries = section0.GetEntries()
2812 self.assertIn('u-boot', section_entries)
2813 entry = section_entries['u-boot']
2814 self.assertEqual(0, entry.offset)
2815 self.assertEqual(0x10, entry.image_pos)
2816 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2817 self.assertEqual(len(U_BOOT_DATA), entry.size)
2820 self.assertIn('section1', entries)
2821 section1 = entries['section1']
2822 self.assertEqual(0x14, section1.offset)
2823 self.assertEqual(0x14, section1.image_pos)
2824 self.assertEqual(0x20, section1.size)
2827 section_entries = section1.GetEntries()
2828 self.assertIn('u-boot', section_entries)
2829 entry = section_entries['u-boot']
2830 self.assertEqual(0, entry.offset)
2831 self.assertEqual(0x14, entry.image_pos)
2832 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2833 self.assertEqual(len(U_BOOT_DATA), entry.size)
2836 self.assertIn('section2', section_entries)
2837 section2 = section_entries['section2']
2838 self.assertEqual(0x4, section2.offset)
2839 self.assertEqual(0x18, section2.image_pos)
2840 self.assertEqual(4, section2.size)
2843 section_entries = section2.GetEntries()
2844 self.assertIn('u-boot', section_entries)
2845 entry = section_entries['u-boot']
2846 self.assertEqual(0, entry.offset)
2847 self.assertEqual(0x18, entry.image_pos)
2848 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2849 self.assertEqual(len(U_BOOT_DATA), entry.size)
2851 def _RunReplaceCmd(self, entry_name, data, decomp=True, allow_resize=True,
2852 dts='132_replace.dts'):
2853 """Replace an entry in an image
2855 This writes the entry data to update it, then opens the updated file and
2856 returns the value that it now finds there.
2859 entry_name: Entry name to replace
2860 data: Data to replace it with
2861 decomp: True to compress the data if needed, False if data is
2862 already compressed so should be used as is
2863 allow_resize: True to allow entries to change size, False to raise
2869 data from fdtmap (excluding header)
2870 Image object that was modified
2872 dtb_data = self._DoReadFileDtb(dts, use_real_dtb=True,
2875 self.assertIn('image', control.images)
2876 image = control.images['image']
2877 entries = image.GetEntries()
2878 orig_dtb_data = entries['u-boot-dtb'].data
2879 orig_fdtmap_data = entries['fdtmap'].data
2881 image_fname = tools.GetOutputFilename('image.bin')
2882 updated_fname = tools.GetOutputFilename('image-updated.bin')
2883 tools.WriteFile(updated_fname, tools.ReadFile(image_fname))
2884 image = control.WriteEntry(updated_fname, entry_name, data, decomp,
2886 data = control.ReadEntry(updated_fname, entry_name, decomp)
2888 # The DT data should not change unless resized:
2889 if not allow_resize:
2890 new_dtb_data = entries['u-boot-dtb'].data
2891 self.assertEqual(new_dtb_data, orig_dtb_data)
2892 new_fdtmap_data = entries['fdtmap'].data
2893 self.assertEqual(new_fdtmap_data, orig_fdtmap_data)
2895 return data, orig_fdtmap_data[fdtmap.FDTMAP_HDR_LEN:], image
2897 def testReplaceSimple(self):
2898 """Test replacing a single file"""
2899 expected = b'x' * len(U_BOOT_DATA)
2900 data, expected_fdtmap, _ = self._RunReplaceCmd('u-boot', expected,
2902 self.assertEqual(expected, data)
2904 # Test that the state looks right. There should be an FDT for the fdtmap
2905 # that we jsut read back in, and it should match what we find in the
2906 # 'control' tables. Checking for an FDT that does not exist should
2908 path, fdtmap = state.GetFdtContents('fdtmap')
2909 self.assertIsNotNone(path)
2910 self.assertEqual(expected_fdtmap, fdtmap)
2912 dtb = state.GetFdtForEtype('fdtmap')
2913 self.assertEqual(dtb.GetContents(), fdtmap)
2915 missing_path, missing_fdtmap = state.GetFdtContents('missing')
2916 self.assertIsNone(missing_path)
2917 self.assertIsNone(missing_fdtmap)
2919 missing_dtb = state.GetFdtForEtype('missing')
2920 self.assertIsNone(missing_dtb)
2922 self.assertEqual('/binman', state.fdt_path_prefix)
2924 def testReplaceResizeFail(self):
2925 """Test replacing a file by something larger"""
2926 expected = U_BOOT_DATA + b'x'
2927 with self.assertRaises(ValueError) as e:
2928 self._RunReplaceCmd('u-boot', expected, allow_resize=False,
2929 dts='139_replace_repack.dts')
2930 self.assertIn("Node '/u-boot': Entry data size does not match, but resize is disabled",
2933 def testReplaceMulti(self):
2934 """Test replacing entry data where multiple images are generated"""
2935 data = self._DoReadFileDtb('133_replace_multi.dts', use_real_dtb=True,
2937 expected = b'x' * len(U_BOOT_DATA)
2938 updated_fname = tools.GetOutputFilename('image-updated.bin')
2939 tools.WriteFile(updated_fname, data)
2940 entry_name = 'u-boot'
2941 control.WriteEntry(updated_fname, entry_name, expected,
2943 data = control.ReadEntry(updated_fname, entry_name)
2944 self.assertEqual(expected, data)
2946 # Check the state looks right.
2947 self.assertEqual('/binman/image', state.fdt_path_prefix)
2949 # Now check we can write the first image
2950 image_fname = tools.GetOutputFilename('first-image.bin')
2951 updated_fname = tools.GetOutputFilename('first-updated.bin')
2952 tools.WriteFile(updated_fname, tools.ReadFile(image_fname))
2953 entry_name = 'u-boot'
2954 control.WriteEntry(updated_fname, entry_name, expected,
2956 data = control.ReadEntry(updated_fname, entry_name)
2957 self.assertEqual(expected, data)
2959 # Check the state looks right.
2960 self.assertEqual('/binman/first-image', state.fdt_path_prefix)
2962 def testUpdateFdtAllRepack(self):
2963 """Test that all device trees are updated with offset/size info"""
2964 data = self._DoReadFileRealDtb('134_fdt_update_all_repack.dts')
2965 SECTION_SIZE = 0x300
2970 'size': SECTION_SIZE + DTB_SIZE * 2 + FDTMAP_SIZE,
2972 'section:offset': 0,
2973 'section:size': SECTION_SIZE,
2974 'section:image-pos': 0,
2975 'section/u-boot-dtb:offset': 4,
2976 'section/u-boot-dtb:size': 636,
2977 'section/u-boot-dtb:image-pos': 4,
2978 'u-boot-spl-dtb:offset': SECTION_SIZE,
2979 'u-boot-spl-dtb:size': DTB_SIZE,
2980 'u-boot-spl-dtb:image-pos': SECTION_SIZE,
2981 'u-boot-tpl-dtb:offset': SECTION_SIZE + DTB_SIZE,
2982 'u-boot-tpl-dtb:image-pos': SECTION_SIZE + DTB_SIZE,
2983 'u-boot-tpl-dtb:size': DTB_SIZE,
2984 'fdtmap:offset': SECTION_SIZE + DTB_SIZE * 2,
2985 'fdtmap:size': FDTMAP_SIZE,
2986 'fdtmap:image-pos': SECTION_SIZE + DTB_SIZE * 2,
2989 'section:orig-size': SECTION_SIZE,
2990 'section/u-boot-dtb:orig-offset': 4,
2993 # We expect three device-tree files in the output, with the first one
2994 # within a fixed-size section.
2995 # Read them in sequence. We look for an 'spl' property in the SPL tree,
2996 # and 'tpl' in the TPL tree, to make sure they are distinct from the
2997 # main U-Boot tree. All three should have the same positions and offset
2998 # except that the main tree should include the main_expected properties
3000 for item in ['', 'spl', 'tpl', None]:
3002 start += 16 # Move past fdtmap header
3003 dtb = fdt.Fdt.FromData(data[start:])
3005 props = self._GetPropTree(dtb,
3006 BASE_DTB_PROPS + REPACK_DTB_PROPS + ['spl', 'tpl'],
3007 prefix='/' if item is None else '/binman/')
3008 expected = dict(base_expected)
3012 # Main DTB and fdtdec should include the 'orig-' properties
3013 expected.update(main_expected)
3014 # Helpful for debugging:
3015 #for prop in sorted(props):
3016 #print('prop %s %s %s' % (prop, props[prop], expected[prop]))
3017 self.assertEqual(expected, props)
3019 start = SECTION_SIZE
3021 start += dtb._fdt_obj.totalsize()
3023 def testFdtmapHeaderMiddle(self):
3024 """Test an FDT map in the middle of an image when it should be at end"""
3025 with self.assertRaises(ValueError) as e:
3026 self._DoReadFileRealDtb('135_fdtmap_hdr_middle.dts')
3027 self.assertIn("Invalid sibling order 'middle' for image-header: Must be at 'end' to match location",
3030 def testFdtmapHeaderStartBad(self):
3031 """Test an FDT map in middle of an image when it should be at start"""
3032 with self.assertRaises(ValueError) as e:
3033 self._DoReadFileRealDtb('136_fdtmap_hdr_startbad.dts')
3034 self.assertIn("Invalid sibling order 'end' for image-header: Must be at 'start' to match location",
3037 def testFdtmapHeaderEndBad(self):
3038 """Test an FDT map at the start of an image when it should be at end"""
3039 with self.assertRaises(ValueError) as e:
3040 self._DoReadFileRealDtb('137_fdtmap_hdr_endbad.dts')
3041 self.assertIn("Invalid sibling order 'start' for image-header: Must be at 'end' to match location",
3044 def testFdtmapHeaderNoSize(self):
3045 """Test an image header at the end of an image with undefined size"""
3046 self._DoReadFileRealDtb('138_fdtmap_hdr_nosize.dts')
3048 def testReplaceResize(self):
3049 """Test replacing a single file in an entry with a larger file"""
3050 expected = U_BOOT_DATA + b'x'
3051 data, _, image = self._RunReplaceCmd('u-boot', expected,
3052 dts='139_replace_repack.dts')
3053 self.assertEqual(expected, data)
3055 entries = image.GetEntries()
3056 dtb_data = entries['u-boot-dtb'].data
3057 dtb = fdt.Fdt.FromData(dtb_data)
3060 # The u-boot section should now be larger in the dtb
3061 node = dtb.GetNode('/binman/u-boot')
3062 self.assertEqual(len(expected), fdt_util.GetInt(node, 'size'))
3064 # Same for the fdtmap
3065 fdata = entries['fdtmap'].data
3066 fdtb = fdt.Fdt.FromData(fdata[fdtmap.FDTMAP_HDR_LEN:])
3068 fnode = fdtb.GetNode('/u-boot')
3069 self.assertEqual(len(expected), fdt_util.GetInt(fnode, 'size'))
3071 def testReplaceResizeNoRepack(self):
3072 """Test replacing an entry with a larger file when not allowed"""
3073 expected = U_BOOT_DATA + b'x'
3074 with self.assertRaises(ValueError) as e:
3075 self._RunReplaceCmd('u-boot', expected)
3076 self.assertIn('Entry data size does not match, but allow-repack is not present for this image',
3079 def testEntryShrink(self):
3080 """Test contracting an entry after it is packed"""
3082 state.SetAllowEntryContraction(True)
3083 data = self._DoReadFileDtb('140_entry_shrink.dts',
3086 state.SetAllowEntryContraction(False)
3087 self.assertEqual(b'a', data[:1])
3088 self.assertEqual(U_BOOT_DATA, data[1:1 + len(U_BOOT_DATA)])
3089 self.assertEqual(b'a', data[-1:])
3091 def testEntryShrinkFail(self):
3092 """Test not being allowed to contract an entry after it is packed"""
3093 data = self._DoReadFileDtb('140_entry_shrink.dts', update_dtb=True)[0]
3095 # In this case there is a spare byte at the end of the data. The size of
3096 # the contents is only 1 byte but we still have the size before it
3098 self.assertEqual(b'a\0', data[:2])
3099 self.assertEqual(U_BOOT_DATA, data[2:2 + len(U_BOOT_DATA)])
3100 self.assertEqual(b'a\0', data[-2:])
3102 def testDescriptorOffset(self):
3103 """Test that the Intel descriptor is always placed at at the start"""
3104 data = self._DoReadFileDtb('141_descriptor_offset.dts')
3105 image = control.images['image']
3106 entries = image.GetEntries()
3107 desc = entries['intel-descriptor']
3108 self.assertEqual(0xff800000, desc.offset);
3109 self.assertEqual(0xff800000, desc.image_pos);
3111 def testReplaceCbfs(self):
3112 """Test replacing a single file in CBFS without changing the size"""
3114 expected = b'x' * len(U_BOOT_DATA)
3115 data = self._DoReadFileRealDtb('142_replace_cbfs.dts')
3116 updated_fname = tools.GetOutputFilename('image-updated.bin')
3117 tools.WriteFile(updated_fname, data)
3118 entry_name = 'section/cbfs/u-boot'
3119 control.WriteEntry(updated_fname, entry_name, expected,
3121 data = control.ReadEntry(updated_fname, entry_name)
3122 self.assertEqual(expected, data)
3124 def testReplaceResizeCbfs(self):
3125 """Test replacing a single file in CBFS with one of a different size"""
3127 expected = U_BOOT_DATA + b'x'
3128 data = self._DoReadFileRealDtb('142_replace_cbfs.dts')
3129 updated_fname = tools.GetOutputFilename('image-updated.bin')
3130 tools.WriteFile(updated_fname, data)
3131 entry_name = 'section/cbfs/u-boot'
3132 control.WriteEntry(updated_fname, entry_name, expected,
3134 data = control.ReadEntry(updated_fname, entry_name)
3135 self.assertEqual(expected, data)
3137 def _SetupForReplace(self):
3138 """Set up some files to use to replace entries
3140 This generates an image, copies it to a new file, extracts all the files
3141 in it and updates some of them
3147 Expected values for updated entries, each a string
3149 data = self._DoReadFileRealDtb('143_replace_all.dts')
3151 updated_fname = tools.GetOutputFilename('image-updated.bin')
3152 tools.WriteFile(updated_fname, data)
3154 outdir = os.path.join(self._indir, 'extract')
3155 einfos = control.ExtractEntries(updated_fname, None, outdir, [])
3157 expected1 = b'x' + U_BOOT_DATA + b'y'
3158 u_boot_fname1 = os.path.join(outdir, 'u-boot')
3159 tools.WriteFile(u_boot_fname1, expected1)
3161 expected2 = b'a' + U_BOOT_DATA + b'b'
3162 u_boot_fname2 = os.path.join(outdir, 'u-boot2')
3163 tools.WriteFile(u_boot_fname2, expected2)
3165 expected_text = b'not the same text'
3166 text_fname = os.path.join(outdir, 'text')
3167 tools.WriteFile(text_fname, expected_text)
3169 dtb_fname = os.path.join(outdir, 'u-boot-dtb')
3170 dtb = fdt.FdtScan(dtb_fname)
3171 node = dtb.GetNode('/binman/text')
3172 node.AddString('my-property', 'the value')
3173 dtb.Sync(auto_resize=True)
3176 return updated_fname, outdir, expected1, expected2, expected_text
3178 def _CheckReplaceMultiple(self, entry_paths):
3179 """Handle replacing the contents of multiple entries
3182 entry_paths: List of entry paths to replace
3186 Dict of entries in the image:
3189 Expected values for updated entries, each a string
3191 updated_fname, outdir, expected1, expected2, expected_text = (
3192 self._SetupForReplace())
3193 control.ReplaceEntries(updated_fname, None, outdir, entry_paths)
3195 image = Image.FromFile(updated_fname)
3197 return image.GetEntries(), expected1, expected2, expected_text
3199 def testReplaceAll(self):
3200 """Test replacing the contents of all entries"""
3201 entries, expected1, expected2, expected_text = (
3202 self._CheckReplaceMultiple([]))
3203 data = entries['u-boot'].data
3204 self.assertEqual(expected1, data)
3206 data = entries['u-boot2'].data
3207 self.assertEqual(expected2, data)
3209 data = entries['text'].data
3210 self.assertEqual(expected_text, data)
3212 # Check that the device tree is updated
3213 data = entries['u-boot-dtb'].data
3214 dtb = fdt.Fdt.FromData(data)
3216 node = dtb.GetNode('/binman/text')
3217 self.assertEqual('the value', node.props['my-property'].value)
3219 def testReplaceSome(self):
3220 """Test replacing the contents of a few entries"""
3221 entries, expected1, expected2, expected_text = (
3222 self._CheckReplaceMultiple(['u-boot2', 'text']))
3224 # This one should not change
3225 data = entries['u-boot'].data
3226 self.assertEqual(U_BOOT_DATA, data)
3228 data = entries['u-boot2'].data
3229 self.assertEqual(expected2, data)
3231 data = entries['text'].data
3232 self.assertEqual(expected_text, data)
3234 def testReplaceCmd(self):
3235 """Test replacing a file fron an image on the command line"""
3236 self._DoReadFileRealDtb('143_replace_all.dts')
3239 tmpdir, updated_fname = self._SetupImageInTmpdir()
3241 fname = os.path.join(tmpdir, 'update-u-boot.bin')
3242 expected = b'x' * len(U_BOOT_DATA)
3243 tools.WriteFile(fname, expected)
3245 self._DoBinman('replace', '-i', updated_fname, 'u-boot', '-f', fname)
3246 data = tools.ReadFile(updated_fname)
3247 self.assertEqual(expected, data[:len(expected)])
3248 map_fname = os.path.join(tmpdir, 'image-updated.map')
3249 self.assertFalse(os.path.exists(map_fname))
3251 shutil.rmtree(tmpdir)
3253 def testReplaceCmdSome(self):
3254 """Test replacing some files fron an image on the command line"""
3255 updated_fname, outdir, expected1, expected2, expected_text = (
3256 self._SetupForReplace())
3258 self._DoBinman('replace', '-i', updated_fname, '-I', outdir,
3261 tools.PrepareOutputDir(None)
3262 image = Image.FromFile(updated_fname)
3264 entries = image.GetEntries()
3266 # This one should not change
3267 data = entries['u-boot'].data
3268 self.assertEqual(U_BOOT_DATA, data)
3270 data = entries['u-boot2'].data
3271 self.assertEqual(expected2, data)
3273 data = entries['text'].data
3274 self.assertEqual(expected_text, data)
3276 def testReplaceMissing(self):
3277 """Test replacing entries where the file is missing"""
3278 updated_fname, outdir, expected1, expected2, expected_text = (
3279 self._SetupForReplace())
3281 # Remove one of the files, to generate a warning
3282 u_boot_fname1 = os.path.join(outdir, 'u-boot')
3283 os.remove(u_boot_fname1)
3285 with test_util.capture_sys_output() as (stdout, stderr):
3286 control.ReplaceEntries(updated_fname, None, outdir, [])
3287 self.assertIn("Skipping entry '/u-boot' from missing file",
3290 def testReplaceCmdMap(self):
3291 """Test replacing a file fron an image on the command line"""
3292 self._DoReadFileRealDtb('143_replace_all.dts')
3295 tmpdir, updated_fname = self._SetupImageInTmpdir()
3297 fname = os.path.join(self._indir, 'update-u-boot.bin')
3298 expected = b'x' * len(U_BOOT_DATA)
3299 tools.WriteFile(fname, expected)
3301 self._DoBinman('replace', '-i', updated_fname, 'u-boot',
3303 map_fname = os.path.join(tmpdir, 'image-updated.map')
3304 self.assertTrue(os.path.exists(map_fname))
3306 shutil.rmtree(tmpdir)
3308 def testReplaceNoEntryPaths(self):
3309 """Test replacing an entry without an entry path"""
3310 self._DoReadFileRealDtb('143_replace_all.dts')
3311 image_fname = tools.GetOutputFilename('image.bin')
3312 with self.assertRaises(ValueError) as e:
3313 control.ReplaceEntries(image_fname, 'fname', None, [])
3314 self.assertIn('Must specify an entry path to read with -f',
3317 def testReplaceTooManyEntryPaths(self):
3318 """Test extracting some entries"""
3319 self._DoReadFileRealDtb('143_replace_all.dts')
3320 image_fname = tools.GetOutputFilename('image.bin')
3321 with self.assertRaises(ValueError) as e:
3322 control.ReplaceEntries(image_fname, 'fname', None, ['a', 'b'])
3323 self.assertIn('Must specify exactly one entry path to write with -f',
3326 def testPackReset16(self):
3327 """Test that an image with an x86 reset16 region can be created"""
3328 data = self._DoReadFile('144_x86_reset16.dts')
3329 self.assertEqual(X86_RESET16_DATA, data[:len(X86_RESET16_DATA)])
3331 def testPackReset16Spl(self):
3332 """Test that an image with an x86 reset16-spl region can be created"""
3333 data = self._DoReadFile('145_x86_reset16_spl.dts')
3334 self.assertEqual(X86_RESET16_SPL_DATA, data[:len(X86_RESET16_SPL_DATA)])
3336 def testPackReset16Tpl(self):
3337 """Test that an image with an x86 reset16-tpl region can be created"""
3338 data = self._DoReadFile('146_x86_reset16_tpl.dts')
3339 self.assertEqual(X86_RESET16_TPL_DATA, data[:len(X86_RESET16_TPL_DATA)])
3341 def testPackIntelFit(self):
3342 """Test that an image with an Intel FIT and pointer can be created"""
3343 data = self._DoReadFile('147_intel_fit.dts')
3344 self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
3346 self.assertEqual(b'_FIT_ \x01\x00\x00\x00\x00\x01\x80}' , fit)
3347 ptr = struct.unpack('<i', data[0x40:0x44])[0]
3349 image = control.images['image']
3350 entries = image.GetEntries()
3351 expected_ptr = entries['intel-fit'].image_pos - (1 << 32)
3352 self.assertEqual(expected_ptr, ptr)
3354 def testPackIntelFitMissing(self):
3355 """Test detection of a FIT pointer with not FIT region"""
3356 with self.assertRaises(ValueError) as e:
3357 self._DoReadFile('148_intel_fit_missing.dts')
3358 self.assertIn("'intel-fit-ptr' section must have an 'intel-fit' sibling",
3361 def _CheckSymbolsTplSection(self, dts, expected_vals):
3362 data = self._DoReadFile(dts)
3363 sym_values = struct.pack('<LQLL', *expected_vals)
3364 upto1 = 4 + len(U_BOOT_SPL_DATA)
3365 expected1 = tools.GetBytes(0xff, 4) + sym_values + U_BOOT_SPL_DATA[20:]
3366 self.assertEqual(expected1, data[:upto1])
3368 upto2 = upto1 + 1 + len(U_BOOT_SPL_DATA)
3369 expected2 = tools.GetBytes(0xff, 1) + sym_values + U_BOOT_SPL_DATA[20:]
3370 self.assertEqual(expected2, data[upto1:upto2])
3372 upto3 = 0x34 + len(U_BOOT_DATA)
3373 expected3 = tools.GetBytes(0xff, 1) + U_BOOT_DATA
3374 self.assertEqual(expected3, data[upto2:upto3])
3376 expected4 = sym_values + U_BOOT_TPL_DATA[20:]
3377 self.assertEqual(expected4, data[upto3:upto3 + len(U_BOOT_TPL_DATA)])
3379 def testSymbolsTplSection(self):
3380 """Test binman can assign symbols embedded in U-Boot TPL in a section"""
3381 self._SetupSplElf('u_boot_binman_syms')
3382 self._SetupTplElf('u_boot_binman_syms')
3383 self._CheckSymbolsTplSection('149_symbols_tpl.dts',
3384 [0x04, 0x1c, 0x10 + 0x34, 0x04])
3386 def testSymbolsTplSectionX86(self):
3387 """Test binman can assign symbols in a section with end-at-4gb"""
3388 self._SetupSplElf('u_boot_binman_syms_x86')
3389 self._SetupTplElf('u_boot_binman_syms_x86')
3390 self._CheckSymbolsTplSection('155_symbols_tpl_x86.dts',
3391 [0xffffff04, 0xffffff1c, 0xffffff34,
3394 def testPackX86RomIfwiSectiom(self):
3395 """Test that a section can be placed in an IFWI region"""
3396 self._SetupIfwi('fitimage.bin')
3397 data = self._DoReadFile('151_x86_rom_ifwi_section.dts')
3398 self._CheckIfwi(data)
3400 def testPackFspM(self):
3401 """Test that an image with a FSP memory-init binary can be created"""
3402 data = self._DoReadFile('152_intel_fsp_m.dts')
3403 self.assertEqual(FSP_M_DATA, data[:len(FSP_M_DATA)])
3405 def testPackFspS(self):
3406 """Test that an image with a FSP silicon-init binary can be created"""
3407 data = self._DoReadFile('153_intel_fsp_s.dts')
3408 self.assertEqual(FSP_S_DATA, data[:len(FSP_S_DATA)])
3410 def testPackFspT(self):
3411 """Test that an image with a FSP temp-ram-init binary can be created"""
3412 data = self._DoReadFile('154_intel_fsp_t.dts')
3413 self.assertEqual(FSP_T_DATA, data[:len(FSP_T_DATA)])
3415 def testMkimage(self):
3416 """Test using mkimage to build an image"""
3417 data = self._DoReadFile('156_mkimage.dts')
3419 # Just check that the data appears in the file somewhere
3420 self.assertIn(U_BOOT_SPL_DATA, data)
3422 def testExtblob(self):
3423 """Test an image with an external blob"""
3424 data = self._DoReadFile('157_blob_ext.dts')
3425 self.assertEqual(REFCODE_DATA, data)
3427 def testExtblobMissing(self):
3428 """Test an image with a missing external blob"""
3429 with self.assertRaises(ValueError) as e:
3430 self._DoReadFile('158_blob_ext_missing.dts')
3431 self.assertIn("Filename 'missing-file' not found in input path",
3434 def testExtblobMissingOk(self):
3435 """Test an image with an missing external blob that is allowed"""
3436 with test_util.capture_sys_output() as (stdout, stderr):
3437 self._DoTestFile('158_blob_ext_missing.dts', allow_missing=True)
3438 err = stderr.getvalue()
3439 self.assertRegex(err, "Image 'main-section'.*missing.*: blob-ext")
3441 def testExtblobMissingOkSect(self):
3442 """Test an image with an missing external blob that is allowed"""
3443 with test_util.capture_sys_output() as (stdout, stderr):
3444 self._DoTestFile('159_blob_ext_missing_sect.dts',
3446 err = stderr.getvalue()
3447 self.assertRegex(err, "Image 'main-section'.*missing.*: "
3448 "blob-ext blob-ext2")
3450 def testPackX86RomMeMissingDesc(self):
3451 """Test that an missing Intel descriptor entry is allowed"""
3452 with test_util.capture_sys_output() as (stdout, stderr):
3453 self._DoTestFile('164_x86_rom_me_missing.dts', allow_missing=True)
3454 err = stderr.getvalue()
3455 self.assertRegex(err,
3456 "Image 'main-section'.*missing.*: intel-descriptor")
3458 def testPackX86RomMissingIfwi(self):
3459 """Test that an x86 ROM with Integrated Firmware Image can be created"""
3460 self._SetupIfwi('fitimage.bin')
3461 pathname = os.path.join(self._indir, 'fitimage.bin')
3463 with test_util.capture_sys_output() as (stdout, stderr):
3464 self._DoTestFile('111_x86_rom_ifwi.dts', allow_missing=True)
3465 err = stderr.getvalue()
3466 self.assertRegex(err, "Image 'main-section'.*missing.*: intel-ifwi")
3468 def testPackOverlap(self):
3469 """Test that zero-size overlapping regions are ignored"""
3470 self._DoTestFile('160_pack_overlap_zero.dts')
3472 def testSimpleFit(self):
3473 """Test an image with a FIT inside"""
3474 data = self._DoReadFile('161_fit.dts')
3475 self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
3476 self.assertEqual(U_BOOT_NODTB_DATA, data[-len(U_BOOT_NODTB_DATA):])
3477 fit_data = data[len(U_BOOT_DATA):-len(U_BOOT_NODTB_DATA)]
3479 # The data should be inside the FIT
3480 dtb = fdt.Fdt.FromData(fit_data)
3482 fnode = dtb.GetNode('/images/kernel')
3483 self.assertIn('data', fnode.props)
3485 fname = os.path.join(self._indir, 'fit_data.fit')
3486 tools.WriteFile(fname, fit_data)
3487 out = tools.Run('dumpimage', '-l', fname)
3489 # Check a few features to make sure the plumbing works. We don't need
3490 # to test the operation of mkimage or dumpimage here. First convert the
3491 # output into a dict where the keys are the fields printed by dumpimage
3492 # and the values are a list of values for each field
3493 lines = out.splitlines()
3495 # Converts "Compression: gzip compressed" into two groups:
3496 # 'Compression' and 'gzip compressed'
3497 re_line = re.compile(r'^ *([^:]*)(?:: *(.*))?$')
3498 vals = collections.defaultdict(list)
3500 mat = re_line.match(line)
3501 vals[mat.group(1)].append(mat.group(2))
3503 self.assertEquals('FIT description: test-desc', lines[0])
3504 self.assertIn('Created:', lines[1])
3505 self.assertIn('Image 0 (kernel)', vals)
3506 self.assertIn('Hash value', vals)
3507 data_sizes = vals.get('Data Size')
3508 self.assertIsNotNone(data_sizes)
3509 self.assertEqual(2, len(data_sizes))
3510 # Format is "4 Bytes = 0.00 KiB = 0.00 MiB" so take the first word
3511 self.assertEqual(len(U_BOOT_DATA), int(data_sizes[0].split()[0]))
3512 self.assertEqual(len(U_BOOT_SPL_DTB_DATA), int(data_sizes[1].split()[0]))
3514 def testFitExternal(self):
3515 """Test an image with an FIT with external images"""
3516 data = self._DoReadFile('162_fit_external.dts')
3517 fit_data = data[len(U_BOOT_DATA):-2] # _testing is 2 bytes
3519 # The data should be outside the FIT
3520 dtb = fdt.Fdt.FromData(fit_data)
3522 fnode = dtb.GetNode('/images/kernel')
3523 self.assertNotIn('data', fnode.props)
3525 def testSectionIgnoreHashSignature(self):
3526 """Test that sections ignore hash, signature nodes for its data"""
3527 data = self._DoReadFile('165_section_ignore_hash_signature.dts')
3528 expected = (U_BOOT_DATA + U_BOOT_DATA)
3529 self.assertEqual(expected, data)
3531 def testPadInSections(self):
3532 """Test pad-before, pad-after for entries in sections"""
3533 data = self._DoReadFile('166_pad_in_sections.dts')
3534 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
3535 U_BOOT_DATA + tools.GetBytes(ord('!'), 6) +
3537 self.assertEqual(expected, data)
3539 def testFitImageSubentryAlignment(self):
3540 """Test relative alignability of FIT image subentries"""
3542 'test-id': TEXT_DATA,
3544 data, _, _, _ = self._DoReadFileDtb('167_fit_image_subentry_alignment.dts',
3545 entry_args=entry_args)
3546 dtb = fdt.Fdt.FromData(data)
3549 node = dtb.GetNode('/images/kernel')
3550 data = dtb.GetProps(node)["data"].bytes
3551 align_pad = 0x10 - (len(U_BOOT_SPL_DATA) % 0x10)
3552 expected = (tools.GetBytes(0, 0x20) + U_BOOT_SPL_DATA +
3553 tools.GetBytes(0, align_pad) + U_BOOT_DATA)
3554 self.assertEqual(expected, data)
3556 node = dtb.GetNode('/images/fdt-1')
3557 data = dtb.GetProps(node)["data"].bytes
3558 expected = (U_BOOT_SPL_DTB_DATA + tools.GetBytes(0, 20) +
3559 tools.ToBytes(TEXT_DATA) + tools.GetBytes(0, 30) +
3561 self.assertEqual(expected, data)
3563 def testFitExtblobMissingOk(self):
3564 """Test a FIT with a missing external blob that is allowed"""
3565 with test_util.capture_sys_output() as (stdout, stderr):
3566 self._DoTestFile('168_fit_missing_blob.dts',
3568 err = stderr.getvalue()
3569 self.assertRegex(err, "Image 'main-section'.*missing.*: atf-bl31")
3571 def testBlobNamedByArgMissing(self):
3572 """Test handling of a missing entry arg"""
3573 with self.assertRaises(ValueError) as e:
3574 self._DoReadFile('068_blob_named_by_arg.dts')
3575 self.assertIn("Missing required properties/entry args: cros-ec-rw-path",
3578 def testPackBl31(self):
3579 """Test that an image with an ATF BL31 binary can be created"""
3580 data = self._DoReadFile('169_atf_bl31.dts')
3581 self.assertEqual(ATF_BL31_DATA, data[:len(ATF_BL31_DATA)])
3583 def testPackScp(self):
3584 """Test that an image with an SCP binary can be created"""
3585 data = self._DoReadFile('172_scp.dts')
3586 self.assertEqual(SCP_DATA, data[:len(SCP_DATA)])
3588 def testFitFdt(self):
3589 """Test an image with an FIT with multiple FDT images"""
3590 def _CheckFdt(seq, expected_data):
3591 """Check the FDT nodes
3594 seq: Sequence number to check (0 or 1)
3595 expected_data: Expected contents of 'data' property
3597 name = 'fdt-%d' % seq
3598 fnode = dtb.GetNode('/images/%s' % name)
3599 self.assertIsNotNone(fnode)
3600 self.assertEqual({'description','type', 'compression', 'data'},
3601 set(fnode.props.keys()))
3602 self.assertEqual(expected_data, fnode.props['data'].bytes)
3603 self.assertEqual('fdt-test-fdt%d.dtb' % seq,
3604 fnode.props['description'].value)
3606 def _CheckConfig(seq, expected_data):
3607 """Check the configuration nodes
3610 seq: Sequence number to check (0 or 1)
3611 expected_data: Expected contents of 'data' property
3613 cnode = dtb.GetNode('/configurations')
3614 self.assertIn('default', cnode.props)
3615 self.assertEqual('config-2', cnode.props['default'].value)
3617 name = 'config-%d' % seq
3618 fnode = dtb.GetNode('/configurations/%s' % name)
3619 self.assertIsNotNone(fnode)
3620 self.assertEqual({'description','firmware', 'loadables', 'fdt'},
3621 set(fnode.props.keys()))
3622 self.assertEqual('conf-test-fdt%d.dtb' % seq,
3623 fnode.props['description'].value)
3624 self.assertEqual('fdt-%d' % seq, fnode.props['fdt'].value)
3627 'of-list': 'test-fdt1 test-fdt2',
3628 'default-dt': 'test-fdt2',
3630 data = self._DoReadFileDtb(
3632 entry_args=entry_args,
3633 extra_indirs=[os.path.join(self._indir, TEST_FDT_SUBDIR)])[0]
3634 self.assertEqual(U_BOOT_NODTB_DATA, data[-len(U_BOOT_NODTB_DATA):])
3635 fit_data = data[len(U_BOOT_DATA):-len(U_BOOT_NODTB_DATA)]
3637 dtb = fdt.Fdt.FromData(fit_data)
3639 fnode = dtb.GetNode('/images/kernel')
3640 self.assertIn('data', fnode.props)
3642 # Check all the properties in fdt-1 and fdt-2
3643 _CheckFdt(1, TEST_FDT1_DATA)
3644 _CheckFdt(2, TEST_FDT2_DATA)
3646 # Check configurations
3647 _CheckConfig(1, TEST_FDT1_DATA)
3648 _CheckConfig(2, TEST_FDT2_DATA)
3650 def testFitFdtMissingList(self):
3651 """Test handling of a missing 'of-list' entry arg"""
3652 with self.assertRaises(ValueError) as e:
3653 self._DoReadFile('172_fit_fdt.dts')
3654 self.assertIn("Generator node requires 'of-list' entry argument",
3657 def testFitFdtEmptyList(self):
3658 """Test handling of an empty 'of-list' entry arg"""
3662 data = self._DoReadFileDtb('170_fit_fdt.dts', entry_args=entry_args)[0]
3664 def testFitFdtMissingProp(self):
3665 """Test handling of a missing 'fit,fdt-list' property"""
3666 with self.assertRaises(ValueError) as e:
3667 self._DoReadFile('171_fit_fdt_missing_prop.dts')
3668 self.assertIn("Generator node requires 'fit,fdt-list' property",
3671 def testFitFdtEmptyList(self):
3672 """Test handling of an empty 'of-list' entry arg"""
3676 data = self._DoReadFileDtb('172_fit_fdt.dts', entry_args=entry_args)[0]
3678 def testFitFdtMissing(self):
3679 """Test handling of a missing 'default-dt' entry arg"""
3681 'of-list': 'test-fdt1 test-fdt2',
3683 with self.assertRaises(ValueError) as e:
3684 self._DoReadFileDtb(
3686 entry_args=entry_args,
3687 extra_indirs=[os.path.join(self._indir, TEST_FDT_SUBDIR)])[0]
3688 self.assertIn("Generated 'default' node requires default-dt entry argument",
3691 def testFitFdtNotInList(self):
3692 """Test handling of a default-dt that is not in the of-list"""
3694 'of-list': 'test-fdt1 test-fdt2',
3695 'default-dt': 'test-fdt3',
3697 with self.assertRaises(ValueError) as e:
3698 self._DoReadFileDtb(
3700 entry_args=entry_args,
3701 extra_indirs=[os.path.join(self._indir, TEST_FDT_SUBDIR)])[0]
3702 self.assertIn("default-dt entry argument 'test-fdt3' not found in fdt list: test-fdt1, test-fdt2",
3705 def testFitExtblobMissingHelp(self):
3706 """Test display of help messages when an external blob is missing"""
3707 control.missing_blob_help = control._ReadMissingBlobHelp()
3708 control.missing_blob_help['wibble'] = 'Wibble test'
3709 control.missing_blob_help['another'] = 'Another test'
3710 with test_util.capture_sys_output() as (stdout, stderr):
3711 self._DoTestFile('168_fit_missing_blob.dts',
3713 err = stderr.getvalue()
3715 # We can get the tag from the name, the type or the missing-msg
3716 # property. Check all three.
3717 self.assertIn('You may need to build ARM Trusted', err)
3718 self.assertIn('Wibble test', err)
3719 self.assertIn('Another test', err)
3721 def testMissingBlob(self):
3722 """Test handling of a blob containing a missing file"""
3723 with self.assertRaises(ValueError) as e:
3724 self._DoTestFile('173_missing_blob.dts', allow_missing=True)
3725 self.assertIn("Filename 'missing' not found in input path",
3728 def testEnvironment(self):
3729 """Test adding a U-Boot environment"""
3730 data = self._DoReadFile('174_env.dts')
3731 self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
3732 self.assertEqual(U_BOOT_NODTB_DATA, data[-len(U_BOOT_NODTB_DATA):])
3733 env = data[len(U_BOOT_DATA):-len(U_BOOT_NODTB_DATA)]
3734 self.assertEqual(b'\x1b\x97\x22\x7c\x01var1=1\0var2="2"\0\0\xff\xff',
3737 def testEnvironmentNoSize(self):
3738 """Test that a missing 'size' property is detected"""
3739 with self.assertRaises(ValueError) as e:
3740 data = self._DoTestFile('175_env_no_size.dts')
3741 self.assertIn("'u-boot-env' entry must have a size property",
3744 def testEnvironmentTooSmall(self):
3745 """Test handling of an environment that does not fit"""
3746 with self.assertRaises(ValueError) as e:
3747 data = self._DoTestFile('176_env_too_small.dts')
3749 # checksum, start byte, environment with \0 terminator, final \0
3750 need = 4 + 1 + len(ENV_DATA) + 1 + 1
3752 self.assertIn("too small to hold data (need %#x more bytes)" % short,
3756 if __name__ == "__main__":