blob: e77fce5a26fc4544f4f6141995013032056f1e34 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001# SPDX-License-Identifier: GPL-2.0+
Simon Glass4f443042016-11-25 20:15:52 -07002# Copyright (c) 2016 Google, Inc
3# Written by Simon Glass <sjg@chromium.org>
4#
Simon Glass4f443042016-11-25 20:15:52 -07005# To run a single test, change to this directory, and:
6#
7# python -m unittest func_test.TestFunctional.testHelp
8
Simon Glasse0e5df92018-09-14 04:57:31 -06009import hashlib
Simon Glass4f443042016-11-25 20:15:52 -070010from optparse import OptionParser
11import os
12import shutil
13import struct
14import sys
15import tempfile
16import unittest
17
18import binman
19import cmdline
20import command
21import control
Simon Glass19790632017-11-13 18:55:01 -070022import elf
Simon Glass99ed4a22017-05-27 07:38:30 -060023import fdt
Simon Glass4f443042016-11-25 20:15:52 -070024import fdt_util
Simon Glass11e36cc2018-07-17 13:25:38 -060025import fmap_util
Simon Glassfd8d1f72018-07-17 13:25:36 -060026import test_util
Simon Glassc55a50f2018-09-14 04:57:19 -060027import state
Simon Glass4f443042016-11-25 20:15:52 -070028import tools
29import tout
30
31# Contents of test files, corresponding to different entry types
Simon Glass6b187df2017-11-12 21:52:27 -070032U_BOOT_DATA = '1234'
33U_BOOT_IMG_DATA = 'img'
Simon Glassf6898902017-11-13 18:54:59 -070034U_BOOT_SPL_DATA = '56780123456789abcde'
Simon Glassb8ef5b62018-07-17 13:25:48 -060035U_BOOT_TPL_DATA = 'tpl'
Simon Glass6b187df2017-11-12 21:52:27 -070036BLOB_DATA = '89'
37ME_DATA = '0abcd'
38VGA_DATA = 'vga'
39U_BOOT_DTB_DATA = 'udtb'
Simon Glass47419ea2017-11-13 18:54:55 -070040U_BOOT_SPL_DTB_DATA = 'spldtb'
Simon Glassb8ef5b62018-07-17 13:25:48 -060041U_BOOT_TPL_DTB_DATA = 'tpldtb'
Simon Glass6b187df2017-11-12 21:52:27 -070042X86_START16_DATA = 'start16'
43X86_START16_SPL_DATA = 'start16spl'
Simon Glass35b384c2018-09-14 04:57:10 -060044X86_START16_TPL_DATA = 'start16tpl'
Jagdish Gediya9d368f32018-09-03 21:35:08 +053045PPC_MPC85XX_BR_DATA = 'ppcmpc85xxbr'
Simon Glass6b187df2017-11-12 21:52:27 -070046U_BOOT_NODTB_DATA = 'nodtb with microcode pointer somewhere in here'
47U_BOOT_SPL_NODTB_DATA = 'splnodtb with microcode pointer somewhere in here'
Simon Glassf0253632018-09-14 04:57:32 -060048U_BOOT_TPL_NODTB_DATA = 'tplnodtb with microcode pointer somewhere in here'
Simon Glass6b187df2017-11-12 21:52:27 -070049FSP_DATA = 'fsp'
50CMC_DATA = 'cmc'
51VBT_DATA = 'vbt'
Simon Glassca4f4ff2017-11-12 21:52:28 -070052MRC_DATA = 'mrc'
Simon Glassbb748372018-07-17 13:25:33 -060053TEXT_DATA = 'text'
54TEXT_DATA2 = 'text2'
55TEXT_DATA3 = 'text3'
Simon Glassec127af2018-07-17 13:25:39 -060056CROS_EC_RW_DATA = 'ecrw'
Simon Glass0ef87aa2018-07-17 13:25:44 -060057GBB_DATA = 'gbbd'
58BMPBLK_DATA = 'bmp'
Simon Glass24d0d3c2018-07-17 13:25:47 -060059VBLOCK_DATA = 'vblk'
Simon Glass0a98b282018-09-14 04:57:28 -060060FILES_DATA = ("sorry I'm late\nOh, don't bother apologising, I'm " +
61 "sorry you're alive\n")
Simon Glass83d73c22018-09-14 04:57:26 -060062COMPRESS_DATA = 'data to compress'
Simon Glass3ae192c2018-10-01 12:22:31 -060063REFCODE_DATA = 'refcode'
Simon Glassec127af2018-07-17 13:25:39 -060064
Simon Glass4f443042016-11-25 20:15:52 -070065
66class 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):
Simon Glass4d5994f2017-11-12 21:52:20 -070082 global entry
83 import entry
84
Simon Glass4f443042016-11-25 20:15:52 -070085 # 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)
Simon Glassb8ef5b62018-07-17 13:25:48 -060096 TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
Simon Glass4f443042016-11-25 20:15:52 -070097 TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
Simon Glasse0ff8552016-11-25 20:15:53 -070098 TestFunctional._MakeInputFile('me.bin', ME_DATA)
99 TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
Simon Glassb8ef5b62018-07-17 13:25:48 -0600100 self._ResetDtbs()
Simon Glasse0ff8552016-11-25 20:15:53 -0700101 TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
Jagdish Gediya9d368f32018-09-03 21:35:08 +0530102 TestFunctional._MakeInputFile('u-boot-br.bin', PPC_MPC85XX_BR_DATA)
Simon Glass87722132017-11-12 21:52:26 -0700103 TestFunctional._MakeInputFile('spl/u-boot-x86-16bit-spl.bin',
104 X86_START16_SPL_DATA)
Simon Glass35b384c2018-09-14 04:57:10 -0600105 TestFunctional._MakeInputFile('tpl/u-boot-x86-16bit-tpl.bin',
106 X86_START16_TPL_DATA)
Simon Glass4f443042016-11-25 20:15:52 -0700107 TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
Simon Glass6b187df2017-11-12 21:52:27 -0700108 TestFunctional._MakeInputFile('spl/u-boot-spl-nodtb.bin',
109 U_BOOT_SPL_NODTB_DATA)
Simon Glassf0253632018-09-14 04:57:32 -0600110 TestFunctional._MakeInputFile('tpl/u-boot-tpl-nodtb.bin',
111 U_BOOT_TPL_NODTB_DATA)
Simon Glassda229092016-11-25 20:15:56 -0700112 TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
113 TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
Bin Meng59ea8c22017-08-15 22:41:54 -0700114 TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
Simon Glassca4f4ff2017-11-12 21:52:28 -0700115 TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
Simon Glassec127af2018-07-17 13:25:39 -0600116 TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
Simon Glass0ef87aa2018-07-17 13:25:44 -0600117 TestFunctional._MakeInputDir('devkeys')
118 TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
Simon Glass3ae192c2018-10-01 12:22:31 -0600119 TestFunctional._MakeInputFile('refcode.bin', REFCODE_DATA)
Simon Glass4f443042016-11-25 20:15:52 -0700120
Simon Glasse0ff8552016-11-25 20:15:53 -0700121 # 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
Simon Glass0a98b282018-09-14 04:57:28 -0600129 shutil.copytree(self.TestFile('files'),
130 os.path.join(self._indir, 'files'))
131
Simon Glass83d73c22018-09-14 04:57:26 -0600132 TestFunctional._MakeInputFile('compress', COMPRESS_DATA)
133
Simon Glass4f443042016-11-25 20:15:52 -0700134 @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
Simon Glassb8ef5b62018-07-17 13:25:48 -0600150 @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
Simon Glass4f443042016-11-25 20:15:52 -0700156 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 """
Simon Glass7fe91732017-11-13 18:55:00 -0700178 args = list(args)
179 if '-D' in sys.argv:
180 args = args + ['-D']
181 (options, args) = cmdline.ParseArgs(args)
Simon Glass4f443042016-11-25 20:15:52 -0700182 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
Simon Glass53af22a2018-07-17 13:25:32 -0600189 def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
Simon Glass93d17412018-09-14 04:57:23 -0600190 entry_args=None, images=None, use_real_dtb=False):
Simon Glass4f443042016-11-25 20:15:52 -0700191 """Run binman with a given test file
192
193 Args:
Simon Glass741f2d62018-10-01 12:22:30 -0600194 fname: Device-tree source filename to use (e.g. 005_simple.dts)
Simon Glass7ae5f312018-06-01 09:38:19 -0600195 debug: True to enable debugging output
Simon Glass3b0c3822018-06-01 09:38:20 -0600196 map: True to output map files for the images
Simon Glass3ab95982018-08-01 15:22:37 -0600197 update_dtb: Update the offset and size of each entry in the device
Simon Glass16b8d6b2018-07-06 10:27:42 -0600198 tree before packing it into the image
Simon Glass0bfa7b02018-09-14 04:57:12 -0600199 entry_args: Dict of entry args to supply to binman
200 key: arg name
201 value: value of that arg
202 images: List of image names to build
Simon Glass4f443042016-11-25 20:15:52 -0700203 """
Simon Glass7fe91732017-11-13 18:55:00 -0700204 args = ['-p', '-I', self._indir, '-d', self.TestFile(fname)]
205 if debug:
206 args.append('-D')
Simon Glass3b0c3822018-06-01 09:38:20 -0600207 if map:
208 args.append('-m')
Simon Glass16b8d6b2018-07-06 10:27:42 -0600209 if update_dtb:
210 args.append('-up')
Simon Glass93d17412018-09-14 04:57:23 -0600211 if not use_real_dtb:
212 args.append('--fake-dtb')
Simon Glass53af22a2018-07-17 13:25:32 -0600213 if entry_args:
214 for arg, value in entry_args.iteritems():
215 args.append('-a%s=%s' % (arg, value))
Simon Glass0bfa7b02018-09-14 04:57:12 -0600216 if images:
217 for image in images:
218 args += ['-i', image]
Simon Glass7fe91732017-11-13 18:55:00 -0700219 return self._DoBinman(*args)
Simon Glass4f443042016-11-25 20:15:52 -0700220
221 def _SetupDtb(self, fname, outfile='u-boot.dtb'):
Simon Glasse0ff8552016-11-25 20:15:53 -0700222 """Set up a new test device-tree file
223
224 The given file is compiled and set up as the device tree to be used
225 for ths test.
226
227 Args:
228 fname: Filename of .dts file to read
Simon Glass7ae5f312018-06-01 09:38:19 -0600229 outfile: Output filename for compiled device-tree binary
Simon Glasse0ff8552016-11-25 20:15:53 -0700230
231 Returns:
Simon Glass7ae5f312018-06-01 09:38:19 -0600232 Contents of device-tree binary
Simon Glasse0ff8552016-11-25 20:15:53 -0700233 """
Simon Glasse0e62752018-10-01 21:12:41 -0600234 tools.PrepareOutputDir(None)
Simon Glass4f443042016-11-25 20:15:52 -0700235 dtb = fdt_util.EnsureCompiled(self.TestFile(fname))
236 with open(dtb) as fd:
237 data = fd.read()
238 TestFunctional._MakeInputFile(outfile, data)
Simon Glasse0e62752018-10-01 21:12:41 -0600239 tools.FinaliseOutputDir()
240 return data
Simon Glass4f443042016-11-25 20:15:52 -0700241
Simon Glass6ed45ba2018-09-14 04:57:24 -0600242 def _GetDtbContentsForSplTpl(self, dtb_data, name):
243 """Create a version of the main DTB for SPL or SPL
244
245 For testing we don't actually have different versions of the DTB. With
246 U-Boot we normally run fdtgrep to remove unwanted nodes, but for tests
247 we don't normally have any unwanted nodes.
248
249 We still want the DTBs for SPL and TPL to be different though, since
250 otherwise it is confusing to know which one we are looking at. So add
251 an 'spl' or 'tpl' property to the top-level node.
252 """
253 dtb = fdt.Fdt.FromData(dtb_data)
254 dtb.Scan()
255 dtb.GetNode('/binman').AddZeroProp(name)
256 dtb.Sync(auto_resize=True)
257 dtb.Pack()
258 return dtb.GetContents()
259
Simon Glass16b8d6b2018-07-06 10:27:42 -0600260 def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
Simon Glass6ed45ba2018-09-14 04:57:24 -0600261 update_dtb=False, entry_args=None, reset_dtbs=True):
Simon Glass4f443042016-11-25 20:15:52 -0700262 """Run binman and return the resulting image
263
264 This runs binman with a given test file and then reads the resulting
265 output file. It is a shortcut function since most tests need to do
266 these steps.
267
268 Raises an assertion failure if binman returns a non-zero exit code.
269
270 Args:
Simon Glass741f2d62018-10-01 12:22:30 -0600271 fname: Device-tree source filename to use (e.g. 005_simple.dts)
Simon Glass4f443042016-11-25 20:15:52 -0700272 use_real_dtb: True to use the test file as the contents of
273 the u-boot-dtb entry. Normally this is not needed and the
274 test contents (the U_BOOT_DTB_DATA string) can be used.
275 But in some test we need the real contents.
Simon Glass3b0c3822018-06-01 09:38:20 -0600276 map: True to output map files for the images
Simon Glass3ab95982018-08-01 15:22:37 -0600277 update_dtb: Update the offset and size of each entry in the device
Simon Glass16b8d6b2018-07-06 10:27:42 -0600278 tree before packing it into the image
Simon Glasse0ff8552016-11-25 20:15:53 -0700279
280 Returns:
281 Tuple:
282 Resulting image contents
283 Device tree contents
Simon Glass3b0c3822018-06-01 09:38:20 -0600284 Map data showing contents of image (or None if none)
Simon Glassea6922e2018-07-17 13:25:27 -0600285 Output device tree binary filename ('u-boot.dtb' path)
Simon Glass4f443042016-11-25 20:15:52 -0700286 """
Simon Glasse0ff8552016-11-25 20:15:53 -0700287 dtb_data = None
Simon Glass4f443042016-11-25 20:15:52 -0700288 # Use the compiled test file as the u-boot-dtb input
289 if use_real_dtb:
Simon Glasse0ff8552016-11-25 20:15:53 -0700290 dtb_data = self._SetupDtb(fname)
Simon Glass6ed45ba2018-09-14 04:57:24 -0600291 infile = os.path.join(self._indir, 'u-boot.dtb')
292
293 # For testing purposes, make a copy of the DT for SPL and TPL. Add
294 # a node indicating which it is, so aid verification.
295 for name in ['spl', 'tpl']:
296 dtb_fname = '%s/u-boot-%s.dtb' % (name, name)
297 outfile = os.path.join(self._indir, dtb_fname)
298 TestFunctional._MakeInputFile(dtb_fname,
299 self._GetDtbContentsForSplTpl(dtb_data, name))
Simon Glass4f443042016-11-25 20:15:52 -0700300
301 try:
Simon Glass53af22a2018-07-17 13:25:32 -0600302 retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
Simon Glass6ed45ba2018-09-14 04:57:24 -0600303 entry_args=entry_args, use_real_dtb=use_real_dtb)
Simon Glass4f443042016-11-25 20:15:52 -0700304 self.assertEqual(0, retcode)
Simon Glass6ed45ba2018-09-14 04:57:24 -0600305 out_dtb_fname = tools.GetOutputFilename('u-boot.dtb.out')
Simon Glass4f443042016-11-25 20:15:52 -0700306
307 # Find the (only) image, read it and return its contents
308 image = control.images['image']
Simon Glass16b8d6b2018-07-06 10:27:42 -0600309 image_fname = tools.GetOutputFilename('image.bin')
310 self.assertTrue(os.path.exists(image_fname))
Simon Glass3b0c3822018-06-01 09:38:20 -0600311 if map:
312 map_fname = tools.GetOutputFilename('image.map')
313 with open(map_fname) as fd:
314 map_data = fd.read()
315 else:
316 map_data = None
Simon Glass16b8d6b2018-07-06 10:27:42 -0600317 with open(image_fname) as fd:
318 return fd.read(), dtb_data, map_data, out_dtb_fname
Simon Glass4f443042016-11-25 20:15:52 -0700319 finally:
320 # Put the test file back
Simon Glass6ed45ba2018-09-14 04:57:24 -0600321 if reset_dtbs and use_real_dtb:
Simon Glassb8ef5b62018-07-17 13:25:48 -0600322 self._ResetDtbs()
Simon Glass4f443042016-11-25 20:15:52 -0700323
Simon Glasse0ff8552016-11-25 20:15:53 -0700324 def _DoReadFile(self, fname, use_real_dtb=False):
Simon Glass7ae5f312018-06-01 09:38:19 -0600325 """Helper function which discards the device-tree binary
326
327 Args:
Simon Glass741f2d62018-10-01 12:22:30 -0600328 fname: Device-tree source filename to use (e.g. 005_simple.dts)
Simon Glass7ae5f312018-06-01 09:38:19 -0600329 use_real_dtb: True to use the test file as the contents of
330 the u-boot-dtb entry. Normally this is not needed and the
331 test contents (the U_BOOT_DTB_DATA string) can be used.
332 But in some test we need the real contents.
Simon Glassea6922e2018-07-17 13:25:27 -0600333
334 Returns:
335 Resulting image contents
Simon Glass7ae5f312018-06-01 09:38:19 -0600336 """
Simon Glasse0ff8552016-11-25 20:15:53 -0700337 return self._DoReadFileDtb(fname, use_real_dtb)[0]
338
Simon Glass4f443042016-11-25 20:15:52 -0700339 @classmethod
340 def _MakeInputFile(self, fname, contents):
341 """Create a new test input file, creating directories as needed
342
343 Args:
Simon Glass3ab95982018-08-01 15:22:37 -0600344 fname: Filename to create
Simon Glass4f443042016-11-25 20:15:52 -0700345 contents: File contents to write in to the file
346 Returns:
347 Full pathname of file created
348 """
349 pathname = os.path.join(self._indir, fname)
350 dirname = os.path.dirname(pathname)
351 if dirname and not os.path.exists(dirname):
352 os.makedirs(dirname)
353 with open(pathname, 'wb') as fd:
354 fd.write(contents)
355 return pathname
356
357 @classmethod
Simon Glass0ef87aa2018-07-17 13:25:44 -0600358 def _MakeInputDir(self, dirname):
359 """Create a new test input directory, creating directories as needed
360
361 Args:
362 dirname: Directory name to create
363
364 Returns:
365 Full pathname of directory created
366 """
367 pathname = os.path.join(self._indir, dirname)
368 if not os.path.exists(pathname):
369 os.makedirs(pathname)
370 return pathname
371
372 @classmethod
Simon Glass11ae93e2018-10-01 21:12:47 -0600373 def _SetupSplElf(self, src_fname='bss_data'):
374 """Set up an ELF file with a '_dt_ucode_base_size' symbol
375
376 Args:
377 Filename of ELF file to use as SPL
378 """
379 with open(self.TestFile(src_fname)) as fd:
380 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
381
382 @classmethod
Simon Glass4f443042016-11-25 20:15:52 -0700383 def TestFile(self, fname):
384 return os.path.join(self._binman_dir, 'test', fname)
385
386 def AssertInList(self, grep_list, target):
387 """Assert that at least one of a list of things is in a target
388
389 Args:
390 grep_list: List of strings to check
391 target: Target string
392 """
393 for grep in grep_list:
394 if grep in target:
395 return
396 self.fail("Error: '%' not found in '%s'" % (grep_list, target))
397
398 def CheckNoGaps(self, entries):
399 """Check that all entries fit together without gaps
400
401 Args:
402 entries: List of entries to check
403 """
Simon Glass3ab95982018-08-01 15:22:37 -0600404 offset = 0
Simon Glass4f443042016-11-25 20:15:52 -0700405 for entry in entries.values():
Simon Glass3ab95982018-08-01 15:22:37 -0600406 self.assertEqual(offset, entry.offset)
407 offset += entry.size
Simon Glass4f443042016-11-25 20:15:52 -0700408
Simon Glasse0ff8552016-11-25 20:15:53 -0700409 def GetFdtLen(self, dtb):
Simon Glass7ae5f312018-06-01 09:38:19 -0600410 """Get the totalsize field from a device-tree binary
Simon Glasse0ff8552016-11-25 20:15:53 -0700411
412 Args:
Simon Glass7ae5f312018-06-01 09:38:19 -0600413 dtb: Device-tree binary contents
Simon Glasse0ff8552016-11-25 20:15:53 -0700414
415 Returns:
Simon Glass7ae5f312018-06-01 09:38:19 -0600416 Total size of device-tree binary, from the header
Simon Glasse0ff8552016-11-25 20:15:53 -0700417 """
418 return struct.unpack('>L', dtb[4:8])[0]
419
Simon Glasscee02e62018-07-17 13:25:52 -0600420 def _GetPropTree(self, dtb, prop_names):
Simon Glass16b8d6b2018-07-06 10:27:42 -0600421 def AddNode(node, path):
422 if node.name != '/':
423 path += '/' + node.name
Simon Glass16b8d6b2018-07-06 10:27:42 -0600424 for subnode in node.subnodes:
425 for prop in subnode.props.values():
Simon Glasscee02e62018-07-17 13:25:52 -0600426 if prop.name in prop_names:
Simon Glass16b8d6b2018-07-06 10:27:42 -0600427 prop_path = path + '/' + subnode.name + ':' + prop.name
428 tree[prop_path[len('/binman/'):]] = fdt_util.fdt32_to_cpu(
429 prop.value)
Simon Glass16b8d6b2018-07-06 10:27:42 -0600430 AddNode(subnode, path)
431
432 tree = {}
Simon Glass16b8d6b2018-07-06 10:27:42 -0600433 AddNode(dtb.GetRoot(), '')
434 return tree
435
Simon Glass4f443042016-11-25 20:15:52 -0700436 def testRun(self):
437 """Test a basic run with valid args"""
438 result = self._RunBinman('-h')
439
440 def testFullHelp(self):
441 """Test that the full help is displayed with -H"""
442 result = self._RunBinman('-H')
443 help_file = os.path.join(self._binman_dir, 'README')
Tom Rini3759df02018-01-16 15:29:50 -0500444 # Remove possible extraneous strings
445 extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
446 gothelp = result.stdout.replace(extra, '')
447 self.assertEqual(len(gothelp), os.path.getsize(help_file))
Simon Glass4f443042016-11-25 20:15:52 -0700448 self.assertEqual(0, len(result.stderr))
449 self.assertEqual(0, result.return_code)
450
451 def testFullHelpInternal(self):
452 """Test that the full help is displayed with -H"""
453 try:
454 command.test_result = command.CommandResult()
455 result = self._DoBinman('-H')
456 help_file = os.path.join(self._binman_dir, 'README')
457 finally:
458 command.test_result = None
459
460 def testHelp(self):
461 """Test that the basic help is displayed with -h"""
462 result = self._RunBinman('-h')
463 self.assertTrue(len(result.stdout) > 200)
464 self.assertEqual(0, len(result.stderr))
465 self.assertEqual(0, result.return_code)
466
Simon Glass4f443042016-11-25 20:15:52 -0700467 def testBoard(self):
468 """Test that we can run it with a specific board"""
Simon Glass741f2d62018-10-01 12:22:30 -0600469 self._SetupDtb('005_simple.dts', 'sandbox/u-boot.dtb')
Simon Glass4f443042016-11-25 20:15:52 -0700470 TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
471 result = self._DoBinman('-b', 'sandbox')
472 self.assertEqual(0, result)
473
474 def testNeedBoard(self):
475 """Test that we get an error when no board ius supplied"""
476 with self.assertRaises(ValueError) as e:
477 result = self._DoBinman()
478 self.assertIn("Must provide a board to process (use -b <board>)",
479 str(e.exception))
480
481 def testMissingDt(self):
Simon Glass7ae5f312018-06-01 09:38:19 -0600482 """Test that an invalid device-tree file generates an error"""
Simon Glass4f443042016-11-25 20:15:52 -0700483 with self.assertRaises(Exception) as e:
484 self._RunBinman('-d', 'missing_file')
485 # We get one error from libfdt, and a different one from fdtget.
486 self.AssertInList(["Couldn't open blob from 'missing_file'",
487 'No such file or directory'], str(e.exception))
488
489 def testBrokenDt(self):
Simon Glass7ae5f312018-06-01 09:38:19 -0600490 """Test that an invalid device-tree source file generates an error
Simon Glass4f443042016-11-25 20:15:52 -0700491
492 Since this is a source file it should be compiled and the error
493 will come from the device-tree compiler (dtc).
494 """
495 with self.assertRaises(Exception) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600496 self._RunBinman('-d', self.TestFile('001_invalid.dts'))
Simon Glass4f443042016-11-25 20:15:52 -0700497 self.assertIn("FATAL ERROR: Unable to parse input tree",
498 str(e.exception))
499
500 def testMissingNode(self):
501 """Test that a device tree without a 'binman' node generates an error"""
502 with self.assertRaises(Exception) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600503 self._DoBinman('-d', self.TestFile('002_missing_node.dts'))
Simon Glass4f443042016-11-25 20:15:52 -0700504 self.assertIn("does not have a 'binman' node", str(e.exception))
505
506 def testEmpty(self):
507 """Test that an empty binman node works OK (i.e. does nothing)"""
Simon Glass741f2d62018-10-01 12:22:30 -0600508 result = self._RunBinman('-d', self.TestFile('003_empty.dts'))
Simon Glass4f443042016-11-25 20:15:52 -0700509 self.assertEqual(0, len(result.stderr))
510 self.assertEqual(0, result.return_code)
511
512 def testInvalidEntry(self):
513 """Test that an invalid entry is flagged"""
514 with self.assertRaises(Exception) as e:
515 result = self._RunBinman('-d',
Simon Glass741f2d62018-10-01 12:22:30 -0600516 self.TestFile('004_invalid_entry.dts'))
Simon Glass4f443042016-11-25 20:15:52 -0700517 self.assertIn("Unknown entry type 'not-a-valid-type' in node "
518 "'/binman/not-a-valid-type'", str(e.exception))
519
520 def testSimple(self):
521 """Test a simple binman with a single file"""
Simon Glass741f2d62018-10-01 12:22:30 -0600522 data = self._DoReadFile('005_simple.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700523 self.assertEqual(U_BOOT_DATA, data)
524
Simon Glass7fe91732017-11-13 18:55:00 -0700525 def testSimpleDebug(self):
526 """Test a simple binman run with debugging enabled"""
Simon Glass741f2d62018-10-01 12:22:30 -0600527 data = self._DoTestFile('005_simple.dts', debug=True)
Simon Glass7fe91732017-11-13 18:55:00 -0700528
Simon Glass4f443042016-11-25 20:15:52 -0700529 def testDual(self):
530 """Test that we can handle creating two images
531
532 This also tests image padding.
533 """
Simon Glass741f2d62018-10-01 12:22:30 -0600534 retcode = self._DoTestFile('006_dual_image.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700535 self.assertEqual(0, retcode)
536
537 image = control.images['image1']
538 self.assertEqual(len(U_BOOT_DATA), image._size)
539 fname = tools.GetOutputFilename('image1.bin')
540 self.assertTrue(os.path.exists(fname))
541 with open(fname) as fd:
542 data = fd.read()
543 self.assertEqual(U_BOOT_DATA, data)
544
545 image = control.images['image2']
546 self.assertEqual(3 + len(U_BOOT_DATA) + 5, image._size)
547 fname = tools.GetOutputFilename('image2.bin')
548 self.assertTrue(os.path.exists(fname))
549 with open(fname) as fd:
550 data = fd.read()
551 self.assertEqual(U_BOOT_DATA, data[3:7])
552 self.assertEqual(chr(0) * 3, data[:3])
553 self.assertEqual(chr(0) * 5, data[7:])
554
555 def testBadAlign(self):
556 """Test that an invalid alignment value is detected"""
557 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600558 self._DoTestFile('007_bad_align.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700559 self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
560 "of two", str(e.exception))
561
562 def testPackSimple(self):
563 """Test that packing works as expected"""
Simon Glass741f2d62018-10-01 12:22:30 -0600564 retcode = self._DoTestFile('008_pack.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700565 self.assertEqual(0, retcode)
566 self.assertIn('image', control.images)
567 image = control.images['image']
Simon Glass8f1da502018-06-01 09:38:12 -0600568 entries = image.GetEntries()
Simon Glass4f443042016-11-25 20:15:52 -0700569 self.assertEqual(5, len(entries))
570
571 # First u-boot
572 self.assertIn('u-boot', entries)
573 entry = entries['u-boot']
Simon Glass3ab95982018-08-01 15:22:37 -0600574 self.assertEqual(0, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700575 self.assertEqual(len(U_BOOT_DATA), entry.size)
576
577 # Second u-boot, aligned to 16-byte boundary
578 self.assertIn('u-boot-align', entries)
579 entry = entries['u-boot-align']
Simon Glass3ab95982018-08-01 15:22:37 -0600580 self.assertEqual(16, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700581 self.assertEqual(len(U_BOOT_DATA), entry.size)
582
583 # Third u-boot, size 23 bytes
584 self.assertIn('u-boot-size', entries)
585 entry = entries['u-boot-size']
Simon Glass3ab95982018-08-01 15:22:37 -0600586 self.assertEqual(20, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700587 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
588 self.assertEqual(23, entry.size)
589
590 # Fourth u-boot, placed immediate after the above
591 self.assertIn('u-boot-next', entries)
592 entry = entries['u-boot-next']
Simon Glass3ab95982018-08-01 15:22:37 -0600593 self.assertEqual(43, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700594 self.assertEqual(len(U_BOOT_DATA), entry.size)
595
Simon Glass3ab95982018-08-01 15:22:37 -0600596 # Fifth u-boot, placed at a fixed offset
Simon Glass4f443042016-11-25 20:15:52 -0700597 self.assertIn('u-boot-fixed', entries)
598 entry = entries['u-boot-fixed']
Simon Glass3ab95982018-08-01 15:22:37 -0600599 self.assertEqual(61, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700600 self.assertEqual(len(U_BOOT_DATA), entry.size)
601
602 self.assertEqual(65, image._size)
603
604 def testPackExtra(self):
605 """Test that extra packing feature works as expected"""
Simon Glass741f2d62018-10-01 12:22:30 -0600606 retcode = self._DoTestFile('009_pack_extra.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700607
608 self.assertEqual(0, retcode)
609 self.assertIn('image', control.images)
610 image = control.images['image']
Simon Glass8f1da502018-06-01 09:38:12 -0600611 entries = image.GetEntries()
Simon Glass4f443042016-11-25 20:15:52 -0700612 self.assertEqual(5, len(entries))
613
614 # First u-boot with padding before and after
615 self.assertIn('u-boot', entries)
616 entry = entries['u-boot']
Simon Glass3ab95982018-08-01 15:22:37 -0600617 self.assertEqual(0, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700618 self.assertEqual(3, entry.pad_before)
619 self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
620
621 # Second u-boot has an aligned size, but it has no effect
622 self.assertIn('u-boot-align-size-nop', entries)
623 entry = entries['u-boot-align-size-nop']
Simon Glass3ab95982018-08-01 15:22:37 -0600624 self.assertEqual(12, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700625 self.assertEqual(4, entry.size)
626
627 # Third u-boot has an aligned size too
628 self.assertIn('u-boot-align-size', entries)
629 entry = entries['u-boot-align-size']
Simon Glass3ab95982018-08-01 15:22:37 -0600630 self.assertEqual(16, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700631 self.assertEqual(32, entry.size)
632
633 # Fourth u-boot has an aligned end
634 self.assertIn('u-boot-align-end', entries)
635 entry = entries['u-boot-align-end']
Simon Glass3ab95982018-08-01 15:22:37 -0600636 self.assertEqual(48, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700637 self.assertEqual(16, entry.size)
638
639 # Fifth u-boot immediately afterwards
640 self.assertIn('u-boot-align-both', entries)
641 entry = entries['u-boot-align-both']
Simon Glass3ab95982018-08-01 15:22:37 -0600642 self.assertEqual(64, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700643 self.assertEqual(64, entry.size)
644
645 self.CheckNoGaps(entries)
646 self.assertEqual(128, image._size)
647
648 def testPackAlignPowerOf2(self):
649 """Test that invalid entry alignment is detected"""
650 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600651 self._DoTestFile('010_pack_align_power2.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700652 self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
653 "of two", str(e.exception))
654
655 def testPackAlignSizePowerOf2(self):
656 """Test that invalid entry size alignment is detected"""
657 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600658 self._DoTestFile('011_pack_align_size_power2.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700659 self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
660 "power of two", str(e.exception))
661
662 def testPackInvalidAlign(self):
Simon Glass3ab95982018-08-01 15:22:37 -0600663 """Test detection of an offset that does not match its alignment"""
Simon Glass4f443042016-11-25 20:15:52 -0700664 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600665 self._DoTestFile('012_pack_inv_align.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600666 self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
Simon Glass4f443042016-11-25 20:15:52 -0700667 "align 0x4 (4)", str(e.exception))
668
669 def testPackInvalidSizeAlign(self):
670 """Test that invalid entry size alignment is detected"""
671 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600672 self._DoTestFile('013_pack_inv_size_align.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700673 self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
674 "align-size 0x4 (4)", str(e.exception))
675
676 def testPackOverlap(self):
677 """Test that overlapping regions are detected"""
678 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600679 self._DoTestFile('014_pack_overlap.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600680 self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
Simon Glass4f443042016-11-25 20:15:52 -0700681 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
682 str(e.exception))
683
684 def testPackEntryOverflow(self):
685 """Test that entries that overflow their size are detected"""
686 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600687 self._DoTestFile('015_pack_overflow.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700688 self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
689 "but entry size is 0x3 (3)", str(e.exception))
690
691 def testPackImageOverflow(self):
692 """Test that entries which overflow the image size are detected"""
693 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600694 self._DoTestFile('016_pack_image_overflow.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600695 self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section "
Simon Glass4f443042016-11-25 20:15:52 -0700696 "size 0x3 (3)", str(e.exception))
697
698 def testPackImageSize(self):
699 """Test that the image size can be set"""
Simon Glass741f2d62018-10-01 12:22:30 -0600700 retcode = self._DoTestFile('017_pack_image_size.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700701 self.assertEqual(0, retcode)
702 self.assertIn('image', control.images)
703 image = control.images['image']
704 self.assertEqual(7, image._size)
705
706 def testPackImageSizeAlign(self):
707 """Test that image size alignemnt works as expected"""
Simon Glass741f2d62018-10-01 12:22:30 -0600708 retcode = self._DoTestFile('018_pack_image_align.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700709 self.assertEqual(0, retcode)
710 self.assertIn('image', control.images)
711 image = control.images['image']
712 self.assertEqual(16, image._size)
713
714 def testPackInvalidImageAlign(self):
715 """Test that invalid image alignment is detected"""
716 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600717 self._DoTestFile('019_pack_inv_image_align.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600718 self.assertIn("Section '/binman': Size 0x7 (7) does not match "
Simon Glass4f443042016-11-25 20:15:52 -0700719 "align-size 0x8 (8)", str(e.exception))
720
721 def testPackAlignPowerOf2(self):
722 """Test that invalid image alignment is detected"""
723 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600724 self._DoTestFile('020_pack_inv_image_align_power2.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600725 self.assertIn("Section '/binman': Alignment size 131 must be a power of "
Simon Glass4f443042016-11-25 20:15:52 -0700726 "two", str(e.exception))
727
728 def testImagePadByte(self):
729 """Test that the image pad byte can be specified"""
Simon Glass11ae93e2018-10-01 21:12:47 -0600730 self._SetupSplElf()
Simon Glass741f2d62018-10-01 12:22:30 -0600731 data = self._DoReadFile('021_image_pad.dts')
Simon Glassf6898902017-11-13 18:54:59 -0700732 self.assertEqual(U_BOOT_SPL_DATA + (chr(0xff) * 1) + U_BOOT_DATA, data)
Simon Glass4f443042016-11-25 20:15:52 -0700733
734 def testImageName(self):
735 """Test that image files can be named"""
Simon Glass741f2d62018-10-01 12:22:30 -0600736 retcode = self._DoTestFile('022_image_name.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700737 self.assertEqual(0, retcode)
738 image = control.images['image1']
739 fname = tools.GetOutputFilename('test-name')
740 self.assertTrue(os.path.exists(fname))
741
742 image = control.images['image2']
743 fname = tools.GetOutputFilename('test-name.xx')
744 self.assertTrue(os.path.exists(fname))
745
746 def testBlobFilename(self):
747 """Test that generic blobs can be provided by filename"""
Simon Glass741f2d62018-10-01 12:22:30 -0600748 data = self._DoReadFile('023_blob.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700749 self.assertEqual(BLOB_DATA, data)
750
751 def testPackSorted(self):
752 """Test that entries can be sorted"""
Simon Glass11ae93e2018-10-01 21:12:47 -0600753 self._SetupSplElf()
Simon Glass741f2d62018-10-01 12:22:30 -0600754 data = self._DoReadFile('024_sorted.dts')
Simon Glassf6898902017-11-13 18:54:59 -0700755 self.assertEqual(chr(0) * 1 + U_BOOT_SPL_DATA + chr(0) * 2 +
Simon Glass4f443042016-11-25 20:15:52 -0700756 U_BOOT_DATA, data)
757
Simon Glass3ab95982018-08-01 15:22:37 -0600758 def testPackZeroOffset(self):
759 """Test that an entry at offset 0 is not given a new offset"""
Simon Glass4f443042016-11-25 20:15:52 -0700760 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600761 self._DoTestFile('025_pack_zero_size.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600762 self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
Simon Glass4f443042016-11-25 20:15:52 -0700763 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
764 str(e.exception))
765
766 def testPackUbootDtb(self):
767 """Test that a device tree can be added to U-Boot"""
Simon Glass741f2d62018-10-01 12:22:30 -0600768 data = self._DoReadFile('026_pack_u_boot_dtb.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700769 self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
Simon Glasse0ff8552016-11-25 20:15:53 -0700770
771 def testPackX86RomNoSize(self):
772 """Test that the end-at-4gb property requires a size property"""
773 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600774 self._DoTestFile('027_pack_4gb_no_size.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600775 self.assertIn("Section '/binman': Section size must be provided when "
Simon Glasse0ff8552016-11-25 20:15:53 -0700776 "using end-at-4gb", str(e.exception))
777
Jagdish Gediya94b57db2018-09-03 21:35:07 +0530778 def test4gbAndSkipAtStartTogether(self):
779 """Test that the end-at-4gb and skip-at-size property can't be used
780 together"""
781 with self.assertRaises(ValueError) as e:
782 self._DoTestFile('80_4gb_and_skip_at_start_together.dts')
783 self.assertIn("Section '/binman': Provide either 'end-at-4gb' or "
784 "'skip-at-start'", str(e.exception))
785
Simon Glasse0ff8552016-11-25 20:15:53 -0700786 def testPackX86RomOutside(self):
Simon Glass3ab95982018-08-01 15:22:37 -0600787 """Test that the end-at-4gb property checks for offset boundaries"""
Simon Glasse0ff8552016-11-25 20:15:53 -0700788 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600789 self._DoTestFile('028_pack_4gb_outside.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600790 self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
Simon Glass8f1da502018-06-01 09:38:12 -0600791 "the section starting at 0xffffffe0 (4294967264)",
Simon Glasse0ff8552016-11-25 20:15:53 -0700792 str(e.exception))
793
794 def testPackX86Rom(self):
795 """Test that a basic x86 ROM can be created"""
Simon Glass11ae93e2018-10-01 21:12:47 -0600796 self._SetupSplElf()
Simon Glass741f2d62018-10-01 12:22:30 -0600797 data = self._DoReadFile('029_x86-rom.dts')
Simon Glassf6898902017-11-13 18:54:59 -0700798 self.assertEqual(U_BOOT_DATA + chr(0) * 7 + U_BOOT_SPL_DATA +
799 chr(0) * 2, data)
Simon Glasse0ff8552016-11-25 20:15:53 -0700800
801 def testPackX86RomMeNoDesc(self):
802 """Test that an invalid Intel descriptor entry is detected"""
803 TestFunctional._MakeInputFile('descriptor.bin', '')
804 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600805 self._DoTestFile('031_x86-rom-me.dts')
Simon Glasse0ff8552016-11-25 20:15:53 -0700806 self.assertIn("Node '/binman/intel-descriptor': Cannot find FD "
807 "signature", str(e.exception))
808
809 def testPackX86RomBadDesc(self):
810 """Test that the Intel requires a descriptor entry"""
811 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600812 self._DoTestFile('030_x86-rom-me-no-desc.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600813 self.assertIn("Node '/binman/intel-me': No offset set with "
814 "offset-unset: should another entry provide this correct "
815 "offset?", str(e.exception))
Simon Glasse0ff8552016-11-25 20:15:53 -0700816
817 def testPackX86RomMe(self):
818 """Test that an x86 ROM with an ME region can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -0600819 data = self._DoReadFile('031_x86-rom-me.dts')
Simon Glasse0ff8552016-11-25 20:15:53 -0700820 self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
821
822 def testPackVga(self):
823 """Test that an image with a VGA binary can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -0600824 data = self._DoReadFile('032_intel-vga.dts')
Simon Glasse0ff8552016-11-25 20:15:53 -0700825 self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
826
827 def testPackStart16(self):
828 """Test that an image with an x86 start16 region can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -0600829 data = self._DoReadFile('033_x86-start16.dts')
Simon Glasse0ff8552016-11-25 20:15:53 -0700830 self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
831
Jagdish Gediya9d368f32018-09-03 21:35:08 +0530832 def testPackPowerpcMpc85xxBootpgResetvec(self):
833 """Test that an image with powerpc-mpc85xx-bootpg-resetvec can be
834 created"""
835 data = self._DoReadFile('81_powerpc_mpc85xx_bootpg_resetvec.dts')
836 self.assertEqual(PPC_MPC85XX_BR_DATA, data[:len(PPC_MPC85XX_BR_DATA)])
837
Simon Glass736bb0a2018-07-06 10:27:17 -0600838 def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False):
Simon Glassadc57012018-07-06 10:27:16 -0600839 """Handle running a test for insertion of microcode
840
841 Args:
842 dts_fname: Name of test .dts file
843 nodtb_data: Data that we expect in the first section
Simon Glass736bb0a2018-07-06 10:27:17 -0600844 ucode_second: True if the microsecond entry is second instead of
845 third
Simon Glassadc57012018-07-06 10:27:16 -0600846
847 Returns:
848 Tuple:
849 Contents of first region (U-Boot or SPL)
Simon Glass3ab95982018-08-01 15:22:37 -0600850 Offset and size components of microcode pointer, as inserted
Simon Glassadc57012018-07-06 10:27:16 -0600851 in the above (two 4-byte words)
852 """
Simon Glass6b187df2017-11-12 21:52:27 -0700853 data = self._DoReadFile(dts_fname, True)
Simon Glasse0ff8552016-11-25 20:15:53 -0700854
855 # Now check the device tree has no microcode
Simon Glass736bb0a2018-07-06 10:27:17 -0600856 if ucode_second:
857 ucode_content = data[len(nodtb_data):]
858 ucode_pos = len(nodtb_data)
859 dtb_with_ucode = ucode_content[16:]
860 fdt_len = self.GetFdtLen(dtb_with_ucode)
861 else:
862 dtb_with_ucode = data[len(nodtb_data):]
863 fdt_len = self.GetFdtLen(dtb_with_ucode)
864 ucode_content = dtb_with_ucode[fdt_len:]
865 ucode_pos = len(nodtb_data) + fdt_len
Simon Glasse0ff8552016-11-25 20:15:53 -0700866 fname = tools.GetOutputFilename('test.dtb')
867 with open(fname, 'wb') as fd:
Simon Glassadc57012018-07-06 10:27:16 -0600868 fd.write(dtb_with_ucode)
Simon Glassec3f3782017-05-27 07:38:29 -0600869 dtb = fdt.FdtScan(fname)
870 ucode = dtb.GetNode('/microcode')
Simon Glasse0ff8552016-11-25 20:15:53 -0700871 self.assertTrue(ucode)
872 for node in ucode.subnodes:
873 self.assertFalse(node.props.get('data'))
874
Simon Glasse0ff8552016-11-25 20:15:53 -0700875 # Check that the microcode appears immediately after the Fdt
876 # This matches the concatenation of the data properties in
Simon Glass87722132017-11-12 21:52:26 -0700877 # the /microcode/update@xxx nodes in 34_x86_ucode.dts.
Simon Glasse0ff8552016-11-25 20:15:53 -0700878 ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
879 0x78235609)
Simon Glassadc57012018-07-06 10:27:16 -0600880 self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
Simon Glasse0ff8552016-11-25 20:15:53 -0700881
882 # Check that the microcode pointer was inserted. It should match the
Simon Glass3ab95982018-08-01 15:22:37 -0600883 # expected offset and size
Simon Glasse0ff8552016-11-25 20:15:53 -0700884 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
885 len(ucode_data))
Simon Glass736bb0a2018-07-06 10:27:17 -0600886 u_boot = data[:len(nodtb_data)]
887 return u_boot, pos_and_size
Simon Glass6b187df2017-11-12 21:52:27 -0700888
889 def testPackUbootMicrocode(self):
890 """Test that x86 microcode can be handled correctly
891
892 We expect to see the following in the image, in order:
893 u-boot-nodtb.bin with a microcode pointer inserted at the correct
894 place
895 u-boot.dtb with the microcode removed
896 the microcode
897 """
Simon Glass741f2d62018-10-01 12:22:30 -0600898 first, pos_and_size = self._RunMicrocodeTest('034_x86_ucode.dts',
Simon Glass6b187df2017-11-12 21:52:27 -0700899 U_BOOT_NODTB_DATA)
Simon Glasse0ff8552016-11-25 20:15:53 -0700900 self.assertEqual('nodtb with microcode' + pos_and_size +
901 ' somewhere in here', first)
902
Simon Glass160a7662017-05-27 07:38:26 -0600903 def _RunPackUbootSingleMicrocode(self):
Simon Glasse0ff8552016-11-25 20:15:53 -0700904 """Test that x86 microcode can be handled correctly
905
906 We expect to see the following in the image, in order:
907 u-boot-nodtb.bin with a microcode pointer inserted at the correct
908 place
909 u-boot.dtb with the microcode
910 an empty microcode region
911 """
912 # We need the libfdt library to run this test since only that allows
913 # finding the offset of a property. This is required by
914 # Entry_u_boot_dtb_with_ucode.ObtainContents().
Simon Glass741f2d62018-10-01 12:22:30 -0600915 data = self._DoReadFile('035_x86_single_ucode.dts', True)
Simon Glasse0ff8552016-11-25 20:15:53 -0700916
917 second = data[len(U_BOOT_NODTB_DATA):]
918
919 fdt_len = self.GetFdtLen(second)
920 third = second[fdt_len:]
921 second = second[:fdt_len]
922
Simon Glass160a7662017-05-27 07:38:26 -0600923 ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
924 self.assertIn(ucode_data, second)
925 ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
Simon Glasse0ff8552016-11-25 20:15:53 -0700926
Simon Glass160a7662017-05-27 07:38:26 -0600927 # Check that the microcode pointer was inserted. It should match the
Simon Glass3ab95982018-08-01 15:22:37 -0600928 # expected offset and size
Simon Glass160a7662017-05-27 07:38:26 -0600929 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
930 len(ucode_data))
931 first = data[:len(U_BOOT_NODTB_DATA)]
932 self.assertEqual('nodtb with microcode' + pos_and_size +
933 ' somewhere in here', first)
Simon Glassc49deb82016-11-25 20:15:54 -0700934
Simon Glass75db0862016-11-25 20:15:55 -0700935 def testPackUbootSingleMicrocode(self):
936 """Test that x86 microcode can be handled correctly with fdt_normal.
937 """
Simon Glass160a7662017-05-27 07:38:26 -0600938 self._RunPackUbootSingleMicrocode()
Simon Glass75db0862016-11-25 20:15:55 -0700939
Simon Glassc49deb82016-11-25 20:15:54 -0700940 def testUBootImg(self):
941 """Test that u-boot.img can be put in a file"""
Simon Glass741f2d62018-10-01 12:22:30 -0600942 data = self._DoReadFile('036_u_boot_img.dts')
Simon Glassc49deb82016-11-25 20:15:54 -0700943 self.assertEqual(U_BOOT_IMG_DATA, data)
Simon Glass75db0862016-11-25 20:15:55 -0700944
945 def testNoMicrocode(self):
946 """Test that a missing microcode region is detected"""
947 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600948 self._DoReadFile('037_x86_no_ucode.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -0700949 self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
950 "node found in ", str(e.exception))
951
952 def testMicrocodeWithoutNode(self):
953 """Test that a missing u-boot-dtb-with-ucode node is detected"""
954 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600955 self._DoReadFile('038_x86_ucode_missing_node.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -0700956 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
957 "microcode region u-boot-dtb-with-ucode", str(e.exception))
958
959 def testMicrocodeWithoutNode2(self):
960 """Test that a missing u-boot-ucode node is detected"""
961 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600962 self._DoReadFile('039_x86_ucode_missing_node2.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -0700963 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
964 "microcode region u-boot-ucode", str(e.exception))
965
966 def testMicrocodeWithoutPtrInElf(self):
967 """Test that a U-Boot binary without the microcode symbol is detected"""
968 # ELF file without a '_dt_ucode_base_size' symbol
Simon Glass75db0862016-11-25 20:15:55 -0700969 try:
970 with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
971 TestFunctional._MakeInputFile('u-boot', fd.read())
972
973 with self.assertRaises(ValueError) as e:
Simon Glass160a7662017-05-27 07:38:26 -0600974 self._RunPackUbootSingleMicrocode()
Simon Glass75db0862016-11-25 20:15:55 -0700975 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
976 "_dt_ucode_base_size symbol in u-boot", str(e.exception))
977
978 finally:
979 # Put the original file back
980 with open(self.TestFile('u_boot_ucode_ptr')) as fd:
981 TestFunctional._MakeInputFile('u-boot', fd.read())
982
983 def testMicrocodeNotInImage(self):
984 """Test that microcode must be placed within the image"""
985 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600986 self._DoReadFile('040_x86_ucode_not_in_image.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -0700987 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
988 "pointer _dt_ucode_base_size at fffffe14 is outside the "
Simon Glass25ac0e62018-06-01 09:38:14 -0600989 "section ranging from 00000000 to 0000002e", str(e.exception))
Simon Glass75db0862016-11-25 20:15:55 -0700990
991 def testWithoutMicrocode(self):
992 """Test that we can cope with an image without microcode (e.g. qemu)"""
993 with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
994 TestFunctional._MakeInputFile('u-boot', fd.read())
Simon Glass741f2d62018-10-01 12:22:30 -0600995 data, dtb, _, _ = self._DoReadFileDtb('044_x86_optional_ucode.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -0700996
997 # Now check the device tree has no microcode
998 self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
999 second = data[len(U_BOOT_NODTB_DATA):]
1000
1001 fdt_len = self.GetFdtLen(second)
1002 self.assertEqual(dtb, second[:fdt_len])
1003
1004 used_len = len(U_BOOT_NODTB_DATA) + fdt_len
1005 third = data[used_len:]
1006 self.assertEqual(chr(0) * (0x200 - used_len), third)
1007
1008 def testUnknownPosSize(self):
1009 """Test that microcode must be placed within the image"""
1010 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001011 self._DoReadFile('041_unknown_pos_size.dts', True)
Simon Glass3ab95982018-08-01 15:22:37 -06001012 self.assertIn("Section '/binman': Unable to set offset/size for unknown "
Simon Glass75db0862016-11-25 20:15:55 -07001013 "entry 'invalid-entry'", str(e.exception))
Simon Glassda229092016-11-25 20:15:56 -07001014
1015 def testPackFsp(self):
1016 """Test that an image with a FSP binary can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001017 data = self._DoReadFile('042_intel-fsp.dts')
Simon Glassda229092016-11-25 20:15:56 -07001018 self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
1019
1020 def testPackCmc(self):
Bin Meng59ea8c22017-08-15 22:41:54 -07001021 """Test that an image with a CMC binary can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001022 data = self._DoReadFile('043_intel-cmc.dts')
Simon Glassda229092016-11-25 20:15:56 -07001023 self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
Bin Meng59ea8c22017-08-15 22:41:54 -07001024
1025 def testPackVbt(self):
1026 """Test that an image with a VBT binary can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001027 data = self._DoReadFile('046_intel-vbt.dts')
Bin Meng59ea8c22017-08-15 22:41:54 -07001028 self.assertEqual(VBT_DATA, data[:len(VBT_DATA)])
Simon Glass9fc60b42017-11-12 21:52:22 -07001029
Simon Glass56509842017-11-12 21:52:25 -07001030 def testSplBssPad(self):
1031 """Test that we can pad SPL's BSS with zeros"""
Simon Glass6b187df2017-11-12 21:52:27 -07001032 # ELF file with a '__bss_size' symbol
Simon Glass11ae93e2018-10-01 21:12:47 -06001033 self._SetupSplElf()
Simon Glass741f2d62018-10-01 12:22:30 -06001034 data = self._DoReadFile('047_spl_bss_pad.dts')
Simon Glass56509842017-11-12 21:52:25 -07001035 self.assertEqual(U_BOOT_SPL_DATA + (chr(0) * 10) + U_BOOT_DATA, data)
1036
Simon Glass86af5112018-10-01 21:12:42 -06001037 def testSplBssPadMissing(self):
1038 """Test that a missing symbol is detected"""
Simon Glass11ae93e2018-10-01 21:12:47 -06001039 self._SetupSplElf('u_boot_ucode_ptr')
Simon Glassb50e5612017-11-13 18:54:54 -07001040 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001041 self._DoReadFile('047_spl_bss_pad.dts')
Simon Glassb50e5612017-11-13 18:54:54 -07001042 self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
1043 str(e.exception))
1044
Simon Glass87722132017-11-12 21:52:26 -07001045 def testPackStart16Spl(self):
Simon Glass35b384c2018-09-14 04:57:10 -06001046 """Test that an image with an x86 start16 SPL region can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001047 data = self._DoReadFile('048_x86-start16-spl.dts')
Simon Glass87722132017-11-12 21:52:26 -07001048 self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)])
1049
Simon Glass736bb0a2018-07-06 10:27:17 -06001050 def _PackUbootSplMicrocode(self, dts, ucode_second=False):
1051 """Helper function for microcode tests
Simon Glass6b187df2017-11-12 21:52:27 -07001052
1053 We expect to see the following in the image, in order:
1054 u-boot-spl-nodtb.bin with a microcode pointer inserted at the
1055 correct place
1056 u-boot.dtb with the microcode removed
1057 the microcode
Simon Glass736bb0a2018-07-06 10:27:17 -06001058
1059 Args:
1060 dts: Device tree file to use for test
1061 ucode_second: True if the microsecond entry is second instead of
1062 third
Simon Glass6b187df2017-11-12 21:52:27 -07001063 """
Simon Glass11ae93e2018-10-01 21:12:47 -06001064 self._SetupSplElf('u_boot_ucode_ptr')
Simon Glass736bb0a2018-07-06 10:27:17 -06001065 first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA,
1066 ucode_second=ucode_second)
Simon Glass6b187df2017-11-12 21:52:27 -07001067 self.assertEqual('splnodtb with microc' + pos_and_size +
1068 'ter somewhere in here', first)
1069
Simon Glass736bb0a2018-07-06 10:27:17 -06001070 def testPackUbootSplMicrocode(self):
1071 """Test that x86 microcode can be handled correctly in SPL"""
Simon Glass741f2d62018-10-01 12:22:30 -06001072 self._PackUbootSplMicrocode('049_x86_ucode_spl.dts')
Simon Glass736bb0a2018-07-06 10:27:17 -06001073
1074 def testPackUbootSplMicrocodeReorder(self):
1075 """Test that order doesn't matter for microcode entries
1076
1077 This is the same as testPackUbootSplMicrocode but when we process the
1078 u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode
1079 entry, so we reply on binman to try later.
1080 """
Simon Glass741f2d62018-10-01 12:22:30 -06001081 self._PackUbootSplMicrocode('058_x86_ucode_spl_needs_retry.dts',
Simon Glass736bb0a2018-07-06 10:27:17 -06001082 ucode_second=True)
1083
Simon Glassca4f4ff2017-11-12 21:52:28 -07001084 def testPackMrc(self):
1085 """Test that an image with an MRC binary can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001086 data = self._DoReadFile('050_intel_mrc.dts')
Simon Glassca4f4ff2017-11-12 21:52:28 -07001087 self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
1088
Simon Glass47419ea2017-11-13 18:54:55 -07001089 def testSplDtb(self):
1090 """Test that an image with spl/u-boot-spl.dtb can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001091 data = self._DoReadFile('051_u_boot_spl_dtb.dts')
Simon Glass47419ea2017-11-13 18:54:55 -07001092 self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
1093
Simon Glass4e6fdbe2017-11-13 18:54:56 -07001094 def testSplNoDtb(self):
1095 """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001096 data = self._DoReadFile('052_u_boot_spl_nodtb.dts')
Simon Glass4e6fdbe2017-11-13 18:54:56 -07001097 self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
1098
Simon Glass19790632017-11-13 18:55:01 -07001099 def testSymbols(self):
1100 """Test binman can assign symbols embedded in U-Boot"""
1101 elf_fname = self.TestFile('u_boot_binman_syms')
1102 syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
1103 addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
Simon Glass3ab95982018-08-01 15:22:37 -06001104 self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
Simon Glass19790632017-11-13 18:55:01 -07001105
Simon Glass11ae93e2018-10-01 21:12:47 -06001106 self._SetupSplElf('u_boot_binman_syms')
Simon Glass741f2d62018-10-01 12:22:30 -06001107 data = self._DoReadFile('053_symbols.dts')
Simon Glass19790632017-11-13 18:55:01 -07001108 sym_values = struct.pack('<LQL', 0x24 + 0, 0x24 + 24, 0x24 + 20)
1109 expected = (sym_values + U_BOOT_SPL_DATA[16:] + chr(0xff) +
1110 U_BOOT_DATA +
1111 sym_values + U_BOOT_SPL_DATA[16:])
1112 self.assertEqual(expected, data)
1113
Simon Glassdd57c132018-06-01 09:38:11 -06001114 def testPackUnitAddress(self):
1115 """Test that we support multiple binaries with the same name"""
Simon Glass741f2d62018-10-01 12:22:30 -06001116 data = self._DoReadFile('054_unit_address.dts')
Simon Glassdd57c132018-06-01 09:38:11 -06001117 self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
1118
Simon Glass18546952018-06-01 09:38:16 -06001119 def testSections(self):
1120 """Basic test of sections"""
Simon Glass741f2d62018-10-01 12:22:30 -06001121 data = self._DoReadFile('055_sections.dts')
Simon Glass8122f392018-07-17 13:25:28 -06001122 expected = (U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12 +
1123 U_BOOT_DATA + '&' * 4)
Simon Glass18546952018-06-01 09:38:16 -06001124 self.assertEqual(expected, data)
Simon Glass9fc60b42017-11-12 21:52:22 -07001125
Simon Glass3b0c3822018-06-01 09:38:20 -06001126 def testMap(self):
1127 """Tests outputting a map of the images"""
Simon Glass741f2d62018-10-01 12:22:30 -06001128 _, _, map_data, _ = self._DoReadFileDtb('055_sections.dts', map=True)
Simon Glass1be70d22018-07-17 13:25:49 -06001129 self.assertEqual('''ImagePos Offset Size Name
113000000000 00000000 00000028 main-section
113100000000 00000000 00000010 section@0
113200000000 00000000 00000004 u-boot
113300000010 00000010 00000010 section@1
113400000010 00000000 00000004 u-boot
113500000020 00000020 00000004 section@2
113600000020 00000000 00000004 u-boot
Simon Glass3b0c3822018-06-01 09:38:20 -06001137''', map_data)
1138
Simon Glassc8d48ef2018-06-01 09:38:21 -06001139 def testNamePrefix(self):
1140 """Tests that name prefixes are used"""
Simon Glass741f2d62018-10-01 12:22:30 -06001141 _, _, map_data, _ = self._DoReadFileDtb('056_name_prefix.dts', map=True)
Simon Glass1be70d22018-07-17 13:25:49 -06001142 self.assertEqual('''ImagePos Offset Size Name
114300000000 00000000 00000028 main-section
114400000000 00000000 00000010 section@0
114500000000 00000000 00000004 ro-u-boot
114600000010 00000010 00000010 section@1
114700000010 00000000 00000004 rw-u-boot
Simon Glassc8d48ef2018-06-01 09:38:21 -06001148''', map_data)
1149
Simon Glass736bb0a2018-07-06 10:27:17 -06001150 def testUnknownContents(self):
1151 """Test that obtaining the contents works as expected"""
1152 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001153 self._DoReadFile('057_unknown_contents.dts', True)
Simon Glass736bb0a2018-07-06 10:27:17 -06001154 self.assertIn("Section '/binman': Internal error: Could not complete "
1155 "processing of contents: remaining [<_testing.Entry__testing ",
1156 str(e.exception))
1157
Simon Glass5c890232018-07-06 10:27:19 -06001158 def testBadChangeSize(self):
1159 """Test that trying to change the size of an entry fails"""
1160 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001161 self._DoReadFile('059_change_size.dts', True)
Simon Glass5c890232018-07-06 10:27:19 -06001162 self.assertIn("Node '/binman/_testing': Cannot update entry size from "
1163 '2 to 1', str(e.exception))
1164
Simon Glass16b8d6b2018-07-06 10:27:42 -06001165 def testUpdateFdt(self):
Simon Glass3ab95982018-08-01 15:22:37 -06001166 """Test that we can update the device tree with offset/size info"""
Simon Glass741f2d62018-10-01 12:22:30 -06001167 _, _, _, out_dtb_fname = self._DoReadFileDtb('060_fdt_update.dts',
Simon Glass16b8d6b2018-07-06 10:27:42 -06001168 update_dtb=True)
Simon Glasscee02e62018-07-17 13:25:52 -06001169 dtb = fdt.Fdt(out_dtb_fname)
1170 dtb.Scan()
1171 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'])
Simon Glass16b8d6b2018-07-06 10:27:42 -06001172 self.assertEqual({
Simon Glassdbf6be92018-08-01 15:22:42 -06001173 'image-pos': 0,
Simon Glass8122f392018-07-17 13:25:28 -06001174 'offset': 0,
Simon Glass3ab95982018-08-01 15:22:37 -06001175 '_testing:offset': 32,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001176 '_testing:size': 1,
Simon Glassdbf6be92018-08-01 15:22:42 -06001177 '_testing:image-pos': 32,
Simon Glass3ab95982018-08-01 15:22:37 -06001178 'section@0/u-boot:offset': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001179 'section@0/u-boot:size': len(U_BOOT_DATA),
Simon Glassdbf6be92018-08-01 15:22:42 -06001180 'section@0/u-boot:image-pos': 0,
Simon Glass3ab95982018-08-01 15:22:37 -06001181 'section@0:offset': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001182 'section@0:size': 16,
Simon Glassdbf6be92018-08-01 15:22:42 -06001183 'section@0:image-pos': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001184
Simon Glass3ab95982018-08-01 15:22:37 -06001185 'section@1/u-boot:offset': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001186 'section@1/u-boot:size': len(U_BOOT_DATA),
Simon Glassdbf6be92018-08-01 15:22:42 -06001187 'section@1/u-boot:image-pos': 16,
Simon Glass3ab95982018-08-01 15:22:37 -06001188 'section@1:offset': 16,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001189 'section@1:size': 16,
Simon Glassdbf6be92018-08-01 15:22:42 -06001190 'section@1:image-pos': 16,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001191 'size': 40
1192 }, props)
1193
1194 def testUpdateFdtBad(self):
1195 """Test that we detect when ProcessFdt never completes"""
1196 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001197 self._DoReadFileDtb('061_fdt_update_bad.dts', update_dtb=True)
Simon Glass16b8d6b2018-07-06 10:27:42 -06001198 self.assertIn('Could not complete processing of Fdt: remaining '
1199 '[<_testing.Entry__testing', str(e.exception))
Simon Glass5c890232018-07-06 10:27:19 -06001200
Simon Glass53af22a2018-07-17 13:25:32 -06001201 def testEntryArgs(self):
1202 """Test passing arguments to entries from the command line"""
1203 entry_args = {
1204 'test-str-arg': 'test1',
1205 'test-int-arg': '456',
1206 }
Simon Glass741f2d62018-10-01 12:22:30 -06001207 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
Simon Glass53af22a2018-07-17 13:25:32 -06001208 self.assertIn('image', control.images)
1209 entry = control.images['image'].GetEntries()['_testing']
1210 self.assertEqual('test0', entry.test_str_fdt)
1211 self.assertEqual('test1', entry.test_str_arg)
1212 self.assertEqual(123, entry.test_int_fdt)
1213 self.assertEqual(456, entry.test_int_arg)
1214
1215 def testEntryArgsMissing(self):
1216 """Test missing arguments and properties"""
1217 entry_args = {
1218 'test-int-arg': '456',
1219 }
Simon Glass741f2d62018-10-01 12:22:30 -06001220 self._DoReadFileDtb('063_entry_args_missing.dts', entry_args=entry_args)
Simon Glass53af22a2018-07-17 13:25:32 -06001221 entry = control.images['image'].GetEntries()['_testing']
1222 self.assertEqual('test0', entry.test_str_fdt)
1223 self.assertEqual(None, entry.test_str_arg)
1224 self.assertEqual(None, entry.test_int_fdt)
1225 self.assertEqual(456, entry.test_int_arg)
1226
1227 def testEntryArgsRequired(self):
1228 """Test missing arguments and properties"""
1229 entry_args = {
1230 'test-int-arg': '456',
1231 }
1232 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001233 self._DoReadFileDtb('064_entry_args_required.dts')
Simon Glass53af22a2018-07-17 13:25:32 -06001234 self.assertIn("Node '/binman/_testing': Missing required "
1235 'properties/entry args: test-str-arg, test-int-fdt, test-int-arg',
1236 str(e.exception))
1237
1238 def testEntryArgsInvalidFormat(self):
1239 """Test that an invalid entry-argument format is detected"""
Simon Glass741f2d62018-10-01 12:22:30 -06001240 args = ['-d', self.TestFile('064_entry_args_required.dts'), '-ano-value']
Simon Glass53af22a2018-07-17 13:25:32 -06001241 with self.assertRaises(ValueError) as e:
1242 self._DoBinman(*args)
1243 self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
1244
1245 def testEntryArgsInvalidInteger(self):
1246 """Test that an invalid entry-argument integer is detected"""
1247 entry_args = {
1248 'test-int-arg': 'abc',
1249 }
1250 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001251 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
Simon Glass53af22a2018-07-17 13:25:32 -06001252 self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
1253 "'test-int-arg' (value 'abc') to integer",
1254 str(e.exception))
1255
1256 def testEntryArgsInvalidDatatype(self):
1257 """Test that an invalid entry-argument datatype is detected
1258
1259 This test could be written in entry_test.py except that it needs
1260 access to control.entry_args, which seems more than that module should
1261 be able to see.
1262 """
1263 entry_args = {
1264 'test-bad-datatype-arg': '12',
1265 }
1266 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001267 self._DoReadFileDtb('065_entry_args_unknown_datatype.dts',
Simon Glass53af22a2018-07-17 13:25:32 -06001268 entry_args=entry_args)
1269 self.assertIn('GetArg() internal error: Unknown data type ',
1270 str(e.exception))
1271
Simon Glassbb748372018-07-17 13:25:33 -06001272 def testText(self):
1273 """Test for a text entry type"""
1274 entry_args = {
1275 'test-id': TEXT_DATA,
1276 'test-id2': TEXT_DATA2,
1277 'test-id3': TEXT_DATA3,
1278 }
Simon Glass741f2d62018-10-01 12:22:30 -06001279 data, _, _, _ = self._DoReadFileDtb('066_text.dts',
Simon Glassbb748372018-07-17 13:25:33 -06001280 entry_args=entry_args)
1281 expected = (TEXT_DATA + chr(0) * (8 - len(TEXT_DATA)) + TEXT_DATA2 +
1282 TEXT_DATA3 + 'some text')
1283 self.assertEqual(expected, data)
1284
Simon Glassfd8d1f72018-07-17 13:25:36 -06001285 def testEntryDocs(self):
1286 """Test for creation of entry documentation"""
1287 with test_util.capture_sys_output() as (stdout, stderr):
1288 control.WriteEntryDocs(binman.GetEntryModules())
1289 self.assertTrue(len(stdout.getvalue()) > 0)
1290
1291 def testEntryDocsMissing(self):
1292 """Test handling of missing entry documentation"""
1293 with self.assertRaises(ValueError) as e:
1294 with test_util.capture_sys_output() as (stdout, stderr):
1295 control.WriteEntryDocs(binman.GetEntryModules(), 'u_boot')
1296 self.assertIn('Documentation is missing for modules: u_boot',
1297 str(e.exception))
1298
Simon Glass11e36cc2018-07-17 13:25:38 -06001299 def testFmap(self):
1300 """Basic test of generation of a flashrom fmap"""
Simon Glass741f2d62018-10-01 12:22:30 -06001301 data = self._DoReadFile('067_fmap.dts')
Simon Glass11e36cc2018-07-17 13:25:38 -06001302 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1303 expected = U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12
1304 self.assertEqual(expected, data[:32])
1305 self.assertEqual('__FMAP__', fhdr.signature)
1306 self.assertEqual(1, fhdr.ver_major)
1307 self.assertEqual(0, fhdr.ver_minor)
1308 self.assertEqual(0, fhdr.base)
1309 self.assertEqual(16 + 16 +
1310 fmap_util.FMAP_HEADER_LEN +
1311 fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
1312 self.assertEqual('FMAP', fhdr.name)
1313 self.assertEqual(3, fhdr.nareas)
1314 for fentry in fentries:
1315 self.assertEqual(0, fentry.flags)
1316
1317 self.assertEqual(0, fentries[0].offset)
1318 self.assertEqual(4, fentries[0].size)
1319 self.assertEqual('RO_U_BOOT', fentries[0].name)
1320
1321 self.assertEqual(16, fentries[1].offset)
1322 self.assertEqual(4, fentries[1].size)
1323 self.assertEqual('RW_U_BOOT', fentries[1].name)
1324
1325 self.assertEqual(32, fentries[2].offset)
1326 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1327 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1328 self.assertEqual('FMAP', fentries[2].name)
1329
Simon Glassec127af2018-07-17 13:25:39 -06001330 def testBlobNamedByArg(self):
1331 """Test we can add a blob with the filename coming from an entry arg"""
1332 entry_args = {
1333 'cros-ec-rw-path': 'ecrw.bin',
1334 }
Simon Glass741f2d62018-10-01 12:22:30 -06001335 data, _, _, _ = self._DoReadFileDtb('068_blob_named_by_arg.dts',
Simon Glassec127af2018-07-17 13:25:39 -06001336 entry_args=entry_args)
1337
Simon Glass3af8e492018-07-17 13:25:40 -06001338 def testFill(self):
1339 """Test for an fill entry type"""
Simon Glass741f2d62018-10-01 12:22:30 -06001340 data = self._DoReadFile('069_fill.dts')
Simon Glass3af8e492018-07-17 13:25:40 -06001341 expected = 8 * chr(0xff) + 8 * chr(0)
1342 self.assertEqual(expected, data)
1343
1344 def testFillNoSize(self):
1345 """Test for an fill entry type with no size"""
1346 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001347 self._DoReadFile('070_fill_no_size.dts')
Simon Glass3af8e492018-07-17 13:25:40 -06001348 self.assertIn("'fill' entry must have a size property",
1349 str(e.exception))
1350
Simon Glass0ef87aa2018-07-17 13:25:44 -06001351 def _HandleGbbCommand(self, pipe_list):
1352 """Fake calls to the futility utility"""
1353 if pipe_list[0][0] == 'futility':
1354 fname = pipe_list[0][-1]
1355 # Append our GBB data to the file, which will happen every time the
1356 # futility command is called.
1357 with open(fname, 'a') as fd:
1358 fd.write(GBB_DATA)
1359 return command.CommandResult()
1360
1361 def testGbb(self):
1362 """Test for the Chromium OS Google Binary Block"""
1363 command.test_result = self._HandleGbbCommand
1364 entry_args = {
1365 'keydir': 'devkeys',
1366 'bmpblk': 'bmpblk.bin',
1367 }
Simon Glass741f2d62018-10-01 12:22:30 -06001368 data, _, _, _ = self._DoReadFileDtb('071_gbb.dts', entry_args=entry_args)
Simon Glass0ef87aa2018-07-17 13:25:44 -06001369
1370 # Since futility
1371 expected = GBB_DATA + GBB_DATA + 8 * chr(0) + (0x2180 - 16) * chr(0)
1372 self.assertEqual(expected, data)
1373
1374 def testGbbTooSmall(self):
1375 """Test for the Chromium OS Google Binary Block being large enough"""
1376 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001377 self._DoReadFileDtb('072_gbb_too_small.dts')
Simon Glass0ef87aa2018-07-17 13:25:44 -06001378 self.assertIn("Node '/binman/gbb': GBB is too small",
1379 str(e.exception))
1380
1381 def testGbbNoSize(self):
1382 """Test for the Chromium OS Google Binary Block having a size"""
1383 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001384 self._DoReadFileDtb('073_gbb_no_size.dts')
Simon Glass0ef87aa2018-07-17 13:25:44 -06001385 self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
1386 str(e.exception))
1387
Simon Glass24d0d3c2018-07-17 13:25:47 -06001388 def _HandleVblockCommand(self, pipe_list):
1389 """Fake calls to the futility utility"""
1390 if pipe_list[0][0] == 'futility':
1391 fname = pipe_list[0][3]
Simon Glassa326b492018-09-14 04:57:11 -06001392 with open(fname, 'wb') as fd:
Simon Glass24d0d3c2018-07-17 13:25:47 -06001393 fd.write(VBLOCK_DATA)
1394 return command.CommandResult()
1395
1396 def testVblock(self):
1397 """Test for the Chromium OS Verified Boot Block"""
1398 command.test_result = self._HandleVblockCommand
1399 entry_args = {
1400 'keydir': 'devkeys',
1401 }
Simon Glass741f2d62018-10-01 12:22:30 -06001402 data, _, _, _ = self._DoReadFileDtb('074_vblock.dts',
Simon Glass24d0d3c2018-07-17 13:25:47 -06001403 entry_args=entry_args)
1404 expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
1405 self.assertEqual(expected, data)
1406
1407 def testVblockNoContent(self):
1408 """Test we detect a vblock which has no content to sign"""
1409 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001410 self._DoReadFile('075_vblock_no_content.dts')
Simon Glass24d0d3c2018-07-17 13:25:47 -06001411 self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
1412 'property', str(e.exception))
1413
1414 def testVblockBadPhandle(self):
1415 """Test that we detect a vblock with an invalid phandle in contents"""
1416 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001417 self._DoReadFile('076_vblock_bad_phandle.dts')
Simon Glass24d0d3c2018-07-17 13:25:47 -06001418 self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
1419 '1000', str(e.exception))
1420
1421 def testVblockBadEntry(self):
1422 """Test that we detect an entry that points to a non-entry"""
1423 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001424 self._DoReadFile('077_vblock_bad_entry.dts')
Simon Glass24d0d3c2018-07-17 13:25:47 -06001425 self.assertIn("Node '/binman/vblock': Cannot find entry for node "
1426 "'other'", str(e.exception))
1427
Simon Glassb8ef5b62018-07-17 13:25:48 -06001428 def testTpl(self):
1429 """Test that an image with TPL and ots device tree can be created"""
1430 # ELF file with a '__bss_size' symbol
1431 with open(self.TestFile('bss_data')) as fd:
1432 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
Simon Glass741f2d62018-10-01 12:22:30 -06001433 data = self._DoReadFile('078_u_boot_tpl.dts')
Simon Glassb8ef5b62018-07-17 13:25:48 -06001434 self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
1435
Simon Glass15a587c2018-07-17 13:25:51 -06001436 def testUsesPos(self):
1437 """Test that the 'pos' property cannot be used anymore"""
1438 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001439 data = self._DoReadFile('079_uses_pos.dts')
Simon Glass15a587c2018-07-17 13:25:51 -06001440 self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
1441 "'pos'", str(e.exception))
1442
Simon Glassd178eab2018-09-14 04:57:08 -06001443 def testFillZero(self):
1444 """Test for an fill entry type with a size of 0"""
Simon Glass741f2d62018-10-01 12:22:30 -06001445 data = self._DoReadFile('080_fill_empty.dts')
Simon Glassd178eab2018-09-14 04:57:08 -06001446 self.assertEqual(chr(0) * 16, data)
1447
Simon Glass0b489362018-09-14 04:57:09 -06001448 def testTextMissing(self):
1449 """Test for a text entry type where there is no text"""
1450 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001451 self._DoReadFileDtb('066_text.dts',)
Simon Glass0b489362018-09-14 04:57:09 -06001452 self.assertIn("Node '/binman/text': No value provided for text label "
1453 "'test-id'", str(e.exception))
1454
Simon Glass35b384c2018-09-14 04:57:10 -06001455 def testPackStart16Tpl(self):
1456 """Test that an image with an x86 start16 TPL region can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001457 data = self._DoReadFile('081_x86-start16-tpl.dts')
Simon Glass35b384c2018-09-14 04:57:10 -06001458 self.assertEqual(X86_START16_TPL_DATA, data[:len(X86_START16_TPL_DATA)])
1459
Simon Glass0bfa7b02018-09-14 04:57:12 -06001460 def testSelectImage(self):
1461 """Test that we can select which images to build"""
1462 with test_util.capture_sys_output() as (stdout, stderr):
Simon Glass741f2d62018-10-01 12:22:30 -06001463 retcode = self._DoTestFile('006_dual_image.dts', images=['image2'])
Simon Glass0bfa7b02018-09-14 04:57:12 -06001464 self.assertEqual(0, retcode)
1465 self.assertIn('Skipping images: image1', stdout.getvalue())
1466
1467 self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
1468 self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
1469
Simon Glass6ed45ba2018-09-14 04:57:24 -06001470 def testUpdateFdtAll(self):
1471 """Test that all device trees are updated with offset/size info"""
Simon Glass741f2d62018-10-01 12:22:30 -06001472 data, _, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
Simon Glass6ed45ba2018-09-14 04:57:24 -06001473 use_real_dtb=True, update_dtb=True)
1474
1475 base_expected = {
1476 'section:image-pos': 0,
1477 'u-boot-tpl-dtb:size': 513,
1478 'u-boot-spl-dtb:size': 513,
1479 'u-boot-spl-dtb:offset': 493,
1480 'image-pos': 0,
1481 'section/u-boot-dtb:image-pos': 0,
1482 'u-boot-spl-dtb:image-pos': 493,
1483 'section/u-boot-dtb:size': 493,
1484 'u-boot-tpl-dtb:image-pos': 1006,
1485 'section/u-boot-dtb:offset': 0,
1486 'section:size': 493,
1487 'offset': 0,
1488 'section:offset': 0,
1489 'u-boot-tpl-dtb:offset': 1006,
1490 'size': 1519
1491 }
1492
1493 # We expect three device-tree files in the output, one after the other.
1494 # Read them in sequence. We look for an 'spl' property in the SPL tree,
1495 # and 'tpl' in the TPL tree, to make sure they are distinct from the
1496 # main U-Boot tree. All three should have the same postions and offset.
1497 start = 0
1498 for item in ['', 'spl', 'tpl']:
1499 dtb = fdt.Fdt.FromData(data[start:])
1500 dtb.Scan()
1501 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos',
1502 'spl', 'tpl'])
1503 expected = dict(base_expected)
1504 if item:
1505 expected[item] = 0
1506 self.assertEqual(expected, props)
1507 start += dtb._fdt_obj.totalsize()
1508
1509 def testUpdateFdtOutput(self):
1510 """Test that output DTB files are updated"""
1511 try:
Simon Glass741f2d62018-10-01 12:22:30 -06001512 data, dtb_data, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
Simon Glass6ed45ba2018-09-14 04:57:24 -06001513 use_real_dtb=True, update_dtb=True, reset_dtbs=False)
1514
1515 # Unfortunately, compiling a source file always results in a file
1516 # called source.dtb (see fdt_util.EnsureCompiled()). The test
Simon Glass741f2d62018-10-01 12:22:30 -06001517 # source file (e.g. test/075_fdt_update_all.dts) thus does not enter
Simon Glass6ed45ba2018-09-14 04:57:24 -06001518 # binman as a file called u-boot.dtb. To fix this, copy the file
1519 # over to the expected place.
1520 #tools.WriteFile(os.path.join(self._indir, 'u-boot.dtb'),
1521 #tools.ReadFile(tools.GetOutputFilename('source.dtb')))
1522 start = 0
1523 for fname in ['u-boot.dtb.out', 'spl/u-boot-spl.dtb.out',
1524 'tpl/u-boot-tpl.dtb.out']:
1525 dtb = fdt.Fdt.FromData(data[start:])
1526 size = dtb._fdt_obj.totalsize()
1527 pathname = tools.GetOutputFilename(os.path.split(fname)[1])
1528 outdata = tools.ReadFile(pathname)
1529 name = os.path.split(fname)[0]
1530
1531 if name:
1532 orig_indata = self._GetDtbContentsForSplTpl(dtb_data, name)
1533 else:
1534 orig_indata = dtb_data
1535 self.assertNotEqual(outdata, orig_indata,
1536 "Expected output file '%s' be updated" % pathname)
1537 self.assertEqual(outdata, data[start:start + size],
1538 "Expected output file '%s' to match output image" %
1539 pathname)
1540 start += size
1541 finally:
1542 self._ResetDtbs()
1543
Simon Glass83d73c22018-09-14 04:57:26 -06001544 def _decompress(self, data):
1545 out = os.path.join(self._indir, 'lz4.tmp')
1546 with open(out, 'wb') as fd:
1547 fd.write(data)
1548 return tools.Run('lz4', '-dc', out)
1549 '''
1550 try:
1551 orig = lz4.frame.decompress(data)
1552 except AttributeError:
1553 orig = lz4.decompress(data)
1554 '''
1555
1556 def testCompress(self):
1557 """Test compression of blobs"""
Simon Glass741f2d62018-10-01 12:22:30 -06001558 data, _, _, out_dtb_fname = self._DoReadFileDtb('083_compress.dts',
Simon Glass83d73c22018-09-14 04:57:26 -06001559 use_real_dtb=True, update_dtb=True)
1560 dtb = fdt.Fdt(out_dtb_fname)
1561 dtb.Scan()
1562 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
1563 orig = self._decompress(data)
1564 self.assertEquals(COMPRESS_DATA, orig)
1565 expected = {
1566 'blob:uncomp-size': len(COMPRESS_DATA),
1567 'blob:size': len(data),
1568 'size': len(data),
1569 }
1570 self.assertEqual(expected, props)
1571
Simon Glass0a98b282018-09-14 04:57:28 -06001572 def testFiles(self):
1573 """Test bringing in multiple files"""
Simon Glass741f2d62018-10-01 12:22:30 -06001574 data = self._DoReadFile('084_files.dts')
Simon Glass0a98b282018-09-14 04:57:28 -06001575 self.assertEqual(FILES_DATA, data)
1576
1577 def testFilesCompress(self):
1578 """Test bringing in multiple files and compressing them"""
Simon Glass741f2d62018-10-01 12:22:30 -06001579 data = self._DoReadFile('085_files_compress.dts')
Simon Glass0a98b282018-09-14 04:57:28 -06001580
1581 image = control.images['image']
1582 entries = image.GetEntries()
1583 files = entries['files']
1584 entries = files._section._entries
1585
1586 orig = ''
1587 for i in range(1, 3):
1588 key = '%d.dat' % i
1589 start = entries[key].image_pos
1590 len = entries[key].size
1591 chunk = data[start:start + len]
1592 orig += self._decompress(chunk)
1593
1594 self.assertEqual(FILES_DATA, orig)
1595
1596 def testFilesMissing(self):
1597 """Test missing files"""
1598 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001599 data = self._DoReadFile('086_files_none.dts')
Simon Glass0a98b282018-09-14 04:57:28 -06001600 self.assertIn("Node '/binman/files': Pattern \'files/*.none\' matched "
1601 'no files', str(e.exception))
1602
1603 def testFilesNoPattern(self):
1604 """Test missing files"""
1605 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001606 data = self._DoReadFile('087_files_no_pattern.dts')
Simon Glass0a98b282018-09-14 04:57:28 -06001607 self.assertIn("Node '/binman/files': Missing 'pattern' property",
1608 str(e.exception))
1609
Simon Glassba64a0b2018-09-14 04:57:29 -06001610 def testExpandSize(self):
1611 """Test an expanding entry"""
Simon Glass741f2d62018-10-01 12:22:30 -06001612 data, _, map_data, _ = self._DoReadFileDtb('088_expand_size.dts',
Simon Glassba64a0b2018-09-14 04:57:29 -06001613 map=True)
1614 expect = ('a' * 8 + U_BOOT_DATA +
1615 MRC_DATA + 'b' * 1 + U_BOOT_DATA +
1616 'c' * 8 + U_BOOT_DATA +
1617 'd' * 8)
1618 self.assertEqual(expect, data)
1619 self.assertEqual('''ImagePos Offset Size Name
162000000000 00000000 00000028 main-section
162100000000 00000000 00000008 fill
162200000008 00000008 00000004 u-boot
16230000000c 0000000c 00000004 section
16240000000c 00000000 00000003 intel-mrc
162500000010 00000010 00000004 u-boot2
162600000014 00000014 0000000c section2
162700000014 00000000 00000008 fill
16280000001c 00000008 00000004 u-boot
162900000020 00000020 00000008 fill2
1630''', map_data)
1631
1632 def testExpandSizeBad(self):
1633 """Test an expanding entry which fails to provide contents"""
Simon Glass163ed6c2018-09-14 04:57:36 -06001634 with test_util.capture_sys_output() as (stdout, stderr):
1635 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001636 self._DoReadFileDtb('089_expand_size_bad.dts', map=True)
Simon Glassba64a0b2018-09-14 04:57:29 -06001637 self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
1638 'expanding entry', str(e.exception))
1639
Simon Glasse0e5df92018-09-14 04:57:31 -06001640 def testHash(self):
1641 """Test hashing of the contents of an entry"""
Simon Glass741f2d62018-10-01 12:22:30 -06001642 _, _, _, out_dtb_fname = self._DoReadFileDtb('090_hash.dts',
Simon Glasse0e5df92018-09-14 04:57:31 -06001643 use_real_dtb=True, update_dtb=True)
1644 dtb = fdt.Fdt(out_dtb_fname)
1645 dtb.Scan()
1646 hash_node = dtb.GetNode('/binman/u-boot/hash').props['value']
1647 m = hashlib.sha256()
1648 m.update(U_BOOT_DATA)
1649 self.assertEqual(m.digest(), ''.join(hash_node.value))
1650
1651 def testHashNoAlgo(self):
1652 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001653 self._DoReadFileDtb('091_hash_no_algo.dts', update_dtb=True)
Simon Glasse0e5df92018-09-14 04:57:31 -06001654 self.assertIn("Node \'/binman/u-boot\': Missing \'algo\' property for "
1655 'hash node', str(e.exception))
1656
1657 def testHashBadAlgo(self):
1658 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001659 self._DoReadFileDtb('092_hash_bad_algo.dts', update_dtb=True)
Simon Glasse0e5df92018-09-14 04:57:31 -06001660 self.assertIn("Node '/binman/u-boot': Unknown hash algorithm",
1661 str(e.exception))
1662
1663 def testHashSection(self):
1664 """Test hashing of the contents of an entry"""
Simon Glass741f2d62018-10-01 12:22:30 -06001665 _, _, _, out_dtb_fname = self._DoReadFileDtb('099_hash_section.dts',
Simon Glasse0e5df92018-09-14 04:57:31 -06001666 use_real_dtb=True, update_dtb=True)
1667 dtb = fdt.Fdt(out_dtb_fname)
1668 dtb.Scan()
1669 hash_node = dtb.GetNode('/binman/section/hash').props['value']
1670 m = hashlib.sha256()
1671 m.update(U_BOOT_DATA)
1672 m.update(16 * 'a')
1673 self.assertEqual(m.digest(), ''.join(hash_node.value))
1674
Simon Glassf0253632018-09-14 04:57:32 -06001675 def testPackUBootTplMicrocode(self):
1676 """Test that x86 microcode can be handled correctly in TPL
1677
1678 We expect to see the following in the image, in order:
1679 u-boot-tpl-nodtb.bin with a microcode pointer inserted at the correct
1680 place
1681 u-boot-tpl.dtb with the microcode removed
1682 the microcode
1683 """
1684 with open(self.TestFile('u_boot_ucode_ptr')) as fd:
1685 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
Simon Glass741f2d62018-10-01 12:22:30 -06001686 first, pos_and_size = self._RunMicrocodeTest('093_x86_tpl_ucode.dts',
Simon Glassf0253632018-09-14 04:57:32 -06001687 U_BOOT_TPL_NODTB_DATA)
1688 self.assertEqual('tplnodtb with microc' + pos_and_size +
1689 'ter somewhere in here', first)
1690
Simon Glassf8f8df62018-09-14 04:57:34 -06001691 def testFmapX86(self):
1692 """Basic test of generation of a flashrom fmap"""
Simon Glass741f2d62018-10-01 12:22:30 -06001693 data = self._DoReadFile('094_fmap_x86.dts')
Simon Glassf8f8df62018-09-14 04:57:34 -06001694 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1695 expected = U_BOOT_DATA + MRC_DATA + 'a' * (32 - 7)
1696 self.assertEqual(expected, data[:32])
1697 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1698
1699 self.assertEqual(0x100, fhdr.image_size)
1700
1701 self.assertEqual(0, fentries[0].offset)
1702 self.assertEqual(4, fentries[0].size)
1703 self.assertEqual('U_BOOT', fentries[0].name)
1704
1705 self.assertEqual(4, fentries[1].offset)
1706 self.assertEqual(3, fentries[1].size)
1707 self.assertEqual('INTEL_MRC', fentries[1].name)
1708
1709 self.assertEqual(32, fentries[2].offset)
1710 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1711 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1712 self.assertEqual('FMAP', fentries[2].name)
1713
1714 def testFmapX86Section(self):
1715 """Basic test of generation of a flashrom fmap"""
Simon Glass741f2d62018-10-01 12:22:30 -06001716 data = self._DoReadFile('095_fmap_x86_section.dts')
Simon Glassf8f8df62018-09-14 04:57:34 -06001717 expected = U_BOOT_DATA + MRC_DATA + 'b' * (32 - 7)
1718 self.assertEqual(expected, data[:32])
1719 fhdr, fentries = fmap_util.DecodeFmap(data[36:])
1720
1721 self.assertEqual(0x100, fhdr.image_size)
1722
1723 self.assertEqual(0, fentries[0].offset)
1724 self.assertEqual(4, fentries[0].size)
1725 self.assertEqual('U_BOOT', fentries[0].name)
1726
1727 self.assertEqual(4, fentries[1].offset)
1728 self.assertEqual(3, fentries[1].size)
1729 self.assertEqual('INTEL_MRC', fentries[1].name)
1730
1731 self.assertEqual(36, fentries[2].offset)
1732 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1733 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1734 self.assertEqual('FMAP', fentries[2].name)
1735
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001736 def testElf(self):
1737 """Basic test of ELF entries"""
Simon Glass11ae93e2018-10-01 21:12:47 -06001738 self._SetupSplElf()
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001739 with open(self.TestFile('bss_data')) as fd:
1740 TestFunctional._MakeInputFile('-boot', fd.read())
Simon Glass741f2d62018-10-01 12:22:30 -06001741 data = self._DoReadFile('096_elf.dts')
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001742
1743 def testElfStripg(self):
1744 """Basic test of ELF entries"""
Simon Glass11ae93e2018-10-01 21:12:47 -06001745 self._SetupSplElf()
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001746 with open(self.TestFile('bss_data')) as fd:
1747 TestFunctional._MakeInputFile('-boot', fd.read())
Simon Glass741f2d62018-10-01 12:22:30 -06001748 data = self._DoReadFile('097_elf_strip.dts')
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001749
Simon Glass163ed6c2018-09-14 04:57:36 -06001750 def testPackOverlapMap(self):
1751 """Test that overlapping regions are detected"""
1752 with test_util.capture_sys_output() as (stdout, stderr):
1753 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001754 self._DoTestFile('014_pack_overlap.dts', map=True)
Simon Glass163ed6c2018-09-14 04:57:36 -06001755 map_fname = tools.GetOutputFilename('image.map')
1756 self.assertEqual("Wrote map file '%s' to show errors\n" % map_fname,
1757 stdout.getvalue())
1758
1759 # We should not get an inmage, but there should be a map file
1760 self.assertFalse(os.path.exists(tools.GetOutputFilename('image.bin')))
1761 self.assertTrue(os.path.exists(map_fname))
1762 map_data = tools.ReadFile(map_fname)
1763 self.assertEqual('''ImagePos Offset Size Name
1764<none> 00000000 00000007 main-section
1765<none> 00000000 00000004 u-boot
1766<none> 00000003 00000004 u-boot-align
1767''', map_data)
1768
Simon Glass3ae192c2018-10-01 12:22:31 -06001769 def testPacRefCode(self):
1770 """Test that an image with an Intel Reference code binary works"""
1771 data = self._DoReadFile('100_intel_refcode.dts')
1772 self.assertEqual(REFCODE_DATA, data[:len(REFCODE_DATA)])
1773
Simon Glass53af22a2018-07-17 13:25:32 -06001774
Simon Glass9fc60b42017-11-12 21:52:22 -07001775if __name__ == "__main__":
1776 unittest.main()