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 optparse import OptionParser
30 # Contents of test files, corresponding to different entry types
32 U_BOOT_IMG_DATA = 'img'
33 U_BOOT_SPL_DATA = '56780123456789abcde'
34 U_BOOT_TPL_DATA = 'tpl'
38 U_BOOT_DTB_DATA = 'udtb'
39 U_BOOT_SPL_DTB_DATA = 'spldtb'
40 U_BOOT_TPL_DTB_DATA = 'tpldtb'
41 X86_START16_DATA = 'start16'
42 X86_START16_SPL_DATA = 'start16spl'
43 X86_START16_TPL_DATA = 'start16tpl'
44 U_BOOT_NODTB_DATA = 'nodtb with microcode pointer somewhere in here'
45 U_BOOT_SPL_NODTB_DATA = 'splnodtb with microcode pointer somewhere in here'
53 CROS_EC_RW_DATA = 'ecrw'
59 class TestFunctional(unittest.TestCase):
60 """Functional tests for binman
62 Most of these use a sample .dts file to build an image and then check
63 that it looks correct. The sample files are in the test/ subdirectory
66 For each entry type a very small test file is created using fixed
67 string contents. This makes it easy to test that things look right, and
70 In some cases a 'real' file must be used - these are also supplied in
78 # Handle the case where argv[0] is 'python'
79 self._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
80 self._binman_pathname = os.path.join(self._binman_dir, 'binman')
82 # Create a temporary directory for input files
83 self._indir = tempfile.mkdtemp(prefix='binmant.')
85 # Create some test files
86 TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
87 TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
88 TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
89 TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
90 TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
91 TestFunctional._MakeInputFile('me.bin', ME_DATA)
92 TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
94 TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
95 TestFunctional._MakeInputFile('spl/u-boot-x86-16bit-spl.bin',
97 TestFunctional._MakeInputFile('tpl/u-boot-x86-16bit-tpl.bin',
99 TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
100 TestFunctional._MakeInputFile('spl/u-boot-spl-nodtb.bin',
101 U_BOOT_SPL_NODTB_DATA)
102 TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
103 TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
104 TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
105 TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
106 TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
107 TestFunctional._MakeInputDir('devkeys')
108 TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
109 self._output_setup = False
111 # ELF file with a '_dt_ucode_base_size' symbol
112 with open(self.TestFile('u_boot_ucode_ptr')) as fd:
113 TestFunctional._MakeInputFile('u-boot', fd.read())
115 # Intel flash descriptor file
116 with open(self.TestFile('descriptor.bin')) as fd:
117 TestFunctional._MakeInputFile('descriptor.bin', fd.read())
120 def tearDownClass(self):
121 """Remove the temporary input directory and its contents"""
123 shutil.rmtree(self._indir)
127 # Enable this to turn on debugging output
128 # tout.Init(tout.DEBUG)
129 command.test_result = None
132 """Remove the temporary output directory"""
133 tools._FinaliseForTest()
136 def _ResetDtbs(self):
137 TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
138 TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
139 TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
141 def _RunBinman(self, *args, **kwargs):
142 """Run binman using the command line
145 Arguments to pass, as a list of strings
146 kwargs: Arguments to pass to Command.RunPipe()
148 result = command.RunPipe([[self._binman_pathname] + list(args)],
149 capture=True, capture_stderr=True, raise_on_error=False)
150 if result.return_code and kwargs.get('raise_on_error', True):
151 raise Exception("Error running '%s': %s" % (' '.join(args),
152 result.stdout + result.stderr))
155 def _DoBinman(self, *args):
156 """Run binman using directly (in the same process)
159 Arguments to pass, as a list of strings
161 Return value (0 for success)
166 (options, args) = cmdline.ParseArgs(args)
167 options.pager = 'binman-invalid-pager'
168 options.build_dir = self._indir
170 # For testing, you can force an increase in verbosity here
171 # options.verbosity = tout.DEBUG
172 return control.Binman(options, args)
174 def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
175 entry_args=None, images=None):
176 """Run binman with a given test file
179 fname: Device-tree source filename to use (e.g. 05_simple.dts)
180 debug: True to enable debugging output
181 map: True to output map files for the images
182 update_dtb: Update the offset and size of each entry in the device
183 tree before packing it into the image
184 entry_args: Dict of entry args to supply to binman
186 value: value of that arg
187 images: List of image names to build
189 args = ['-p', '-I', self._indir, '-d', self.TestFile(fname)]
197 for arg, value in entry_args.iteritems():
198 args.append('-a%s=%s' % (arg, value))
201 args += ['-i', image]
202 return self._DoBinman(*args)
204 def _SetupDtb(self, fname, outfile='u-boot.dtb'):
205 """Set up a new test device-tree file
207 The given file is compiled and set up as the device tree to be used
211 fname: Filename of .dts file to read
212 outfile: Output filename for compiled device-tree binary
215 Contents of device-tree binary
217 if not self._output_setup:
218 tools.PrepareOutputDir(self._indir, True)
219 self._output_setup = True
220 dtb = fdt_util.EnsureCompiled(self.TestFile(fname))
221 with open(dtb) as fd:
223 TestFunctional._MakeInputFile(outfile, data)
226 def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
227 update_dtb=False, entry_args=None):
228 """Run binman and return the resulting image
230 This runs binman with a given test file and then reads the resulting
231 output file. It is a shortcut function since most tests need to do
234 Raises an assertion failure if binman returns a non-zero exit code.
237 fname: Device-tree source filename to use (e.g. 05_simple.dts)
238 use_real_dtb: True to use the test file as the contents of
239 the u-boot-dtb entry. Normally this is not needed and the
240 test contents (the U_BOOT_DTB_DATA string) can be used.
241 But in some test we need the real contents.
242 map: True to output map files for the images
243 update_dtb: Update the offset and size of each entry in the device
244 tree before packing it into the image
248 Resulting image contents
250 Map data showing contents of image (or None if none)
251 Output device tree binary filename ('u-boot.dtb' path)
254 # Use the compiled test file as the u-boot-dtb input
256 dtb_data = self._SetupDtb(fname)
259 retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
260 entry_args=entry_args)
261 self.assertEqual(0, retcode)
262 out_dtb_fname = state.GetFdtPath('u-boot.dtb')
264 # Find the (only) image, read it and return its contents
265 image = control.images['image']
266 image_fname = tools.GetOutputFilename('image.bin')
267 self.assertTrue(os.path.exists(image_fname))
269 map_fname = tools.GetOutputFilename('image.map')
270 with open(map_fname) as fd:
274 with open(image_fname) as fd:
275 return fd.read(), dtb_data, map_data, out_dtb_fname
277 # Put the test file back
281 def _DoReadFile(self, fname, use_real_dtb=False):
282 """Helper function which discards the device-tree binary
285 fname: Device-tree source filename to use (e.g. 05_simple.dts)
286 use_real_dtb: True to use the test file as the contents of
287 the u-boot-dtb entry. Normally this is not needed and the
288 test contents (the U_BOOT_DTB_DATA string) can be used.
289 But in some test we need the real contents.
292 Resulting image contents
294 return self._DoReadFileDtb(fname, use_real_dtb)[0]
297 def _MakeInputFile(self, fname, contents):
298 """Create a new test input file, creating directories as needed
301 fname: Filename to create
302 contents: File contents to write in to the file
304 Full pathname of file created
306 pathname = os.path.join(self._indir, fname)
307 dirname = os.path.dirname(pathname)
308 if dirname and not os.path.exists(dirname):
310 with open(pathname, 'wb') as fd:
315 def _MakeInputDir(self, dirname):
316 """Create a new test input directory, creating directories as needed
319 dirname: Directory name to create
322 Full pathname of directory created
324 pathname = os.path.join(self._indir, dirname)
325 if not os.path.exists(pathname):
326 os.makedirs(pathname)
330 def TestFile(self, fname):
331 return os.path.join(self._binman_dir, 'test', fname)
333 def AssertInList(self, grep_list, target):
334 """Assert that at least one of a list of things is in a target
337 grep_list: List of strings to check
338 target: Target string
340 for grep in grep_list:
343 self.fail("Error: '%' not found in '%s'" % (grep_list, target))
345 def CheckNoGaps(self, entries):
346 """Check that all entries fit together without gaps
349 entries: List of entries to check
352 for entry in entries.values():
353 self.assertEqual(offset, entry.offset)
356 def GetFdtLen(self, dtb):
357 """Get the totalsize field from a device-tree binary
360 dtb: Device-tree binary contents
363 Total size of device-tree binary, from the header
365 return struct.unpack('>L', dtb[4:8])[0]
367 def _GetPropTree(self, dtb, prop_names):
368 def AddNode(node, path):
370 path += '/' + node.name
371 for subnode in node.subnodes:
372 for prop in subnode.props.values():
373 if prop.name in prop_names:
374 prop_path = path + '/' + subnode.name + ':' + prop.name
375 tree[prop_path[len('/binman/'):]] = fdt_util.fdt32_to_cpu(
377 AddNode(subnode, path)
380 AddNode(dtb.GetRoot(), '')
384 """Test a basic run with valid args"""
385 result = self._RunBinman('-h')
387 def testFullHelp(self):
388 """Test that the full help is displayed with -H"""
389 result = self._RunBinman('-H')
390 help_file = os.path.join(self._binman_dir, 'README')
391 # Remove possible extraneous strings
392 extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
393 gothelp = result.stdout.replace(extra, '')
394 self.assertEqual(len(gothelp), os.path.getsize(help_file))
395 self.assertEqual(0, len(result.stderr))
396 self.assertEqual(0, result.return_code)
398 def testFullHelpInternal(self):
399 """Test that the full help is displayed with -H"""
401 command.test_result = command.CommandResult()
402 result = self._DoBinman('-H')
403 help_file = os.path.join(self._binman_dir, 'README')
405 command.test_result = None
408 """Test that the basic help is displayed with -h"""
409 result = self._RunBinman('-h')
410 self.assertTrue(len(result.stdout) > 200)
411 self.assertEqual(0, len(result.stderr))
412 self.assertEqual(0, result.return_code)
415 """Test that we can run it with a specific board"""
416 self._SetupDtb('05_simple.dts', 'sandbox/u-boot.dtb')
417 TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
418 result = self._DoBinman('-b', 'sandbox')
419 self.assertEqual(0, result)
421 def testNeedBoard(self):
422 """Test that we get an error when no board ius supplied"""
423 with self.assertRaises(ValueError) as e:
424 result = self._DoBinman()
425 self.assertIn("Must provide a board to process (use -b <board>)",
428 def testMissingDt(self):
429 """Test that an invalid device-tree file generates an error"""
430 with self.assertRaises(Exception) as e:
431 self._RunBinman('-d', 'missing_file')
432 # We get one error from libfdt, and a different one from fdtget.
433 self.AssertInList(["Couldn't open blob from 'missing_file'",
434 'No such file or directory'], str(e.exception))
436 def testBrokenDt(self):
437 """Test that an invalid device-tree source file generates an error
439 Since this is a source file it should be compiled and the error
440 will come from the device-tree compiler (dtc).
442 with self.assertRaises(Exception) as e:
443 self._RunBinman('-d', self.TestFile('01_invalid.dts'))
444 self.assertIn("FATAL ERROR: Unable to parse input tree",
447 def testMissingNode(self):
448 """Test that a device tree without a 'binman' node generates an error"""
449 with self.assertRaises(Exception) as e:
450 self._DoBinman('-d', self.TestFile('02_missing_node.dts'))
451 self.assertIn("does not have a 'binman' node", str(e.exception))
454 """Test that an empty binman node works OK (i.e. does nothing)"""
455 result = self._RunBinman('-d', self.TestFile('03_empty.dts'))
456 self.assertEqual(0, len(result.stderr))
457 self.assertEqual(0, result.return_code)
459 def testInvalidEntry(self):
460 """Test that an invalid entry is flagged"""
461 with self.assertRaises(Exception) as e:
462 result = self._RunBinman('-d',
463 self.TestFile('04_invalid_entry.dts'))
464 self.assertIn("Unknown entry type 'not-a-valid-type' in node "
465 "'/binman/not-a-valid-type'", str(e.exception))
467 def testSimple(self):
468 """Test a simple binman with a single file"""
469 data = self._DoReadFile('05_simple.dts')
470 self.assertEqual(U_BOOT_DATA, data)
472 def testSimpleDebug(self):
473 """Test a simple binman run with debugging enabled"""
474 data = self._DoTestFile('05_simple.dts', debug=True)
477 """Test that we can handle creating two images
479 This also tests image padding.
481 retcode = self._DoTestFile('06_dual_image.dts')
482 self.assertEqual(0, retcode)
484 image = control.images['image1']
485 self.assertEqual(len(U_BOOT_DATA), image._size)
486 fname = tools.GetOutputFilename('image1.bin')
487 self.assertTrue(os.path.exists(fname))
488 with open(fname) as fd:
490 self.assertEqual(U_BOOT_DATA, data)
492 image = control.images['image2']
493 self.assertEqual(3 + len(U_BOOT_DATA) + 5, image._size)
494 fname = tools.GetOutputFilename('image2.bin')
495 self.assertTrue(os.path.exists(fname))
496 with open(fname) as fd:
498 self.assertEqual(U_BOOT_DATA, data[3:7])
499 self.assertEqual(chr(0) * 3, data[:3])
500 self.assertEqual(chr(0) * 5, data[7:])
502 def testBadAlign(self):
503 """Test that an invalid alignment value is detected"""
504 with self.assertRaises(ValueError) as e:
505 self._DoTestFile('07_bad_align.dts')
506 self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
507 "of two", str(e.exception))
509 def testPackSimple(self):
510 """Test that packing works as expected"""
511 retcode = self._DoTestFile('08_pack.dts')
512 self.assertEqual(0, retcode)
513 self.assertIn('image', control.images)
514 image = control.images['image']
515 entries = image.GetEntries()
516 self.assertEqual(5, len(entries))
519 self.assertIn('u-boot', entries)
520 entry = entries['u-boot']
521 self.assertEqual(0, entry.offset)
522 self.assertEqual(len(U_BOOT_DATA), entry.size)
524 # Second u-boot, aligned to 16-byte boundary
525 self.assertIn('u-boot-align', entries)
526 entry = entries['u-boot-align']
527 self.assertEqual(16, entry.offset)
528 self.assertEqual(len(U_BOOT_DATA), entry.size)
530 # Third u-boot, size 23 bytes
531 self.assertIn('u-boot-size', entries)
532 entry = entries['u-boot-size']
533 self.assertEqual(20, entry.offset)
534 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
535 self.assertEqual(23, entry.size)
537 # Fourth u-boot, placed immediate after the above
538 self.assertIn('u-boot-next', entries)
539 entry = entries['u-boot-next']
540 self.assertEqual(43, entry.offset)
541 self.assertEqual(len(U_BOOT_DATA), entry.size)
543 # Fifth u-boot, placed at a fixed offset
544 self.assertIn('u-boot-fixed', entries)
545 entry = entries['u-boot-fixed']
546 self.assertEqual(61, entry.offset)
547 self.assertEqual(len(U_BOOT_DATA), entry.size)
549 self.assertEqual(65, image._size)
551 def testPackExtra(self):
552 """Test that extra packing feature works as expected"""
553 retcode = self._DoTestFile('09_pack_extra.dts')
555 self.assertEqual(0, retcode)
556 self.assertIn('image', control.images)
557 image = control.images['image']
558 entries = image.GetEntries()
559 self.assertEqual(5, len(entries))
561 # First u-boot with padding before and after
562 self.assertIn('u-boot', entries)
563 entry = entries['u-boot']
564 self.assertEqual(0, entry.offset)
565 self.assertEqual(3, entry.pad_before)
566 self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
568 # Second u-boot has an aligned size, but it has no effect
569 self.assertIn('u-boot-align-size-nop', entries)
570 entry = entries['u-boot-align-size-nop']
571 self.assertEqual(12, entry.offset)
572 self.assertEqual(4, entry.size)
574 # Third u-boot has an aligned size too
575 self.assertIn('u-boot-align-size', entries)
576 entry = entries['u-boot-align-size']
577 self.assertEqual(16, entry.offset)
578 self.assertEqual(32, entry.size)
580 # Fourth u-boot has an aligned end
581 self.assertIn('u-boot-align-end', entries)
582 entry = entries['u-boot-align-end']
583 self.assertEqual(48, entry.offset)
584 self.assertEqual(16, entry.size)
586 # Fifth u-boot immediately afterwards
587 self.assertIn('u-boot-align-both', entries)
588 entry = entries['u-boot-align-both']
589 self.assertEqual(64, entry.offset)
590 self.assertEqual(64, entry.size)
592 self.CheckNoGaps(entries)
593 self.assertEqual(128, image._size)
595 def testPackAlignPowerOf2(self):
596 """Test that invalid entry alignment is detected"""
597 with self.assertRaises(ValueError) as e:
598 self._DoTestFile('10_pack_align_power2.dts')
599 self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
600 "of two", str(e.exception))
602 def testPackAlignSizePowerOf2(self):
603 """Test that invalid entry size alignment is detected"""
604 with self.assertRaises(ValueError) as e:
605 self._DoTestFile('11_pack_align_size_power2.dts')
606 self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
607 "power of two", str(e.exception))
609 def testPackInvalidAlign(self):
610 """Test detection of an offset that does not match its alignment"""
611 with self.assertRaises(ValueError) as e:
612 self._DoTestFile('12_pack_inv_align.dts')
613 self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
614 "align 0x4 (4)", str(e.exception))
616 def testPackInvalidSizeAlign(self):
617 """Test that invalid entry size alignment is detected"""
618 with self.assertRaises(ValueError) as e:
619 self._DoTestFile('13_pack_inv_size_align.dts')
620 self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
621 "align-size 0x4 (4)", str(e.exception))
623 def testPackOverlap(self):
624 """Test that overlapping regions are detected"""
625 with self.assertRaises(ValueError) as e:
626 self._DoTestFile('14_pack_overlap.dts')
627 self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
628 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
631 def testPackEntryOverflow(self):
632 """Test that entries that overflow their size are detected"""
633 with self.assertRaises(ValueError) as e:
634 self._DoTestFile('15_pack_overflow.dts')
635 self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
636 "but entry size is 0x3 (3)", str(e.exception))
638 def testPackImageOverflow(self):
639 """Test that entries which overflow the image size are detected"""
640 with self.assertRaises(ValueError) as e:
641 self._DoTestFile('16_pack_image_overflow.dts')
642 self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section "
643 "size 0x3 (3)", str(e.exception))
645 def testPackImageSize(self):
646 """Test that the image size can be set"""
647 retcode = self._DoTestFile('17_pack_image_size.dts')
648 self.assertEqual(0, retcode)
649 self.assertIn('image', control.images)
650 image = control.images['image']
651 self.assertEqual(7, image._size)
653 def testPackImageSizeAlign(self):
654 """Test that image size alignemnt works as expected"""
655 retcode = self._DoTestFile('18_pack_image_align.dts')
656 self.assertEqual(0, retcode)
657 self.assertIn('image', control.images)
658 image = control.images['image']
659 self.assertEqual(16, image._size)
661 def testPackInvalidImageAlign(self):
662 """Test that invalid image alignment is detected"""
663 with self.assertRaises(ValueError) as e:
664 self._DoTestFile('19_pack_inv_image_align.dts')
665 self.assertIn("Section '/binman': Size 0x7 (7) does not match "
666 "align-size 0x8 (8)", str(e.exception))
668 def testPackAlignPowerOf2(self):
669 """Test that invalid image alignment is detected"""
670 with self.assertRaises(ValueError) as e:
671 self._DoTestFile('20_pack_inv_image_align_power2.dts')
672 self.assertIn("Section '/binman': Alignment size 131 must be a power of "
673 "two", str(e.exception))
675 def testImagePadByte(self):
676 """Test that the image pad byte can be specified"""
677 with open(self.TestFile('bss_data')) as fd:
678 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
679 data = self._DoReadFile('21_image_pad.dts')
680 self.assertEqual(U_BOOT_SPL_DATA + (chr(0xff) * 1) + U_BOOT_DATA, data)
682 def testImageName(self):
683 """Test that image files can be named"""
684 retcode = self._DoTestFile('22_image_name.dts')
685 self.assertEqual(0, retcode)
686 image = control.images['image1']
687 fname = tools.GetOutputFilename('test-name')
688 self.assertTrue(os.path.exists(fname))
690 image = control.images['image2']
691 fname = tools.GetOutputFilename('test-name.xx')
692 self.assertTrue(os.path.exists(fname))
694 def testBlobFilename(self):
695 """Test that generic blobs can be provided by filename"""
696 data = self._DoReadFile('23_blob.dts')
697 self.assertEqual(BLOB_DATA, data)
699 def testPackSorted(self):
700 """Test that entries can be sorted"""
701 data = self._DoReadFile('24_sorted.dts')
702 self.assertEqual(chr(0) * 1 + U_BOOT_SPL_DATA + chr(0) * 2 +
705 def testPackZeroOffset(self):
706 """Test that an entry at offset 0 is not given a new offset"""
707 with self.assertRaises(ValueError) as e:
708 self._DoTestFile('25_pack_zero_size.dts')
709 self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
710 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
713 def testPackUbootDtb(self):
714 """Test that a device tree can be added to U-Boot"""
715 data = self._DoReadFile('26_pack_u_boot_dtb.dts')
716 self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
718 def testPackX86RomNoSize(self):
719 """Test that the end-at-4gb property requires a size property"""
720 with self.assertRaises(ValueError) as e:
721 self._DoTestFile('27_pack_4gb_no_size.dts')
722 self.assertIn("Section '/binman': Section size must be provided when "
723 "using end-at-4gb", str(e.exception))
725 def testPackX86RomOutside(self):
726 """Test that the end-at-4gb property checks for offset boundaries"""
727 with self.assertRaises(ValueError) as e:
728 self._DoTestFile('28_pack_4gb_outside.dts')
729 self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
730 "the section starting at 0xffffffe0 (4294967264)",
733 def testPackX86Rom(self):
734 """Test that a basic x86 ROM can be created"""
735 data = self._DoReadFile('29_x86-rom.dts')
736 self.assertEqual(U_BOOT_DATA + chr(0) * 7 + U_BOOT_SPL_DATA +
739 def testPackX86RomMeNoDesc(self):
740 """Test that an invalid Intel descriptor entry is detected"""
741 TestFunctional._MakeInputFile('descriptor.bin', '')
742 with self.assertRaises(ValueError) as e:
743 self._DoTestFile('31_x86-rom-me.dts')
744 self.assertIn("Node '/binman/intel-descriptor': Cannot find FD "
745 "signature", str(e.exception))
747 def testPackX86RomBadDesc(self):
748 """Test that the Intel requires a descriptor entry"""
749 with self.assertRaises(ValueError) as e:
750 self._DoTestFile('30_x86-rom-me-no-desc.dts')
751 self.assertIn("Node '/binman/intel-me': No offset set with "
752 "offset-unset: should another entry provide this correct "
753 "offset?", str(e.exception))
755 def testPackX86RomMe(self):
756 """Test that an x86 ROM with an ME region can be created"""
757 data = self._DoReadFile('31_x86-rom-me.dts')
758 self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
760 def testPackVga(self):
761 """Test that an image with a VGA binary can be created"""
762 data = self._DoReadFile('32_intel-vga.dts')
763 self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
765 def testPackStart16(self):
766 """Test that an image with an x86 start16 region can be created"""
767 data = self._DoReadFile('33_x86-start16.dts')
768 self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
770 def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False):
771 """Handle running a test for insertion of microcode
774 dts_fname: Name of test .dts file
775 nodtb_data: Data that we expect in the first section
776 ucode_second: True if the microsecond entry is second instead of
781 Contents of first region (U-Boot or SPL)
782 Offset and size components of microcode pointer, as inserted
783 in the above (two 4-byte words)
785 data = self._DoReadFile(dts_fname, True)
787 # Now check the device tree has no microcode
789 ucode_content = data[len(nodtb_data):]
790 ucode_pos = len(nodtb_data)
791 dtb_with_ucode = ucode_content[16:]
792 fdt_len = self.GetFdtLen(dtb_with_ucode)
794 dtb_with_ucode = data[len(nodtb_data):]
795 fdt_len = self.GetFdtLen(dtb_with_ucode)
796 ucode_content = dtb_with_ucode[fdt_len:]
797 ucode_pos = len(nodtb_data) + fdt_len
798 fname = tools.GetOutputFilename('test.dtb')
799 with open(fname, 'wb') as fd:
800 fd.write(dtb_with_ucode)
801 dtb = fdt.FdtScan(fname)
802 ucode = dtb.GetNode('/microcode')
803 self.assertTrue(ucode)
804 for node in ucode.subnodes:
805 self.assertFalse(node.props.get('data'))
807 # Check that the microcode appears immediately after the Fdt
808 # This matches the concatenation of the data properties in
809 # the /microcode/update@xxx nodes in 34_x86_ucode.dts.
810 ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
812 self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
814 # Check that the microcode pointer was inserted. It should match the
815 # expected offset and size
816 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
818 u_boot = data[:len(nodtb_data)]
819 return u_boot, pos_and_size
821 def testPackUbootMicrocode(self):
822 """Test that x86 microcode can be handled correctly
824 We expect to see the following in the image, in order:
825 u-boot-nodtb.bin with a microcode pointer inserted at the correct
827 u-boot.dtb with the microcode removed
830 first, pos_and_size = self._RunMicrocodeTest('34_x86_ucode.dts',
832 self.assertEqual('nodtb with microcode' + pos_and_size +
833 ' somewhere in here', first)
835 def _RunPackUbootSingleMicrocode(self):
836 """Test that x86 microcode can be handled correctly
838 We expect to see the following in the image, in order:
839 u-boot-nodtb.bin with a microcode pointer inserted at the correct
841 u-boot.dtb with the microcode
842 an empty microcode region
844 # We need the libfdt library to run this test since only that allows
845 # finding the offset of a property. This is required by
846 # Entry_u_boot_dtb_with_ucode.ObtainContents().
847 data = self._DoReadFile('35_x86_single_ucode.dts', True)
849 second = data[len(U_BOOT_NODTB_DATA):]
851 fdt_len = self.GetFdtLen(second)
852 third = second[fdt_len:]
853 second = second[:fdt_len]
855 ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
856 self.assertIn(ucode_data, second)
857 ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
859 # Check that the microcode pointer was inserted. It should match the
860 # expected offset and size
861 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
863 first = data[:len(U_BOOT_NODTB_DATA)]
864 self.assertEqual('nodtb with microcode' + pos_and_size +
865 ' somewhere in here', first)
867 def testPackUbootSingleMicrocode(self):
868 """Test that x86 microcode can be handled correctly with fdt_normal.
870 self._RunPackUbootSingleMicrocode()
872 def testUBootImg(self):
873 """Test that u-boot.img can be put in a file"""
874 data = self._DoReadFile('36_u_boot_img.dts')
875 self.assertEqual(U_BOOT_IMG_DATA, data)
877 def testNoMicrocode(self):
878 """Test that a missing microcode region is detected"""
879 with self.assertRaises(ValueError) as e:
880 self._DoReadFile('37_x86_no_ucode.dts', True)
881 self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
882 "node found in ", str(e.exception))
884 def testMicrocodeWithoutNode(self):
885 """Test that a missing u-boot-dtb-with-ucode node is detected"""
886 with self.assertRaises(ValueError) as e:
887 self._DoReadFile('38_x86_ucode_missing_node.dts', True)
888 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
889 "microcode region u-boot-dtb-with-ucode", str(e.exception))
891 def testMicrocodeWithoutNode2(self):
892 """Test that a missing u-boot-ucode node is detected"""
893 with self.assertRaises(ValueError) as e:
894 self._DoReadFile('39_x86_ucode_missing_node2.dts', True)
895 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
896 "microcode region u-boot-ucode", str(e.exception))
898 def testMicrocodeWithoutPtrInElf(self):
899 """Test that a U-Boot binary without the microcode symbol is detected"""
900 # ELF file without a '_dt_ucode_base_size' symbol
902 with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
903 TestFunctional._MakeInputFile('u-boot', fd.read())
905 with self.assertRaises(ValueError) as e:
906 self._RunPackUbootSingleMicrocode()
907 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
908 "_dt_ucode_base_size symbol in u-boot", str(e.exception))
911 # Put the original file back
912 with open(self.TestFile('u_boot_ucode_ptr')) as fd:
913 TestFunctional._MakeInputFile('u-boot', fd.read())
915 def testMicrocodeNotInImage(self):
916 """Test that microcode must be placed within the image"""
917 with self.assertRaises(ValueError) as e:
918 self._DoReadFile('40_x86_ucode_not_in_image.dts', True)
919 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
920 "pointer _dt_ucode_base_size at fffffe14 is outside the "
921 "section ranging from 00000000 to 0000002e", str(e.exception))
923 def testWithoutMicrocode(self):
924 """Test that we can cope with an image without microcode (e.g. qemu)"""
925 with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
926 TestFunctional._MakeInputFile('u-boot', fd.read())
927 data, dtb, _, _ = self._DoReadFileDtb('44_x86_optional_ucode.dts', True)
929 # Now check the device tree has no microcode
930 self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
931 second = data[len(U_BOOT_NODTB_DATA):]
933 fdt_len = self.GetFdtLen(second)
934 self.assertEqual(dtb, second[:fdt_len])
936 used_len = len(U_BOOT_NODTB_DATA) + fdt_len
937 third = data[used_len:]
938 self.assertEqual(chr(0) * (0x200 - used_len), third)
940 def testUnknownPosSize(self):
941 """Test that microcode must be placed within the image"""
942 with self.assertRaises(ValueError) as e:
943 self._DoReadFile('41_unknown_pos_size.dts', True)
944 self.assertIn("Section '/binman': Unable to set offset/size for unknown "
945 "entry 'invalid-entry'", str(e.exception))
947 def testPackFsp(self):
948 """Test that an image with a FSP binary can be created"""
949 data = self._DoReadFile('42_intel-fsp.dts')
950 self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
952 def testPackCmc(self):
953 """Test that an image with a CMC binary can be created"""
954 data = self._DoReadFile('43_intel-cmc.dts')
955 self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
957 def testPackVbt(self):
958 """Test that an image with a VBT binary can be created"""
959 data = self._DoReadFile('46_intel-vbt.dts')
960 self.assertEqual(VBT_DATA, data[:len(VBT_DATA)])
962 def testSplBssPad(self):
963 """Test that we can pad SPL's BSS with zeros"""
964 # ELF file with a '__bss_size' symbol
965 with open(self.TestFile('bss_data')) as fd:
966 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
967 data = self._DoReadFile('47_spl_bss_pad.dts')
968 self.assertEqual(U_BOOT_SPL_DATA + (chr(0) * 10) + U_BOOT_DATA, data)
970 with open(self.TestFile('u_boot_ucode_ptr')) as fd:
971 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
972 with self.assertRaises(ValueError) as e:
973 data = self._DoReadFile('47_spl_bss_pad.dts')
974 self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
977 def testPackStart16Spl(self):
978 """Test that an image with an x86 start16 SPL region can be created"""
979 data = self._DoReadFile('48_x86-start16-spl.dts')
980 self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)])
982 def _PackUbootSplMicrocode(self, dts, ucode_second=False):
983 """Helper function for microcode tests
985 We expect to see the following in the image, in order:
986 u-boot-spl-nodtb.bin with a microcode pointer inserted at the
988 u-boot.dtb with the microcode removed
992 dts: Device tree file to use for test
993 ucode_second: True if the microsecond entry is second instead of
996 # ELF file with a '_dt_ucode_base_size' symbol
997 with open(self.TestFile('u_boot_ucode_ptr')) as fd:
998 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
999 first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA,
1000 ucode_second=ucode_second)
1001 self.assertEqual('splnodtb with microc' + pos_and_size +
1002 'ter somewhere in here', first)
1004 def testPackUbootSplMicrocode(self):
1005 """Test that x86 microcode can be handled correctly in SPL"""
1006 self._PackUbootSplMicrocode('49_x86_ucode_spl.dts')
1008 def testPackUbootSplMicrocodeReorder(self):
1009 """Test that order doesn't matter for microcode entries
1011 This is the same as testPackUbootSplMicrocode but when we process the
1012 u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode
1013 entry, so we reply on binman to try later.
1015 self._PackUbootSplMicrocode('58_x86_ucode_spl_needs_retry.dts',
1018 def testPackMrc(self):
1019 """Test that an image with an MRC binary can be created"""
1020 data = self._DoReadFile('50_intel_mrc.dts')
1021 self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
1023 def testSplDtb(self):
1024 """Test that an image with spl/u-boot-spl.dtb can be created"""
1025 data = self._DoReadFile('51_u_boot_spl_dtb.dts')
1026 self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
1028 def testSplNoDtb(self):
1029 """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
1030 data = self._DoReadFile('52_u_boot_spl_nodtb.dts')
1031 self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
1033 def testSymbols(self):
1034 """Test binman can assign symbols embedded in U-Boot"""
1035 elf_fname = self.TestFile('u_boot_binman_syms')
1036 syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
1037 addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
1038 self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
1040 with open(self.TestFile('u_boot_binman_syms')) as fd:
1041 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
1042 data = self._DoReadFile('53_symbols.dts')
1043 sym_values = struct.pack('<LQL', 0x24 + 0, 0x24 + 24, 0x24 + 20)
1044 expected = (sym_values + U_BOOT_SPL_DATA[16:] + chr(0xff) +
1046 sym_values + U_BOOT_SPL_DATA[16:])
1047 self.assertEqual(expected, data)
1049 def testPackUnitAddress(self):
1050 """Test that we support multiple binaries with the same name"""
1051 data = self._DoReadFile('54_unit_address.dts')
1052 self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
1054 def testSections(self):
1055 """Basic test of sections"""
1056 data = self._DoReadFile('55_sections.dts')
1057 expected = (U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12 +
1058 U_BOOT_DATA + '&' * 4)
1059 self.assertEqual(expected, data)
1062 """Tests outputting a map of the images"""
1063 _, _, map_data, _ = self._DoReadFileDtb('55_sections.dts', map=True)
1064 self.assertEqual('''ImagePos Offset Size Name
1065 00000000 00000000 00000028 main-section
1066 00000000 00000000 00000010 section@0
1067 00000000 00000000 00000004 u-boot
1068 00000010 00000010 00000010 section@1
1069 00000010 00000000 00000004 u-boot
1070 00000020 00000020 00000004 section@2
1071 00000020 00000000 00000004 u-boot
1074 def testNamePrefix(self):
1075 """Tests that name prefixes are used"""
1076 _, _, map_data, _ = self._DoReadFileDtb('56_name_prefix.dts', map=True)
1077 self.assertEqual('''ImagePos Offset Size Name
1078 00000000 00000000 00000028 main-section
1079 00000000 00000000 00000010 section@0
1080 00000000 00000000 00000004 ro-u-boot
1081 00000010 00000010 00000010 section@1
1082 00000010 00000000 00000004 rw-u-boot
1085 def testUnknownContents(self):
1086 """Test that obtaining the contents works as expected"""
1087 with self.assertRaises(ValueError) as e:
1088 self._DoReadFile('57_unknown_contents.dts', True)
1089 self.assertIn("Section '/binman': Internal error: Could not complete "
1090 "processing of contents: remaining [<_testing.Entry__testing ",
1093 def testBadChangeSize(self):
1094 """Test that trying to change the size of an entry fails"""
1095 with self.assertRaises(ValueError) as e:
1096 self._DoReadFile('59_change_size.dts', True)
1097 self.assertIn("Node '/binman/_testing': Cannot update entry size from "
1098 '2 to 1', str(e.exception))
1100 def testUpdateFdt(self):
1101 """Test that we can update the device tree with offset/size info"""
1102 _, _, _, out_dtb_fname = self._DoReadFileDtb('60_fdt_update.dts',
1104 dtb = fdt.Fdt(out_dtb_fname)
1106 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'])
1110 '_testing:offset': 32,
1112 '_testing:image-pos': 32,
1113 'section@0/u-boot:offset': 0,
1114 'section@0/u-boot:size': len(U_BOOT_DATA),
1115 'section@0/u-boot:image-pos': 0,
1116 'section@0:offset': 0,
1117 'section@0:size': 16,
1118 'section@0:image-pos': 0,
1120 'section@1/u-boot:offset': 0,
1121 'section@1/u-boot:size': len(U_BOOT_DATA),
1122 'section@1/u-boot:image-pos': 16,
1123 'section@1:offset': 16,
1124 'section@1:size': 16,
1125 'section@1:image-pos': 16,
1129 def testUpdateFdtBad(self):
1130 """Test that we detect when ProcessFdt never completes"""
1131 with self.assertRaises(ValueError) as e:
1132 self._DoReadFileDtb('61_fdt_update_bad.dts', update_dtb=True)
1133 self.assertIn('Could not complete processing of Fdt: remaining '
1134 '[<_testing.Entry__testing', str(e.exception))
1136 def testEntryArgs(self):
1137 """Test passing arguments to entries from the command line"""
1139 'test-str-arg': 'test1',
1140 'test-int-arg': '456',
1142 self._DoReadFileDtb('62_entry_args.dts', entry_args=entry_args)
1143 self.assertIn('image', control.images)
1144 entry = control.images['image'].GetEntries()['_testing']
1145 self.assertEqual('test0', entry.test_str_fdt)
1146 self.assertEqual('test1', entry.test_str_arg)
1147 self.assertEqual(123, entry.test_int_fdt)
1148 self.assertEqual(456, entry.test_int_arg)
1150 def testEntryArgsMissing(self):
1151 """Test missing arguments and properties"""
1153 'test-int-arg': '456',
1155 self._DoReadFileDtb('63_entry_args_missing.dts', entry_args=entry_args)
1156 entry = control.images['image'].GetEntries()['_testing']
1157 self.assertEqual('test0', entry.test_str_fdt)
1158 self.assertEqual(None, entry.test_str_arg)
1159 self.assertEqual(None, entry.test_int_fdt)
1160 self.assertEqual(456, entry.test_int_arg)
1162 def testEntryArgsRequired(self):
1163 """Test missing arguments and properties"""
1165 'test-int-arg': '456',
1167 with self.assertRaises(ValueError) as e:
1168 self._DoReadFileDtb('64_entry_args_required.dts')
1169 self.assertIn("Node '/binman/_testing': Missing required "
1170 'properties/entry args: test-str-arg, test-int-fdt, test-int-arg',
1173 def testEntryArgsInvalidFormat(self):
1174 """Test that an invalid entry-argument format is detected"""
1175 args = ['-d', self.TestFile('64_entry_args_required.dts'), '-ano-value']
1176 with self.assertRaises(ValueError) as e:
1177 self._DoBinman(*args)
1178 self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
1180 def testEntryArgsInvalidInteger(self):
1181 """Test that an invalid entry-argument integer is detected"""
1183 'test-int-arg': 'abc',
1185 with self.assertRaises(ValueError) as e:
1186 self._DoReadFileDtb('62_entry_args.dts', entry_args=entry_args)
1187 self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
1188 "'test-int-arg' (value 'abc') to integer",
1191 def testEntryArgsInvalidDatatype(self):
1192 """Test that an invalid entry-argument datatype is detected
1194 This test could be written in entry_test.py except that it needs
1195 access to control.entry_args, which seems more than that module should
1199 'test-bad-datatype-arg': '12',
1201 with self.assertRaises(ValueError) as e:
1202 self._DoReadFileDtb('65_entry_args_unknown_datatype.dts',
1203 entry_args=entry_args)
1204 self.assertIn('GetArg() internal error: Unknown data type ',
1208 """Test for a text entry type"""
1210 'test-id': TEXT_DATA,
1211 'test-id2': TEXT_DATA2,
1212 'test-id3': TEXT_DATA3,
1214 data, _, _, _ = self._DoReadFileDtb('66_text.dts',
1215 entry_args=entry_args)
1216 expected = (TEXT_DATA + chr(0) * (8 - len(TEXT_DATA)) + TEXT_DATA2 +
1217 TEXT_DATA3 + 'some text')
1218 self.assertEqual(expected, data)
1220 def testEntryDocs(self):
1221 """Test for creation of entry documentation"""
1222 with test_util.capture_sys_output() as (stdout, stderr):
1223 control.WriteEntryDocs(binman.GetEntryModules())
1224 self.assertTrue(len(stdout.getvalue()) > 0)
1226 def testEntryDocsMissing(self):
1227 """Test handling of missing entry documentation"""
1228 with self.assertRaises(ValueError) as e:
1229 with test_util.capture_sys_output() as (stdout, stderr):
1230 control.WriteEntryDocs(binman.GetEntryModules(), 'u_boot')
1231 self.assertIn('Documentation is missing for modules: u_boot',
1235 """Basic test of generation of a flashrom fmap"""
1236 data = self._DoReadFile('67_fmap.dts')
1237 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1238 expected = U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12
1239 self.assertEqual(expected, data[:32])
1240 self.assertEqual('__FMAP__', fhdr.signature)
1241 self.assertEqual(1, fhdr.ver_major)
1242 self.assertEqual(0, fhdr.ver_minor)
1243 self.assertEqual(0, fhdr.base)
1244 self.assertEqual(16 + 16 +
1245 fmap_util.FMAP_HEADER_LEN +
1246 fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
1247 self.assertEqual('FMAP', fhdr.name)
1248 self.assertEqual(3, fhdr.nareas)
1249 for fentry in fentries:
1250 self.assertEqual(0, fentry.flags)
1252 self.assertEqual(0, fentries[0].offset)
1253 self.assertEqual(4, fentries[0].size)
1254 self.assertEqual('RO_U_BOOT', fentries[0].name)
1256 self.assertEqual(16, fentries[1].offset)
1257 self.assertEqual(4, fentries[1].size)
1258 self.assertEqual('RW_U_BOOT', fentries[1].name)
1260 self.assertEqual(32, fentries[2].offset)
1261 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1262 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1263 self.assertEqual('FMAP', fentries[2].name)
1265 def testBlobNamedByArg(self):
1266 """Test we can add a blob with the filename coming from an entry arg"""
1268 'cros-ec-rw-path': 'ecrw.bin',
1270 data, _, _, _ = self._DoReadFileDtb('68_blob_named_by_arg.dts',
1271 entry_args=entry_args)
1274 """Test for an fill entry type"""
1275 data = self._DoReadFile('69_fill.dts')
1276 expected = 8 * chr(0xff) + 8 * chr(0)
1277 self.assertEqual(expected, data)
1279 def testFillNoSize(self):
1280 """Test for an fill entry type with no size"""
1281 with self.assertRaises(ValueError) as e:
1282 self._DoReadFile('70_fill_no_size.dts')
1283 self.assertIn("'fill' entry must have a size property",
1286 def _HandleGbbCommand(self, pipe_list):
1287 """Fake calls to the futility utility"""
1288 if pipe_list[0][0] == 'futility':
1289 fname = pipe_list[0][-1]
1290 # Append our GBB data to the file, which will happen every time the
1291 # futility command is called.
1292 with open(fname, 'a') as fd:
1294 return command.CommandResult()
1297 """Test for the Chromium OS Google Binary Block"""
1298 command.test_result = self._HandleGbbCommand
1300 'keydir': 'devkeys',
1301 'bmpblk': 'bmpblk.bin',
1303 data, _, _, _ = self._DoReadFileDtb('71_gbb.dts', entry_args=entry_args)
1306 expected = GBB_DATA + GBB_DATA + 8 * chr(0) + (0x2180 - 16) * chr(0)
1307 self.assertEqual(expected, data)
1309 def testGbbTooSmall(self):
1310 """Test for the Chromium OS Google Binary Block being large enough"""
1311 with self.assertRaises(ValueError) as e:
1312 self._DoReadFileDtb('72_gbb_too_small.dts')
1313 self.assertIn("Node '/binman/gbb': GBB is too small",
1316 def testGbbNoSize(self):
1317 """Test for the Chromium OS Google Binary Block having a size"""
1318 with self.assertRaises(ValueError) as e:
1319 self._DoReadFileDtb('73_gbb_no_size.dts')
1320 self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
1323 def _HandleVblockCommand(self, pipe_list):
1324 """Fake calls to the futility utility"""
1325 if pipe_list[0][0] == 'futility':
1326 fname = pipe_list[0][3]
1327 with open(fname, 'wb') as fd:
1328 fd.write(VBLOCK_DATA)
1329 return command.CommandResult()
1331 def testVblock(self):
1332 """Test for the Chromium OS Verified Boot Block"""
1333 command.test_result = self._HandleVblockCommand
1335 'keydir': 'devkeys',
1337 data, _, _, _ = self._DoReadFileDtb('74_vblock.dts',
1338 entry_args=entry_args)
1339 expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
1340 self.assertEqual(expected, data)
1342 def testVblockNoContent(self):
1343 """Test we detect a vblock which has no content to sign"""
1344 with self.assertRaises(ValueError) as e:
1345 self._DoReadFile('75_vblock_no_content.dts')
1346 self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
1347 'property', str(e.exception))
1349 def testVblockBadPhandle(self):
1350 """Test that we detect a vblock with an invalid phandle in contents"""
1351 with self.assertRaises(ValueError) as e:
1352 self._DoReadFile('76_vblock_bad_phandle.dts')
1353 self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
1354 '1000', str(e.exception))
1356 def testVblockBadEntry(self):
1357 """Test that we detect an entry that points to a non-entry"""
1358 with self.assertRaises(ValueError) as e:
1359 self._DoReadFile('77_vblock_bad_entry.dts')
1360 self.assertIn("Node '/binman/vblock': Cannot find entry for node "
1361 "'other'", str(e.exception))
1364 """Test that an image with TPL and ots device tree can be created"""
1365 # ELF file with a '__bss_size' symbol
1366 with open(self.TestFile('bss_data')) as fd:
1367 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1368 data = self._DoReadFile('78_u_boot_tpl.dts')
1369 self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
1371 def testUsesPos(self):
1372 """Test that the 'pos' property cannot be used anymore"""
1373 with self.assertRaises(ValueError) as e:
1374 data = self._DoReadFile('79_uses_pos.dts')
1375 self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
1376 "'pos'", str(e.exception))
1378 def testFillZero(self):
1379 """Test for an fill entry type with a size of 0"""
1380 data = self._DoReadFile('80_fill_empty.dts')
1381 self.assertEqual(chr(0) * 16, data)
1383 def testTextMissing(self):
1384 """Test for a text entry type where there is no text"""
1385 with self.assertRaises(ValueError) as e:
1386 self._DoReadFileDtb('66_text.dts',)
1387 self.assertIn("Node '/binman/text': No value provided for text label "
1388 "'test-id'", str(e.exception))
1390 def testPackStart16Tpl(self):
1391 """Test that an image with an x86 start16 TPL region can be created"""
1392 data = self._DoReadFile('81_x86-start16-tpl.dts')
1393 self.assertEqual(X86_START16_TPL_DATA, data[:len(X86_START16_TPL_DATA)])
1395 def testSelectImage(self):
1396 """Test that we can select which images to build"""
1397 with test_util.capture_sys_output() as (stdout, stderr):
1398 retcode = self._DoTestFile('06_dual_image.dts', images=['image2'])
1399 self.assertEqual(0, retcode)
1400 self.assertIn('Skipping images: image1', stdout.getvalue())
1402 self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
1403 self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
1406 if __name__ == "__main__":