1 # SPDX-License-Identifier: GPL-2.0+
2 # Copyright (c) 2016 Google, Inc
3 # Written by Simon Glass <sjg@chromium.org>
5 # To run a single test, change to this directory, and:
7 # python -m unittest func_test.TestFunctional.testHelp
9 from __future__ import print_function
12 from optparse import OptionParser
35 # Contents of test files, corresponding to different entry types
37 U_BOOT_IMG_DATA = b'img'
38 U_BOOT_SPL_DATA = b'56780123456789abcde'
39 U_BOOT_TPL_DATA = b'tpl'
43 U_BOOT_DTB_DATA = b'udtb'
44 U_BOOT_SPL_DTB_DATA = b'spldtb'
45 U_BOOT_TPL_DTB_DATA = b'tpldtb'
46 X86_START16_DATA = b'start16'
47 X86_START16_SPL_DATA = b'start16spl'
48 X86_START16_TPL_DATA = b'start16tpl'
49 PPC_MPC85XX_BR_DATA = b'ppcmpc85xxbr'
50 U_BOOT_NODTB_DATA = b'nodtb with microcode pointer somewhere in here'
51 U_BOOT_SPL_NODTB_DATA = b'splnodtb with microcode pointer somewhere in here'
52 U_BOOT_TPL_NODTB_DATA = b'tplnodtb with microcode pointer somewhere in here'
60 CROS_EC_RW_DATA = b'ecrw'
64 FILES_DATA = (b"sorry I'm late\nOh, don't bother apologising, I'm " +
65 b"sorry you're alive\n")
66 COMPRESS_DATA = b'compress xxxxxxxxxxxxxxxxxxxxxx data'
67 REFCODE_DATA = b'refcode'
70 class TestFunctional(unittest.TestCase):
71 """Functional tests for binman
73 Most of these use a sample .dts file to build an image and then check
74 that it looks correct. The sample files are in the test/ subdirectory
77 For each entry type a very small test file is created using fixed
78 string contents. This makes it easy to test that things look right, and
81 In some cases a 'real' file must be used - these are also supplied in
89 # Handle the case where argv[0] is 'python'
90 self._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
91 self._binman_pathname = os.path.join(self._binman_dir, 'binman')
93 # Create a temporary directory for input files
94 self._indir = tempfile.mkdtemp(prefix='binmant.')
96 # Create some test files
97 TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
98 TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
99 TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
100 TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
101 TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
102 TestFunctional._MakeInputFile('me.bin', ME_DATA)
103 TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
105 TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
106 TestFunctional._MakeInputFile('u-boot-br.bin', PPC_MPC85XX_BR_DATA)
107 TestFunctional._MakeInputFile('spl/u-boot-x86-16bit-spl.bin',
108 X86_START16_SPL_DATA)
109 TestFunctional._MakeInputFile('tpl/u-boot-x86-16bit-tpl.bin',
110 X86_START16_TPL_DATA)
111 TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
112 TestFunctional._MakeInputFile('spl/u-boot-spl-nodtb.bin',
113 U_BOOT_SPL_NODTB_DATA)
114 TestFunctional._MakeInputFile('tpl/u-boot-tpl-nodtb.bin',
115 U_BOOT_TPL_NODTB_DATA)
116 TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
117 TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
118 TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
119 TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
120 TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
121 TestFunctional._MakeInputDir('devkeys')
122 TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
123 TestFunctional._MakeInputFile('refcode.bin', REFCODE_DATA)
125 # ELF file with a '_dt_ucode_base_size' symbol
126 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
127 TestFunctional._MakeInputFile('u-boot', fd.read())
129 # Intel flash descriptor file
130 with open(self.TestFile('descriptor.bin'), 'rb') as fd:
131 TestFunctional._MakeInputFile('descriptor.bin', fd.read())
133 shutil.copytree(self.TestFile('files'),
134 os.path.join(self._indir, 'files'))
136 TestFunctional._MakeInputFile('compress', COMPRESS_DATA)
138 # Travis-CI may have an old lz4
141 tools.Run('lz4', '--no-frame-crc', '-c',
142 os.path.join(self._indir, 'u-boot.bin'))
144 self.have_lz4 = False
147 def tearDownClass(self):
148 """Remove the temporary input directory and its contents"""
149 if self.preserve_indir:
150 print('Preserving input dir: %s' % self._indir)
153 shutil.rmtree(self._indir)
157 def setup_test_args(cls, preserve_indir=False, preserve_outdirs=False,
159 """Accept arguments controlling test execution
162 preserve_indir: Preserve the shared input directory used by all
164 preserve_outdir: Preserve the output directories used by tests. Each
165 test has its own, so this is normally only useful when running a
167 toolpath: ist of paths to use for tools
169 cls.preserve_indir = preserve_indir
170 cls.preserve_outdirs = preserve_outdirs
171 cls.toolpath = toolpath
174 if not self.have_lz4:
175 self.skipTest('lz4 --no-frame-crc not available')
178 # Enable this to turn on debugging output
179 # tout.Init(tout.DEBUG)
180 command.test_result = None
183 """Remove the temporary output directory"""
184 if self.preserve_outdirs:
185 print('Preserving output dir: %s' % tools.outdir)
187 tools._FinaliseForTest()
190 def _ResetDtbs(self):
191 TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
192 TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
193 TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
195 def _GetVerbosity(self):
196 """Check if verbosity should be enabled
199 list containing either:
200 - Verbosity flag (e.g. '-v2') if it is present on the cmd line
201 - nothing if the flag is not present
203 for arg in sys.argv[1:]:
204 if arg.startswith('-v'):
208 def _RunBinman(self, *args, **kwargs):
209 """Run binman using the command line
212 Arguments to pass, as a list of strings
213 kwargs: Arguments to pass to Command.RunPipe()
215 result = command.RunPipe([[self._binman_pathname] + list(args)],
216 capture=True, capture_stderr=True, raise_on_error=False)
217 if result.return_code and kwargs.get('raise_on_error', True):
218 raise Exception("Error running '%s': %s" % (' '.join(args),
219 result.stdout + result.stderr))
222 def _DoBinman(self, *args):
223 """Run binman using directly (in the same process)
226 Arguments to pass, as a list of strings
228 Return value (0 for success)
233 (options, args) = cmdline.ParseArgs(args)
234 options.pager = 'binman-invalid-pager'
235 options.build_dir = self._indir
237 # For testing, you can force an increase in verbosity here
238 # options.verbosity = tout.DEBUG
239 return control.Binman(options, args)
241 def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
242 entry_args=None, images=None, use_real_dtb=False,
244 """Run binman with a given test file
247 fname: Device-tree source filename to use (e.g. 005_simple.dts)
248 debug: True to enable debugging output
249 map: True to output map files for the images
250 update_dtb: Update the offset and size of each entry in the device
251 tree before packing it into the image
252 entry_args: Dict of entry args to supply to binman
254 value: value of that arg
255 images: List of image names to build
257 args = ['-p', '-I', self._indir, '-d', self.TestFile(fname)]
265 args.append('--fake-dtb')
266 if verbosity is not None:
267 args.append('-v%d' % verbosity)
269 args += self._GetVerbosity()
271 for arg, value in entry_args.items():
272 args.append('-a%s=%s' % (arg, value))
275 args += ['-i', image]
277 for path in self.toolpath:
278 args += ['--toolpath', path]
279 return self._DoBinman(*args)
281 def _SetupDtb(self, fname, outfile='u-boot.dtb'):
282 """Set up a new test device-tree file
284 The given file is compiled and set up as the device tree to be used
288 fname: Filename of .dts file to read
289 outfile: Output filename for compiled device-tree binary
292 Contents of device-tree binary
294 tools.PrepareOutputDir(None)
295 dtb = fdt_util.EnsureCompiled(self.TestFile(fname))
296 with open(dtb, 'rb') as fd:
298 TestFunctional._MakeInputFile(outfile, data)
299 tools.FinaliseOutputDir()
302 def _GetDtbContentsForSplTpl(self, dtb_data, name):
303 """Create a version of the main DTB for SPL or SPL
305 For testing we don't actually have different versions of the DTB. With
306 U-Boot we normally run fdtgrep to remove unwanted nodes, but for tests
307 we don't normally have any unwanted nodes.
309 We still want the DTBs for SPL and TPL to be different though, since
310 otherwise it is confusing to know which one we are looking at. So add
311 an 'spl' or 'tpl' property to the top-level node.
313 dtb = fdt.Fdt.FromData(dtb_data)
315 dtb.GetNode('/binman').AddZeroProp(name)
316 dtb.Sync(auto_resize=True)
318 return dtb.GetContents()
320 def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
321 update_dtb=False, entry_args=None, reset_dtbs=True):
322 """Run binman and return the resulting image
324 This runs binman with a given test file and then reads the resulting
325 output file. It is a shortcut function since most tests need to do
328 Raises an assertion failure if binman returns a non-zero exit code.
331 fname: Device-tree source filename to use (e.g. 005_simple.dts)
332 use_real_dtb: True to use the test file as the contents of
333 the u-boot-dtb entry. Normally this is not needed and the
334 test contents (the U_BOOT_DTB_DATA string) can be used.
335 But in some test we need the real contents.
336 map: True to output map files for the images
337 update_dtb: Update the offset and size of each entry in the device
338 tree before packing it into the image
342 Resulting image contents
344 Map data showing contents of image (or None if none)
345 Output device tree binary filename ('u-boot.dtb' path)
348 # Use the compiled test file as the u-boot-dtb input
350 dtb_data = self._SetupDtb(fname)
352 # For testing purposes, make a copy of the DT for SPL and TPL. Add
353 # a node indicating which it is, so aid verification.
354 for name in ['spl', 'tpl']:
355 dtb_fname = '%s/u-boot-%s.dtb' % (name, name)
356 outfile = os.path.join(self._indir, dtb_fname)
357 TestFunctional._MakeInputFile(dtb_fname,
358 self._GetDtbContentsForSplTpl(dtb_data, name))
361 retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
362 entry_args=entry_args, use_real_dtb=use_real_dtb)
363 self.assertEqual(0, retcode)
364 out_dtb_fname = tools.GetOutputFilename('u-boot.dtb.out')
366 # Find the (only) image, read it and return its contents
367 image = control.images['image']
368 image_fname = tools.GetOutputFilename('image.bin')
369 self.assertTrue(os.path.exists(image_fname))
371 map_fname = tools.GetOutputFilename('image.map')
372 with open(map_fname) as fd:
376 with open(image_fname, 'rb') as fd:
377 return fd.read(), dtb_data, map_data, out_dtb_fname
379 # Put the test file back
380 if reset_dtbs and use_real_dtb:
383 def _DoReadFile(self, fname, use_real_dtb=False):
384 """Helper function which discards the device-tree binary
387 fname: Device-tree source filename to use (e.g. 005_simple.dts)
388 use_real_dtb: True to use the test file as the contents of
389 the u-boot-dtb entry. Normally this is not needed and the
390 test contents (the U_BOOT_DTB_DATA string) can be used.
391 But in some test we need the real contents.
394 Resulting image contents
396 return self._DoReadFileDtb(fname, use_real_dtb)[0]
399 def _MakeInputFile(self, fname, contents):
400 """Create a new test input file, creating directories as needed
403 fname: Filename to create
404 contents: File contents to write in to the file
406 Full pathname of file created
408 pathname = os.path.join(self._indir, fname)
409 dirname = os.path.dirname(pathname)
410 if dirname and not os.path.exists(dirname):
412 with open(pathname, 'wb') as fd:
417 def _MakeInputDir(self, dirname):
418 """Create a new test input directory, creating directories as needed
421 dirname: Directory name to create
424 Full pathname of directory created
426 pathname = os.path.join(self._indir, dirname)
427 if not os.path.exists(pathname):
428 os.makedirs(pathname)
432 def _SetupSplElf(self, src_fname='bss_data'):
433 """Set up an ELF file with a '_dt_ucode_base_size' symbol
436 Filename of ELF file to use as SPL
438 with open(self.TestFile(src_fname), 'rb') as fd:
439 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
442 def TestFile(self, fname):
443 return os.path.join(self._binman_dir, 'test', fname)
445 def AssertInList(self, grep_list, target):
446 """Assert that at least one of a list of things is in a target
449 grep_list: List of strings to check
450 target: Target string
452 for grep in grep_list:
455 self.fail("Error: '%s' not found in '%s'" % (grep_list, target))
457 def CheckNoGaps(self, entries):
458 """Check that all entries fit together without gaps
461 entries: List of entries to check
464 for entry in entries.values():
465 self.assertEqual(offset, entry.offset)
468 def GetFdtLen(self, dtb):
469 """Get the totalsize field from a device-tree binary
472 dtb: Device-tree binary contents
475 Total size of device-tree binary, from the header
477 return struct.unpack('>L', dtb[4:8])[0]
479 def _GetPropTree(self, dtb, prop_names):
480 def AddNode(node, path):
482 path += '/' + node.name
483 for subnode in node.subnodes:
484 for prop in subnode.props.values():
485 if prop.name in prop_names:
486 prop_path = path + '/' + subnode.name + ':' + prop.name
487 tree[prop_path[len('/binman/'):]] = fdt_util.fdt32_to_cpu(
489 AddNode(subnode, path)
492 AddNode(dtb.GetRoot(), '')
496 """Test a basic run with valid args"""
497 result = self._RunBinman('-h')
499 def testFullHelp(self):
500 """Test that the full help is displayed with -H"""
501 result = self._RunBinman('-H')
502 help_file = os.path.join(self._binman_dir, 'README')
503 # Remove possible extraneous strings
504 extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
505 gothelp = result.stdout.replace(extra, '')
506 self.assertEqual(len(gothelp), os.path.getsize(help_file))
507 self.assertEqual(0, len(result.stderr))
508 self.assertEqual(0, result.return_code)
510 def testFullHelpInternal(self):
511 """Test that the full help is displayed with -H"""
513 command.test_result = command.CommandResult()
514 result = self._DoBinman('-H')
515 help_file = os.path.join(self._binman_dir, 'README')
517 command.test_result = None
520 """Test that the basic help is displayed with -h"""
521 result = self._RunBinman('-h')
522 self.assertTrue(len(result.stdout) > 200)
523 self.assertEqual(0, len(result.stderr))
524 self.assertEqual(0, result.return_code)
527 """Test that we can run it with a specific board"""
528 self._SetupDtb('005_simple.dts', 'sandbox/u-boot.dtb')
529 TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
530 result = self._DoBinman('-b', 'sandbox')
531 self.assertEqual(0, result)
533 def testNeedBoard(self):
534 """Test that we get an error when no board ius supplied"""
535 with self.assertRaises(ValueError) as e:
536 result = self._DoBinman()
537 self.assertIn("Must provide a board to process (use -b <board>)",
540 def testMissingDt(self):
541 """Test that an invalid device-tree file generates an error"""
542 with self.assertRaises(Exception) as e:
543 self._RunBinman('-d', 'missing_file')
544 # We get one error from libfdt, and a different one from fdtget.
545 self.AssertInList(["Couldn't open blob from 'missing_file'",
546 'No such file or directory'], str(e.exception))
548 def testBrokenDt(self):
549 """Test that an invalid device-tree source file generates an error
551 Since this is a source file it should be compiled and the error
552 will come from the device-tree compiler (dtc).
554 with self.assertRaises(Exception) as e:
555 self._RunBinman('-d', self.TestFile('001_invalid.dts'))
556 self.assertIn("FATAL ERROR: Unable to parse input tree",
559 def testMissingNode(self):
560 """Test that a device tree without a 'binman' node generates an error"""
561 with self.assertRaises(Exception) as e:
562 self._DoBinman('-d', self.TestFile('002_missing_node.dts'))
563 self.assertIn("does not have a 'binman' node", str(e.exception))
566 """Test that an empty binman node works OK (i.e. does nothing)"""
567 result = self._RunBinman('-d', self.TestFile('003_empty.dts'))
568 self.assertEqual(0, len(result.stderr))
569 self.assertEqual(0, result.return_code)
571 def testInvalidEntry(self):
572 """Test that an invalid entry is flagged"""
573 with self.assertRaises(Exception) as e:
574 result = self._RunBinman('-d',
575 self.TestFile('004_invalid_entry.dts'))
576 self.assertIn("Unknown entry type 'not-a-valid-type' in node "
577 "'/binman/not-a-valid-type'", str(e.exception))
579 def testSimple(self):
580 """Test a simple binman with a single file"""
581 data = self._DoReadFile('005_simple.dts')
582 self.assertEqual(U_BOOT_DATA, data)
584 def testSimpleDebug(self):
585 """Test a simple binman run with debugging enabled"""
586 data = self._DoTestFile('005_simple.dts', debug=True)
589 """Test that we can handle creating two images
591 This also tests image padding.
593 retcode = self._DoTestFile('006_dual_image.dts')
594 self.assertEqual(0, retcode)
596 image = control.images['image1']
597 self.assertEqual(len(U_BOOT_DATA), image._size)
598 fname = tools.GetOutputFilename('image1.bin')
599 self.assertTrue(os.path.exists(fname))
600 with open(fname, 'rb') as fd:
602 self.assertEqual(U_BOOT_DATA, data)
604 image = control.images['image2']
605 self.assertEqual(3 + len(U_BOOT_DATA) + 5, image._size)
606 fname = tools.GetOutputFilename('image2.bin')
607 self.assertTrue(os.path.exists(fname))
608 with open(fname, 'rb') as fd:
610 self.assertEqual(U_BOOT_DATA, data[3:7])
611 self.assertEqual(tools.GetBytes(0, 3), data[:3])
612 self.assertEqual(tools.GetBytes(0, 5), data[7:])
614 def testBadAlign(self):
615 """Test that an invalid alignment value is detected"""
616 with self.assertRaises(ValueError) as e:
617 self._DoTestFile('007_bad_align.dts')
618 self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
619 "of two", str(e.exception))
621 def testPackSimple(self):
622 """Test that packing works as expected"""
623 retcode = self._DoTestFile('008_pack.dts')
624 self.assertEqual(0, retcode)
625 self.assertIn('image', control.images)
626 image = control.images['image']
627 entries = image.GetEntries()
628 self.assertEqual(5, len(entries))
631 self.assertIn('u-boot', entries)
632 entry = entries['u-boot']
633 self.assertEqual(0, entry.offset)
634 self.assertEqual(len(U_BOOT_DATA), entry.size)
636 # Second u-boot, aligned to 16-byte boundary
637 self.assertIn('u-boot-align', entries)
638 entry = entries['u-boot-align']
639 self.assertEqual(16, entry.offset)
640 self.assertEqual(len(U_BOOT_DATA), entry.size)
642 # Third u-boot, size 23 bytes
643 self.assertIn('u-boot-size', entries)
644 entry = entries['u-boot-size']
645 self.assertEqual(20, entry.offset)
646 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
647 self.assertEqual(23, entry.size)
649 # Fourth u-boot, placed immediate after the above
650 self.assertIn('u-boot-next', entries)
651 entry = entries['u-boot-next']
652 self.assertEqual(43, entry.offset)
653 self.assertEqual(len(U_BOOT_DATA), entry.size)
655 # Fifth u-boot, placed at a fixed offset
656 self.assertIn('u-boot-fixed', entries)
657 entry = entries['u-boot-fixed']
658 self.assertEqual(61, entry.offset)
659 self.assertEqual(len(U_BOOT_DATA), entry.size)
661 self.assertEqual(65, image._size)
663 def testPackExtra(self):
664 """Test that extra packing feature works as expected"""
665 retcode = self._DoTestFile('009_pack_extra.dts')
667 self.assertEqual(0, retcode)
668 self.assertIn('image', control.images)
669 image = control.images['image']
670 entries = image.GetEntries()
671 self.assertEqual(5, len(entries))
673 # First u-boot with padding before and after
674 self.assertIn('u-boot', entries)
675 entry = entries['u-boot']
676 self.assertEqual(0, entry.offset)
677 self.assertEqual(3, entry.pad_before)
678 self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
680 # Second u-boot has an aligned size, but it has no effect
681 self.assertIn('u-boot-align-size-nop', entries)
682 entry = entries['u-boot-align-size-nop']
683 self.assertEqual(12, entry.offset)
684 self.assertEqual(4, entry.size)
686 # Third u-boot has an aligned size too
687 self.assertIn('u-boot-align-size', entries)
688 entry = entries['u-boot-align-size']
689 self.assertEqual(16, entry.offset)
690 self.assertEqual(32, entry.size)
692 # Fourth u-boot has an aligned end
693 self.assertIn('u-boot-align-end', entries)
694 entry = entries['u-boot-align-end']
695 self.assertEqual(48, entry.offset)
696 self.assertEqual(16, entry.size)
698 # Fifth u-boot immediately afterwards
699 self.assertIn('u-boot-align-both', entries)
700 entry = entries['u-boot-align-both']
701 self.assertEqual(64, entry.offset)
702 self.assertEqual(64, entry.size)
704 self.CheckNoGaps(entries)
705 self.assertEqual(128, image._size)
707 def testPackAlignPowerOf2(self):
708 """Test that invalid entry alignment is detected"""
709 with self.assertRaises(ValueError) as e:
710 self._DoTestFile('010_pack_align_power2.dts')
711 self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
712 "of two", str(e.exception))
714 def testPackAlignSizePowerOf2(self):
715 """Test that invalid entry size alignment is detected"""
716 with self.assertRaises(ValueError) as e:
717 self._DoTestFile('011_pack_align_size_power2.dts')
718 self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
719 "power of two", str(e.exception))
721 def testPackInvalidAlign(self):
722 """Test detection of an offset that does not match its alignment"""
723 with self.assertRaises(ValueError) as e:
724 self._DoTestFile('012_pack_inv_align.dts')
725 self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
726 "align 0x4 (4)", str(e.exception))
728 def testPackInvalidSizeAlign(self):
729 """Test that invalid entry size alignment is detected"""
730 with self.assertRaises(ValueError) as e:
731 self._DoTestFile('013_pack_inv_size_align.dts')
732 self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
733 "align-size 0x4 (4)", str(e.exception))
735 def testPackOverlap(self):
736 """Test that overlapping regions are detected"""
737 with self.assertRaises(ValueError) as e:
738 self._DoTestFile('014_pack_overlap.dts')
739 self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
740 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
743 def testPackEntryOverflow(self):
744 """Test that entries that overflow their size are detected"""
745 with self.assertRaises(ValueError) as e:
746 self._DoTestFile('015_pack_overflow.dts')
747 self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
748 "but entry size is 0x3 (3)", str(e.exception))
750 def testPackImageOverflow(self):
751 """Test that entries which overflow the image size are detected"""
752 with self.assertRaises(ValueError) as e:
753 self._DoTestFile('016_pack_image_overflow.dts')
754 self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section "
755 "size 0x3 (3)", str(e.exception))
757 def testPackImageSize(self):
758 """Test that the image size can be set"""
759 retcode = self._DoTestFile('017_pack_image_size.dts')
760 self.assertEqual(0, retcode)
761 self.assertIn('image', control.images)
762 image = control.images['image']
763 self.assertEqual(7, image._size)
765 def testPackImageSizeAlign(self):
766 """Test that image size alignemnt works as expected"""
767 retcode = self._DoTestFile('018_pack_image_align.dts')
768 self.assertEqual(0, retcode)
769 self.assertIn('image', control.images)
770 image = control.images['image']
771 self.assertEqual(16, image._size)
773 def testPackInvalidImageAlign(self):
774 """Test that invalid image alignment is detected"""
775 with self.assertRaises(ValueError) as e:
776 self._DoTestFile('019_pack_inv_image_align.dts')
777 self.assertIn("Section '/binman': Size 0x7 (7) does not match "
778 "align-size 0x8 (8)", str(e.exception))
780 def testPackAlignPowerOf2(self):
781 """Test that invalid image alignment is detected"""
782 with self.assertRaises(ValueError) as e:
783 self._DoTestFile('020_pack_inv_image_align_power2.dts')
784 self.assertIn("Section '/binman': Alignment size 131 must be a power of "
785 "two", str(e.exception))
787 def testImagePadByte(self):
788 """Test that the image pad byte can be specified"""
790 data = self._DoReadFile('021_image_pad.dts')
791 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0xff, 1) +
794 def testImageName(self):
795 """Test that image files can be named"""
796 retcode = self._DoTestFile('022_image_name.dts')
797 self.assertEqual(0, retcode)
798 image = control.images['image1']
799 fname = tools.GetOutputFilename('test-name')
800 self.assertTrue(os.path.exists(fname))
802 image = control.images['image2']
803 fname = tools.GetOutputFilename('test-name.xx')
804 self.assertTrue(os.path.exists(fname))
806 def testBlobFilename(self):
807 """Test that generic blobs can be provided by filename"""
808 data = self._DoReadFile('023_blob.dts')
809 self.assertEqual(BLOB_DATA, data)
811 def testPackSorted(self):
812 """Test that entries can be sorted"""
814 data = self._DoReadFile('024_sorted.dts')
815 self.assertEqual(tools.GetBytes(0, 1) + U_BOOT_SPL_DATA +
816 tools.GetBytes(0, 2) + U_BOOT_DATA, data)
818 def testPackZeroOffset(self):
819 """Test that an entry at offset 0 is not given a new offset"""
820 with self.assertRaises(ValueError) as e:
821 self._DoTestFile('025_pack_zero_size.dts')
822 self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
823 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
826 def testPackUbootDtb(self):
827 """Test that a device tree can be added to U-Boot"""
828 data = self._DoReadFile('026_pack_u_boot_dtb.dts')
829 self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
831 def testPackX86RomNoSize(self):
832 """Test that the end-at-4gb property requires a size property"""
833 with self.assertRaises(ValueError) as e:
834 self._DoTestFile('027_pack_4gb_no_size.dts')
835 self.assertIn("Section '/binman': Section size must be provided when "
836 "using end-at-4gb", str(e.exception))
838 def test4gbAndSkipAtStartTogether(self):
839 """Test that the end-at-4gb and skip-at-size property can't be used
841 with self.assertRaises(ValueError) as e:
842 self._DoTestFile('80_4gb_and_skip_at_start_together.dts')
843 self.assertIn("Section '/binman': Provide either 'end-at-4gb' or "
844 "'skip-at-start'", str(e.exception))
846 def testPackX86RomOutside(self):
847 """Test that the end-at-4gb property checks for offset boundaries"""
848 with self.assertRaises(ValueError) as e:
849 self._DoTestFile('028_pack_4gb_outside.dts')
850 self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
851 "the section starting at 0xffffffe0 (4294967264)",
854 def testPackX86Rom(self):
855 """Test that a basic x86 ROM can be created"""
857 data = self._DoReadFile('029_x86-rom.dts')
858 self.assertEqual(U_BOOT_DATA + tools.GetBytes(0, 7) + U_BOOT_SPL_DATA +
859 tools.GetBytes(0, 2), data)
861 def testPackX86RomMeNoDesc(self):
862 """Test that an invalid Intel descriptor entry is detected"""
863 TestFunctional._MakeInputFile('descriptor.bin', b'')
864 with self.assertRaises(ValueError) as e:
865 self._DoTestFile('031_x86-rom-me.dts')
866 self.assertIn("Node '/binman/intel-descriptor': Cannot find Intel Flash Descriptor (FD) signature",
869 def testPackX86RomBadDesc(self):
870 """Test that the Intel requires a descriptor entry"""
871 with self.assertRaises(ValueError) as e:
872 self._DoTestFile('030_x86-rom-me-no-desc.dts')
873 self.assertIn("Node '/binman/intel-me': No offset set with "
874 "offset-unset: should another entry provide this correct "
875 "offset?", str(e.exception))
877 def testPackX86RomMe(self):
878 """Test that an x86 ROM with an ME region can be created"""
879 data = self._DoReadFile('031_x86-rom-me.dts')
880 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
881 if data[:0x1000] != expected_desc:
882 self.fail('Expected descriptor binary at start of image')
883 self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
885 def testPackVga(self):
886 """Test that an image with a VGA binary can be created"""
887 data = self._DoReadFile('032_intel-vga.dts')
888 self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
890 def testPackStart16(self):
891 """Test that an image with an x86 start16 region can be created"""
892 data = self._DoReadFile('033_x86-start16.dts')
893 self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
895 def testPackPowerpcMpc85xxBootpgResetvec(self):
896 """Test that an image with powerpc-mpc85xx-bootpg-resetvec can be
898 data = self._DoReadFile('81_powerpc_mpc85xx_bootpg_resetvec.dts')
899 self.assertEqual(PPC_MPC85XX_BR_DATA, data[:len(PPC_MPC85XX_BR_DATA)])
901 def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False):
902 """Handle running a test for insertion of microcode
905 dts_fname: Name of test .dts file
906 nodtb_data: Data that we expect in the first section
907 ucode_second: True if the microsecond entry is second instead of
912 Contents of first region (U-Boot or SPL)
913 Offset and size components of microcode pointer, as inserted
914 in the above (two 4-byte words)
916 data = self._DoReadFile(dts_fname, True)
918 # Now check the device tree has no microcode
920 ucode_content = data[len(nodtb_data):]
921 ucode_pos = len(nodtb_data)
922 dtb_with_ucode = ucode_content[16:]
923 fdt_len = self.GetFdtLen(dtb_with_ucode)
925 dtb_with_ucode = data[len(nodtb_data):]
926 fdt_len = self.GetFdtLen(dtb_with_ucode)
927 ucode_content = dtb_with_ucode[fdt_len:]
928 ucode_pos = len(nodtb_data) + fdt_len
929 fname = tools.GetOutputFilename('test.dtb')
930 with open(fname, 'wb') as fd:
931 fd.write(dtb_with_ucode)
932 dtb = fdt.FdtScan(fname)
933 ucode = dtb.GetNode('/microcode')
934 self.assertTrue(ucode)
935 for node in ucode.subnodes:
936 self.assertFalse(node.props.get('data'))
938 # Check that the microcode appears immediately after the Fdt
939 # This matches the concatenation of the data properties in
940 # the /microcode/update@xxx nodes in 34_x86_ucode.dts.
941 ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
943 self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
945 # Check that the microcode pointer was inserted. It should match the
946 # expected offset and size
947 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
949 u_boot = data[:len(nodtb_data)]
950 return u_boot, pos_and_size
952 def testPackUbootMicrocode(self):
953 """Test that x86 microcode can be handled correctly
955 We expect to see the following in the image, in order:
956 u-boot-nodtb.bin with a microcode pointer inserted at the correct
958 u-boot.dtb with the microcode removed
961 first, pos_and_size = self._RunMicrocodeTest('034_x86_ucode.dts',
963 self.assertEqual(b'nodtb with microcode' + pos_and_size +
964 b' somewhere in here', first)
966 def _RunPackUbootSingleMicrocode(self):
967 """Test that x86 microcode can be handled correctly
969 We expect to see the following in the image, in order:
970 u-boot-nodtb.bin with a microcode pointer inserted at the correct
972 u-boot.dtb with the microcode
973 an empty microcode region
975 # We need the libfdt library to run this test since only that allows
976 # finding the offset of a property. This is required by
977 # Entry_u_boot_dtb_with_ucode.ObtainContents().
978 data = self._DoReadFile('035_x86_single_ucode.dts', True)
980 second = data[len(U_BOOT_NODTB_DATA):]
982 fdt_len = self.GetFdtLen(second)
983 third = second[fdt_len:]
984 second = second[:fdt_len]
986 ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
987 self.assertIn(ucode_data, second)
988 ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
990 # Check that the microcode pointer was inserted. It should match the
991 # expected offset and size
992 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
994 first = data[:len(U_BOOT_NODTB_DATA)]
995 self.assertEqual(b'nodtb with microcode' + pos_and_size +
996 b' somewhere in here', first)
998 def testPackUbootSingleMicrocode(self):
999 """Test that x86 microcode can be handled correctly with fdt_normal.
1001 self._RunPackUbootSingleMicrocode()
1003 def testUBootImg(self):
1004 """Test that u-boot.img can be put in a file"""
1005 data = self._DoReadFile('036_u_boot_img.dts')
1006 self.assertEqual(U_BOOT_IMG_DATA, data)
1008 def testNoMicrocode(self):
1009 """Test that a missing microcode region is detected"""
1010 with self.assertRaises(ValueError) as e:
1011 self._DoReadFile('037_x86_no_ucode.dts', True)
1012 self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
1013 "node found in ", str(e.exception))
1015 def testMicrocodeWithoutNode(self):
1016 """Test that a missing u-boot-dtb-with-ucode node is detected"""
1017 with self.assertRaises(ValueError) as e:
1018 self._DoReadFile('038_x86_ucode_missing_node.dts', True)
1019 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1020 "microcode region u-boot-dtb-with-ucode", str(e.exception))
1022 def testMicrocodeWithoutNode2(self):
1023 """Test that a missing u-boot-ucode node is detected"""
1024 with self.assertRaises(ValueError) as e:
1025 self._DoReadFile('039_x86_ucode_missing_node2.dts', True)
1026 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1027 "microcode region u-boot-ucode", str(e.exception))
1029 def testMicrocodeWithoutPtrInElf(self):
1030 """Test that a U-Boot binary without the microcode symbol is detected"""
1031 # ELF file without a '_dt_ucode_base_size' symbol
1033 with open(self.TestFile('u_boot_no_ucode_ptr'), 'rb') as fd:
1034 TestFunctional._MakeInputFile('u-boot', fd.read())
1036 with self.assertRaises(ValueError) as e:
1037 self._RunPackUbootSingleMicrocode()
1038 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
1039 "_dt_ucode_base_size symbol in u-boot", str(e.exception))
1042 # Put the original file back
1043 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
1044 TestFunctional._MakeInputFile('u-boot', fd.read())
1046 def testMicrocodeNotInImage(self):
1047 """Test that microcode must be placed within the image"""
1048 with self.assertRaises(ValueError) as e:
1049 self._DoReadFile('040_x86_ucode_not_in_image.dts', True)
1050 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
1051 "pointer _dt_ucode_base_size at fffffe14 is outside the "
1052 "section ranging from 00000000 to 0000002e", str(e.exception))
1054 def testWithoutMicrocode(self):
1055 """Test that we can cope with an image without microcode (e.g. qemu)"""
1056 with open(self.TestFile('u_boot_no_ucode_ptr'), 'rb') as fd:
1057 TestFunctional._MakeInputFile('u-boot', fd.read())
1058 data, dtb, _, _ = self._DoReadFileDtb('044_x86_optional_ucode.dts', True)
1060 # Now check the device tree has no microcode
1061 self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
1062 second = data[len(U_BOOT_NODTB_DATA):]
1064 fdt_len = self.GetFdtLen(second)
1065 self.assertEqual(dtb, second[:fdt_len])
1067 used_len = len(U_BOOT_NODTB_DATA) + fdt_len
1068 third = data[used_len:]
1069 self.assertEqual(tools.GetBytes(0, 0x200 - used_len), third)
1071 def testUnknownPosSize(self):
1072 """Test that microcode must be placed within the image"""
1073 with self.assertRaises(ValueError) as e:
1074 self._DoReadFile('041_unknown_pos_size.dts', True)
1075 self.assertIn("Section '/binman': Unable to set offset/size for unknown "
1076 "entry 'invalid-entry'", str(e.exception))
1078 def testPackFsp(self):
1079 """Test that an image with a FSP binary can be created"""
1080 data = self._DoReadFile('042_intel-fsp.dts')
1081 self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
1083 def testPackCmc(self):
1084 """Test that an image with a CMC binary can be created"""
1085 data = self._DoReadFile('043_intel-cmc.dts')
1086 self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
1088 def testPackVbt(self):
1089 """Test that an image with a VBT binary can be created"""
1090 data = self._DoReadFile('046_intel-vbt.dts')
1091 self.assertEqual(VBT_DATA, data[:len(VBT_DATA)])
1093 def testSplBssPad(self):
1094 """Test that we can pad SPL's BSS with zeros"""
1095 # ELF file with a '__bss_size' symbol
1097 data = self._DoReadFile('047_spl_bss_pad.dts')
1098 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0, 10) + U_BOOT_DATA,
1101 def testSplBssPadMissing(self):
1102 """Test that a missing symbol is detected"""
1103 self._SetupSplElf('u_boot_ucode_ptr')
1104 with self.assertRaises(ValueError) as e:
1105 self._DoReadFile('047_spl_bss_pad.dts')
1106 self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
1109 def testPackStart16Spl(self):
1110 """Test that an image with an x86 start16 SPL region can be created"""
1111 data = self._DoReadFile('048_x86-start16-spl.dts')
1112 self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)])
1114 def _PackUbootSplMicrocode(self, dts, ucode_second=False):
1115 """Helper function for microcode tests
1117 We expect to see the following in the image, in order:
1118 u-boot-spl-nodtb.bin with a microcode pointer inserted at the
1120 u-boot.dtb with the microcode removed
1124 dts: Device tree file to use for test
1125 ucode_second: True if the microsecond entry is second instead of
1128 self._SetupSplElf('u_boot_ucode_ptr')
1129 first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA,
1130 ucode_second=ucode_second)
1131 self.assertEqual(b'splnodtb with microc' + pos_and_size +
1132 b'ter somewhere in here', first)
1134 def testPackUbootSplMicrocode(self):
1135 """Test that x86 microcode can be handled correctly in SPL"""
1136 self._PackUbootSplMicrocode('049_x86_ucode_spl.dts')
1138 def testPackUbootSplMicrocodeReorder(self):
1139 """Test that order doesn't matter for microcode entries
1141 This is the same as testPackUbootSplMicrocode but when we process the
1142 u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode
1143 entry, so we reply on binman to try later.
1145 self._PackUbootSplMicrocode('058_x86_ucode_spl_needs_retry.dts',
1148 def testPackMrc(self):
1149 """Test that an image with an MRC binary can be created"""
1150 data = self._DoReadFile('050_intel_mrc.dts')
1151 self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
1153 def testSplDtb(self):
1154 """Test that an image with spl/u-boot-spl.dtb can be created"""
1155 data = self._DoReadFile('051_u_boot_spl_dtb.dts')
1156 self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
1158 def testSplNoDtb(self):
1159 """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
1160 data = self._DoReadFile('052_u_boot_spl_nodtb.dts')
1161 self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
1163 def testSymbols(self):
1164 """Test binman can assign symbols embedded in U-Boot"""
1165 elf_fname = self.TestFile('u_boot_binman_syms')
1166 syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
1167 addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
1168 self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
1170 self._SetupSplElf('u_boot_binman_syms')
1171 data = self._DoReadFile('053_symbols.dts')
1172 sym_values = struct.pack('<LQL', 0x24 + 0, 0x24 + 24, 0x24 + 20)
1173 expected = (sym_values + U_BOOT_SPL_DATA[16:] +
1174 tools.GetBytes(0xff, 1) + U_BOOT_DATA + sym_values +
1175 U_BOOT_SPL_DATA[16:])
1176 self.assertEqual(expected, data)
1178 def testPackUnitAddress(self):
1179 """Test that we support multiple binaries with the same name"""
1180 data = self._DoReadFile('054_unit_address.dts')
1181 self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
1183 def testSections(self):
1184 """Basic test of sections"""
1185 data = self._DoReadFile('055_sections.dts')
1186 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1187 U_BOOT_DATA + tools.GetBytes(ord('a'), 12) +
1188 U_BOOT_DATA + tools.GetBytes(ord('&'), 4))
1189 self.assertEqual(expected, data)
1192 """Tests outputting a map of the images"""
1193 _, _, map_data, _ = self._DoReadFileDtb('055_sections.dts', map=True)
1194 self.assertEqual('''ImagePos Offset Size Name
1195 00000000 00000000 00000028 main-section
1196 00000000 00000000 00000010 section@0
1197 00000000 00000000 00000004 u-boot
1198 00000010 00000010 00000010 section@1
1199 00000010 00000000 00000004 u-boot
1200 00000020 00000020 00000004 section@2
1201 00000020 00000000 00000004 u-boot
1204 def testNamePrefix(self):
1205 """Tests that name prefixes are used"""
1206 _, _, map_data, _ = self._DoReadFileDtb('056_name_prefix.dts', map=True)
1207 self.assertEqual('''ImagePos Offset Size Name
1208 00000000 00000000 00000028 main-section
1209 00000000 00000000 00000010 section@0
1210 00000000 00000000 00000004 ro-u-boot
1211 00000010 00000010 00000010 section@1
1212 00000010 00000000 00000004 rw-u-boot
1215 def testUnknownContents(self):
1216 """Test that obtaining the contents works as expected"""
1217 with self.assertRaises(ValueError) as e:
1218 self._DoReadFile('057_unknown_contents.dts', True)
1219 self.assertIn("Section '/binman': Internal error: Could not complete "
1220 "processing of contents: remaining [<_testing.Entry__testing ",
1223 def testBadChangeSize(self):
1224 """Test that trying to change the size of an entry fails"""
1225 with self.assertRaises(ValueError) as e:
1226 self._DoReadFile('059_change_size.dts', True)
1227 self.assertIn("Node '/binman/_testing': Cannot update entry size from "
1228 '2 to 1', str(e.exception))
1230 def testUpdateFdt(self):
1231 """Test that we can update the device tree with offset/size info"""
1232 _, _, _, out_dtb_fname = self._DoReadFileDtb('060_fdt_update.dts',
1234 dtb = fdt.Fdt(out_dtb_fname)
1236 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'])
1240 '_testing:offset': 32,
1242 '_testing:image-pos': 32,
1243 'section@0/u-boot:offset': 0,
1244 'section@0/u-boot:size': len(U_BOOT_DATA),
1245 'section@0/u-boot:image-pos': 0,
1246 'section@0:offset': 0,
1247 'section@0:size': 16,
1248 'section@0:image-pos': 0,
1250 'section@1/u-boot:offset': 0,
1251 'section@1/u-boot:size': len(U_BOOT_DATA),
1252 'section@1/u-boot:image-pos': 16,
1253 'section@1:offset': 16,
1254 'section@1:size': 16,
1255 'section@1:image-pos': 16,
1259 def testUpdateFdtBad(self):
1260 """Test that we detect when ProcessFdt never completes"""
1261 with self.assertRaises(ValueError) as e:
1262 self._DoReadFileDtb('061_fdt_update_bad.dts', update_dtb=True)
1263 self.assertIn('Could not complete processing of Fdt: remaining '
1264 '[<_testing.Entry__testing', str(e.exception))
1266 def testEntryArgs(self):
1267 """Test passing arguments to entries from the command line"""
1269 'test-str-arg': 'test1',
1270 'test-int-arg': '456',
1272 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
1273 self.assertIn('image', control.images)
1274 entry = control.images['image'].GetEntries()['_testing']
1275 self.assertEqual('test0', entry.test_str_fdt)
1276 self.assertEqual('test1', entry.test_str_arg)
1277 self.assertEqual(123, entry.test_int_fdt)
1278 self.assertEqual(456, entry.test_int_arg)
1280 def testEntryArgsMissing(self):
1281 """Test missing arguments and properties"""
1283 'test-int-arg': '456',
1285 self._DoReadFileDtb('063_entry_args_missing.dts', entry_args=entry_args)
1286 entry = control.images['image'].GetEntries()['_testing']
1287 self.assertEqual('test0', entry.test_str_fdt)
1288 self.assertEqual(None, entry.test_str_arg)
1289 self.assertEqual(None, entry.test_int_fdt)
1290 self.assertEqual(456, entry.test_int_arg)
1292 def testEntryArgsRequired(self):
1293 """Test missing arguments and properties"""
1295 'test-int-arg': '456',
1297 with self.assertRaises(ValueError) as e:
1298 self._DoReadFileDtb('064_entry_args_required.dts')
1299 self.assertIn("Node '/binman/_testing': Missing required "
1300 'properties/entry args: test-str-arg, test-int-fdt, test-int-arg',
1303 def testEntryArgsInvalidFormat(self):
1304 """Test that an invalid entry-argument format is detected"""
1305 args = ['-d', self.TestFile('064_entry_args_required.dts'), '-ano-value']
1306 with self.assertRaises(ValueError) as e:
1307 self._DoBinman(*args)
1308 self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
1310 def testEntryArgsInvalidInteger(self):
1311 """Test that an invalid entry-argument integer is detected"""
1313 'test-int-arg': 'abc',
1315 with self.assertRaises(ValueError) as e:
1316 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
1317 self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
1318 "'test-int-arg' (value 'abc') to integer",
1321 def testEntryArgsInvalidDatatype(self):
1322 """Test that an invalid entry-argument datatype is detected
1324 This test could be written in entry_test.py except that it needs
1325 access to control.entry_args, which seems more than that module should
1329 'test-bad-datatype-arg': '12',
1331 with self.assertRaises(ValueError) as e:
1332 self._DoReadFileDtb('065_entry_args_unknown_datatype.dts',
1333 entry_args=entry_args)
1334 self.assertIn('GetArg() internal error: Unknown data type ',
1338 """Test for a text entry type"""
1340 'test-id': TEXT_DATA,
1341 'test-id2': TEXT_DATA2,
1342 'test-id3': TEXT_DATA3,
1344 data, _, _, _ = self._DoReadFileDtb('066_text.dts',
1345 entry_args=entry_args)
1346 expected = (tools.ToBytes(TEXT_DATA) +
1347 tools.GetBytes(0, 8 - len(TEXT_DATA)) +
1348 tools.ToBytes(TEXT_DATA2) + tools.ToBytes(TEXT_DATA3) +
1349 b'some text' + b'more text')
1350 self.assertEqual(expected, data)
1352 def testEntryDocs(self):
1353 """Test for creation of entry documentation"""
1354 with test_util.capture_sys_output() as (stdout, stderr):
1355 control.WriteEntryDocs(binman.GetEntryModules())
1356 self.assertTrue(len(stdout.getvalue()) > 0)
1358 def testEntryDocsMissing(self):
1359 """Test handling of missing entry documentation"""
1360 with self.assertRaises(ValueError) as e:
1361 with test_util.capture_sys_output() as (stdout, stderr):
1362 control.WriteEntryDocs(binman.GetEntryModules(), 'u_boot')
1363 self.assertIn('Documentation is missing for modules: u_boot',
1367 """Basic test of generation of a flashrom fmap"""
1368 data = self._DoReadFile('067_fmap.dts')
1369 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1370 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1371 U_BOOT_DATA + tools.GetBytes(ord('a'), 12))
1372 self.assertEqual(expected, data[:32])
1373 self.assertEqual(b'__FMAP__', fhdr.signature)
1374 self.assertEqual(1, fhdr.ver_major)
1375 self.assertEqual(0, fhdr.ver_minor)
1376 self.assertEqual(0, fhdr.base)
1377 self.assertEqual(16 + 16 +
1378 fmap_util.FMAP_HEADER_LEN +
1379 fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
1380 self.assertEqual(b'FMAP', fhdr.name)
1381 self.assertEqual(3, fhdr.nareas)
1382 for fentry in fentries:
1383 self.assertEqual(0, fentry.flags)
1385 self.assertEqual(0, fentries[0].offset)
1386 self.assertEqual(4, fentries[0].size)
1387 self.assertEqual(b'RO_U_BOOT', fentries[0].name)
1389 self.assertEqual(16, fentries[1].offset)
1390 self.assertEqual(4, fentries[1].size)
1391 self.assertEqual(b'RW_U_BOOT', fentries[1].name)
1393 self.assertEqual(32, fentries[2].offset)
1394 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1395 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1396 self.assertEqual(b'FMAP', fentries[2].name)
1398 def testBlobNamedByArg(self):
1399 """Test we can add a blob with the filename coming from an entry arg"""
1401 'cros-ec-rw-path': 'ecrw.bin',
1403 data, _, _, _ = self._DoReadFileDtb('068_blob_named_by_arg.dts',
1404 entry_args=entry_args)
1407 """Test for an fill entry type"""
1408 data = self._DoReadFile('069_fill.dts')
1409 expected = tools.GetBytes(0xff, 8) + tools.GetBytes(0, 8)
1410 self.assertEqual(expected, data)
1412 def testFillNoSize(self):
1413 """Test for an fill entry type with no size"""
1414 with self.assertRaises(ValueError) as e:
1415 self._DoReadFile('070_fill_no_size.dts')
1416 self.assertIn("'fill' entry must have a size property",
1419 def _HandleGbbCommand(self, pipe_list):
1420 """Fake calls to the futility utility"""
1421 if pipe_list[0][0] == 'futility':
1422 fname = pipe_list[0][-1]
1423 # Append our GBB data to the file, which will happen every time the
1424 # futility command is called.
1425 with open(fname, 'ab') as fd:
1427 return command.CommandResult()
1430 """Test for the Chromium OS Google Binary Block"""
1431 command.test_result = self._HandleGbbCommand
1433 'keydir': 'devkeys',
1434 'bmpblk': 'bmpblk.bin',
1436 data, _, _, _ = self._DoReadFileDtb('071_gbb.dts', entry_args=entry_args)
1439 expected = (GBB_DATA + GBB_DATA + tools.GetBytes(0, 8) +
1440 tools.GetBytes(0, 0x2180 - 16))
1441 self.assertEqual(expected, data)
1443 def testGbbTooSmall(self):
1444 """Test for the Chromium OS Google Binary Block being large enough"""
1445 with self.assertRaises(ValueError) as e:
1446 self._DoReadFileDtb('072_gbb_too_small.dts')
1447 self.assertIn("Node '/binman/gbb': GBB is too small",
1450 def testGbbNoSize(self):
1451 """Test for the Chromium OS Google Binary Block having a size"""
1452 with self.assertRaises(ValueError) as e:
1453 self._DoReadFileDtb('073_gbb_no_size.dts')
1454 self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
1457 def _HandleVblockCommand(self, pipe_list):
1458 """Fake calls to the futility utility"""
1459 if pipe_list[0][0] == 'futility':
1460 fname = pipe_list[0][3]
1461 with open(fname, 'wb') as fd:
1462 fd.write(VBLOCK_DATA)
1463 return command.CommandResult()
1465 def testVblock(self):
1466 """Test for the Chromium OS Verified Boot Block"""
1467 command.test_result = self._HandleVblockCommand
1469 'keydir': 'devkeys',
1471 data, _, _, _ = self._DoReadFileDtb('074_vblock.dts',
1472 entry_args=entry_args)
1473 expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
1474 self.assertEqual(expected, data)
1476 def testVblockNoContent(self):
1477 """Test we detect a vblock which has no content to sign"""
1478 with self.assertRaises(ValueError) as e:
1479 self._DoReadFile('075_vblock_no_content.dts')
1480 self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
1481 'property', str(e.exception))
1483 def testVblockBadPhandle(self):
1484 """Test that we detect a vblock with an invalid phandle in contents"""
1485 with self.assertRaises(ValueError) as e:
1486 self._DoReadFile('076_vblock_bad_phandle.dts')
1487 self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
1488 '1000', str(e.exception))
1490 def testVblockBadEntry(self):
1491 """Test that we detect an entry that points to a non-entry"""
1492 with self.assertRaises(ValueError) as e:
1493 self._DoReadFile('077_vblock_bad_entry.dts')
1494 self.assertIn("Node '/binman/vblock': Cannot find entry for node "
1495 "'other'", str(e.exception))
1498 """Test that an image with TPL and ots device tree can be created"""
1499 # ELF file with a '__bss_size' symbol
1500 with open(self.TestFile('bss_data'), 'rb') as fd:
1501 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1502 data = self._DoReadFile('078_u_boot_tpl.dts')
1503 self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
1505 def testUsesPos(self):
1506 """Test that the 'pos' property cannot be used anymore"""
1507 with self.assertRaises(ValueError) as e:
1508 data = self._DoReadFile('079_uses_pos.dts')
1509 self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
1510 "'pos'", str(e.exception))
1512 def testFillZero(self):
1513 """Test for an fill entry type with a size of 0"""
1514 data = self._DoReadFile('080_fill_empty.dts')
1515 self.assertEqual(tools.GetBytes(0, 16), data)
1517 def testTextMissing(self):
1518 """Test for a text entry type where there is no text"""
1519 with self.assertRaises(ValueError) as e:
1520 self._DoReadFileDtb('066_text.dts',)
1521 self.assertIn("Node '/binman/text': No value provided for text label "
1522 "'test-id'", str(e.exception))
1524 def testPackStart16Tpl(self):
1525 """Test that an image with an x86 start16 TPL region can be created"""
1526 data = self._DoReadFile('081_x86-start16-tpl.dts')
1527 self.assertEqual(X86_START16_TPL_DATA, data[:len(X86_START16_TPL_DATA)])
1529 def testSelectImage(self):
1530 """Test that we can select which images to build"""
1531 expected = 'Skipping images: image1'
1533 # We should only get the expected message in verbose mode
1534 for verbosity in (0, 2):
1535 with test_util.capture_sys_output() as (stdout, stderr):
1536 retcode = self._DoTestFile('006_dual_image.dts',
1537 verbosity=verbosity,
1539 self.assertEqual(0, retcode)
1541 self.assertIn(expected, stdout.getvalue())
1543 self.assertNotIn(expected, stdout.getvalue())
1545 self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
1546 self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
1548 def testUpdateFdtAll(self):
1549 """Test that all device trees are updated with offset/size info"""
1550 data, _, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
1551 use_real_dtb=True, update_dtb=True)
1554 'section:image-pos': 0,
1555 'u-boot-tpl-dtb:size': 513,
1556 'u-boot-spl-dtb:size': 513,
1557 'u-boot-spl-dtb:offset': 493,
1559 'section/u-boot-dtb:image-pos': 0,
1560 'u-boot-spl-dtb:image-pos': 493,
1561 'section/u-boot-dtb:size': 493,
1562 'u-boot-tpl-dtb:image-pos': 1006,
1563 'section/u-boot-dtb:offset': 0,
1564 'section:size': 493,
1566 'section:offset': 0,
1567 'u-boot-tpl-dtb:offset': 1006,
1571 # We expect three device-tree files in the output, one after the other.
1572 # Read them in sequence. We look for an 'spl' property in the SPL tree,
1573 # and 'tpl' in the TPL tree, to make sure they are distinct from the
1574 # main U-Boot tree. All three should have the same postions and offset.
1576 for item in ['', 'spl', 'tpl']:
1577 dtb = fdt.Fdt.FromData(data[start:])
1579 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos',
1581 expected = dict(base_expected)
1584 self.assertEqual(expected, props)
1585 start += dtb._fdt_obj.totalsize()
1587 def testUpdateFdtOutput(self):
1588 """Test that output DTB files are updated"""
1590 data, dtb_data, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
1591 use_real_dtb=True, update_dtb=True, reset_dtbs=False)
1593 # Unfortunately, compiling a source file always results in a file
1594 # called source.dtb (see fdt_util.EnsureCompiled()). The test
1595 # source file (e.g. test/075_fdt_update_all.dts) thus does not enter
1596 # binman as a file called u-boot.dtb. To fix this, copy the file
1597 # over to the expected place.
1598 #tools.WriteFile(os.path.join(self._indir, 'u-boot.dtb'),
1599 #tools.ReadFile(tools.GetOutputFilename('source.dtb')))
1601 for fname in ['u-boot.dtb.out', 'spl/u-boot-spl.dtb.out',
1602 'tpl/u-boot-tpl.dtb.out']:
1603 dtb = fdt.Fdt.FromData(data[start:])
1604 size = dtb._fdt_obj.totalsize()
1605 pathname = tools.GetOutputFilename(os.path.split(fname)[1])
1606 outdata = tools.ReadFile(pathname)
1607 name = os.path.split(fname)[0]
1610 orig_indata = self._GetDtbContentsForSplTpl(dtb_data, name)
1612 orig_indata = dtb_data
1613 self.assertNotEqual(outdata, orig_indata,
1614 "Expected output file '%s' be updated" % pathname)
1615 self.assertEqual(outdata, data[start:start + size],
1616 "Expected output file '%s' to match output image" %
1622 def _decompress(self, data):
1623 return tools.Decompress(data, 'lz4')
1625 def testCompress(self):
1626 """Test compression of blobs"""
1628 data, _, _, out_dtb_fname = self._DoReadFileDtb('083_compress.dts',
1629 use_real_dtb=True, update_dtb=True)
1630 dtb = fdt.Fdt(out_dtb_fname)
1632 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
1633 orig = self._decompress(data)
1634 self.assertEquals(COMPRESS_DATA, orig)
1636 'blob:uncomp-size': len(COMPRESS_DATA),
1637 'blob:size': len(data),
1640 self.assertEqual(expected, props)
1642 def testFiles(self):
1643 """Test bringing in multiple files"""
1644 data = self._DoReadFile('084_files.dts')
1645 self.assertEqual(FILES_DATA, data)
1647 def testFilesCompress(self):
1648 """Test bringing in multiple files and compressing them"""
1650 data = self._DoReadFile('085_files_compress.dts')
1652 image = control.images['image']
1653 entries = image.GetEntries()
1654 files = entries['files']
1655 entries = files._section._entries
1658 for i in range(1, 3):
1660 start = entries[key].image_pos
1661 len = entries[key].size
1662 chunk = data[start:start + len]
1663 orig += self._decompress(chunk)
1665 self.assertEqual(FILES_DATA, orig)
1667 def testFilesMissing(self):
1668 """Test missing files"""
1669 with self.assertRaises(ValueError) as e:
1670 data = self._DoReadFile('086_files_none.dts')
1671 self.assertIn("Node '/binman/files': Pattern \'files/*.none\' matched "
1672 'no files', str(e.exception))
1674 def testFilesNoPattern(self):
1675 """Test missing files"""
1676 with self.assertRaises(ValueError) as e:
1677 data = self._DoReadFile('087_files_no_pattern.dts')
1678 self.assertIn("Node '/binman/files': Missing 'pattern' property",
1681 def testExpandSize(self):
1682 """Test an expanding entry"""
1683 data, _, map_data, _ = self._DoReadFileDtb('088_expand_size.dts',
1685 expect = (tools.GetBytes(ord('a'), 8) + U_BOOT_DATA +
1686 MRC_DATA + tools.GetBytes(ord('b'), 1) + U_BOOT_DATA +
1687 tools.GetBytes(ord('c'), 8) + U_BOOT_DATA +
1688 tools.GetBytes(ord('d'), 8))
1689 self.assertEqual(expect, data)
1690 self.assertEqual('''ImagePos Offset Size Name
1691 00000000 00000000 00000028 main-section
1692 00000000 00000000 00000008 fill
1693 00000008 00000008 00000004 u-boot
1694 0000000c 0000000c 00000004 section
1695 0000000c 00000000 00000003 intel-mrc
1696 00000010 00000010 00000004 u-boot2
1697 00000014 00000014 0000000c section2
1698 00000014 00000000 00000008 fill
1699 0000001c 00000008 00000004 u-boot
1700 00000020 00000020 00000008 fill2
1703 def testExpandSizeBad(self):
1704 """Test an expanding entry which fails to provide contents"""
1705 with test_util.capture_sys_output() as (stdout, stderr):
1706 with self.assertRaises(ValueError) as e:
1707 self._DoReadFileDtb('089_expand_size_bad.dts', map=True)
1708 self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
1709 'expanding entry', str(e.exception))
1712 """Test hashing of the contents of an entry"""
1713 _, _, _, out_dtb_fname = self._DoReadFileDtb('090_hash.dts',
1714 use_real_dtb=True, update_dtb=True)
1715 dtb = fdt.Fdt(out_dtb_fname)
1717 hash_node = dtb.GetNode('/binman/u-boot/hash').props['value']
1718 m = hashlib.sha256()
1719 m.update(U_BOOT_DATA)
1720 self.assertEqual(m.digest(), b''.join(hash_node.value))
1722 def testHashNoAlgo(self):
1723 with self.assertRaises(ValueError) as e:
1724 self._DoReadFileDtb('091_hash_no_algo.dts', update_dtb=True)
1725 self.assertIn("Node \'/binman/u-boot\': Missing \'algo\' property for "
1726 'hash node', str(e.exception))
1728 def testHashBadAlgo(self):
1729 with self.assertRaises(ValueError) as e:
1730 self._DoReadFileDtb('092_hash_bad_algo.dts', update_dtb=True)
1731 self.assertIn("Node '/binman/u-boot': Unknown hash algorithm",
1734 def testHashSection(self):
1735 """Test hashing of the contents of an entry"""
1736 _, _, _, out_dtb_fname = self._DoReadFileDtb('099_hash_section.dts',
1737 use_real_dtb=True, update_dtb=True)
1738 dtb = fdt.Fdt(out_dtb_fname)
1740 hash_node = dtb.GetNode('/binman/section/hash').props['value']
1741 m = hashlib.sha256()
1742 m.update(U_BOOT_DATA)
1743 m.update(tools.GetBytes(ord('a'), 16))
1744 self.assertEqual(m.digest(), b''.join(hash_node.value))
1746 def testPackUBootTplMicrocode(self):
1747 """Test that x86 microcode can be handled correctly in TPL
1749 We expect to see the following in the image, in order:
1750 u-boot-tpl-nodtb.bin with a microcode pointer inserted at the correct
1752 u-boot-tpl.dtb with the microcode removed
1755 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
1756 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1757 first, pos_and_size = self._RunMicrocodeTest('093_x86_tpl_ucode.dts',
1758 U_BOOT_TPL_NODTB_DATA)
1759 self.assertEqual(b'tplnodtb with microc' + pos_and_size +
1760 b'ter somewhere in here', first)
1762 def testFmapX86(self):
1763 """Basic test of generation of a flashrom fmap"""
1764 data = self._DoReadFile('094_fmap_x86.dts')
1765 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1766 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('a'), 32 - 7)
1767 self.assertEqual(expected, data[:32])
1768 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1770 self.assertEqual(0x100, fhdr.image_size)
1772 self.assertEqual(0, fentries[0].offset)
1773 self.assertEqual(4, fentries[0].size)
1774 self.assertEqual(b'U_BOOT', fentries[0].name)
1776 self.assertEqual(4, fentries[1].offset)
1777 self.assertEqual(3, fentries[1].size)
1778 self.assertEqual(b'INTEL_MRC', fentries[1].name)
1780 self.assertEqual(32, fentries[2].offset)
1781 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1782 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1783 self.assertEqual(b'FMAP', fentries[2].name)
1785 def testFmapX86Section(self):
1786 """Basic test of generation of a flashrom fmap"""
1787 data = self._DoReadFile('095_fmap_x86_section.dts')
1788 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('b'), 32 - 7)
1789 self.assertEqual(expected, data[:32])
1790 fhdr, fentries = fmap_util.DecodeFmap(data[36:])
1792 self.assertEqual(0x100, fhdr.image_size)
1794 self.assertEqual(0, fentries[0].offset)
1795 self.assertEqual(4, fentries[0].size)
1796 self.assertEqual(b'U_BOOT', fentries[0].name)
1798 self.assertEqual(4, fentries[1].offset)
1799 self.assertEqual(3, fentries[1].size)
1800 self.assertEqual(b'INTEL_MRC', fentries[1].name)
1802 self.assertEqual(36, fentries[2].offset)
1803 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1804 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1805 self.assertEqual(b'FMAP', fentries[2].name)
1808 """Basic test of ELF entries"""
1810 with open(self.TestFile('bss_data'), 'rb') as fd:
1811 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1812 with open(self.TestFile('bss_data'), 'rb') as fd:
1813 TestFunctional._MakeInputFile('-boot', fd.read())
1814 data = self._DoReadFile('096_elf.dts')
1816 def testElfStrip(self):
1817 """Basic test of ELF entries"""
1819 with open(self.TestFile('bss_data'), 'rb') as fd:
1820 TestFunctional._MakeInputFile('-boot', fd.read())
1821 data = self._DoReadFile('097_elf_strip.dts')
1823 def testPackOverlapMap(self):
1824 """Test that overlapping regions are detected"""
1825 with test_util.capture_sys_output() as (stdout, stderr):
1826 with self.assertRaises(ValueError) as e:
1827 self._DoTestFile('014_pack_overlap.dts', map=True)
1828 map_fname = tools.GetOutputFilename('image.map')
1829 self.assertEqual("Wrote map file '%s' to show errors\n" % map_fname,
1832 # We should not get an inmage, but there should be a map file
1833 self.assertFalse(os.path.exists(tools.GetOutputFilename('image.bin')))
1834 self.assertTrue(os.path.exists(map_fname))
1835 map_data = tools.ReadFile(map_fname, binary=False)
1836 self.assertEqual('''ImagePos Offset Size Name
1837 <none> 00000000 00000007 main-section
1838 <none> 00000000 00000004 u-boot
1839 <none> 00000003 00000004 u-boot-align
1842 def testPackRefCode(self):
1843 """Test that an image with an Intel Reference code binary works"""
1844 data = self._DoReadFile('100_intel_refcode.dts')
1845 self.assertEqual(REFCODE_DATA, data[:len(REFCODE_DATA)])
1847 def testSectionOffset(self):
1848 """Tests use of a section with an offset"""
1849 data, _, map_data, _ = self._DoReadFileDtb('101_sections_offset.dts',
1851 self.assertEqual('''ImagePos Offset Size Name
1852 00000000 00000000 00000038 main-section
1853 00000004 00000004 00000010 section@0
1854 00000004 00000000 00000004 u-boot
1855 00000018 00000018 00000010 section@1
1856 00000018 00000000 00000004 u-boot
1857 0000002c 0000002c 00000004 section@2
1858 0000002c 00000000 00000004 u-boot
1860 self.assertEqual(data,
1861 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1862 tools.GetBytes(0x21, 12) +
1863 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1864 tools.GetBytes(0x61, 12) +
1865 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1866 tools.GetBytes(0x26, 8))
1868 def testCbfsRaw(self):
1869 """Test base handling of a Coreboot Filesystem (CBFS)
1871 The exact contents of the CBFS is verified by similar tests in
1872 cbfs_util_test.py. The tests here merely check that the files added to
1873 the CBFS can be found in the final image.
1875 data = self._DoReadFile('102_cbfs_raw.dts')
1878 cbfs = cbfs_util.CbfsReader(data)
1879 self.assertEqual(size, cbfs.rom_size)
1881 self.assertIn('u-boot-dtb', cbfs.files)
1882 cfile = cbfs.files['u-boot-dtb']
1883 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
1885 def testCbfsArch(self):
1886 """Test on non-x86 architecture"""
1887 data = self._DoReadFile('103_cbfs_raw_ppc.dts')
1890 cbfs = cbfs_util.CbfsReader(data)
1891 self.assertEqual(size, cbfs.rom_size)
1893 self.assertIn('u-boot-dtb', cbfs.files)
1894 cfile = cbfs.files['u-boot-dtb']
1895 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
1897 def testCbfsStage(self):
1898 """Tests handling of a Coreboot Filesystem (CBFS)"""
1899 if not elf.ELF_TOOLS:
1900 self.skipTest('Python elftools not available')
1901 elf_fname = os.path.join(self._indir, 'cbfs-stage.elf')
1902 elf.MakeElf(elf_fname, U_BOOT_DATA, U_BOOT_DTB_DATA)
1905 data = self._DoReadFile('104_cbfs_stage.dts')
1906 cbfs = cbfs_util.CbfsReader(data)
1907 self.assertEqual(size, cbfs.rom_size)
1909 self.assertIn('u-boot', cbfs.files)
1910 cfile = cbfs.files['u-boot']
1911 self.assertEqual(U_BOOT_DATA + U_BOOT_DTB_DATA, cfile.data)
1913 def testCbfsRawCompress(self):
1914 """Test handling of compressing raw files"""
1916 data = self._DoReadFile('105_cbfs_raw_compress.dts')
1919 cbfs = cbfs_util.CbfsReader(data)
1920 self.assertIn('u-boot', cbfs.files)
1921 cfile = cbfs.files['u-boot']
1922 self.assertEqual(COMPRESS_DATA, cfile.data)
1924 def testCbfsBadArch(self):
1925 """Test handling of a bad architecture"""
1926 with self.assertRaises(ValueError) as e:
1927 self._DoReadFile('106_cbfs_bad_arch.dts')
1928 self.assertIn("Invalid architecture 'bad-arch'", str(e.exception))
1930 def testCbfsNoSize(self):
1931 """Test handling of a missing size property"""
1932 with self.assertRaises(ValueError) as e:
1933 self._DoReadFile('107_cbfs_no_size.dts')
1934 self.assertIn('entry must have a size property', str(e.exception))
1936 def testCbfsNoCOntents(self):
1937 """Test handling of a CBFS entry which does not provide contentsy"""
1938 with self.assertRaises(ValueError) as e:
1939 self._DoReadFile('108_cbfs_no_contents.dts')
1940 self.assertIn('Could not complete processing of contents',
1943 def testCbfsBadCompress(self):
1944 """Test handling of a bad architecture"""
1945 with self.assertRaises(ValueError) as e:
1946 self._DoReadFile('109_cbfs_bad_compress.dts')
1947 self.assertIn("Invalid compression in 'u-boot': 'invalid-algo'",
1950 def testCbfsNamedEntries(self):
1951 """Test handling of named entries"""
1952 data = self._DoReadFile('110_cbfs_name.dts')
1954 cbfs = cbfs_util.CbfsReader(data)
1955 self.assertIn('FRED', cbfs.files)
1956 cfile1 = cbfs.files['FRED']
1957 self.assertEqual(U_BOOT_DATA, cfile1.data)
1959 self.assertIn('hello', cbfs.files)
1960 cfile2 = cbfs.files['hello']
1961 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
1963 def _SetupIfwi(self, fname):
1964 """Set up to run an IFWI test
1967 fname: Filename of input file to provide (fitimage.bin or ifwi.bin)
1971 # Intel Integrated Firmware Image (IFWI) file
1972 with gzip.open(self.TestFile('%s.gz' % fname), 'rb') as fd:
1974 TestFunctional._MakeInputFile(fname,data)
1976 def _CheckIfwi(self, data):
1977 """Check that an image with an IFWI contains the correct output
1980 data: Conents of output file
1982 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
1983 if data[:0x1000] != expected_desc:
1984 self.fail('Expected descriptor binary at start of image')
1986 # We expect to find the TPL wil in subpart IBBP entry IBBL
1987 image_fname = tools.GetOutputFilename('image.bin')
1988 tpl_fname = tools.GetOutputFilename('tpl.out')
1989 tools.RunIfwiTool(image_fname, tools.CMD_EXTRACT, fname=tpl_fname,
1990 subpart='IBBP', entry_name='IBBL')
1992 tpl_data = tools.ReadFile(tpl_fname)
1993 self.assertEqual(tpl_data[:len(U_BOOT_TPL_DATA)], U_BOOT_TPL_DATA)
1995 def testPackX86RomIfwi(self):
1996 """Test that an x86 ROM with Integrated Firmware Image can be created"""
1997 self._SetupIfwi('fitimage.bin')
1998 data = self._DoReadFile('111_x86-rom-ifwi.dts')
1999 self._CheckIfwi(data)
2001 def testPackX86RomIfwiNoDesc(self):
2002 """Test that an x86 ROM with IFWI can be created from an ifwi.bin file"""
2003 self._SetupIfwi('ifwi.bin')
2004 data = self._DoReadFile('112_x86-rom-ifwi-nodesc.dts')
2005 self._CheckIfwi(data)
2007 def testPackX86RomIfwiNoData(self):
2008 """Test that an x86 ROM with IFWI handles missing data"""
2009 self._SetupIfwi('ifwi.bin')
2010 with self.assertRaises(ValueError) as e:
2011 data = self._DoReadFile('113_x86-rom-ifwi-nodata.dts')
2012 self.assertIn('Could not complete processing of contents',
2015 def testCbfsOffset(self):
2016 """Test a CBFS with files at particular offsets
2018 Like all CFBS tests, this is just checking the logic that calls
2019 cbfs_util. See cbfs_util_test for fully tests (e.g. test_cbfs_offset()).
2021 data = self._DoReadFile('114_cbfs_offset.dts')
2024 cbfs = cbfs_util.CbfsReader(data)
2025 self.assertEqual(size, cbfs.rom_size)
2027 self.assertIn('u-boot', cbfs.files)
2028 cfile = cbfs.files['u-boot']
2029 self.assertEqual(U_BOOT_DATA, cfile.data)
2030 self.assertEqual(0x40, cfile.cbfs_offset)
2032 self.assertIn('u-boot-dtb', cbfs.files)
2033 cfile2 = cbfs.files['u-boot-dtb']
2034 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
2035 self.assertEqual(0x140, cfile2.cbfs_offset)
2038 if __name__ == "__main__":