binman: Allow sections to have an offset
[project/bcm63xx/u-boot.git] / tools / binman / ftest.py
1 # SPDX-License-Identifier: GPL-2.0+
2 # Copyright (c) 2016 Google, Inc
3 # Written by Simon Glass <sjg@chromium.org>
4 #
5 # To run a single test, change to this directory, and:
6 #
7 # python -m unittest func_test.TestFunctional.testHelp
8
9 import hashlib
10 from optparse import OptionParser
11 import os
12 import shutil
13 import struct
14 import sys
15 import tempfile
16 import unittest
17
18 import binman
19 import cmdline
20 import command
21 import control
22 import elf
23 import fdt
24 import fdt_util
25 import fmap_util
26 import test_util
27 import state
28 import tools
29 import tout
30
31 # Contents of test files, corresponding to different entry types
32 U_BOOT_DATA = '1234'
33 U_BOOT_IMG_DATA = 'img'
34 U_BOOT_SPL_DATA = '56780123456789abcde'
35 U_BOOT_TPL_DATA = 'tpl'
36 BLOB_DATA = '89'
37 ME_DATA = '0abcd'
38 VGA_DATA = 'vga'
39 U_BOOT_DTB_DATA = 'udtb'
40 U_BOOT_SPL_DTB_DATA = 'spldtb'
41 U_BOOT_TPL_DTB_DATA = 'tpldtb'
42 X86_START16_DATA = 'start16'
43 X86_START16_SPL_DATA = 'start16spl'
44 X86_START16_TPL_DATA = 'start16tpl'
45 PPC_MPC85XX_BR_DATA = 'ppcmpc85xxbr'
46 U_BOOT_NODTB_DATA = 'nodtb with microcode pointer somewhere in here'
47 U_BOOT_SPL_NODTB_DATA = 'splnodtb with microcode pointer somewhere in here'
48 U_BOOT_TPL_NODTB_DATA = 'tplnodtb with microcode pointer somewhere in here'
49 FSP_DATA = 'fsp'
50 CMC_DATA = 'cmc'
51 VBT_DATA = 'vbt'
52 MRC_DATA = 'mrc'
53 TEXT_DATA = 'text'
54 TEXT_DATA2 = 'text2'
55 TEXT_DATA3 = 'text3'
56 CROS_EC_RW_DATA = 'ecrw'
57 GBB_DATA = 'gbbd'
58 BMPBLK_DATA = 'bmp'
59 VBLOCK_DATA = 'vblk'
60 FILES_DATA = ("sorry I'm late\nOh, don't bother apologising, I'm " +
61 "sorry you're alive\n")
62 COMPRESS_DATA = 'data to compress'
63 REFCODE_DATA = 'refcode'
64
65
66 class TestFunctional(unittest.TestCase):
67 """Functional tests for binman
68
69 Most of these use a sample .dts file to build an image and then check
70 that it looks correct. The sample files are in the test/ subdirectory
71 and are numbered.
72
73 For each entry type a very small test file is created using fixed
74 string contents. This makes it easy to test that things look right, and
75 debug problems.
76
77 In some cases a 'real' file must be used - these are also supplied in
78 the test/ diurectory.
79 """
80 @classmethod
81 def setUpClass(self):
82 global entry
83 import entry
84
85 # Handle the case where argv[0] is 'python'
86 self._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
87 self._binman_pathname = os.path.join(self._binman_dir, 'binman')
88
89 # Create a temporary directory for input files
90 self._indir = tempfile.mkdtemp(prefix='binmant.')
91
92 # Create some test files
93 TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
94 TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
95 TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
96 TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
97 TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
98 TestFunctional._MakeInputFile('me.bin', ME_DATA)
99 TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
100 self._ResetDtbs()
101 TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
102 TestFunctional._MakeInputFile('u-boot-br.bin', PPC_MPC85XX_BR_DATA)
103 TestFunctional._MakeInputFile('spl/u-boot-x86-16bit-spl.bin',
104 X86_START16_SPL_DATA)
105 TestFunctional._MakeInputFile('tpl/u-boot-x86-16bit-tpl.bin',
106 X86_START16_TPL_DATA)
107 TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
108 TestFunctional._MakeInputFile('spl/u-boot-spl-nodtb.bin',
109 U_BOOT_SPL_NODTB_DATA)
110 TestFunctional._MakeInputFile('tpl/u-boot-tpl-nodtb.bin',
111 U_BOOT_TPL_NODTB_DATA)
112 TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
113 TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
114 TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
115 TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
116 TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
117 TestFunctional._MakeInputDir('devkeys')
118 TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
119 TestFunctional._MakeInputFile('refcode.bin', REFCODE_DATA)
120
121 # ELF file with a '_dt_ucode_base_size' symbol
122 with open(self.TestFile('u_boot_ucode_ptr')) as fd:
123 TestFunctional._MakeInputFile('u-boot', fd.read())
124
125 # Intel flash descriptor file
126 with open(self.TestFile('descriptor.bin')) as fd:
127 TestFunctional._MakeInputFile('descriptor.bin', fd.read())
128
129 shutil.copytree(self.TestFile('files'),
130 os.path.join(self._indir, 'files'))
131
132 TestFunctional._MakeInputFile('compress', COMPRESS_DATA)
133
134 @classmethod
135 def tearDownClass(self):
136 """Remove the temporary input directory and its contents"""
137 if self._indir:
138 shutil.rmtree(self._indir)
139 self._indir = None
140
141 def setUp(self):
142 # Enable this to turn on debugging output
143 # tout.Init(tout.DEBUG)
144 command.test_result = None
145
146 def tearDown(self):
147 """Remove the temporary output directory"""
148 tools._FinaliseForTest()
149
150 @classmethod
151 def _ResetDtbs(self):
152 TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
153 TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
154 TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
155
156 def _RunBinman(self, *args, **kwargs):
157 """Run binman using the command line
158
159 Args:
160 Arguments to pass, as a list of strings
161 kwargs: Arguments to pass to Command.RunPipe()
162 """
163 result = command.RunPipe([[self._binman_pathname] + list(args)],
164 capture=True, capture_stderr=True, raise_on_error=False)
165 if result.return_code and kwargs.get('raise_on_error', True):
166 raise Exception("Error running '%s': %s" % (' '.join(args),
167 result.stdout + result.stderr))
168 return result
169
170 def _DoBinman(self, *args):
171 """Run binman using directly (in the same process)
172
173 Args:
174 Arguments to pass, as a list of strings
175 Returns:
176 Return value (0 for success)
177 """
178 args = list(args)
179 if '-D' in sys.argv:
180 args = args + ['-D']
181 (options, args) = cmdline.ParseArgs(args)
182 options.pager = 'binman-invalid-pager'
183 options.build_dir = self._indir
184
185 # For testing, you can force an increase in verbosity here
186 # options.verbosity = tout.DEBUG
187 return control.Binman(options, args)
188
189 def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
190 entry_args=None, images=None, use_real_dtb=False,
191 verbosity=None):
192 """Run binman with a given test file
193
194 Args:
195 fname: Device-tree source filename to use (e.g. 005_simple.dts)
196 debug: True to enable debugging output
197 map: True to output map files for the images
198 update_dtb: Update the offset and size of each entry in the device
199 tree before packing it into the image
200 entry_args: Dict of entry args to supply to binman
201 key: arg name
202 value: value of that arg
203 images: List of image names to build
204 """
205 args = ['-p', '-I', self._indir, '-d', self.TestFile(fname)]
206 if debug:
207 args.append('-D')
208 if map:
209 args.append('-m')
210 if update_dtb:
211 args.append('-up')
212 if not use_real_dtb:
213 args.append('--fake-dtb')
214 if verbosity is not None:
215 args.append('-v%d' % verbosity)
216 if entry_args:
217 for arg, value in entry_args.iteritems():
218 args.append('-a%s=%s' % (arg, value))
219 if images:
220 for image in images:
221 args += ['-i', image]
222 return self._DoBinman(*args)
223
224 def _SetupDtb(self, fname, outfile='u-boot.dtb'):
225 """Set up a new test device-tree file
226
227 The given file is compiled and set up as the device tree to be used
228 for ths test.
229
230 Args:
231 fname: Filename of .dts file to read
232 outfile: Output filename for compiled device-tree binary
233
234 Returns:
235 Contents of device-tree binary
236 """
237 tools.PrepareOutputDir(None)
238 dtb = fdt_util.EnsureCompiled(self.TestFile(fname))
239 with open(dtb) as fd:
240 data = fd.read()
241 TestFunctional._MakeInputFile(outfile, data)
242 tools.FinaliseOutputDir()
243 return data
244
245 def _GetDtbContentsForSplTpl(self, dtb_data, name):
246 """Create a version of the main DTB for SPL or SPL
247
248 For testing we don't actually have different versions of the DTB. With
249 U-Boot we normally run fdtgrep to remove unwanted nodes, but for tests
250 we don't normally have any unwanted nodes.
251
252 We still want the DTBs for SPL and TPL to be different though, since
253 otherwise it is confusing to know which one we are looking at. So add
254 an 'spl' or 'tpl' property to the top-level node.
255 """
256 dtb = fdt.Fdt.FromData(dtb_data)
257 dtb.Scan()
258 dtb.GetNode('/binman').AddZeroProp(name)
259 dtb.Sync(auto_resize=True)
260 dtb.Pack()
261 return dtb.GetContents()
262
263 def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
264 update_dtb=False, entry_args=None, reset_dtbs=True):
265 """Run binman and return the resulting image
266
267 This runs binman with a given test file and then reads the resulting
268 output file. It is a shortcut function since most tests need to do
269 these steps.
270
271 Raises an assertion failure if binman returns a non-zero exit code.
272
273 Args:
274 fname: Device-tree source filename to use (e.g. 005_simple.dts)
275 use_real_dtb: True to use the test file as the contents of
276 the u-boot-dtb entry. Normally this is not needed and the
277 test contents (the U_BOOT_DTB_DATA string) can be used.
278 But in some test we need the real contents.
279 map: True to output map files for the images
280 update_dtb: Update the offset and size of each entry in the device
281 tree before packing it into the image
282
283 Returns:
284 Tuple:
285 Resulting image contents
286 Device tree contents
287 Map data showing contents of image (or None if none)
288 Output device tree binary filename ('u-boot.dtb' path)
289 """
290 dtb_data = None
291 # Use the compiled test file as the u-boot-dtb input
292 if use_real_dtb:
293 dtb_data = self._SetupDtb(fname)
294 infile = os.path.join(self._indir, 'u-boot.dtb')
295
296 # For testing purposes, make a copy of the DT for SPL and TPL. Add
297 # a node indicating which it is, so aid verification.
298 for name in ['spl', 'tpl']:
299 dtb_fname = '%s/u-boot-%s.dtb' % (name, name)
300 outfile = os.path.join(self._indir, dtb_fname)
301 TestFunctional._MakeInputFile(dtb_fname,
302 self._GetDtbContentsForSplTpl(dtb_data, name))
303
304 try:
305 retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
306 entry_args=entry_args, use_real_dtb=use_real_dtb)
307 self.assertEqual(0, retcode)
308 out_dtb_fname = tools.GetOutputFilename('u-boot.dtb.out')
309
310 # Find the (only) image, read it and return its contents
311 image = control.images['image']
312 image_fname = tools.GetOutputFilename('image.bin')
313 self.assertTrue(os.path.exists(image_fname))
314 if map:
315 map_fname = tools.GetOutputFilename('image.map')
316 with open(map_fname) as fd:
317 map_data = fd.read()
318 else:
319 map_data = None
320 with open(image_fname) as fd:
321 return fd.read(), dtb_data, map_data, out_dtb_fname
322 finally:
323 # Put the test file back
324 if reset_dtbs and use_real_dtb:
325 self._ResetDtbs()
326
327 def _DoReadFile(self, fname, use_real_dtb=False):
328 """Helper function which discards the device-tree binary
329
330 Args:
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
337 Returns:
338 Resulting image contents
339 """
340 return self._DoReadFileDtb(fname, use_real_dtb)[0]
341
342 @classmethod
343 def _MakeInputFile(self, fname, contents):
344 """Create a new test input file, creating directories as needed
345
346 Args:
347 fname: Filename to create
348 contents: File contents to write in to the file
349 Returns:
350 Full pathname of file created
351 """
352 pathname = os.path.join(self._indir, fname)
353 dirname = os.path.dirname(pathname)
354 if dirname and not os.path.exists(dirname):
355 os.makedirs(dirname)
356 with open(pathname, 'wb') as fd:
357 fd.write(contents)
358 return pathname
359
360 @classmethod
361 def _MakeInputDir(self, dirname):
362 """Create a new test input directory, creating directories as needed
363
364 Args:
365 dirname: Directory name to create
366
367 Returns:
368 Full pathname of directory created
369 """
370 pathname = os.path.join(self._indir, dirname)
371 if not os.path.exists(pathname):
372 os.makedirs(pathname)
373 return pathname
374
375 @classmethod
376 def _SetupSplElf(self, src_fname='bss_data'):
377 """Set up an ELF file with a '_dt_ucode_base_size' symbol
378
379 Args:
380 Filename of ELF file to use as SPL
381 """
382 with open(self.TestFile(src_fname)) as fd:
383 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
384
385 @classmethod
386 def TestFile(self, fname):
387 return os.path.join(self._binman_dir, 'test', fname)
388
389 def AssertInList(self, grep_list, target):
390 """Assert that at least one of a list of things is in a target
391
392 Args:
393 grep_list: List of strings to check
394 target: Target string
395 """
396 for grep in grep_list:
397 if grep in target:
398 return
399 self.fail("Error: '%' not found in '%s'" % (grep_list, target))
400
401 def CheckNoGaps(self, entries):
402 """Check that all entries fit together without gaps
403
404 Args:
405 entries: List of entries to check
406 """
407 offset = 0
408 for entry in entries.values():
409 self.assertEqual(offset, entry.offset)
410 offset += entry.size
411
412 def GetFdtLen(self, dtb):
413 """Get the totalsize field from a device-tree binary
414
415 Args:
416 dtb: Device-tree binary contents
417
418 Returns:
419 Total size of device-tree binary, from the header
420 """
421 return struct.unpack('>L', dtb[4:8])[0]
422
423 def _GetPropTree(self, dtb, prop_names):
424 def AddNode(node, path):
425 if node.name != '/':
426 path += '/' + node.name
427 for subnode in node.subnodes:
428 for prop in subnode.props.values():
429 if prop.name in prop_names:
430 prop_path = path + '/' + subnode.name + ':' + prop.name
431 tree[prop_path[len('/binman/'):]] = fdt_util.fdt32_to_cpu(
432 prop.value)
433 AddNode(subnode, path)
434
435 tree = {}
436 AddNode(dtb.GetRoot(), '')
437 return tree
438
439 def testRun(self):
440 """Test a basic run with valid args"""
441 result = self._RunBinman('-h')
442
443 def testFullHelp(self):
444 """Test that the full help is displayed with -H"""
445 result = self._RunBinman('-H')
446 help_file = os.path.join(self._binman_dir, 'README')
447 # Remove possible extraneous strings
448 extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
449 gothelp = result.stdout.replace(extra, '')
450 self.assertEqual(len(gothelp), os.path.getsize(help_file))
451 self.assertEqual(0, len(result.stderr))
452 self.assertEqual(0, result.return_code)
453
454 def testFullHelpInternal(self):
455 """Test that the full help is displayed with -H"""
456 try:
457 command.test_result = command.CommandResult()
458 result = self._DoBinman('-H')
459 help_file = os.path.join(self._binman_dir, 'README')
460 finally:
461 command.test_result = None
462
463 def testHelp(self):
464 """Test that the basic help is displayed with -h"""
465 result = self._RunBinman('-h')
466 self.assertTrue(len(result.stdout) > 200)
467 self.assertEqual(0, len(result.stderr))
468 self.assertEqual(0, result.return_code)
469
470 def testBoard(self):
471 """Test that we can run it with a specific board"""
472 self._SetupDtb('005_simple.dts', 'sandbox/u-boot.dtb')
473 TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
474 result = self._DoBinman('-b', 'sandbox')
475 self.assertEqual(0, result)
476
477 def testNeedBoard(self):
478 """Test that we get an error when no board ius supplied"""
479 with self.assertRaises(ValueError) as e:
480 result = self._DoBinman()
481 self.assertIn("Must provide a board to process (use -b <board>)",
482 str(e.exception))
483
484 def testMissingDt(self):
485 """Test that an invalid device-tree file generates an error"""
486 with self.assertRaises(Exception) as e:
487 self._RunBinman('-d', 'missing_file')
488 # We get one error from libfdt, and a different one from fdtget.
489 self.AssertInList(["Couldn't open blob from 'missing_file'",
490 'No such file or directory'], str(e.exception))
491
492 def testBrokenDt(self):
493 """Test that an invalid device-tree source file generates an error
494
495 Since this is a source file it should be compiled and the error
496 will come from the device-tree compiler (dtc).
497 """
498 with self.assertRaises(Exception) as e:
499 self._RunBinman('-d', self.TestFile('001_invalid.dts'))
500 self.assertIn("FATAL ERROR: Unable to parse input tree",
501 str(e.exception))
502
503 def testMissingNode(self):
504 """Test that a device tree without a 'binman' node generates an error"""
505 with self.assertRaises(Exception) as e:
506 self._DoBinman('-d', self.TestFile('002_missing_node.dts'))
507 self.assertIn("does not have a 'binman' node", str(e.exception))
508
509 def testEmpty(self):
510 """Test that an empty binman node works OK (i.e. does nothing)"""
511 result = self._RunBinman('-d', self.TestFile('003_empty.dts'))
512 self.assertEqual(0, len(result.stderr))
513 self.assertEqual(0, result.return_code)
514
515 def testInvalidEntry(self):
516 """Test that an invalid entry is flagged"""
517 with self.assertRaises(Exception) as e:
518 result = self._RunBinman('-d',
519 self.TestFile('004_invalid_entry.dts'))
520 self.assertIn("Unknown entry type 'not-a-valid-type' in node "
521 "'/binman/not-a-valid-type'", str(e.exception))
522
523 def testSimple(self):
524 """Test a simple binman with a single file"""
525 data = self._DoReadFile('005_simple.dts')
526 self.assertEqual(U_BOOT_DATA, data)
527
528 def testSimpleDebug(self):
529 """Test a simple binman run with debugging enabled"""
530 data = self._DoTestFile('005_simple.dts', debug=True)
531
532 def testDual(self):
533 """Test that we can handle creating two images
534
535 This also tests image padding.
536 """
537 retcode = self._DoTestFile('006_dual_image.dts')
538 self.assertEqual(0, retcode)
539
540 image = control.images['image1']
541 self.assertEqual(len(U_BOOT_DATA), image._size)
542 fname = tools.GetOutputFilename('image1.bin')
543 self.assertTrue(os.path.exists(fname))
544 with open(fname) as fd:
545 data = fd.read()
546 self.assertEqual(U_BOOT_DATA, data)
547
548 image = control.images['image2']
549 self.assertEqual(3 + len(U_BOOT_DATA) + 5, image._size)
550 fname = tools.GetOutputFilename('image2.bin')
551 self.assertTrue(os.path.exists(fname))
552 with open(fname) as fd:
553 data = fd.read()
554 self.assertEqual(U_BOOT_DATA, data[3:7])
555 self.assertEqual(chr(0) * 3, data[:3])
556 self.assertEqual(chr(0) * 5, data[7:])
557
558 def testBadAlign(self):
559 """Test that an invalid alignment value is detected"""
560 with self.assertRaises(ValueError) as e:
561 self._DoTestFile('007_bad_align.dts')
562 self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
563 "of two", str(e.exception))
564
565 def testPackSimple(self):
566 """Test that packing works as expected"""
567 retcode = self._DoTestFile('008_pack.dts')
568 self.assertEqual(0, retcode)
569 self.assertIn('image', control.images)
570 image = control.images['image']
571 entries = image.GetEntries()
572 self.assertEqual(5, len(entries))
573
574 # First u-boot
575 self.assertIn('u-boot', entries)
576 entry = entries['u-boot']
577 self.assertEqual(0, entry.offset)
578 self.assertEqual(len(U_BOOT_DATA), entry.size)
579
580 # Second u-boot, aligned to 16-byte boundary
581 self.assertIn('u-boot-align', entries)
582 entry = entries['u-boot-align']
583 self.assertEqual(16, entry.offset)
584 self.assertEqual(len(U_BOOT_DATA), entry.size)
585
586 # Third u-boot, size 23 bytes
587 self.assertIn('u-boot-size', entries)
588 entry = entries['u-boot-size']
589 self.assertEqual(20, entry.offset)
590 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
591 self.assertEqual(23, entry.size)
592
593 # Fourth u-boot, placed immediate after the above
594 self.assertIn('u-boot-next', entries)
595 entry = entries['u-boot-next']
596 self.assertEqual(43, entry.offset)
597 self.assertEqual(len(U_BOOT_DATA), entry.size)
598
599 # Fifth u-boot, placed at a fixed offset
600 self.assertIn('u-boot-fixed', entries)
601 entry = entries['u-boot-fixed']
602 self.assertEqual(61, entry.offset)
603 self.assertEqual(len(U_BOOT_DATA), entry.size)
604
605 self.assertEqual(65, image._size)
606
607 def testPackExtra(self):
608 """Test that extra packing feature works as expected"""
609 retcode = self._DoTestFile('009_pack_extra.dts')
610
611 self.assertEqual(0, retcode)
612 self.assertIn('image', control.images)
613 image = control.images['image']
614 entries = image.GetEntries()
615 self.assertEqual(5, len(entries))
616
617 # First u-boot with padding before and after
618 self.assertIn('u-boot', entries)
619 entry = entries['u-boot']
620 self.assertEqual(0, entry.offset)
621 self.assertEqual(3, entry.pad_before)
622 self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
623
624 # Second u-boot has an aligned size, but it has no effect
625 self.assertIn('u-boot-align-size-nop', entries)
626 entry = entries['u-boot-align-size-nop']
627 self.assertEqual(12, entry.offset)
628 self.assertEqual(4, entry.size)
629
630 # Third u-boot has an aligned size too
631 self.assertIn('u-boot-align-size', entries)
632 entry = entries['u-boot-align-size']
633 self.assertEqual(16, entry.offset)
634 self.assertEqual(32, entry.size)
635
636 # Fourth u-boot has an aligned end
637 self.assertIn('u-boot-align-end', entries)
638 entry = entries['u-boot-align-end']
639 self.assertEqual(48, entry.offset)
640 self.assertEqual(16, entry.size)
641
642 # Fifth u-boot immediately afterwards
643 self.assertIn('u-boot-align-both', entries)
644 entry = entries['u-boot-align-both']
645 self.assertEqual(64, entry.offset)
646 self.assertEqual(64, entry.size)
647
648 self.CheckNoGaps(entries)
649 self.assertEqual(128, image._size)
650
651 def testPackAlignPowerOf2(self):
652 """Test that invalid entry alignment is detected"""
653 with self.assertRaises(ValueError) as e:
654 self._DoTestFile('010_pack_align_power2.dts')
655 self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
656 "of two", str(e.exception))
657
658 def testPackAlignSizePowerOf2(self):
659 """Test that invalid entry size alignment is detected"""
660 with self.assertRaises(ValueError) as e:
661 self._DoTestFile('011_pack_align_size_power2.dts')
662 self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
663 "power of two", str(e.exception))
664
665 def testPackInvalidAlign(self):
666 """Test detection of an offset that does not match its alignment"""
667 with self.assertRaises(ValueError) as e:
668 self._DoTestFile('012_pack_inv_align.dts')
669 self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
670 "align 0x4 (4)", str(e.exception))
671
672 def testPackInvalidSizeAlign(self):
673 """Test that invalid entry size alignment is detected"""
674 with self.assertRaises(ValueError) as e:
675 self._DoTestFile('013_pack_inv_size_align.dts')
676 self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
677 "align-size 0x4 (4)", str(e.exception))
678
679 def testPackOverlap(self):
680 """Test that overlapping regions are detected"""
681 with self.assertRaises(ValueError) as e:
682 self._DoTestFile('014_pack_overlap.dts')
683 self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
684 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
685 str(e.exception))
686
687 def testPackEntryOverflow(self):
688 """Test that entries that overflow their size are detected"""
689 with self.assertRaises(ValueError) as e:
690 self._DoTestFile('015_pack_overflow.dts')
691 self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
692 "but entry size is 0x3 (3)", str(e.exception))
693
694 def testPackImageOverflow(self):
695 """Test that entries which overflow the image size are detected"""
696 with self.assertRaises(ValueError) as e:
697 self._DoTestFile('016_pack_image_overflow.dts')
698 self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section "
699 "size 0x3 (3)", str(e.exception))
700
701 def testPackImageSize(self):
702 """Test that the image size can be set"""
703 retcode = self._DoTestFile('017_pack_image_size.dts')
704 self.assertEqual(0, retcode)
705 self.assertIn('image', control.images)
706 image = control.images['image']
707 self.assertEqual(7, image._size)
708
709 def testPackImageSizeAlign(self):
710 """Test that image size alignemnt works as expected"""
711 retcode = self._DoTestFile('018_pack_image_align.dts')
712 self.assertEqual(0, retcode)
713 self.assertIn('image', control.images)
714 image = control.images['image']
715 self.assertEqual(16, image._size)
716
717 def testPackInvalidImageAlign(self):
718 """Test that invalid image alignment is detected"""
719 with self.assertRaises(ValueError) as e:
720 self._DoTestFile('019_pack_inv_image_align.dts')
721 self.assertIn("Section '/binman': Size 0x7 (7) does not match "
722 "align-size 0x8 (8)", str(e.exception))
723
724 def testPackAlignPowerOf2(self):
725 """Test that invalid image alignment is detected"""
726 with self.assertRaises(ValueError) as e:
727 self._DoTestFile('020_pack_inv_image_align_power2.dts')
728 self.assertIn("Section '/binman': Alignment size 131 must be a power of "
729 "two", str(e.exception))
730
731 def testImagePadByte(self):
732 """Test that the image pad byte can be specified"""
733 self._SetupSplElf()
734 data = self._DoReadFile('021_image_pad.dts')
735 self.assertEqual(U_BOOT_SPL_DATA + (chr(0xff) * 1) + U_BOOT_DATA, data)
736
737 def testImageName(self):
738 """Test that image files can be named"""
739 retcode = self._DoTestFile('022_image_name.dts')
740 self.assertEqual(0, retcode)
741 image = control.images['image1']
742 fname = tools.GetOutputFilename('test-name')
743 self.assertTrue(os.path.exists(fname))
744
745 image = control.images['image2']
746 fname = tools.GetOutputFilename('test-name.xx')
747 self.assertTrue(os.path.exists(fname))
748
749 def testBlobFilename(self):
750 """Test that generic blobs can be provided by filename"""
751 data = self._DoReadFile('023_blob.dts')
752 self.assertEqual(BLOB_DATA, data)
753
754 def testPackSorted(self):
755 """Test that entries can be sorted"""
756 self._SetupSplElf()
757 data = self._DoReadFile('024_sorted.dts')
758 self.assertEqual(chr(0) * 1 + U_BOOT_SPL_DATA + chr(0) * 2 +
759 U_BOOT_DATA, data)
760
761 def testPackZeroOffset(self):
762 """Test that an entry at offset 0 is not given a new offset"""
763 with self.assertRaises(ValueError) as e:
764 self._DoTestFile('025_pack_zero_size.dts')
765 self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
766 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
767 str(e.exception))
768
769 def testPackUbootDtb(self):
770 """Test that a device tree can be added to U-Boot"""
771 data = self._DoReadFile('026_pack_u_boot_dtb.dts')
772 self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
773
774 def testPackX86RomNoSize(self):
775 """Test that the end-at-4gb property requires a size property"""
776 with self.assertRaises(ValueError) as e:
777 self._DoTestFile('027_pack_4gb_no_size.dts')
778 self.assertIn("Section '/binman': Section size must be provided when "
779 "using end-at-4gb", str(e.exception))
780
781 def test4gbAndSkipAtStartTogether(self):
782 """Test that the end-at-4gb and skip-at-size property can't be used
783 together"""
784 with self.assertRaises(ValueError) as e:
785 self._DoTestFile('80_4gb_and_skip_at_start_together.dts')
786 self.assertIn("Section '/binman': Provide either 'end-at-4gb' or "
787 "'skip-at-start'", str(e.exception))
788
789 def testPackX86RomOutside(self):
790 """Test that the end-at-4gb property checks for offset boundaries"""
791 with self.assertRaises(ValueError) as e:
792 self._DoTestFile('028_pack_4gb_outside.dts')
793 self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
794 "the section starting at 0xffffffe0 (4294967264)",
795 str(e.exception))
796
797 def testPackX86Rom(self):
798 """Test that a basic x86 ROM can be created"""
799 self._SetupSplElf()
800 data = self._DoReadFile('029_x86-rom.dts')
801 self.assertEqual(U_BOOT_DATA + chr(0) * 7 + U_BOOT_SPL_DATA +
802 chr(0) * 2, data)
803
804 def testPackX86RomMeNoDesc(self):
805 """Test that an invalid Intel descriptor entry is detected"""
806 TestFunctional._MakeInputFile('descriptor.bin', '')
807 with self.assertRaises(ValueError) as e:
808 self._DoTestFile('031_x86-rom-me.dts')
809 self.assertIn("Node '/binman/intel-descriptor': Cannot find FD "
810 "signature", str(e.exception))
811
812 def testPackX86RomBadDesc(self):
813 """Test that the Intel requires a descriptor entry"""
814 with self.assertRaises(ValueError) as e:
815 self._DoTestFile('030_x86-rom-me-no-desc.dts')
816 self.assertIn("Node '/binman/intel-me': No offset set with "
817 "offset-unset: should another entry provide this correct "
818 "offset?", str(e.exception))
819
820 def testPackX86RomMe(self):
821 """Test that an x86 ROM with an ME region can be created"""
822 data = self._DoReadFile('031_x86-rom-me.dts')
823 self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
824
825 def testPackVga(self):
826 """Test that an image with a VGA binary can be created"""
827 data = self._DoReadFile('032_intel-vga.dts')
828 self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
829
830 def testPackStart16(self):
831 """Test that an image with an x86 start16 region can be created"""
832 data = self._DoReadFile('033_x86-start16.dts')
833 self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
834
835 def testPackPowerpcMpc85xxBootpgResetvec(self):
836 """Test that an image with powerpc-mpc85xx-bootpg-resetvec can be
837 created"""
838 data = self._DoReadFile('81_powerpc_mpc85xx_bootpg_resetvec.dts')
839 self.assertEqual(PPC_MPC85XX_BR_DATA, data[:len(PPC_MPC85XX_BR_DATA)])
840
841 def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False):
842 """Handle running a test for insertion of microcode
843
844 Args:
845 dts_fname: Name of test .dts file
846 nodtb_data: Data that we expect in the first section
847 ucode_second: True if the microsecond entry is second instead of
848 third
849
850 Returns:
851 Tuple:
852 Contents of first region (U-Boot or SPL)
853 Offset and size components of microcode pointer, as inserted
854 in the above (two 4-byte words)
855 """
856 data = self._DoReadFile(dts_fname, True)
857
858 # Now check the device tree has no microcode
859 if ucode_second:
860 ucode_content = data[len(nodtb_data):]
861 ucode_pos = len(nodtb_data)
862 dtb_with_ucode = ucode_content[16:]
863 fdt_len = self.GetFdtLen(dtb_with_ucode)
864 else:
865 dtb_with_ucode = data[len(nodtb_data):]
866 fdt_len = self.GetFdtLen(dtb_with_ucode)
867 ucode_content = dtb_with_ucode[fdt_len:]
868 ucode_pos = len(nodtb_data) + fdt_len
869 fname = tools.GetOutputFilename('test.dtb')
870 with open(fname, 'wb') as fd:
871 fd.write(dtb_with_ucode)
872 dtb = fdt.FdtScan(fname)
873 ucode = dtb.GetNode('/microcode')
874 self.assertTrue(ucode)
875 for node in ucode.subnodes:
876 self.assertFalse(node.props.get('data'))
877
878 # Check that the microcode appears immediately after the Fdt
879 # This matches the concatenation of the data properties in
880 # the /microcode/update@xxx nodes in 34_x86_ucode.dts.
881 ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
882 0x78235609)
883 self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
884
885 # Check that the microcode pointer was inserted. It should match the
886 # expected offset and size
887 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
888 len(ucode_data))
889 u_boot = data[:len(nodtb_data)]
890 return u_boot, pos_and_size
891
892 def testPackUbootMicrocode(self):
893 """Test that x86 microcode can be handled correctly
894
895 We expect to see the following in the image, in order:
896 u-boot-nodtb.bin with a microcode pointer inserted at the correct
897 place
898 u-boot.dtb with the microcode removed
899 the microcode
900 """
901 first, pos_and_size = self._RunMicrocodeTest('034_x86_ucode.dts',
902 U_BOOT_NODTB_DATA)
903 self.assertEqual('nodtb with microcode' + pos_and_size +
904 ' somewhere in here', first)
905
906 def _RunPackUbootSingleMicrocode(self):
907 """Test that x86 microcode can be handled correctly
908
909 We expect to see the following in the image, in order:
910 u-boot-nodtb.bin with a microcode pointer inserted at the correct
911 place
912 u-boot.dtb with the microcode
913 an empty microcode region
914 """
915 # We need the libfdt library to run this test since only that allows
916 # finding the offset of a property. This is required by
917 # Entry_u_boot_dtb_with_ucode.ObtainContents().
918 data = self._DoReadFile('035_x86_single_ucode.dts', True)
919
920 second = data[len(U_BOOT_NODTB_DATA):]
921
922 fdt_len = self.GetFdtLen(second)
923 third = second[fdt_len:]
924 second = second[:fdt_len]
925
926 ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
927 self.assertIn(ucode_data, second)
928 ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
929
930 # Check that the microcode pointer was inserted. It should match the
931 # expected offset and size
932 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
933 len(ucode_data))
934 first = data[:len(U_BOOT_NODTB_DATA)]
935 self.assertEqual('nodtb with microcode' + pos_and_size +
936 ' somewhere in here', first)
937
938 def testPackUbootSingleMicrocode(self):
939 """Test that x86 microcode can be handled correctly with fdt_normal.
940 """
941 self._RunPackUbootSingleMicrocode()
942
943 def testUBootImg(self):
944 """Test that u-boot.img can be put in a file"""
945 data = self._DoReadFile('036_u_boot_img.dts')
946 self.assertEqual(U_BOOT_IMG_DATA, data)
947
948 def testNoMicrocode(self):
949 """Test that a missing microcode region is detected"""
950 with self.assertRaises(ValueError) as e:
951 self._DoReadFile('037_x86_no_ucode.dts', True)
952 self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
953 "node found in ", str(e.exception))
954
955 def testMicrocodeWithoutNode(self):
956 """Test that a missing u-boot-dtb-with-ucode node is detected"""
957 with self.assertRaises(ValueError) as e:
958 self._DoReadFile('038_x86_ucode_missing_node.dts', True)
959 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
960 "microcode region u-boot-dtb-with-ucode", str(e.exception))
961
962 def testMicrocodeWithoutNode2(self):
963 """Test that a missing u-boot-ucode node is detected"""
964 with self.assertRaises(ValueError) as e:
965 self._DoReadFile('039_x86_ucode_missing_node2.dts', True)
966 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
967 "microcode region u-boot-ucode", str(e.exception))
968
969 def testMicrocodeWithoutPtrInElf(self):
970 """Test that a U-Boot binary without the microcode symbol is detected"""
971 # ELF file without a '_dt_ucode_base_size' symbol
972 try:
973 with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
974 TestFunctional._MakeInputFile('u-boot', fd.read())
975
976 with self.assertRaises(ValueError) as e:
977 self._RunPackUbootSingleMicrocode()
978 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
979 "_dt_ucode_base_size symbol in u-boot", str(e.exception))
980
981 finally:
982 # Put the original file back
983 with open(self.TestFile('u_boot_ucode_ptr')) as fd:
984 TestFunctional._MakeInputFile('u-boot', fd.read())
985
986 def testMicrocodeNotInImage(self):
987 """Test that microcode must be placed within the image"""
988 with self.assertRaises(ValueError) as e:
989 self._DoReadFile('040_x86_ucode_not_in_image.dts', True)
990 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
991 "pointer _dt_ucode_base_size at fffffe14 is outside the "
992 "section ranging from 00000000 to 0000002e", str(e.exception))
993
994 def testWithoutMicrocode(self):
995 """Test that we can cope with an image without microcode (e.g. qemu)"""
996 with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
997 TestFunctional._MakeInputFile('u-boot', fd.read())
998 data, dtb, _, _ = self._DoReadFileDtb('044_x86_optional_ucode.dts', True)
999
1000 # Now check the device tree has no microcode
1001 self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
1002 second = data[len(U_BOOT_NODTB_DATA):]
1003
1004 fdt_len = self.GetFdtLen(second)
1005 self.assertEqual(dtb, second[:fdt_len])
1006
1007 used_len = len(U_BOOT_NODTB_DATA) + fdt_len
1008 third = data[used_len:]
1009 self.assertEqual(chr(0) * (0x200 - used_len), third)
1010
1011 def testUnknownPosSize(self):
1012 """Test that microcode must be placed within the image"""
1013 with self.assertRaises(ValueError) as e:
1014 self._DoReadFile('041_unknown_pos_size.dts', True)
1015 self.assertIn("Section '/binman': Unable to set offset/size for unknown "
1016 "entry 'invalid-entry'", str(e.exception))
1017
1018 def testPackFsp(self):
1019 """Test that an image with a FSP binary can be created"""
1020 data = self._DoReadFile('042_intel-fsp.dts')
1021 self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
1022
1023 def testPackCmc(self):
1024 """Test that an image with a CMC binary can be created"""
1025 data = self._DoReadFile('043_intel-cmc.dts')
1026 self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
1027
1028 def testPackVbt(self):
1029 """Test that an image with a VBT binary can be created"""
1030 data = self._DoReadFile('046_intel-vbt.dts')
1031 self.assertEqual(VBT_DATA, data[:len(VBT_DATA)])
1032
1033 def testSplBssPad(self):
1034 """Test that we can pad SPL's BSS with zeros"""
1035 # ELF file with a '__bss_size' symbol
1036 self._SetupSplElf()
1037 data = self._DoReadFile('047_spl_bss_pad.dts')
1038 self.assertEqual(U_BOOT_SPL_DATA + (chr(0) * 10) + U_BOOT_DATA, data)
1039
1040 def testSplBssPadMissing(self):
1041 """Test that a missing symbol is detected"""
1042 self._SetupSplElf('u_boot_ucode_ptr')
1043 with self.assertRaises(ValueError) as e:
1044 self._DoReadFile('047_spl_bss_pad.dts')
1045 self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
1046 str(e.exception))
1047
1048 def testPackStart16Spl(self):
1049 """Test that an image with an x86 start16 SPL region can be created"""
1050 data = self._DoReadFile('048_x86-start16-spl.dts')
1051 self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)])
1052
1053 def _PackUbootSplMicrocode(self, dts, ucode_second=False):
1054 """Helper function for microcode tests
1055
1056 We expect to see the following in the image, in order:
1057 u-boot-spl-nodtb.bin with a microcode pointer inserted at the
1058 correct place
1059 u-boot.dtb with the microcode removed
1060 the microcode
1061
1062 Args:
1063 dts: Device tree file to use for test
1064 ucode_second: True if the microsecond entry is second instead of
1065 third
1066 """
1067 self._SetupSplElf('u_boot_ucode_ptr')
1068 first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA,
1069 ucode_second=ucode_second)
1070 self.assertEqual('splnodtb with microc' + pos_and_size +
1071 'ter somewhere in here', first)
1072
1073 def testPackUbootSplMicrocode(self):
1074 """Test that x86 microcode can be handled correctly in SPL"""
1075 self._PackUbootSplMicrocode('049_x86_ucode_spl.dts')
1076
1077 def testPackUbootSplMicrocodeReorder(self):
1078 """Test that order doesn't matter for microcode entries
1079
1080 This is the same as testPackUbootSplMicrocode but when we process the
1081 u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode
1082 entry, so we reply on binman to try later.
1083 """
1084 self._PackUbootSplMicrocode('058_x86_ucode_spl_needs_retry.dts',
1085 ucode_second=True)
1086
1087 def testPackMrc(self):
1088 """Test that an image with an MRC binary can be created"""
1089 data = self._DoReadFile('050_intel_mrc.dts')
1090 self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
1091
1092 def testSplDtb(self):
1093 """Test that an image with spl/u-boot-spl.dtb can be created"""
1094 data = self._DoReadFile('051_u_boot_spl_dtb.dts')
1095 self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
1096
1097 def testSplNoDtb(self):
1098 """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
1099 data = self._DoReadFile('052_u_boot_spl_nodtb.dts')
1100 self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
1101
1102 def testSymbols(self):
1103 """Test binman can assign symbols embedded in U-Boot"""
1104 elf_fname = self.TestFile('u_boot_binman_syms')
1105 syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
1106 addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
1107 self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
1108
1109 self._SetupSplElf('u_boot_binman_syms')
1110 data = self._DoReadFile('053_symbols.dts')
1111 sym_values = struct.pack('<LQL', 0x24 + 0, 0x24 + 24, 0x24 + 20)
1112 expected = (sym_values + U_BOOT_SPL_DATA[16:] + chr(0xff) +
1113 U_BOOT_DATA +
1114 sym_values + U_BOOT_SPL_DATA[16:])
1115 self.assertEqual(expected, data)
1116
1117 def testPackUnitAddress(self):
1118 """Test that we support multiple binaries with the same name"""
1119 data = self._DoReadFile('054_unit_address.dts')
1120 self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
1121
1122 def testSections(self):
1123 """Basic test of sections"""
1124 data = self._DoReadFile('055_sections.dts')
1125 expected = (U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12 +
1126 U_BOOT_DATA + '&' * 4)
1127 self.assertEqual(expected, data)
1128
1129 def testMap(self):
1130 """Tests outputting a map of the images"""
1131 _, _, map_data, _ = self._DoReadFileDtb('055_sections.dts', map=True)
1132 self.assertEqual('''ImagePos Offset Size Name
1133 00000000 00000000 00000028 main-section
1134 00000000 00000000 00000010 section@0
1135 00000000 00000000 00000004 u-boot
1136 00000010 00000010 00000010 section@1
1137 00000010 00000000 00000004 u-boot
1138 00000020 00000020 00000004 section@2
1139 00000020 00000000 00000004 u-boot
1140 ''', map_data)
1141
1142 def testNamePrefix(self):
1143 """Tests that name prefixes are used"""
1144 _, _, map_data, _ = self._DoReadFileDtb('056_name_prefix.dts', map=True)
1145 self.assertEqual('''ImagePos Offset Size Name
1146 00000000 00000000 00000028 main-section
1147 00000000 00000000 00000010 section@0
1148 00000000 00000000 00000004 ro-u-boot
1149 00000010 00000010 00000010 section@1
1150 00000010 00000000 00000004 rw-u-boot
1151 ''', map_data)
1152
1153 def testUnknownContents(self):
1154 """Test that obtaining the contents works as expected"""
1155 with self.assertRaises(ValueError) as e:
1156 self._DoReadFile('057_unknown_contents.dts', True)
1157 self.assertIn("Section '/binman': Internal error: Could not complete "
1158 "processing of contents: remaining [<_testing.Entry__testing ",
1159 str(e.exception))
1160
1161 def testBadChangeSize(self):
1162 """Test that trying to change the size of an entry fails"""
1163 with self.assertRaises(ValueError) as e:
1164 self._DoReadFile('059_change_size.dts', True)
1165 self.assertIn("Node '/binman/_testing': Cannot update entry size from "
1166 '2 to 1', str(e.exception))
1167
1168 def testUpdateFdt(self):
1169 """Test that we can update the device tree with offset/size info"""
1170 _, _, _, out_dtb_fname = self._DoReadFileDtb('060_fdt_update.dts',
1171 update_dtb=True)
1172 dtb = fdt.Fdt(out_dtb_fname)
1173 dtb.Scan()
1174 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'])
1175 self.assertEqual({
1176 'image-pos': 0,
1177 'offset': 0,
1178 '_testing:offset': 32,
1179 '_testing:size': 1,
1180 '_testing:image-pos': 32,
1181 'section@0/u-boot:offset': 0,
1182 'section@0/u-boot:size': len(U_BOOT_DATA),
1183 'section@0/u-boot:image-pos': 0,
1184 'section@0:offset': 0,
1185 'section@0:size': 16,
1186 'section@0:image-pos': 0,
1187
1188 'section@1/u-boot:offset': 0,
1189 'section@1/u-boot:size': len(U_BOOT_DATA),
1190 'section@1/u-boot:image-pos': 16,
1191 'section@1:offset': 16,
1192 'section@1:size': 16,
1193 'section@1:image-pos': 16,
1194 'size': 40
1195 }, props)
1196
1197 def testUpdateFdtBad(self):
1198 """Test that we detect when ProcessFdt never completes"""
1199 with self.assertRaises(ValueError) as e:
1200 self._DoReadFileDtb('061_fdt_update_bad.dts', update_dtb=True)
1201 self.assertIn('Could not complete processing of Fdt: remaining '
1202 '[<_testing.Entry__testing', str(e.exception))
1203
1204 def testEntryArgs(self):
1205 """Test passing arguments to entries from the command line"""
1206 entry_args = {
1207 'test-str-arg': 'test1',
1208 'test-int-arg': '456',
1209 }
1210 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
1211 self.assertIn('image', control.images)
1212 entry = control.images['image'].GetEntries()['_testing']
1213 self.assertEqual('test0', entry.test_str_fdt)
1214 self.assertEqual('test1', entry.test_str_arg)
1215 self.assertEqual(123, entry.test_int_fdt)
1216 self.assertEqual(456, entry.test_int_arg)
1217
1218 def testEntryArgsMissing(self):
1219 """Test missing arguments and properties"""
1220 entry_args = {
1221 'test-int-arg': '456',
1222 }
1223 self._DoReadFileDtb('063_entry_args_missing.dts', entry_args=entry_args)
1224 entry = control.images['image'].GetEntries()['_testing']
1225 self.assertEqual('test0', entry.test_str_fdt)
1226 self.assertEqual(None, entry.test_str_arg)
1227 self.assertEqual(None, entry.test_int_fdt)
1228 self.assertEqual(456, entry.test_int_arg)
1229
1230 def testEntryArgsRequired(self):
1231 """Test missing arguments and properties"""
1232 entry_args = {
1233 'test-int-arg': '456',
1234 }
1235 with self.assertRaises(ValueError) as e:
1236 self._DoReadFileDtb('064_entry_args_required.dts')
1237 self.assertIn("Node '/binman/_testing': Missing required "
1238 'properties/entry args: test-str-arg, test-int-fdt, test-int-arg',
1239 str(e.exception))
1240
1241 def testEntryArgsInvalidFormat(self):
1242 """Test that an invalid entry-argument format is detected"""
1243 args = ['-d', self.TestFile('064_entry_args_required.dts'), '-ano-value']
1244 with self.assertRaises(ValueError) as e:
1245 self._DoBinman(*args)
1246 self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
1247
1248 def testEntryArgsInvalidInteger(self):
1249 """Test that an invalid entry-argument integer is detected"""
1250 entry_args = {
1251 'test-int-arg': 'abc',
1252 }
1253 with self.assertRaises(ValueError) as e:
1254 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
1255 self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
1256 "'test-int-arg' (value 'abc') to integer",
1257 str(e.exception))
1258
1259 def testEntryArgsInvalidDatatype(self):
1260 """Test that an invalid entry-argument datatype is detected
1261
1262 This test could be written in entry_test.py except that it needs
1263 access to control.entry_args, which seems more than that module should
1264 be able to see.
1265 """
1266 entry_args = {
1267 'test-bad-datatype-arg': '12',
1268 }
1269 with self.assertRaises(ValueError) as e:
1270 self._DoReadFileDtb('065_entry_args_unknown_datatype.dts',
1271 entry_args=entry_args)
1272 self.assertIn('GetArg() internal error: Unknown data type ',
1273 str(e.exception))
1274
1275 def testText(self):
1276 """Test for a text entry type"""
1277 entry_args = {
1278 'test-id': TEXT_DATA,
1279 'test-id2': TEXT_DATA2,
1280 'test-id3': TEXT_DATA3,
1281 }
1282 data, _, _, _ = self._DoReadFileDtb('066_text.dts',
1283 entry_args=entry_args)
1284 expected = (TEXT_DATA + chr(0) * (8 - len(TEXT_DATA)) + TEXT_DATA2 +
1285 TEXT_DATA3 + 'some text')
1286 self.assertEqual(expected, data)
1287
1288 def testEntryDocs(self):
1289 """Test for creation of entry documentation"""
1290 with test_util.capture_sys_output() as (stdout, stderr):
1291 control.WriteEntryDocs(binman.GetEntryModules())
1292 self.assertTrue(len(stdout.getvalue()) > 0)
1293
1294 def testEntryDocsMissing(self):
1295 """Test handling of missing entry documentation"""
1296 with self.assertRaises(ValueError) as e:
1297 with test_util.capture_sys_output() as (stdout, stderr):
1298 control.WriteEntryDocs(binman.GetEntryModules(), 'u_boot')
1299 self.assertIn('Documentation is missing for modules: u_boot',
1300 str(e.exception))
1301
1302 def testFmap(self):
1303 """Basic test of generation of a flashrom fmap"""
1304 data = self._DoReadFile('067_fmap.dts')
1305 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1306 expected = U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12
1307 self.assertEqual(expected, data[:32])
1308 self.assertEqual('__FMAP__', fhdr.signature)
1309 self.assertEqual(1, fhdr.ver_major)
1310 self.assertEqual(0, fhdr.ver_minor)
1311 self.assertEqual(0, fhdr.base)
1312 self.assertEqual(16 + 16 +
1313 fmap_util.FMAP_HEADER_LEN +
1314 fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
1315 self.assertEqual('FMAP', fhdr.name)
1316 self.assertEqual(3, fhdr.nareas)
1317 for fentry in fentries:
1318 self.assertEqual(0, fentry.flags)
1319
1320 self.assertEqual(0, fentries[0].offset)
1321 self.assertEqual(4, fentries[0].size)
1322 self.assertEqual('RO_U_BOOT', fentries[0].name)
1323
1324 self.assertEqual(16, fentries[1].offset)
1325 self.assertEqual(4, fentries[1].size)
1326 self.assertEqual('RW_U_BOOT', fentries[1].name)
1327
1328 self.assertEqual(32, fentries[2].offset)
1329 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1330 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1331 self.assertEqual('FMAP', fentries[2].name)
1332
1333 def testBlobNamedByArg(self):
1334 """Test we can add a blob with the filename coming from an entry arg"""
1335 entry_args = {
1336 'cros-ec-rw-path': 'ecrw.bin',
1337 }
1338 data, _, _, _ = self._DoReadFileDtb('068_blob_named_by_arg.dts',
1339 entry_args=entry_args)
1340
1341 def testFill(self):
1342 """Test for an fill entry type"""
1343 data = self._DoReadFile('069_fill.dts')
1344 expected = 8 * chr(0xff) + 8 * chr(0)
1345 self.assertEqual(expected, data)
1346
1347 def testFillNoSize(self):
1348 """Test for an fill entry type with no size"""
1349 with self.assertRaises(ValueError) as e:
1350 self._DoReadFile('070_fill_no_size.dts')
1351 self.assertIn("'fill' entry must have a size property",
1352 str(e.exception))
1353
1354 def _HandleGbbCommand(self, pipe_list):
1355 """Fake calls to the futility utility"""
1356 if pipe_list[0][0] == 'futility':
1357 fname = pipe_list[0][-1]
1358 # Append our GBB data to the file, which will happen every time the
1359 # futility command is called.
1360 with open(fname, 'a') as fd:
1361 fd.write(GBB_DATA)
1362 return command.CommandResult()
1363
1364 def testGbb(self):
1365 """Test for the Chromium OS Google Binary Block"""
1366 command.test_result = self._HandleGbbCommand
1367 entry_args = {
1368 'keydir': 'devkeys',
1369 'bmpblk': 'bmpblk.bin',
1370 }
1371 data, _, _, _ = self._DoReadFileDtb('071_gbb.dts', entry_args=entry_args)
1372
1373 # Since futility
1374 expected = GBB_DATA + GBB_DATA + 8 * chr(0) + (0x2180 - 16) * chr(0)
1375 self.assertEqual(expected, data)
1376
1377 def testGbbTooSmall(self):
1378 """Test for the Chromium OS Google Binary Block being large enough"""
1379 with self.assertRaises(ValueError) as e:
1380 self._DoReadFileDtb('072_gbb_too_small.dts')
1381 self.assertIn("Node '/binman/gbb': GBB is too small",
1382 str(e.exception))
1383
1384 def testGbbNoSize(self):
1385 """Test for the Chromium OS Google Binary Block having a size"""
1386 with self.assertRaises(ValueError) as e:
1387 self._DoReadFileDtb('073_gbb_no_size.dts')
1388 self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
1389 str(e.exception))
1390
1391 def _HandleVblockCommand(self, pipe_list):
1392 """Fake calls to the futility utility"""
1393 if pipe_list[0][0] == 'futility':
1394 fname = pipe_list[0][3]
1395 with open(fname, 'wb') as fd:
1396 fd.write(VBLOCK_DATA)
1397 return command.CommandResult()
1398
1399 def testVblock(self):
1400 """Test for the Chromium OS Verified Boot Block"""
1401 command.test_result = self._HandleVblockCommand
1402 entry_args = {
1403 'keydir': 'devkeys',
1404 }
1405 data, _, _, _ = self._DoReadFileDtb('074_vblock.dts',
1406 entry_args=entry_args)
1407 expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
1408 self.assertEqual(expected, data)
1409
1410 def testVblockNoContent(self):
1411 """Test we detect a vblock which has no content to sign"""
1412 with self.assertRaises(ValueError) as e:
1413 self._DoReadFile('075_vblock_no_content.dts')
1414 self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
1415 'property', str(e.exception))
1416
1417 def testVblockBadPhandle(self):
1418 """Test that we detect a vblock with an invalid phandle in contents"""
1419 with self.assertRaises(ValueError) as e:
1420 self._DoReadFile('076_vblock_bad_phandle.dts')
1421 self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
1422 '1000', str(e.exception))
1423
1424 def testVblockBadEntry(self):
1425 """Test that we detect an entry that points to a non-entry"""
1426 with self.assertRaises(ValueError) as e:
1427 self._DoReadFile('077_vblock_bad_entry.dts')
1428 self.assertIn("Node '/binman/vblock': Cannot find entry for node "
1429 "'other'", str(e.exception))
1430
1431 def testTpl(self):
1432 """Test that an image with TPL and ots device tree can be created"""
1433 # ELF file with a '__bss_size' symbol
1434 with open(self.TestFile('bss_data')) as fd:
1435 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1436 data = self._DoReadFile('078_u_boot_tpl.dts')
1437 self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
1438
1439 def testUsesPos(self):
1440 """Test that the 'pos' property cannot be used anymore"""
1441 with self.assertRaises(ValueError) as e:
1442 data = self._DoReadFile('079_uses_pos.dts')
1443 self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
1444 "'pos'", str(e.exception))
1445
1446 def testFillZero(self):
1447 """Test for an fill entry type with a size of 0"""
1448 data = self._DoReadFile('080_fill_empty.dts')
1449 self.assertEqual(chr(0) * 16, data)
1450
1451 def testTextMissing(self):
1452 """Test for a text entry type where there is no text"""
1453 with self.assertRaises(ValueError) as e:
1454 self._DoReadFileDtb('066_text.dts',)
1455 self.assertIn("Node '/binman/text': No value provided for text label "
1456 "'test-id'", str(e.exception))
1457
1458 def testPackStart16Tpl(self):
1459 """Test that an image with an x86 start16 TPL region can be created"""
1460 data = self._DoReadFile('081_x86-start16-tpl.dts')
1461 self.assertEqual(X86_START16_TPL_DATA, data[:len(X86_START16_TPL_DATA)])
1462
1463 def testSelectImage(self):
1464 """Test that we can select which images to build"""
1465 expected = 'Skipping images: image1'
1466
1467 # We should only get the expected message in verbose mode
1468 for verbosity in (None, 2):
1469 with test_util.capture_sys_output() as (stdout, stderr):
1470 retcode = self._DoTestFile('006_dual_image.dts',
1471 verbosity=verbosity,
1472 images=['image2'])
1473 self.assertEqual(0, retcode)
1474 if verbosity:
1475 self.assertIn(expected, stdout.getvalue())
1476 else:
1477 self.assertNotIn(expected, stdout.getvalue())
1478
1479 self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
1480 self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
1481
1482 def testUpdateFdtAll(self):
1483 """Test that all device trees are updated with offset/size info"""
1484 data, _, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
1485 use_real_dtb=True, update_dtb=True)
1486
1487 base_expected = {
1488 'section:image-pos': 0,
1489 'u-boot-tpl-dtb:size': 513,
1490 'u-boot-spl-dtb:size': 513,
1491 'u-boot-spl-dtb:offset': 493,
1492 'image-pos': 0,
1493 'section/u-boot-dtb:image-pos': 0,
1494 'u-boot-spl-dtb:image-pos': 493,
1495 'section/u-boot-dtb:size': 493,
1496 'u-boot-tpl-dtb:image-pos': 1006,
1497 'section/u-boot-dtb:offset': 0,
1498 'section:size': 493,
1499 'offset': 0,
1500 'section:offset': 0,
1501 'u-boot-tpl-dtb:offset': 1006,
1502 'size': 1519
1503 }
1504
1505 # We expect three device-tree files in the output, one after the other.
1506 # Read them in sequence. We look for an 'spl' property in the SPL tree,
1507 # and 'tpl' in the TPL tree, to make sure they are distinct from the
1508 # main U-Boot tree. All three should have the same postions and offset.
1509 start = 0
1510 for item in ['', 'spl', 'tpl']:
1511 dtb = fdt.Fdt.FromData(data[start:])
1512 dtb.Scan()
1513 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos',
1514 'spl', 'tpl'])
1515 expected = dict(base_expected)
1516 if item:
1517 expected[item] = 0
1518 self.assertEqual(expected, props)
1519 start += dtb._fdt_obj.totalsize()
1520
1521 def testUpdateFdtOutput(self):
1522 """Test that output DTB files are updated"""
1523 try:
1524 data, dtb_data, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
1525 use_real_dtb=True, update_dtb=True, reset_dtbs=False)
1526
1527 # Unfortunately, compiling a source file always results in a file
1528 # called source.dtb (see fdt_util.EnsureCompiled()). The test
1529 # source file (e.g. test/075_fdt_update_all.dts) thus does not enter
1530 # binman as a file called u-boot.dtb. To fix this, copy the file
1531 # over to the expected place.
1532 #tools.WriteFile(os.path.join(self._indir, 'u-boot.dtb'),
1533 #tools.ReadFile(tools.GetOutputFilename('source.dtb')))
1534 start = 0
1535 for fname in ['u-boot.dtb.out', 'spl/u-boot-spl.dtb.out',
1536 'tpl/u-boot-tpl.dtb.out']:
1537 dtb = fdt.Fdt.FromData(data[start:])
1538 size = dtb._fdt_obj.totalsize()
1539 pathname = tools.GetOutputFilename(os.path.split(fname)[1])
1540 outdata = tools.ReadFile(pathname)
1541 name = os.path.split(fname)[0]
1542
1543 if name:
1544 orig_indata = self._GetDtbContentsForSplTpl(dtb_data, name)
1545 else:
1546 orig_indata = dtb_data
1547 self.assertNotEqual(outdata, orig_indata,
1548 "Expected output file '%s' be updated" % pathname)
1549 self.assertEqual(outdata, data[start:start + size],
1550 "Expected output file '%s' to match output image" %
1551 pathname)
1552 start += size
1553 finally:
1554 self._ResetDtbs()
1555
1556 def _decompress(self, data):
1557 out = os.path.join(self._indir, 'lz4.tmp')
1558 with open(out, 'wb') as fd:
1559 fd.write(data)
1560 return tools.Run('lz4', '-dc', out)
1561 '''
1562 try:
1563 orig = lz4.frame.decompress(data)
1564 except AttributeError:
1565 orig = lz4.decompress(data)
1566 '''
1567
1568 def testCompress(self):
1569 """Test compression of blobs"""
1570 data, _, _, out_dtb_fname = self._DoReadFileDtb('083_compress.dts',
1571 use_real_dtb=True, update_dtb=True)
1572 dtb = fdt.Fdt(out_dtb_fname)
1573 dtb.Scan()
1574 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
1575 orig = self._decompress(data)
1576 self.assertEquals(COMPRESS_DATA, orig)
1577 expected = {
1578 'blob:uncomp-size': len(COMPRESS_DATA),
1579 'blob:size': len(data),
1580 'size': len(data),
1581 }
1582 self.assertEqual(expected, props)
1583
1584 def testFiles(self):
1585 """Test bringing in multiple files"""
1586 data = self._DoReadFile('084_files.dts')
1587 self.assertEqual(FILES_DATA, data)
1588
1589 def testFilesCompress(self):
1590 """Test bringing in multiple files and compressing them"""
1591 data = self._DoReadFile('085_files_compress.dts')
1592
1593 image = control.images['image']
1594 entries = image.GetEntries()
1595 files = entries['files']
1596 entries = files._section._entries
1597
1598 orig = ''
1599 for i in range(1, 3):
1600 key = '%d.dat' % i
1601 start = entries[key].image_pos
1602 len = entries[key].size
1603 chunk = data[start:start + len]
1604 orig += self._decompress(chunk)
1605
1606 self.assertEqual(FILES_DATA, orig)
1607
1608 def testFilesMissing(self):
1609 """Test missing files"""
1610 with self.assertRaises(ValueError) as e:
1611 data = self._DoReadFile('086_files_none.dts')
1612 self.assertIn("Node '/binman/files': Pattern \'files/*.none\' matched "
1613 'no files', str(e.exception))
1614
1615 def testFilesNoPattern(self):
1616 """Test missing files"""
1617 with self.assertRaises(ValueError) as e:
1618 data = self._DoReadFile('087_files_no_pattern.dts')
1619 self.assertIn("Node '/binman/files': Missing 'pattern' property",
1620 str(e.exception))
1621
1622 def testExpandSize(self):
1623 """Test an expanding entry"""
1624 data, _, map_data, _ = self._DoReadFileDtb('088_expand_size.dts',
1625 map=True)
1626 expect = ('a' * 8 + U_BOOT_DATA +
1627 MRC_DATA + 'b' * 1 + U_BOOT_DATA +
1628 'c' * 8 + U_BOOT_DATA +
1629 'd' * 8)
1630 self.assertEqual(expect, data)
1631 self.assertEqual('''ImagePos Offset Size Name
1632 00000000 00000000 00000028 main-section
1633 00000000 00000000 00000008 fill
1634 00000008 00000008 00000004 u-boot
1635 0000000c 0000000c 00000004 section
1636 0000000c 00000000 00000003 intel-mrc
1637 00000010 00000010 00000004 u-boot2
1638 00000014 00000014 0000000c section2
1639 00000014 00000000 00000008 fill
1640 0000001c 00000008 00000004 u-boot
1641 00000020 00000020 00000008 fill2
1642 ''', map_data)
1643
1644 def testExpandSizeBad(self):
1645 """Test an expanding entry which fails to provide contents"""
1646 with test_util.capture_sys_output() as (stdout, stderr):
1647 with self.assertRaises(ValueError) as e:
1648 self._DoReadFileDtb('089_expand_size_bad.dts', map=True)
1649 self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
1650 'expanding entry', str(e.exception))
1651
1652 def testHash(self):
1653 """Test hashing of the contents of an entry"""
1654 _, _, _, out_dtb_fname = self._DoReadFileDtb('090_hash.dts',
1655 use_real_dtb=True, update_dtb=True)
1656 dtb = fdt.Fdt(out_dtb_fname)
1657 dtb.Scan()
1658 hash_node = dtb.GetNode('/binman/u-boot/hash').props['value']
1659 m = hashlib.sha256()
1660 m.update(U_BOOT_DATA)
1661 self.assertEqual(m.digest(), ''.join(hash_node.value))
1662
1663 def testHashNoAlgo(self):
1664 with self.assertRaises(ValueError) as e:
1665 self._DoReadFileDtb('091_hash_no_algo.dts', update_dtb=True)
1666 self.assertIn("Node \'/binman/u-boot\': Missing \'algo\' property for "
1667 'hash node', str(e.exception))
1668
1669 def testHashBadAlgo(self):
1670 with self.assertRaises(ValueError) as e:
1671 self._DoReadFileDtb('092_hash_bad_algo.dts', update_dtb=True)
1672 self.assertIn("Node '/binman/u-boot': Unknown hash algorithm",
1673 str(e.exception))
1674
1675 def testHashSection(self):
1676 """Test hashing of the contents of an entry"""
1677 _, _, _, out_dtb_fname = self._DoReadFileDtb('099_hash_section.dts',
1678 use_real_dtb=True, update_dtb=True)
1679 dtb = fdt.Fdt(out_dtb_fname)
1680 dtb.Scan()
1681 hash_node = dtb.GetNode('/binman/section/hash').props['value']
1682 m = hashlib.sha256()
1683 m.update(U_BOOT_DATA)
1684 m.update(16 * 'a')
1685 self.assertEqual(m.digest(), ''.join(hash_node.value))
1686
1687 def testPackUBootTplMicrocode(self):
1688 """Test that x86 microcode can be handled correctly in TPL
1689
1690 We expect to see the following in the image, in order:
1691 u-boot-tpl-nodtb.bin with a microcode pointer inserted at the correct
1692 place
1693 u-boot-tpl.dtb with the microcode removed
1694 the microcode
1695 """
1696 with open(self.TestFile('u_boot_ucode_ptr')) as fd:
1697 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1698 first, pos_and_size = self._RunMicrocodeTest('093_x86_tpl_ucode.dts',
1699 U_BOOT_TPL_NODTB_DATA)
1700 self.assertEqual('tplnodtb with microc' + pos_and_size +
1701 'ter somewhere in here', first)
1702
1703 def testFmapX86(self):
1704 """Basic test of generation of a flashrom fmap"""
1705 data = self._DoReadFile('094_fmap_x86.dts')
1706 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1707 expected = U_BOOT_DATA + MRC_DATA + 'a' * (32 - 7)
1708 self.assertEqual(expected, data[:32])
1709 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1710
1711 self.assertEqual(0x100, fhdr.image_size)
1712
1713 self.assertEqual(0, fentries[0].offset)
1714 self.assertEqual(4, fentries[0].size)
1715 self.assertEqual('U_BOOT', fentries[0].name)
1716
1717 self.assertEqual(4, fentries[1].offset)
1718 self.assertEqual(3, fentries[1].size)
1719 self.assertEqual('INTEL_MRC', fentries[1].name)
1720
1721 self.assertEqual(32, fentries[2].offset)
1722 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1723 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1724 self.assertEqual('FMAP', fentries[2].name)
1725
1726 def testFmapX86Section(self):
1727 """Basic test of generation of a flashrom fmap"""
1728 data = self._DoReadFile('095_fmap_x86_section.dts')
1729 expected = U_BOOT_DATA + MRC_DATA + 'b' * (32 - 7)
1730 self.assertEqual(expected, data[:32])
1731 fhdr, fentries = fmap_util.DecodeFmap(data[36:])
1732
1733 self.assertEqual(0x100, fhdr.image_size)
1734
1735 self.assertEqual(0, fentries[0].offset)
1736 self.assertEqual(4, fentries[0].size)
1737 self.assertEqual('U_BOOT', fentries[0].name)
1738
1739 self.assertEqual(4, fentries[1].offset)
1740 self.assertEqual(3, fentries[1].size)
1741 self.assertEqual('INTEL_MRC', fentries[1].name)
1742
1743 self.assertEqual(36, fentries[2].offset)
1744 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1745 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1746 self.assertEqual('FMAP', fentries[2].name)
1747
1748 def testElf(self):
1749 """Basic test of ELF entries"""
1750 self._SetupSplElf()
1751 with open(self.TestFile('bss_data')) as fd:
1752 TestFunctional._MakeInputFile('-boot', fd.read())
1753 data = self._DoReadFile('096_elf.dts')
1754
1755 def testElfStripg(self):
1756 """Basic test of ELF entries"""
1757 self._SetupSplElf()
1758 with open(self.TestFile('bss_data')) as fd:
1759 TestFunctional._MakeInputFile('-boot', fd.read())
1760 data = self._DoReadFile('097_elf_strip.dts')
1761
1762 def testPackOverlapMap(self):
1763 """Test that overlapping regions are detected"""
1764 with test_util.capture_sys_output() as (stdout, stderr):
1765 with self.assertRaises(ValueError) as e:
1766 self._DoTestFile('014_pack_overlap.dts', map=True)
1767 map_fname = tools.GetOutputFilename('image.map')
1768 self.assertEqual("Wrote map file '%s' to show errors\n" % map_fname,
1769 stdout.getvalue())
1770
1771 # We should not get an inmage, but there should be a map file
1772 self.assertFalse(os.path.exists(tools.GetOutputFilename('image.bin')))
1773 self.assertTrue(os.path.exists(map_fname))
1774 map_data = tools.ReadFile(map_fname)
1775 self.assertEqual('''ImagePos Offset Size Name
1776 <none> 00000000 00000007 main-section
1777 <none> 00000000 00000004 u-boot
1778 <none> 00000003 00000004 u-boot-align
1779 ''', map_data)
1780
1781 def testPacRefCode(self):
1782 """Test that an image with an Intel Reference code binary works"""
1783 data = self._DoReadFile('100_intel_refcode.dts')
1784 self.assertEqual(REFCODE_DATA, data[:len(REFCODE_DATA)])
1785
1786 def testSectionOffset(self):
1787 """Tests use of a section with an offset"""
1788 data, _, map_data, _ = self._DoReadFileDtb('101_sections_offset.dts',
1789 map=True)
1790 self.assertEqual('''ImagePos Offset Size Name
1791 00000000 00000000 00000038 main-section
1792 00000004 00000004 00000010 section@0
1793 00000004 00000000 00000004 u-boot
1794 00000018 00000018 00000010 section@1
1795 00000018 00000000 00000004 u-boot
1796 0000002c 0000002c 00000004 section@2
1797 0000002c 00000000 00000004 u-boot
1798 ''', map_data)
1799 self.assertEqual(data,
1800 4 * chr(0x26) + U_BOOT_DATA + 12 * chr(0x21) +
1801 4 * chr(0x26) + U_BOOT_DATA + 12 * chr(0x61) +
1802 4 * chr(0x26) + U_BOOT_DATA + 8 * chr(0x26))
1803
1804
1805 if __name__ == "__main__":
1806 unittest.main()