blob: 6fdecb2f3bff810416419e4a53c35f338c9e2348 [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 Glassd5164a72019-07-08 13:18:49 -06009from __future__ import print_function
10
Simon Glasse0e5df92018-09-14 04:57:31 -060011import hashlib
Simon Glass4f443042016-11-25 20:15:52 -070012from optparse import OptionParser
13import os
14import shutil
15import struct
16import sys
17import tempfile
18import unittest
19
20import binman
Simon Glassac62fba2019-07-08 13:18:53 -060021import cbfs_util
Simon Glass4f443042016-11-25 20:15:52 -070022import cmdline
23import command
24import control
Simon Glass19790632017-11-13 18:55:01 -070025import elf
Simon Glass99ed4a22017-05-27 07:38:30 -060026import fdt
Simon Glass4f443042016-11-25 20:15:52 -070027import fdt_util
Simon Glass11e36cc2018-07-17 13:25:38 -060028import fmap_util
Simon Glassfd8d1f72018-07-17 13:25:36 -060029import test_util
Simon Glassc5ac1382019-07-08 13:18:54 -060030import gzip
Simon Glassc55a50f2018-09-14 04:57:19 -060031import state
Simon Glass4f443042016-11-25 20:15:52 -070032import tools
33import tout
34
35# Contents of test files, corresponding to different entry types
Simon Glassc6c10e72019-05-17 22:00:46 -060036U_BOOT_DATA = b'1234'
37U_BOOT_IMG_DATA = b'img'
38U_BOOT_SPL_DATA = b'56780123456789abcde'
39U_BOOT_TPL_DATA = b'tpl'
40BLOB_DATA = b'89'
41ME_DATA = b'0abcd'
42VGA_DATA = b'vga'
43U_BOOT_DTB_DATA = b'udtb'
44U_BOOT_SPL_DTB_DATA = b'spldtb'
45U_BOOT_TPL_DTB_DATA = b'tpldtb'
46X86_START16_DATA = b'start16'
47X86_START16_SPL_DATA = b'start16spl'
48X86_START16_TPL_DATA = b'start16tpl'
49PPC_MPC85XX_BR_DATA = b'ppcmpc85xxbr'
50U_BOOT_NODTB_DATA = b'nodtb with microcode pointer somewhere in here'
51U_BOOT_SPL_NODTB_DATA = b'splnodtb with microcode pointer somewhere in here'
52U_BOOT_TPL_NODTB_DATA = b'tplnodtb with microcode pointer somewhere in here'
53FSP_DATA = b'fsp'
54CMC_DATA = b'cmc'
55VBT_DATA = b'vbt'
56MRC_DATA = b'mrc'
Simon Glassbb748372018-07-17 13:25:33 -060057TEXT_DATA = 'text'
58TEXT_DATA2 = 'text2'
59TEXT_DATA3 = 'text3'
Simon Glassc6c10e72019-05-17 22:00:46 -060060CROS_EC_RW_DATA = b'ecrw'
61GBB_DATA = b'gbbd'
62BMPBLK_DATA = b'bmp'
63VBLOCK_DATA = b'vblk'
64FILES_DATA = (b"sorry I'm late\nOh, don't bother apologising, I'm " +
65 b"sorry you're alive\n")
Simon Glassff5c7e32019-07-08 13:18:42 -060066COMPRESS_DATA = b'compress xxxxxxxxxxxxxxxxxxxxxx data'
Simon Glassc6c10e72019-05-17 22:00:46 -060067REFCODE_DATA = b'refcode'
Simon Glassec127af2018-07-17 13:25:39 -060068
Simon Glass4f443042016-11-25 20:15:52 -070069
70class TestFunctional(unittest.TestCase):
71 """Functional tests for binman
72
73 Most of these use a sample .dts file to build an image and then check
74 that it looks correct. The sample files are in the test/ subdirectory
75 and are numbered.
76
77 For each entry type a very small test file is created using fixed
78 string contents. This makes it easy to test that things look right, and
79 debug problems.
80
81 In some cases a 'real' file must be used - these are also supplied in
82 the test/ diurectory.
83 """
84 @classmethod
85 def setUpClass(self):
Simon Glass4d5994f2017-11-12 21:52:20 -070086 global entry
87 import entry
88
Simon Glass4f443042016-11-25 20:15:52 -070089 # Handle the case where argv[0] is 'python'
90 self._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
91 self._binman_pathname = os.path.join(self._binman_dir, 'binman')
92
93 # Create a temporary directory for input files
94 self._indir = tempfile.mkdtemp(prefix='binmant.')
95
96 # Create some test files
97 TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
98 TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
99 TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
Simon Glassb8ef5b62018-07-17 13:25:48 -0600100 TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
Simon Glass4f443042016-11-25 20:15:52 -0700101 TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
Simon Glasse0ff8552016-11-25 20:15:53 -0700102 TestFunctional._MakeInputFile('me.bin', ME_DATA)
103 TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
Simon Glassb8ef5b62018-07-17 13:25:48 -0600104 self._ResetDtbs()
Simon Glasse0ff8552016-11-25 20:15:53 -0700105 TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
Jagdish Gediya9d368f32018-09-03 21:35:08 +0530106 TestFunctional._MakeInputFile('u-boot-br.bin', PPC_MPC85XX_BR_DATA)
Simon Glass87722132017-11-12 21:52:26 -0700107 TestFunctional._MakeInputFile('spl/u-boot-x86-16bit-spl.bin',
108 X86_START16_SPL_DATA)
Simon Glass35b384c2018-09-14 04:57:10 -0600109 TestFunctional._MakeInputFile('tpl/u-boot-x86-16bit-tpl.bin',
110 X86_START16_TPL_DATA)
Simon Glass4f443042016-11-25 20:15:52 -0700111 TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
Simon Glass6b187df2017-11-12 21:52:27 -0700112 TestFunctional._MakeInputFile('spl/u-boot-spl-nodtb.bin',
113 U_BOOT_SPL_NODTB_DATA)
Simon Glassf0253632018-09-14 04:57:32 -0600114 TestFunctional._MakeInputFile('tpl/u-boot-tpl-nodtb.bin',
115 U_BOOT_TPL_NODTB_DATA)
Simon Glassda229092016-11-25 20:15:56 -0700116 TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
117 TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
Bin Meng59ea8c22017-08-15 22:41:54 -0700118 TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
Simon Glassca4f4ff2017-11-12 21:52:28 -0700119 TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
Simon Glassec127af2018-07-17 13:25:39 -0600120 TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
Simon Glass0ef87aa2018-07-17 13:25:44 -0600121 TestFunctional._MakeInputDir('devkeys')
122 TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
Simon Glass3ae192c2018-10-01 12:22:31 -0600123 TestFunctional._MakeInputFile('refcode.bin', REFCODE_DATA)
Simon Glass4f443042016-11-25 20:15:52 -0700124
Simon Glasse0ff8552016-11-25 20:15:53 -0700125 # ELF file with a '_dt_ucode_base_size' symbol
Simon Glass1d0ebf72019-05-14 15:53:42 -0600126 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
Simon Glasse0ff8552016-11-25 20:15:53 -0700127 TestFunctional._MakeInputFile('u-boot', fd.read())
128
129 # Intel flash descriptor file
Simon Glass1d0ebf72019-05-14 15:53:42 -0600130 with open(self.TestFile('descriptor.bin'), 'rb') as fd:
Simon Glasse0ff8552016-11-25 20:15:53 -0700131 TestFunctional._MakeInputFile('descriptor.bin', fd.read())
132
Simon Glass0a98b282018-09-14 04:57:28 -0600133 shutil.copytree(self.TestFile('files'),
134 os.path.join(self._indir, 'files'))
135
Simon Glass83d73c22018-09-14 04:57:26 -0600136 TestFunctional._MakeInputFile('compress', COMPRESS_DATA)
137
Simon Glassac62fba2019-07-08 13:18:53 -0600138 # Travis-CI may have an old lz4
139 self.have_lz4 = True
140 try:
141 tools.Run('lz4', '--no-frame-crc', '-c',
142 os.path.join(self._indir, 'u-boot.bin'))
143 except:
144 self.have_lz4 = False
145
Simon Glass4f443042016-11-25 20:15:52 -0700146 @classmethod
147 def tearDownClass(self):
148 """Remove the temporary input directory and its contents"""
Simon Glassd5164a72019-07-08 13:18:49 -0600149 if self.preserve_indir:
150 print('Preserving input dir: %s' % self._indir)
151 else:
152 if self._indir:
153 shutil.rmtree(self._indir)
Simon Glass4f443042016-11-25 20:15:52 -0700154 self._indir = None
155
Simon Glassd5164a72019-07-08 13:18:49 -0600156 @classmethod
Simon Glass8acce602019-07-08 13:18:50 -0600157 def setup_test_args(cls, preserve_indir=False, preserve_outdirs=False,
158 toolpath=None):
Simon Glassd5164a72019-07-08 13:18:49 -0600159 """Accept arguments controlling test execution
160
161 Args:
162 preserve_indir: Preserve the shared input directory used by all
163 tests in this class.
164 preserve_outdir: Preserve the output directories used by tests. Each
165 test has its own, so this is normally only useful when running a
166 single test.
Simon Glass8acce602019-07-08 13:18:50 -0600167 toolpath: ist of paths to use for tools
Simon Glassd5164a72019-07-08 13:18:49 -0600168 """
169 cls.preserve_indir = preserve_indir
170 cls.preserve_outdirs = preserve_outdirs
Simon Glass8acce602019-07-08 13:18:50 -0600171 cls.toolpath = toolpath
Simon Glassd5164a72019-07-08 13:18:49 -0600172
Simon Glassac62fba2019-07-08 13:18:53 -0600173 def _CheckLz4(self):
174 if not self.have_lz4:
175 self.skipTest('lz4 --no-frame-crc not available')
176
Simon Glass4f443042016-11-25 20:15:52 -0700177 def setUp(self):
178 # Enable this to turn on debugging output
179 # tout.Init(tout.DEBUG)
180 command.test_result = None
181
182 def tearDown(self):
183 """Remove the temporary output directory"""
Simon Glassd5164a72019-07-08 13:18:49 -0600184 if self.preserve_outdirs:
185 print('Preserving output dir: %s' % tools.outdir)
186 else:
187 tools._FinaliseForTest()
Simon Glass4f443042016-11-25 20:15:52 -0700188
Simon Glassb8ef5b62018-07-17 13:25:48 -0600189 @classmethod
190 def _ResetDtbs(self):
191 TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
192 TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
193 TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
194
Simon Glassee0c9a72019-07-08 13:18:48 -0600195 def _GetVerbosity(self):
196 """Check if verbosity should be enabled
197
198 Returns:
199 list containing either:
200 - Verbosity flag (e.g. '-v2') if it is present on the cmd line
201 - nothing if the flag is not present
202 """
203 for arg in sys.argv[1:]:
204 if arg.startswith('-v'):
205 return [arg]
206 return []
207
Simon Glass4f443042016-11-25 20:15:52 -0700208 def _RunBinman(self, *args, **kwargs):
209 """Run binman using the command line
210
211 Args:
212 Arguments to pass, as a list of strings
213 kwargs: Arguments to pass to Command.RunPipe()
214 """
215 result = command.RunPipe([[self._binman_pathname] + list(args)],
216 capture=True, capture_stderr=True, raise_on_error=False)
217 if result.return_code and kwargs.get('raise_on_error', True):
218 raise Exception("Error running '%s': %s" % (' '.join(args),
219 result.stdout + result.stderr))
220 return result
221
222 def _DoBinman(self, *args):
223 """Run binman using directly (in the same process)
224
225 Args:
226 Arguments to pass, as a list of strings
227 Returns:
228 Return value (0 for success)
229 """
Simon Glass7fe91732017-11-13 18:55:00 -0700230 args = list(args)
231 if '-D' in sys.argv:
232 args = args + ['-D']
233 (options, args) = cmdline.ParseArgs(args)
Simon Glass4f443042016-11-25 20:15:52 -0700234 options.pager = 'binman-invalid-pager'
235 options.build_dir = self._indir
236
237 # For testing, you can force an increase in verbosity here
238 # options.verbosity = tout.DEBUG
239 return control.Binman(options, args)
240
Simon Glass53af22a2018-07-17 13:25:32 -0600241 def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
Simon Glasseb833d82019-04-25 21:58:34 -0600242 entry_args=None, images=None, use_real_dtb=False,
243 verbosity=None):
Simon Glass4f443042016-11-25 20:15:52 -0700244 """Run binman with a given test file
245
246 Args:
Simon Glass741f2d62018-10-01 12:22:30 -0600247 fname: Device-tree source filename to use (e.g. 005_simple.dts)
Simon Glass7ae5f312018-06-01 09:38:19 -0600248 debug: True to enable debugging output
Simon Glass3b0c3822018-06-01 09:38:20 -0600249 map: True to output map files for the images
Simon Glass3ab95982018-08-01 15:22:37 -0600250 update_dtb: Update the offset and size of each entry in the device
Simon Glass16b8d6b2018-07-06 10:27:42 -0600251 tree before packing it into the image
Simon Glass0bfa7b02018-09-14 04:57:12 -0600252 entry_args: Dict of entry args to supply to binman
253 key: arg name
254 value: value of that arg
255 images: List of image names to build
Simon Glass4f443042016-11-25 20:15:52 -0700256 """
Simon Glass7fe91732017-11-13 18:55:00 -0700257 args = ['-p', '-I', self._indir, '-d', self.TestFile(fname)]
258 if debug:
259 args.append('-D')
Simon Glass3b0c3822018-06-01 09:38:20 -0600260 if map:
261 args.append('-m')
Simon Glass16b8d6b2018-07-06 10:27:42 -0600262 if update_dtb:
Simon Glass2569e102019-07-08 13:18:47 -0600263 args.append('-u')
Simon Glass93d17412018-09-14 04:57:23 -0600264 if not use_real_dtb:
265 args.append('--fake-dtb')
Simon Glasseb833d82019-04-25 21:58:34 -0600266 if verbosity is not None:
267 args.append('-v%d' % verbosity)
Simon Glassee0c9a72019-07-08 13:18:48 -0600268 else:
269 args += self._GetVerbosity()
Simon Glass53af22a2018-07-17 13:25:32 -0600270 if entry_args:
Simon Glass50979152019-05-14 15:53:41 -0600271 for arg, value in entry_args.items():
Simon Glass53af22a2018-07-17 13:25:32 -0600272 args.append('-a%s=%s' % (arg, value))
Simon Glass0bfa7b02018-09-14 04:57:12 -0600273 if images:
274 for image in images:
275 args += ['-i', image]
Simon Glass8acce602019-07-08 13:18:50 -0600276 if self.toolpath:
277 for path in self.toolpath:
278 args += ['--toolpath', path]
Simon Glass7fe91732017-11-13 18:55:00 -0700279 return self._DoBinman(*args)
Simon Glass4f443042016-11-25 20:15:52 -0700280
281 def _SetupDtb(self, fname, outfile='u-boot.dtb'):
Simon Glasse0ff8552016-11-25 20:15:53 -0700282 """Set up a new test device-tree file
283
284 The given file is compiled and set up as the device tree to be used
285 for ths test.
286
287 Args:
288 fname: Filename of .dts file to read
Simon Glass7ae5f312018-06-01 09:38:19 -0600289 outfile: Output filename for compiled device-tree binary
Simon Glasse0ff8552016-11-25 20:15:53 -0700290
291 Returns:
Simon Glass7ae5f312018-06-01 09:38:19 -0600292 Contents of device-tree binary
Simon Glasse0ff8552016-11-25 20:15:53 -0700293 """
Simon Glasse0e62752018-10-01 21:12:41 -0600294 tools.PrepareOutputDir(None)
Simon Glass4f443042016-11-25 20:15:52 -0700295 dtb = fdt_util.EnsureCompiled(self.TestFile(fname))
Simon Glass1d0ebf72019-05-14 15:53:42 -0600296 with open(dtb, 'rb') as fd:
Simon Glass4f443042016-11-25 20:15:52 -0700297 data = fd.read()
298 TestFunctional._MakeInputFile(outfile, data)
Simon Glasse0e62752018-10-01 21:12:41 -0600299 tools.FinaliseOutputDir()
300 return data
Simon Glass4f443042016-11-25 20:15:52 -0700301
Simon Glass6ed45ba2018-09-14 04:57:24 -0600302 def _GetDtbContentsForSplTpl(self, dtb_data, name):
303 """Create a version of the main DTB for SPL or SPL
304
305 For testing we don't actually have different versions of the DTB. With
306 U-Boot we normally run fdtgrep to remove unwanted nodes, but for tests
307 we don't normally have any unwanted nodes.
308
309 We still want the DTBs for SPL and TPL to be different though, since
310 otherwise it is confusing to know which one we are looking at. So add
311 an 'spl' or 'tpl' property to the top-level node.
312 """
313 dtb = fdt.Fdt.FromData(dtb_data)
314 dtb.Scan()
315 dtb.GetNode('/binman').AddZeroProp(name)
316 dtb.Sync(auto_resize=True)
317 dtb.Pack()
318 return dtb.GetContents()
319
Simon Glass16b8d6b2018-07-06 10:27:42 -0600320 def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
Simon Glass6ed45ba2018-09-14 04:57:24 -0600321 update_dtb=False, entry_args=None, reset_dtbs=True):
Simon Glass4f443042016-11-25 20:15:52 -0700322 """Run binman and return the resulting image
323
324 This runs binman with a given test file and then reads the resulting
325 output file. It is a shortcut function since most tests need to do
326 these steps.
327
328 Raises an assertion failure if binman returns a non-zero exit code.
329
330 Args:
Simon Glass741f2d62018-10-01 12:22:30 -0600331 fname: Device-tree source filename to use (e.g. 005_simple.dts)
Simon Glass4f443042016-11-25 20:15:52 -0700332 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.
Simon Glass3b0c3822018-06-01 09:38:20 -0600336 map: True to output map files for the images
Simon Glass3ab95982018-08-01 15:22:37 -0600337 update_dtb: Update the offset and size of each entry in the device
Simon Glass16b8d6b2018-07-06 10:27:42 -0600338 tree before packing it into the image
Simon Glasse0ff8552016-11-25 20:15:53 -0700339
340 Returns:
341 Tuple:
342 Resulting image contents
343 Device tree contents
Simon Glass3b0c3822018-06-01 09:38:20 -0600344 Map data showing contents of image (or None if none)
Simon Glassea6922e2018-07-17 13:25:27 -0600345 Output device tree binary filename ('u-boot.dtb' path)
Simon Glass4f443042016-11-25 20:15:52 -0700346 """
Simon Glasse0ff8552016-11-25 20:15:53 -0700347 dtb_data = None
Simon Glass4f443042016-11-25 20:15:52 -0700348 # Use the compiled test file as the u-boot-dtb input
349 if use_real_dtb:
Simon Glasse0ff8552016-11-25 20:15:53 -0700350 dtb_data = self._SetupDtb(fname)
Simon Glass6ed45ba2018-09-14 04:57:24 -0600351
352 # For testing purposes, make a copy of the DT for SPL and TPL. Add
353 # a node indicating which it is, so aid verification.
354 for name in ['spl', 'tpl']:
355 dtb_fname = '%s/u-boot-%s.dtb' % (name, name)
356 outfile = os.path.join(self._indir, dtb_fname)
357 TestFunctional._MakeInputFile(dtb_fname,
358 self._GetDtbContentsForSplTpl(dtb_data, name))
Simon Glass4f443042016-11-25 20:15:52 -0700359
360 try:
Simon Glass53af22a2018-07-17 13:25:32 -0600361 retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
Simon Glass6ed45ba2018-09-14 04:57:24 -0600362 entry_args=entry_args, use_real_dtb=use_real_dtb)
Simon Glass4f443042016-11-25 20:15:52 -0700363 self.assertEqual(0, retcode)
Simon Glass6ed45ba2018-09-14 04:57:24 -0600364 out_dtb_fname = tools.GetOutputFilename('u-boot.dtb.out')
Simon Glass4f443042016-11-25 20:15:52 -0700365
366 # Find the (only) image, read it and return its contents
367 image = control.images['image']
Simon Glass16b8d6b2018-07-06 10:27:42 -0600368 image_fname = tools.GetOutputFilename('image.bin')
369 self.assertTrue(os.path.exists(image_fname))
Simon Glass3b0c3822018-06-01 09:38:20 -0600370 if map:
371 map_fname = tools.GetOutputFilename('image.map')
372 with open(map_fname) as fd:
373 map_data = fd.read()
374 else:
375 map_data = None
Simon Glass1d0ebf72019-05-14 15:53:42 -0600376 with open(image_fname, 'rb') as fd:
Simon Glass16b8d6b2018-07-06 10:27:42 -0600377 return fd.read(), dtb_data, map_data, out_dtb_fname
Simon Glass4f443042016-11-25 20:15:52 -0700378 finally:
379 # Put the test file back
Simon Glass6ed45ba2018-09-14 04:57:24 -0600380 if reset_dtbs and use_real_dtb:
Simon Glassb8ef5b62018-07-17 13:25:48 -0600381 self._ResetDtbs()
Simon Glass4f443042016-11-25 20:15:52 -0700382
Simon Glass3c081312019-07-08 14:25:26 -0600383 def _DoReadFileRealDtb(self, fname):
384 """Run binman with a real .dtb file and return the resulting data
385
386 Args:
387 fname: DT source filename to use (e.g. 082_fdt_update_all.dts)
388
389 Returns:
390 Resulting image contents
391 """
392 return self._DoReadFileDtb(fname, use_real_dtb=True, update_dtb=True)[0]
393
Simon Glasse0ff8552016-11-25 20:15:53 -0700394 def _DoReadFile(self, fname, use_real_dtb=False):
Simon Glass7ae5f312018-06-01 09:38:19 -0600395 """Helper function which discards the device-tree binary
396
397 Args:
Simon Glass741f2d62018-10-01 12:22:30 -0600398 fname: Device-tree source filename to use (e.g. 005_simple.dts)
Simon Glass7ae5f312018-06-01 09:38:19 -0600399 use_real_dtb: True to use the test file as the contents of
400 the u-boot-dtb entry. Normally this is not needed and the
401 test contents (the U_BOOT_DTB_DATA string) can be used.
402 But in some test we need the real contents.
Simon Glassea6922e2018-07-17 13:25:27 -0600403
404 Returns:
405 Resulting image contents
Simon Glass7ae5f312018-06-01 09:38:19 -0600406 """
Simon Glasse0ff8552016-11-25 20:15:53 -0700407 return self._DoReadFileDtb(fname, use_real_dtb)[0]
408
Simon Glass4f443042016-11-25 20:15:52 -0700409 @classmethod
410 def _MakeInputFile(self, fname, contents):
411 """Create a new test input file, creating directories as needed
412
413 Args:
Simon Glass3ab95982018-08-01 15:22:37 -0600414 fname: Filename to create
Simon Glass4f443042016-11-25 20:15:52 -0700415 contents: File contents to write in to the file
416 Returns:
417 Full pathname of file created
418 """
419 pathname = os.path.join(self._indir, fname)
420 dirname = os.path.dirname(pathname)
421 if dirname and not os.path.exists(dirname):
422 os.makedirs(dirname)
423 with open(pathname, 'wb') as fd:
424 fd.write(contents)
425 return pathname
426
427 @classmethod
Simon Glass0ef87aa2018-07-17 13:25:44 -0600428 def _MakeInputDir(self, dirname):
429 """Create a new test input directory, creating directories as needed
430
431 Args:
432 dirname: Directory name to create
433
434 Returns:
435 Full pathname of directory created
436 """
437 pathname = os.path.join(self._indir, dirname)
438 if not os.path.exists(pathname):
439 os.makedirs(pathname)
440 return pathname
441
442 @classmethod
Simon Glass11ae93e2018-10-01 21:12:47 -0600443 def _SetupSplElf(self, src_fname='bss_data'):
444 """Set up an ELF file with a '_dt_ucode_base_size' symbol
445
446 Args:
447 Filename of ELF file to use as SPL
448 """
Simon Glass1d0ebf72019-05-14 15:53:42 -0600449 with open(self.TestFile(src_fname), 'rb') as fd:
Simon Glass11ae93e2018-10-01 21:12:47 -0600450 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
451
452 @classmethod
Simon Glass4f443042016-11-25 20:15:52 -0700453 def TestFile(self, fname):
454 return os.path.join(self._binman_dir, 'test', fname)
455
456 def AssertInList(self, grep_list, target):
457 """Assert that at least one of a list of things is in a target
458
459 Args:
460 grep_list: List of strings to check
461 target: Target string
462 """
463 for grep in grep_list:
464 if grep in target:
465 return
Simon Glass1fc62de2019-05-17 22:00:50 -0600466 self.fail("Error: '%s' not found in '%s'" % (grep_list, target))
Simon Glass4f443042016-11-25 20:15:52 -0700467
468 def CheckNoGaps(self, entries):
469 """Check that all entries fit together without gaps
470
471 Args:
472 entries: List of entries to check
473 """
Simon Glass3ab95982018-08-01 15:22:37 -0600474 offset = 0
Simon Glass4f443042016-11-25 20:15:52 -0700475 for entry in entries.values():
Simon Glass3ab95982018-08-01 15:22:37 -0600476 self.assertEqual(offset, entry.offset)
477 offset += entry.size
Simon Glass4f443042016-11-25 20:15:52 -0700478
Simon Glasse0ff8552016-11-25 20:15:53 -0700479 def GetFdtLen(self, dtb):
Simon Glass7ae5f312018-06-01 09:38:19 -0600480 """Get the totalsize field from a device-tree binary
Simon Glasse0ff8552016-11-25 20:15:53 -0700481
482 Args:
Simon Glass7ae5f312018-06-01 09:38:19 -0600483 dtb: Device-tree binary contents
Simon Glasse0ff8552016-11-25 20:15:53 -0700484
485 Returns:
Simon Glass7ae5f312018-06-01 09:38:19 -0600486 Total size of device-tree binary, from the header
Simon Glasse0ff8552016-11-25 20:15:53 -0700487 """
488 return struct.unpack('>L', dtb[4:8])[0]
489
Simon Glass086cec92019-07-08 14:25:27 -0600490 def _GetPropTree(self, dtb, prop_names, prefix='/binman/'):
Simon Glass16b8d6b2018-07-06 10:27:42 -0600491 def AddNode(node, path):
492 if node.name != '/':
493 path += '/' + node.name
Simon Glass086cec92019-07-08 14:25:27 -0600494 for prop in node.props.values():
495 if prop.name in prop_names:
496 prop_path = path + ':' + prop.name
497 tree[prop_path[len(prefix):]] = fdt_util.fdt32_to_cpu(
498 prop.value)
Simon Glass16b8d6b2018-07-06 10:27:42 -0600499 for subnode in node.subnodes:
Simon Glass16b8d6b2018-07-06 10:27:42 -0600500 AddNode(subnode, path)
501
502 tree = {}
Simon Glass16b8d6b2018-07-06 10:27:42 -0600503 AddNode(dtb.GetRoot(), '')
504 return tree
505
Simon Glass4f443042016-11-25 20:15:52 -0700506 def testRun(self):
507 """Test a basic run with valid args"""
508 result = self._RunBinman('-h')
509
510 def testFullHelp(self):
511 """Test that the full help is displayed with -H"""
512 result = self._RunBinman('-H')
513 help_file = os.path.join(self._binman_dir, 'README')
Tom Rini3759df02018-01-16 15:29:50 -0500514 # Remove possible extraneous strings
515 extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
516 gothelp = result.stdout.replace(extra, '')
517 self.assertEqual(len(gothelp), os.path.getsize(help_file))
Simon Glass4f443042016-11-25 20:15:52 -0700518 self.assertEqual(0, len(result.stderr))
519 self.assertEqual(0, result.return_code)
520
521 def testFullHelpInternal(self):
522 """Test that the full help is displayed with -H"""
523 try:
524 command.test_result = command.CommandResult()
525 result = self._DoBinman('-H')
526 help_file = os.path.join(self._binman_dir, 'README')
527 finally:
528 command.test_result = None
529
530 def testHelp(self):
531 """Test that the basic help is displayed with -h"""
532 result = self._RunBinman('-h')
533 self.assertTrue(len(result.stdout) > 200)
534 self.assertEqual(0, len(result.stderr))
535 self.assertEqual(0, result.return_code)
536
Simon Glass4f443042016-11-25 20:15:52 -0700537 def testBoard(self):
538 """Test that we can run it with a specific board"""
Simon Glass741f2d62018-10-01 12:22:30 -0600539 self._SetupDtb('005_simple.dts', 'sandbox/u-boot.dtb')
Simon Glass4f443042016-11-25 20:15:52 -0700540 TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
541 result = self._DoBinman('-b', 'sandbox')
542 self.assertEqual(0, result)
543
544 def testNeedBoard(self):
545 """Test that we get an error when no board ius supplied"""
546 with self.assertRaises(ValueError) as e:
547 result = self._DoBinman()
548 self.assertIn("Must provide a board to process (use -b <board>)",
549 str(e.exception))
550
551 def testMissingDt(self):
Simon Glass7ae5f312018-06-01 09:38:19 -0600552 """Test that an invalid device-tree file generates an error"""
Simon Glass4f443042016-11-25 20:15:52 -0700553 with self.assertRaises(Exception) as e:
554 self._RunBinman('-d', 'missing_file')
555 # We get one error from libfdt, and a different one from fdtget.
556 self.AssertInList(["Couldn't open blob from 'missing_file'",
557 'No such file or directory'], str(e.exception))
558
559 def testBrokenDt(self):
Simon Glass7ae5f312018-06-01 09:38:19 -0600560 """Test that an invalid device-tree source file generates an error
Simon Glass4f443042016-11-25 20:15:52 -0700561
562 Since this is a source file it should be compiled and the error
563 will come from the device-tree compiler (dtc).
564 """
565 with self.assertRaises(Exception) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600566 self._RunBinman('-d', self.TestFile('001_invalid.dts'))
Simon Glass4f443042016-11-25 20:15:52 -0700567 self.assertIn("FATAL ERROR: Unable to parse input tree",
568 str(e.exception))
569
570 def testMissingNode(self):
571 """Test that a device tree without a 'binman' node generates an error"""
572 with self.assertRaises(Exception) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600573 self._DoBinman('-d', self.TestFile('002_missing_node.dts'))
Simon Glass4f443042016-11-25 20:15:52 -0700574 self.assertIn("does not have a 'binman' node", str(e.exception))
575
576 def testEmpty(self):
577 """Test that an empty binman node works OK (i.e. does nothing)"""
Simon Glass741f2d62018-10-01 12:22:30 -0600578 result = self._RunBinman('-d', self.TestFile('003_empty.dts'))
Simon Glass4f443042016-11-25 20:15:52 -0700579 self.assertEqual(0, len(result.stderr))
580 self.assertEqual(0, result.return_code)
581
582 def testInvalidEntry(self):
583 """Test that an invalid entry is flagged"""
584 with self.assertRaises(Exception) as e:
585 result = self._RunBinman('-d',
Simon Glass741f2d62018-10-01 12:22:30 -0600586 self.TestFile('004_invalid_entry.dts'))
Simon Glass4f443042016-11-25 20:15:52 -0700587 self.assertIn("Unknown entry type 'not-a-valid-type' in node "
588 "'/binman/not-a-valid-type'", str(e.exception))
589
590 def testSimple(self):
591 """Test a simple binman with a single file"""
Simon Glass741f2d62018-10-01 12:22:30 -0600592 data = self._DoReadFile('005_simple.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700593 self.assertEqual(U_BOOT_DATA, data)
594
Simon Glass7fe91732017-11-13 18:55:00 -0700595 def testSimpleDebug(self):
596 """Test a simple binman run with debugging enabled"""
Simon Glass741f2d62018-10-01 12:22:30 -0600597 data = self._DoTestFile('005_simple.dts', debug=True)
Simon Glass7fe91732017-11-13 18:55:00 -0700598
Simon Glass4f443042016-11-25 20:15:52 -0700599 def testDual(self):
600 """Test that we can handle creating two images
601
602 This also tests image padding.
603 """
Simon Glass741f2d62018-10-01 12:22:30 -0600604 retcode = self._DoTestFile('006_dual_image.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700605 self.assertEqual(0, retcode)
606
607 image = control.images['image1']
608 self.assertEqual(len(U_BOOT_DATA), image._size)
609 fname = tools.GetOutputFilename('image1.bin')
610 self.assertTrue(os.path.exists(fname))
Simon Glass1d0ebf72019-05-14 15:53:42 -0600611 with open(fname, 'rb') as fd:
Simon Glass4f443042016-11-25 20:15:52 -0700612 data = fd.read()
613 self.assertEqual(U_BOOT_DATA, data)
614
615 image = control.images['image2']
616 self.assertEqual(3 + len(U_BOOT_DATA) + 5, image._size)
617 fname = tools.GetOutputFilename('image2.bin')
618 self.assertTrue(os.path.exists(fname))
Simon Glass1d0ebf72019-05-14 15:53:42 -0600619 with open(fname, 'rb') as fd:
Simon Glass4f443042016-11-25 20:15:52 -0700620 data = fd.read()
621 self.assertEqual(U_BOOT_DATA, data[3:7])
Simon Glasse6d85ff2019-05-14 15:53:47 -0600622 self.assertEqual(tools.GetBytes(0, 3), data[:3])
623 self.assertEqual(tools.GetBytes(0, 5), data[7:])
Simon Glass4f443042016-11-25 20:15:52 -0700624
625 def testBadAlign(self):
626 """Test that an invalid alignment value is detected"""
627 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600628 self._DoTestFile('007_bad_align.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700629 self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
630 "of two", str(e.exception))
631
632 def testPackSimple(self):
633 """Test that packing works as expected"""
Simon Glass741f2d62018-10-01 12:22:30 -0600634 retcode = self._DoTestFile('008_pack.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700635 self.assertEqual(0, retcode)
636 self.assertIn('image', control.images)
637 image = control.images['image']
Simon Glass8f1da502018-06-01 09:38:12 -0600638 entries = image.GetEntries()
Simon Glass4f443042016-11-25 20:15:52 -0700639 self.assertEqual(5, len(entries))
640
641 # First u-boot
642 self.assertIn('u-boot', entries)
643 entry = entries['u-boot']
Simon Glass3ab95982018-08-01 15:22:37 -0600644 self.assertEqual(0, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700645 self.assertEqual(len(U_BOOT_DATA), entry.size)
646
647 # Second u-boot, aligned to 16-byte boundary
648 self.assertIn('u-boot-align', entries)
649 entry = entries['u-boot-align']
Simon Glass3ab95982018-08-01 15:22:37 -0600650 self.assertEqual(16, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700651 self.assertEqual(len(U_BOOT_DATA), entry.size)
652
653 # Third u-boot, size 23 bytes
654 self.assertIn('u-boot-size', entries)
655 entry = entries['u-boot-size']
Simon Glass3ab95982018-08-01 15:22:37 -0600656 self.assertEqual(20, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700657 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
658 self.assertEqual(23, entry.size)
659
660 # Fourth u-boot, placed immediate after the above
661 self.assertIn('u-boot-next', entries)
662 entry = entries['u-boot-next']
Simon Glass3ab95982018-08-01 15:22:37 -0600663 self.assertEqual(43, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700664 self.assertEqual(len(U_BOOT_DATA), entry.size)
665
Simon Glass3ab95982018-08-01 15:22:37 -0600666 # Fifth u-boot, placed at a fixed offset
Simon Glass4f443042016-11-25 20:15:52 -0700667 self.assertIn('u-boot-fixed', entries)
668 entry = entries['u-boot-fixed']
Simon Glass3ab95982018-08-01 15:22:37 -0600669 self.assertEqual(61, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700670 self.assertEqual(len(U_BOOT_DATA), entry.size)
671
672 self.assertEqual(65, image._size)
673
674 def testPackExtra(self):
675 """Test that extra packing feature works as expected"""
Simon Glass741f2d62018-10-01 12:22:30 -0600676 retcode = self._DoTestFile('009_pack_extra.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700677
678 self.assertEqual(0, retcode)
679 self.assertIn('image', control.images)
680 image = control.images['image']
Simon Glass8f1da502018-06-01 09:38:12 -0600681 entries = image.GetEntries()
Simon Glass4f443042016-11-25 20:15:52 -0700682 self.assertEqual(5, len(entries))
683
684 # First u-boot with padding before and after
685 self.assertIn('u-boot', entries)
686 entry = entries['u-boot']
Simon Glass3ab95982018-08-01 15:22:37 -0600687 self.assertEqual(0, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700688 self.assertEqual(3, entry.pad_before)
689 self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
690
691 # Second u-boot has an aligned size, but it has no effect
692 self.assertIn('u-boot-align-size-nop', entries)
693 entry = entries['u-boot-align-size-nop']
Simon Glass3ab95982018-08-01 15:22:37 -0600694 self.assertEqual(12, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700695 self.assertEqual(4, entry.size)
696
697 # Third u-boot has an aligned size too
698 self.assertIn('u-boot-align-size', entries)
699 entry = entries['u-boot-align-size']
Simon Glass3ab95982018-08-01 15:22:37 -0600700 self.assertEqual(16, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700701 self.assertEqual(32, entry.size)
702
703 # Fourth u-boot has an aligned end
704 self.assertIn('u-boot-align-end', entries)
705 entry = entries['u-boot-align-end']
Simon Glass3ab95982018-08-01 15:22:37 -0600706 self.assertEqual(48, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700707 self.assertEqual(16, entry.size)
708
709 # Fifth u-boot immediately afterwards
710 self.assertIn('u-boot-align-both', entries)
711 entry = entries['u-boot-align-both']
Simon Glass3ab95982018-08-01 15:22:37 -0600712 self.assertEqual(64, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700713 self.assertEqual(64, entry.size)
714
715 self.CheckNoGaps(entries)
716 self.assertEqual(128, image._size)
717
718 def testPackAlignPowerOf2(self):
719 """Test that invalid entry alignment is detected"""
720 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600721 self._DoTestFile('010_pack_align_power2.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700722 self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
723 "of two", str(e.exception))
724
725 def testPackAlignSizePowerOf2(self):
726 """Test that invalid entry size alignment is detected"""
727 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600728 self._DoTestFile('011_pack_align_size_power2.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700729 self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
730 "power of two", str(e.exception))
731
732 def testPackInvalidAlign(self):
Simon Glass3ab95982018-08-01 15:22:37 -0600733 """Test detection of an offset that does not match its alignment"""
Simon Glass4f443042016-11-25 20:15:52 -0700734 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600735 self._DoTestFile('012_pack_inv_align.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600736 self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
Simon Glass4f443042016-11-25 20:15:52 -0700737 "align 0x4 (4)", str(e.exception))
738
739 def testPackInvalidSizeAlign(self):
740 """Test that invalid entry size alignment is detected"""
741 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600742 self._DoTestFile('013_pack_inv_size_align.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700743 self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
744 "align-size 0x4 (4)", str(e.exception))
745
746 def testPackOverlap(self):
747 """Test that overlapping regions are detected"""
748 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600749 self._DoTestFile('014_pack_overlap.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600750 self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
Simon Glass4f443042016-11-25 20:15:52 -0700751 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
752 str(e.exception))
753
754 def testPackEntryOverflow(self):
755 """Test that entries that overflow their size are detected"""
756 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600757 self._DoTestFile('015_pack_overflow.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700758 self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
759 "but entry size is 0x3 (3)", str(e.exception))
760
761 def testPackImageOverflow(self):
762 """Test that entries which overflow the image size are detected"""
763 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600764 self._DoTestFile('016_pack_image_overflow.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600765 self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section "
Simon Glass4f443042016-11-25 20:15:52 -0700766 "size 0x3 (3)", str(e.exception))
767
768 def testPackImageSize(self):
769 """Test that the image size can be set"""
Simon Glass741f2d62018-10-01 12:22:30 -0600770 retcode = self._DoTestFile('017_pack_image_size.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700771 self.assertEqual(0, retcode)
772 self.assertIn('image', control.images)
773 image = control.images['image']
774 self.assertEqual(7, image._size)
775
776 def testPackImageSizeAlign(self):
777 """Test that image size alignemnt works as expected"""
Simon Glass741f2d62018-10-01 12:22:30 -0600778 retcode = self._DoTestFile('018_pack_image_align.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700779 self.assertEqual(0, retcode)
780 self.assertIn('image', control.images)
781 image = control.images['image']
782 self.assertEqual(16, image._size)
783
784 def testPackInvalidImageAlign(self):
785 """Test that invalid image alignment is detected"""
786 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600787 self._DoTestFile('019_pack_inv_image_align.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600788 self.assertIn("Section '/binman': Size 0x7 (7) does not match "
Simon Glass4f443042016-11-25 20:15:52 -0700789 "align-size 0x8 (8)", str(e.exception))
790
791 def testPackAlignPowerOf2(self):
792 """Test that invalid image alignment is detected"""
793 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600794 self._DoTestFile('020_pack_inv_image_align_power2.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600795 self.assertIn("Section '/binman': Alignment size 131 must be a power of "
Simon Glass4f443042016-11-25 20:15:52 -0700796 "two", str(e.exception))
797
798 def testImagePadByte(self):
799 """Test that the image pad byte can be specified"""
Simon Glass11ae93e2018-10-01 21:12:47 -0600800 self._SetupSplElf()
Simon Glass741f2d62018-10-01 12:22:30 -0600801 data = self._DoReadFile('021_image_pad.dts')
Simon Glasse6d85ff2019-05-14 15:53:47 -0600802 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0xff, 1) +
803 U_BOOT_DATA, data)
Simon Glass4f443042016-11-25 20:15:52 -0700804
805 def testImageName(self):
806 """Test that image files can be named"""
Simon Glass741f2d62018-10-01 12:22:30 -0600807 retcode = self._DoTestFile('022_image_name.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700808 self.assertEqual(0, retcode)
809 image = control.images['image1']
810 fname = tools.GetOutputFilename('test-name')
811 self.assertTrue(os.path.exists(fname))
812
813 image = control.images['image2']
814 fname = tools.GetOutputFilename('test-name.xx')
815 self.assertTrue(os.path.exists(fname))
816
817 def testBlobFilename(self):
818 """Test that generic blobs can be provided by filename"""
Simon Glass741f2d62018-10-01 12:22:30 -0600819 data = self._DoReadFile('023_blob.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700820 self.assertEqual(BLOB_DATA, data)
821
822 def testPackSorted(self):
823 """Test that entries can be sorted"""
Simon Glass11ae93e2018-10-01 21:12:47 -0600824 self._SetupSplElf()
Simon Glass741f2d62018-10-01 12:22:30 -0600825 data = self._DoReadFile('024_sorted.dts')
Simon Glasse6d85ff2019-05-14 15:53:47 -0600826 self.assertEqual(tools.GetBytes(0, 1) + U_BOOT_SPL_DATA +
827 tools.GetBytes(0, 2) + U_BOOT_DATA, data)
Simon Glass4f443042016-11-25 20:15:52 -0700828
Simon Glass3ab95982018-08-01 15:22:37 -0600829 def testPackZeroOffset(self):
830 """Test that an entry at offset 0 is not given a new offset"""
Simon Glass4f443042016-11-25 20:15:52 -0700831 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600832 self._DoTestFile('025_pack_zero_size.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600833 self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
Simon Glass4f443042016-11-25 20:15:52 -0700834 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
835 str(e.exception))
836
837 def testPackUbootDtb(self):
838 """Test that a device tree can be added to U-Boot"""
Simon Glass741f2d62018-10-01 12:22:30 -0600839 data = self._DoReadFile('026_pack_u_boot_dtb.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700840 self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
Simon Glasse0ff8552016-11-25 20:15:53 -0700841
842 def testPackX86RomNoSize(self):
843 """Test that the end-at-4gb property requires a size property"""
844 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600845 self._DoTestFile('027_pack_4gb_no_size.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600846 self.assertIn("Section '/binman': Section size must be provided when "
Simon Glasse0ff8552016-11-25 20:15:53 -0700847 "using end-at-4gb", str(e.exception))
848
Jagdish Gediya94b57db2018-09-03 21:35:07 +0530849 def test4gbAndSkipAtStartTogether(self):
850 """Test that the end-at-4gb and skip-at-size property can't be used
851 together"""
852 with self.assertRaises(ValueError) as e:
853 self._DoTestFile('80_4gb_and_skip_at_start_together.dts')
854 self.assertIn("Section '/binman': Provide either 'end-at-4gb' or "
855 "'skip-at-start'", str(e.exception))
856
Simon Glasse0ff8552016-11-25 20:15:53 -0700857 def testPackX86RomOutside(self):
Simon Glass3ab95982018-08-01 15:22:37 -0600858 """Test that the end-at-4gb property checks for offset boundaries"""
Simon Glasse0ff8552016-11-25 20:15:53 -0700859 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600860 self._DoTestFile('028_pack_4gb_outside.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600861 self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
Simon Glass8f1da502018-06-01 09:38:12 -0600862 "the section starting at 0xffffffe0 (4294967264)",
Simon Glasse0ff8552016-11-25 20:15:53 -0700863 str(e.exception))
864
865 def testPackX86Rom(self):
866 """Test that a basic x86 ROM can be created"""
Simon Glass11ae93e2018-10-01 21:12:47 -0600867 self._SetupSplElf()
Simon Glass741f2d62018-10-01 12:22:30 -0600868 data = self._DoReadFile('029_x86-rom.dts')
Simon Glasse6d85ff2019-05-14 15:53:47 -0600869 self.assertEqual(U_BOOT_DATA + tools.GetBytes(0, 7) + U_BOOT_SPL_DATA +
870 tools.GetBytes(0, 2), data)
Simon Glasse0ff8552016-11-25 20:15:53 -0700871
872 def testPackX86RomMeNoDesc(self):
873 """Test that an invalid Intel descriptor entry is detected"""
Simon Glassc6c10e72019-05-17 22:00:46 -0600874 TestFunctional._MakeInputFile('descriptor.bin', b'')
Simon Glasse0ff8552016-11-25 20:15:53 -0700875 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600876 self._DoTestFile('031_x86-rom-me.dts')
Simon Glass458be452019-07-08 13:18:32 -0600877 self.assertIn("Node '/binman/intel-descriptor': Cannot find Intel Flash Descriptor (FD) signature",
878 str(e.exception))
Simon Glasse0ff8552016-11-25 20:15:53 -0700879
880 def testPackX86RomBadDesc(self):
881 """Test that the Intel requires a descriptor entry"""
882 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600883 self._DoTestFile('030_x86-rom-me-no-desc.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600884 self.assertIn("Node '/binman/intel-me': No offset set with "
885 "offset-unset: should another entry provide this correct "
886 "offset?", str(e.exception))
Simon Glasse0ff8552016-11-25 20:15:53 -0700887
888 def testPackX86RomMe(self):
889 """Test that an x86 ROM with an ME region can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -0600890 data = self._DoReadFile('031_x86-rom-me.dts')
Simon Glassc5ac1382019-07-08 13:18:54 -0600891 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
892 if data[:0x1000] != expected_desc:
893 self.fail('Expected descriptor binary at start of image')
Simon Glasse0ff8552016-11-25 20:15:53 -0700894 self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
895
896 def testPackVga(self):
897 """Test that an image with a VGA binary can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -0600898 data = self._DoReadFile('032_intel-vga.dts')
Simon Glasse0ff8552016-11-25 20:15:53 -0700899 self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
900
901 def testPackStart16(self):
902 """Test that an image with an x86 start16 region can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -0600903 data = self._DoReadFile('033_x86-start16.dts')
Simon Glasse0ff8552016-11-25 20:15:53 -0700904 self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
905
Jagdish Gediya9d368f32018-09-03 21:35:08 +0530906 def testPackPowerpcMpc85xxBootpgResetvec(self):
907 """Test that an image with powerpc-mpc85xx-bootpg-resetvec can be
908 created"""
909 data = self._DoReadFile('81_powerpc_mpc85xx_bootpg_resetvec.dts')
910 self.assertEqual(PPC_MPC85XX_BR_DATA, data[:len(PPC_MPC85XX_BR_DATA)])
911
Simon Glass736bb0a2018-07-06 10:27:17 -0600912 def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False):
Simon Glassadc57012018-07-06 10:27:16 -0600913 """Handle running a test for insertion of microcode
914
915 Args:
916 dts_fname: Name of test .dts file
917 nodtb_data: Data that we expect in the first section
Simon Glass736bb0a2018-07-06 10:27:17 -0600918 ucode_second: True if the microsecond entry is second instead of
919 third
Simon Glassadc57012018-07-06 10:27:16 -0600920
921 Returns:
922 Tuple:
923 Contents of first region (U-Boot or SPL)
Simon Glass3ab95982018-08-01 15:22:37 -0600924 Offset and size components of microcode pointer, as inserted
Simon Glassadc57012018-07-06 10:27:16 -0600925 in the above (two 4-byte words)
926 """
Simon Glass6b187df2017-11-12 21:52:27 -0700927 data = self._DoReadFile(dts_fname, True)
Simon Glasse0ff8552016-11-25 20:15:53 -0700928
929 # Now check the device tree has no microcode
Simon Glass736bb0a2018-07-06 10:27:17 -0600930 if ucode_second:
931 ucode_content = data[len(nodtb_data):]
932 ucode_pos = len(nodtb_data)
933 dtb_with_ucode = ucode_content[16:]
934 fdt_len = self.GetFdtLen(dtb_with_ucode)
935 else:
936 dtb_with_ucode = data[len(nodtb_data):]
937 fdt_len = self.GetFdtLen(dtb_with_ucode)
938 ucode_content = dtb_with_ucode[fdt_len:]
939 ucode_pos = len(nodtb_data) + fdt_len
Simon Glasse0ff8552016-11-25 20:15:53 -0700940 fname = tools.GetOutputFilename('test.dtb')
941 with open(fname, 'wb') as fd:
Simon Glassadc57012018-07-06 10:27:16 -0600942 fd.write(dtb_with_ucode)
Simon Glassec3f3782017-05-27 07:38:29 -0600943 dtb = fdt.FdtScan(fname)
944 ucode = dtb.GetNode('/microcode')
Simon Glasse0ff8552016-11-25 20:15:53 -0700945 self.assertTrue(ucode)
946 for node in ucode.subnodes:
947 self.assertFalse(node.props.get('data'))
948
Simon Glasse0ff8552016-11-25 20:15:53 -0700949 # Check that the microcode appears immediately after the Fdt
950 # This matches the concatenation of the data properties in
Simon Glass87722132017-11-12 21:52:26 -0700951 # the /microcode/update@xxx nodes in 34_x86_ucode.dts.
Simon Glasse0ff8552016-11-25 20:15:53 -0700952 ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
953 0x78235609)
Simon Glassadc57012018-07-06 10:27:16 -0600954 self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
Simon Glasse0ff8552016-11-25 20:15:53 -0700955
956 # Check that the microcode pointer was inserted. It should match the
Simon Glass3ab95982018-08-01 15:22:37 -0600957 # expected offset and size
Simon Glasse0ff8552016-11-25 20:15:53 -0700958 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
959 len(ucode_data))
Simon Glass736bb0a2018-07-06 10:27:17 -0600960 u_boot = data[:len(nodtb_data)]
961 return u_boot, pos_and_size
Simon Glass6b187df2017-11-12 21:52:27 -0700962
963 def testPackUbootMicrocode(self):
964 """Test that x86 microcode can be handled correctly
965
966 We expect to see the following in the image, in order:
967 u-boot-nodtb.bin with a microcode pointer inserted at the correct
968 place
969 u-boot.dtb with the microcode removed
970 the microcode
971 """
Simon Glass741f2d62018-10-01 12:22:30 -0600972 first, pos_and_size = self._RunMicrocodeTest('034_x86_ucode.dts',
Simon Glass6b187df2017-11-12 21:52:27 -0700973 U_BOOT_NODTB_DATA)
Simon Glassc6c10e72019-05-17 22:00:46 -0600974 self.assertEqual(b'nodtb with microcode' + pos_and_size +
975 b' somewhere in here', first)
Simon Glasse0ff8552016-11-25 20:15:53 -0700976
Simon Glass160a7662017-05-27 07:38:26 -0600977 def _RunPackUbootSingleMicrocode(self):
Simon Glasse0ff8552016-11-25 20:15:53 -0700978 """Test that x86 microcode can be handled correctly
979
980 We expect to see the following in the image, in order:
981 u-boot-nodtb.bin with a microcode pointer inserted at the correct
982 place
983 u-boot.dtb with the microcode
984 an empty microcode region
985 """
986 # We need the libfdt library to run this test since only that allows
987 # finding the offset of a property. This is required by
988 # Entry_u_boot_dtb_with_ucode.ObtainContents().
Simon Glass741f2d62018-10-01 12:22:30 -0600989 data = self._DoReadFile('035_x86_single_ucode.dts', True)
Simon Glasse0ff8552016-11-25 20:15:53 -0700990
991 second = data[len(U_BOOT_NODTB_DATA):]
992
993 fdt_len = self.GetFdtLen(second)
994 third = second[fdt_len:]
995 second = second[:fdt_len]
996
Simon Glass160a7662017-05-27 07:38:26 -0600997 ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
998 self.assertIn(ucode_data, second)
999 ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
Simon Glasse0ff8552016-11-25 20:15:53 -07001000
Simon Glass160a7662017-05-27 07:38:26 -06001001 # Check that the microcode pointer was inserted. It should match the
Simon Glass3ab95982018-08-01 15:22:37 -06001002 # expected offset and size
Simon Glass160a7662017-05-27 07:38:26 -06001003 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
1004 len(ucode_data))
1005 first = data[:len(U_BOOT_NODTB_DATA)]
Simon Glassc6c10e72019-05-17 22:00:46 -06001006 self.assertEqual(b'nodtb with microcode' + pos_and_size +
1007 b' somewhere in here', first)
Simon Glassc49deb82016-11-25 20:15:54 -07001008
Simon Glass75db0862016-11-25 20:15:55 -07001009 def testPackUbootSingleMicrocode(self):
1010 """Test that x86 microcode can be handled correctly with fdt_normal.
1011 """
Simon Glass160a7662017-05-27 07:38:26 -06001012 self._RunPackUbootSingleMicrocode()
Simon Glass75db0862016-11-25 20:15:55 -07001013
Simon Glassc49deb82016-11-25 20:15:54 -07001014 def testUBootImg(self):
1015 """Test that u-boot.img can be put in a file"""
Simon Glass741f2d62018-10-01 12:22:30 -06001016 data = self._DoReadFile('036_u_boot_img.dts')
Simon Glassc49deb82016-11-25 20:15:54 -07001017 self.assertEqual(U_BOOT_IMG_DATA, data)
Simon Glass75db0862016-11-25 20:15:55 -07001018
1019 def testNoMicrocode(self):
1020 """Test that a missing microcode region is detected"""
1021 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001022 self._DoReadFile('037_x86_no_ucode.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -07001023 self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
1024 "node found in ", str(e.exception))
1025
1026 def testMicrocodeWithoutNode(self):
1027 """Test that a missing u-boot-dtb-with-ucode node is detected"""
1028 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001029 self._DoReadFile('038_x86_ucode_missing_node.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -07001030 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1031 "microcode region u-boot-dtb-with-ucode", str(e.exception))
1032
1033 def testMicrocodeWithoutNode2(self):
1034 """Test that a missing u-boot-ucode node is detected"""
1035 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001036 self._DoReadFile('039_x86_ucode_missing_node2.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -07001037 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1038 "microcode region u-boot-ucode", str(e.exception))
1039
1040 def testMicrocodeWithoutPtrInElf(self):
1041 """Test that a U-Boot binary without the microcode symbol is detected"""
1042 # ELF file without a '_dt_ucode_base_size' symbol
Simon Glass75db0862016-11-25 20:15:55 -07001043 try:
Simon Glass1d0ebf72019-05-14 15:53:42 -06001044 with open(self.TestFile('u_boot_no_ucode_ptr'), 'rb') as fd:
Simon Glass75db0862016-11-25 20:15:55 -07001045 TestFunctional._MakeInputFile('u-boot', fd.read())
1046
1047 with self.assertRaises(ValueError) as e:
Simon Glass160a7662017-05-27 07:38:26 -06001048 self._RunPackUbootSingleMicrocode()
Simon Glass75db0862016-11-25 20:15:55 -07001049 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
1050 "_dt_ucode_base_size symbol in u-boot", str(e.exception))
1051
1052 finally:
1053 # Put the original file back
Simon Glass1d0ebf72019-05-14 15:53:42 -06001054 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
Simon Glass75db0862016-11-25 20:15:55 -07001055 TestFunctional._MakeInputFile('u-boot', fd.read())
1056
1057 def testMicrocodeNotInImage(self):
1058 """Test that microcode must be placed within the image"""
1059 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001060 self._DoReadFile('040_x86_ucode_not_in_image.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -07001061 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
1062 "pointer _dt_ucode_base_size at fffffe14 is outside the "
Simon Glass25ac0e62018-06-01 09:38:14 -06001063 "section ranging from 00000000 to 0000002e", str(e.exception))
Simon Glass75db0862016-11-25 20:15:55 -07001064
1065 def testWithoutMicrocode(self):
1066 """Test that we can cope with an image without microcode (e.g. qemu)"""
Simon Glass1d0ebf72019-05-14 15:53:42 -06001067 with open(self.TestFile('u_boot_no_ucode_ptr'), 'rb') as fd:
Simon Glass75db0862016-11-25 20:15:55 -07001068 TestFunctional._MakeInputFile('u-boot', fd.read())
Simon Glass741f2d62018-10-01 12:22:30 -06001069 data, dtb, _, _ = self._DoReadFileDtb('044_x86_optional_ucode.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -07001070
1071 # Now check the device tree has no microcode
1072 self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
1073 second = data[len(U_BOOT_NODTB_DATA):]
1074
1075 fdt_len = self.GetFdtLen(second)
1076 self.assertEqual(dtb, second[:fdt_len])
1077
1078 used_len = len(U_BOOT_NODTB_DATA) + fdt_len
1079 third = data[used_len:]
Simon Glasse6d85ff2019-05-14 15:53:47 -06001080 self.assertEqual(tools.GetBytes(0, 0x200 - used_len), third)
Simon Glass75db0862016-11-25 20:15:55 -07001081
1082 def testUnknownPosSize(self):
1083 """Test that microcode must be placed within the image"""
1084 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001085 self._DoReadFile('041_unknown_pos_size.dts', True)
Simon Glass3ab95982018-08-01 15:22:37 -06001086 self.assertIn("Section '/binman': Unable to set offset/size for unknown "
Simon Glass75db0862016-11-25 20:15:55 -07001087 "entry 'invalid-entry'", str(e.exception))
Simon Glassda229092016-11-25 20:15:56 -07001088
1089 def testPackFsp(self):
1090 """Test that an image with a FSP binary can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001091 data = self._DoReadFile('042_intel-fsp.dts')
Simon Glassda229092016-11-25 20:15:56 -07001092 self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
1093
1094 def testPackCmc(self):
Bin Meng59ea8c22017-08-15 22:41:54 -07001095 """Test that an image with a CMC binary can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001096 data = self._DoReadFile('043_intel-cmc.dts')
Simon Glassda229092016-11-25 20:15:56 -07001097 self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
Bin Meng59ea8c22017-08-15 22:41:54 -07001098
1099 def testPackVbt(self):
1100 """Test that an image with a VBT binary can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001101 data = self._DoReadFile('046_intel-vbt.dts')
Bin Meng59ea8c22017-08-15 22:41:54 -07001102 self.assertEqual(VBT_DATA, data[:len(VBT_DATA)])
Simon Glass9fc60b42017-11-12 21:52:22 -07001103
Simon Glass56509842017-11-12 21:52:25 -07001104 def testSplBssPad(self):
1105 """Test that we can pad SPL's BSS with zeros"""
Simon Glass6b187df2017-11-12 21:52:27 -07001106 # ELF file with a '__bss_size' symbol
Simon Glass11ae93e2018-10-01 21:12:47 -06001107 self._SetupSplElf()
Simon Glass741f2d62018-10-01 12:22:30 -06001108 data = self._DoReadFile('047_spl_bss_pad.dts')
Simon Glasse6d85ff2019-05-14 15:53:47 -06001109 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0, 10) + U_BOOT_DATA,
1110 data)
Simon Glass56509842017-11-12 21:52:25 -07001111
Simon Glass86af5112018-10-01 21:12:42 -06001112 def testSplBssPadMissing(self):
1113 """Test that a missing symbol is detected"""
Simon Glass11ae93e2018-10-01 21:12:47 -06001114 self._SetupSplElf('u_boot_ucode_ptr')
Simon Glassb50e5612017-11-13 18:54:54 -07001115 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001116 self._DoReadFile('047_spl_bss_pad.dts')
Simon Glassb50e5612017-11-13 18:54:54 -07001117 self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
1118 str(e.exception))
1119
Simon Glass87722132017-11-12 21:52:26 -07001120 def testPackStart16Spl(self):
Simon Glass35b384c2018-09-14 04:57:10 -06001121 """Test that an image with an x86 start16 SPL region can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001122 data = self._DoReadFile('048_x86-start16-spl.dts')
Simon Glass87722132017-11-12 21:52:26 -07001123 self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)])
1124
Simon Glass736bb0a2018-07-06 10:27:17 -06001125 def _PackUbootSplMicrocode(self, dts, ucode_second=False):
1126 """Helper function for microcode tests
Simon Glass6b187df2017-11-12 21:52:27 -07001127
1128 We expect to see the following in the image, in order:
1129 u-boot-spl-nodtb.bin with a microcode pointer inserted at the
1130 correct place
1131 u-boot.dtb with the microcode removed
1132 the microcode
Simon Glass736bb0a2018-07-06 10:27:17 -06001133
1134 Args:
1135 dts: Device tree file to use for test
1136 ucode_second: True if the microsecond entry is second instead of
1137 third
Simon Glass6b187df2017-11-12 21:52:27 -07001138 """
Simon Glass11ae93e2018-10-01 21:12:47 -06001139 self._SetupSplElf('u_boot_ucode_ptr')
Simon Glass736bb0a2018-07-06 10:27:17 -06001140 first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA,
1141 ucode_second=ucode_second)
Simon Glassc6c10e72019-05-17 22:00:46 -06001142 self.assertEqual(b'splnodtb with microc' + pos_and_size +
1143 b'ter somewhere in here', first)
Simon Glass6b187df2017-11-12 21:52:27 -07001144
Simon Glass736bb0a2018-07-06 10:27:17 -06001145 def testPackUbootSplMicrocode(self):
1146 """Test that x86 microcode can be handled correctly in SPL"""
Simon Glass741f2d62018-10-01 12:22:30 -06001147 self._PackUbootSplMicrocode('049_x86_ucode_spl.dts')
Simon Glass736bb0a2018-07-06 10:27:17 -06001148
1149 def testPackUbootSplMicrocodeReorder(self):
1150 """Test that order doesn't matter for microcode entries
1151
1152 This is the same as testPackUbootSplMicrocode but when we process the
1153 u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode
1154 entry, so we reply on binman to try later.
1155 """
Simon Glass741f2d62018-10-01 12:22:30 -06001156 self._PackUbootSplMicrocode('058_x86_ucode_spl_needs_retry.dts',
Simon Glass736bb0a2018-07-06 10:27:17 -06001157 ucode_second=True)
1158
Simon Glassca4f4ff2017-11-12 21:52:28 -07001159 def testPackMrc(self):
1160 """Test that an image with an MRC binary can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001161 data = self._DoReadFile('050_intel_mrc.dts')
Simon Glassca4f4ff2017-11-12 21:52:28 -07001162 self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
1163
Simon Glass47419ea2017-11-13 18:54:55 -07001164 def testSplDtb(self):
1165 """Test that an image with spl/u-boot-spl.dtb can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001166 data = self._DoReadFile('051_u_boot_spl_dtb.dts')
Simon Glass47419ea2017-11-13 18:54:55 -07001167 self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
1168
Simon Glass4e6fdbe2017-11-13 18:54:56 -07001169 def testSplNoDtb(self):
1170 """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001171 data = self._DoReadFile('052_u_boot_spl_nodtb.dts')
Simon Glass4e6fdbe2017-11-13 18:54:56 -07001172 self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
1173
Simon Glass19790632017-11-13 18:55:01 -07001174 def testSymbols(self):
1175 """Test binman can assign symbols embedded in U-Boot"""
1176 elf_fname = self.TestFile('u_boot_binman_syms')
1177 syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
1178 addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
Simon Glass3ab95982018-08-01 15:22:37 -06001179 self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
Simon Glass19790632017-11-13 18:55:01 -07001180
Simon Glass11ae93e2018-10-01 21:12:47 -06001181 self._SetupSplElf('u_boot_binman_syms')
Simon Glass741f2d62018-10-01 12:22:30 -06001182 data = self._DoReadFile('053_symbols.dts')
Simon Glass19790632017-11-13 18:55:01 -07001183 sym_values = struct.pack('<LQL', 0x24 + 0, 0x24 + 24, 0x24 + 20)
Simon Glasse6d85ff2019-05-14 15:53:47 -06001184 expected = (sym_values + U_BOOT_SPL_DATA[16:] +
1185 tools.GetBytes(0xff, 1) + U_BOOT_DATA + sym_values +
1186 U_BOOT_SPL_DATA[16:])
Simon Glass19790632017-11-13 18:55:01 -07001187 self.assertEqual(expected, data)
1188
Simon Glassdd57c132018-06-01 09:38:11 -06001189 def testPackUnitAddress(self):
1190 """Test that we support multiple binaries with the same name"""
Simon Glass741f2d62018-10-01 12:22:30 -06001191 data = self._DoReadFile('054_unit_address.dts')
Simon Glassdd57c132018-06-01 09:38:11 -06001192 self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
1193
Simon Glass18546952018-06-01 09:38:16 -06001194 def testSections(self):
1195 """Basic test of sections"""
Simon Glass741f2d62018-10-01 12:22:30 -06001196 data = self._DoReadFile('055_sections.dts')
Simon Glassc6c10e72019-05-17 22:00:46 -06001197 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1198 U_BOOT_DATA + tools.GetBytes(ord('a'), 12) +
1199 U_BOOT_DATA + tools.GetBytes(ord('&'), 4))
Simon Glass18546952018-06-01 09:38:16 -06001200 self.assertEqual(expected, data)
Simon Glass9fc60b42017-11-12 21:52:22 -07001201
Simon Glass3b0c3822018-06-01 09:38:20 -06001202 def testMap(self):
1203 """Tests outputting a map of the images"""
Simon Glass741f2d62018-10-01 12:22:30 -06001204 _, _, map_data, _ = self._DoReadFileDtb('055_sections.dts', map=True)
Simon Glass1be70d22018-07-17 13:25:49 -06001205 self.assertEqual('''ImagePos Offset Size Name
120600000000 00000000 00000028 main-section
120700000000 00000000 00000010 section@0
120800000000 00000000 00000004 u-boot
120900000010 00000010 00000010 section@1
121000000010 00000000 00000004 u-boot
121100000020 00000020 00000004 section@2
121200000020 00000000 00000004 u-boot
Simon Glass3b0c3822018-06-01 09:38:20 -06001213''', map_data)
1214
Simon Glassc8d48ef2018-06-01 09:38:21 -06001215 def testNamePrefix(self):
1216 """Tests that name prefixes are used"""
Simon Glass741f2d62018-10-01 12:22:30 -06001217 _, _, map_data, _ = self._DoReadFileDtb('056_name_prefix.dts', map=True)
Simon Glass1be70d22018-07-17 13:25:49 -06001218 self.assertEqual('''ImagePos Offset Size Name
121900000000 00000000 00000028 main-section
122000000000 00000000 00000010 section@0
122100000000 00000000 00000004 ro-u-boot
122200000010 00000010 00000010 section@1
122300000010 00000000 00000004 rw-u-boot
Simon Glassc8d48ef2018-06-01 09:38:21 -06001224''', map_data)
1225
Simon Glass736bb0a2018-07-06 10:27:17 -06001226 def testUnknownContents(self):
1227 """Test that obtaining the contents works as expected"""
1228 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001229 self._DoReadFile('057_unknown_contents.dts', True)
Simon Glass736bb0a2018-07-06 10:27:17 -06001230 self.assertIn("Section '/binman': Internal error: Could not complete "
1231 "processing of contents: remaining [<_testing.Entry__testing ",
1232 str(e.exception))
1233
Simon Glass5c890232018-07-06 10:27:19 -06001234 def testBadChangeSize(self):
1235 """Test that trying to change the size of an entry fails"""
1236 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001237 self._DoReadFile('059_change_size.dts', True)
Simon Glass5c890232018-07-06 10:27:19 -06001238 self.assertIn("Node '/binman/_testing': Cannot update entry size from "
1239 '2 to 1', str(e.exception))
1240
Simon Glass16b8d6b2018-07-06 10:27:42 -06001241 def testUpdateFdt(self):
Simon Glass3ab95982018-08-01 15:22:37 -06001242 """Test that we can update the device tree with offset/size info"""
Simon Glass741f2d62018-10-01 12:22:30 -06001243 _, _, _, out_dtb_fname = self._DoReadFileDtb('060_fdt_update.dts',
Simon Glass16b8d6b2018-07-06 10:27:42 -06001244 update_dtb=True)
Simon Glasscee02e62018-07-17 13:25:52 -06001245 dtb = fdt.Fdt(out_dtb_fname)
1246 dtb.Scan()
1247 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'])
Simon Glass16b8d6b2018-07-06 10:27:42 -06001248 self.assertEqual({
Simon Glassdbf6be92018-08-01 15:22:42 -06001249 'image-pos': 0,
Simon Glass8122f392018-07-17 13:25:28 -06001250 'offset': 0,
Simon Glass3ab95982018-08-01 15:22:37 -06001251 '_testing:offset': 32,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001252 '_testing:size': 1,
Simon Glassdbf6be92018-08-01 15:22:42 -06001253 '_testing:image-pos': 32,
Simon Glass3ab95982018-08-01 15:22:37 -06001254 'section@0/u-boot:offset': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001255 'section@0/u-boot:size': len(U_BOOT_DATA),
Simon Glassdbf6be92018-08-01 15:22:42 -06001256 'section@0/u-boot:image-pos': 0,
Simon Glass3ab95982018-08-01 15:22:37 -06001257 'section@0:offset': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001258 'section@0:size': 16,
Simon Glassdbf6be92018-08-01 15:22:42 -06001259 'section@0:image-pos': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001260
Simon Glass3ab95982018-08-01 15:22:37 -06001261 'section@1/u-boot:offset': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001262 'section@1/u-boot:size': len(U_BOOT_DATA),
Simon Glassdbf6be92018-08-01 15:22:42 -06001263 'section@1/u-boot:image-pos': 16,
Simon Glass3ab95982018-08-01 15:22:37 -06001264 'section@1:offset': 16,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001265 'section@1:size': 16,
Simon Glassdbf6be92018-08-01 15:22:42 -06001266 'section@1:image-pos': 16,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001267 'size': 40
1268 }, props)
1269
1270 def testUpdateFdtBad(self):
1271 """Test that we detect when ProcessFdt never completes"""
1272 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001273 self._DoReadFileDtb('061_fdt_update_bad.dts', update_dtb=True)
Simon Glass16b8d6b2018-07-06 10:27:42 -06001274 self.assertIn('Could not complete processing of Fdt: remaining '
1275 '[<_testing.Entry__testing', str(e.exception))
Simon Glass5c890232018-07-06 10:27:19 -06001276
Simon Glass53af22a2018-07-17 13:25:32 -06001277 def testEntryArgs(self):
1278 """Test passing arguments to entries from the command line"""
1279 entry_args = {
1280 'test-str-arg': 'test1',
1281 'test-int-arg': '456',
1282 }
Simon Glass741f2d62018-10-01 12:22:30 -06001283 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
Simon Glass53af22a2018-07-17 13:25:32 -06001284 self.assertIn('image', control.images)
1285 entry = control.images['image'].GetEntries()['_testing']
1286 self.assertEqual('test0', entry.test_str_fdt)
1287 self.assertEqual('test1', entry.test_str_arg)
1288 self.assertEqual(123, entry.test_int_fdt)
1289 self.assertEqual(456, entry.test_int_arg)
1290
1291 def testEntryArgsMissing(self):
1292 """Test missing arguments and properties"""
1293 entry_args = {
1294 'test-int-arg': '456',
1295 }
Simon Glass741f2d62018-10-01 12:22:30 -06001296 self._DoReadFileDtb('063_entry_args_missing.dts', entry_args=entry_args)
Simon Glass53af22a2018-07-17 13:25:32 -06001297 entry = control.images['image'].GetEntries()['_testing']
1298 self.assertEqual('test0', entry.test_str_fdt)
1299 self.assertEqual(None, entry.test_str_arg)
1300 self.assertEqual(None, entry.test_int_fdt)
1301 self.assertEqual(456, entry.test_int_arg)
1302
1303 def testEntryArgsRequired(self):
1304 """Test missing arguments and properties"""
1305 entry_args = {
1306 'test-int-arg': '456',
1307 }
1308 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001309 self._DoReadFileDtb('064_entry_args_required.dts')
Simon Glass53af22a2018-07-17 13:25:32 -06001310 self.assertIn("Node '/binman/_testing': Missing required "
1311 'properties/entry args: test-str-arg, test-int-fdt, test-int-arg',
1312 str(e.exception))
1313
1314 def testEntryArgsInvalidFormat(self):
1315 """Test that an invalid entry-argument format is detected"""
Simon Glass741f2d62018-10-01 12:22:30 -06001316 args = ['-d', self.TestFile('064_entry_args_required.dts'), '-ano-value']
Simon Glass53af22a2018-07-17 13:25:32 -06001317 with self.assertRaises(ValueError) as e:
1318 self._DoBinman(*args)
1319 self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
1320
1321 def testEntryArgsInvalidInteger(self):
1322 """Test that an invalid entry-argument integer is detected"""
1323 entry_args = {
1324 'test-int-arg': 'abc',
1325 }
1326 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001327 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
Simon Glass53af22a2018-07-17 13:25:32 -06001328 self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
1329 "'test-int-arg' (value 'abc') to integer",
1330 str(e.exception))
1331
1332 def testEntryArgsInvalidDatatype(self):
1333 """Test that an invalid entry-argument datatype is detected
1334
1335 This test could be written in entry_test.py except that it needs
1336 access to control.entry_args, which seems more than that module should
1337 be able to see.
1338 """
1339 entry_args = {
1340 'test-bad-datatype-arg': '12',
1341 }
1342 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001343 self._DoReadFileDtb('065_entry_args_unknown_datatype.dts',
Simon Glass53af22a2018-07-17 13:25:32 -06001344 entry_args=entry_args)
1345 self.assertIn('GetArg() internal error: Unknown data type ',
1346 str(e.exception))
1347
Simon Glassbb748372018-07-17 13:25:33 -06001348 def testText(self):
1349 """Test for a text entry type"""
1350 entry_args = {
1351 'test-id': TEXT_DATA,
1352 'test-id2': TEXT_DATA2,
1353 'test-id3': TEXT_DATA3,
1354 }
Simon Glass741f2d62018-10-01 12:22:30 -06001355 data, _, _, _ = self._DoReadFileDtb('066_text.dts',
Simon Glassbb748372018-07-17 13:25:33 -06001356 entry_args=entry_args)
Simon Glassc6c10e72019-05-17 22:00:46 -06001357 expected = (tools.ToBytes(TEXT_DATA) +
1358 tools.GetBytes(0, 8 - len(TEXT_DATA)) +
1359 tools.ToBytes(TEXT_DATA2) + tools.ToBytes(TEXT_DATA3) +
Simon Glassaa88b502019-07-08 13:18:40 -06001360 b'some text' + b'more text')
Simon Glassbb748372018-07-17 13:25:33 -06001361 self.assertEqual(expected, data)
1362
Simon Glassfd8d1f72018-07-17 13:25:36 -06001363 def testEntryDocs(self):
1364 """Test for creation of entry documentation"""
1365 with test_util.capture_sys_output() as (stdout, stderr):
1366 control.WriteEntryDocs(binman.GetEntryModules())
1367 self.assertTrue(len(stdout.getvalue()) > 0)
1368
1369 def testEntryDocsMissing(self):
1370 """Test handling of missing entry documentation"""
1371 with self.assertRaises(ValueError) as e:
1372 with test_util.capture_sys_output() as (stdout, stderr):
1373 control.WriteEntryDocs(binman.GetEntryModules(), 'u_boot')
1374 self.assertIn('Documentation is missing for modules: u_boot',
1375 str(e.exception))
1376
Simon Glass11e36cc2018-07-17 13:25:38 -06001377 def testFmap(self):
1378 """Basic test of generation of a flashrom fmap"""
Simon Glass741f2d62018-10-01 12:22:30 -06001379 data = self._DoReadFile('067_fmap.dts')
Simon Glass11e36cc2018-07-17 13:25:38 -06001380 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
Simon Glassc6c10e72019-05-17 22:00:46 -06001381 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1382 U_BOOT_DATA + tools.GetBytes(ord('a'), 12))
Simon Glass11e36cc2018-07-17 13:25:38 -06001383 self.assertEqual(expected, data[:32])
Simon Glassc6c10e72019-05-17 22:00:46 -06001384 self.assertEqual(b'__FMAP__', fhdr.signature)
Simon Glass11e36cc2018-07-17 13:25:38 -06001385 self.assertEqual(1, fhdr.ver_major)
1386 self.assertEqual(0, fhdr.ver_minor)
1387 self.assertEqual(0, fhdr.base)
1388 self.assertEqual(16 + 16 +
1389 fmap_util.FMAP_HEADER_LEN +
1390 fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001391 self.assertEqual(b'FMAP', fhdr.name)
Simon Glass11e36cc2018-07-17 13:25:38 -06001392 self.assertEqual(3, fhdr.nareas)
1393 for fentry in fentries:
1394 self.assertEqual(0, fentry.flags)
1395
1396 self.assertEqual(0, fentries[0].offset)
1397 self.assertEqual(4, fentries[0].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001398 self.assertEqual(b'RO_U_BOOT', fentries[0].name)
Simon Glass11e36cc2018-07-17 13:25:38 -06001399
1400 self.assertEqual(16, fentries[1].offset)
1401 self.assertEqual(4, fentries[1].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001402 self.assertEqual(b'RW_U_BOOT', fentries[1].name)
Simon Glass11e36cc2018-07-17 13:25:38 -06001403
1404 self.assertEqual(32, fentries[2].offset)
1405 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1406 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001407 self.assertEqual(b'FMAP', fentries[2].name)
Simon Glass11e36cc2018-07-17 13:25:38 -06001408
Simon Glassec127af2018-07-17 13:25:39 -06001409 def testBlobNamedByArg(self):
1410 """Test we can add a blob with the filename coming from an entry arg"""
1411 entry_args = {
1412 'cros-ec-rw-path': 'ecrw.bin',
1413 }
Simon Glass741f2d62018-10-01 12:22:30 -06001414 data, _, _, _ = self._DoReadFileDtb('068_blob_named_by_arg.dts',
Simon Glassec127af2018-07-17 13:25:39 -06001415 entry_args=entry_args)
1416
Simon Glass3af8e492018-07-17 13:25:40 -06001417 def testFill(self):
1418 """Test for an fill entry type"""
Simon Glass741f2d62018-10-01 12:22:30 -06001419 data = self._DoReadFile('069_fill.dts')
Simon Glasse6d85ff2019-05-14 15:53:47 -06001420 expected = tools.GetBytes(0xff, 8) + tools.GetBytes(0, 8)
Simon Glass3af8e492018-07-17 13:25:40 -06001421 self.assertEqual(expected, data)
1422
1423 def testFillNoSize(self):
1424 """Test for an fill entry type with no size"""
1425 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001426 self._DoReadFile('070_fill_no_size.dts')
Simon Glass3af8e492018-07-17 13:25:40 -06001427 self.assertIn("'fill' entry must have a size property",
1428 str(e.exception))
1429
Simon Glass0ef87aa2018-07-17 13:25:44 -06001430 def _HandleGbbCommand(self, pipe_list):
1431 """Fake calls to the futility utility"""
1432 if pipe_list[0][0] == 'futility':
1433 fname = pipe_list[0][-1]
1434 # Append our GBB data to the file, which will happen every time the
1435 # futility command is called.
Simon Glass1d0ebf72019-05-14 15:53:42 -06001436 with open(fname, 'ab') as fd:
Simon Glass0ef87aa2018-07-17 13:25:44 -06001437 fd.write(GBB_DATA)
1438 return command.CommandResult()
1439
1440 def testGbb(self):
1441 """Test for the Chromium OS Google Binary Block"""
1442 command.test_result = self._HandleGbbCommand
1443 entry_args = {
1444 'keydir': 'devkeys',
1445 'bmpblk': 'bmpblk.bin',
1446 }
Simon Glass741f2d62018-10-01 12:22:30 -06001447 data, _, _, _ = self._DoReadFileDtb('071_gbb.dts', entry_args=entry_args)
Simon Glass0ef87aa2018-07-17 13:25:44 -06001448
1449 # Since futility
Simon Glasse6d85ff2019-05-14 15:53:47 -06001450 expected = (GBB_DATA + GBB_DATA + tools.GetBytes(0, 8) +
1451 tools.GetBytes(0, 0x2180 - 16))
Simon Glass0ef87aa2018-07-17 13:25:44 -06001452 self.assertEqual(expected, data)
1453
1454 def testGbbTooSmall(self):
1455 """Test for the Chromium OS Google Binary Block being large enough"""
1456 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001457 self._DoReadFileDtb('072_gbb_too_small.dts')
Simon Glass0ef87aa2018-07-17 13:25:44 -06001458 self.assertIn("Node '/binman/gbb': GBB is too small",
1459 str(e.exception))
1460
1461 def testGbbNoSize(self):
1462 """Test for the Chromium OS Google Binary Block having a size"""
1463 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001464 self._DoReadFileDtb('073_gbb_no_size.dts')
Simon Glass0ef87aa2018-07-17 13:25:44 -06001465 self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
1466 str(e.exception))
1467
Simon Glass24d0d3c2018-07-17 13:25:47 -06001468 def _HandleVblockCommand(self, pipe_list):
1469 """Fake calls to the futility utility"""
1470 if pipe_list[0][0] == 'futility':
1471 fname = pipe_list[0][3]
Simon Glassa326b492018-09-14 04:57:11 -06001472 with open(fname, 'wb') as fd:
Simon Glass24d0d3c2018-07-17 13:25:47 -06001473 fd.write(VBLOCK_DATA)
1474 return command.CommandResult()
1475
1476 def testVblock(self):
1477 """Test for the Chromium OS Verified Boot Block"""
1478 command.test_result = self._HandleVblockCommand
1479 entry_args = {
1480 'keydir': 'devkeys',
1481 }
Simon Glass741f2d62018-10-01 12:22:30 -06001482 data, _, _, _ = self._DoReadFileDtb('074_vblock.dts',
Simon Glass24d0d3c2018-07-17 13:25:47 -06001483 entry_args=entry_args)
1484 expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
1485 self.assertEqual(expected, data)
1486
1487 def testVblockNoContent(self):
1488 """Test we detect a vblock which has no content to sign"""
1489 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001490 self._DoReadFile('075_vblock_no_content.dts')
Simon Glass24d0d3c2018-07-17 13:25:47 -06001491 self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
1492 'property', str(e.exception))
1493
1494 def testVblockBadPhandle(self):
1495 """Test that we detect a vblock with an invalid phandle in contents"""
1496 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001497 self._DoReadFile('076_vblock_bad_phandle.dts')
Simon Glass24d0d3c2018-07-17 13:25:47 -06001498 self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
1499 '1000', str(e.exception))
1500
1501 def testVblockBadEntry(self):
1502 """Test that we detect an entry that points to a non-entry"""
1503 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001504 self._DoReadFile('077_vblock_bad_entry.dts')
Simon Glass24d0d3c2018-07-17 13:25:47 -06001505 self.assertIn("Node '/binman/vblock': Cannot find entry for node "
1506 "'other'", str(e.exception))
1507
Simon Glassb8ef5b62018-07-17 13:25:48 -06001508 def testTpl(self):
1509 """Test that an image with TPL and ots device tree can be created"""
1510 # ELF file with a '__bss_size' symbol
Simon Glass1d0ebf72019-05-14 15:53:42 -06001511 with open(self.TestFile('bss_data'), 'rb') as fd:
Simon Glassb8ef5b62018-07-17 13:25:48 -06001512 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
Simon Glass741f2d62018-10-01 12:22:30 -06001513 data = self._DoReadFile('078_u_boot_tpl.dts')
Simon Glassb8ef5b62018-07-17 13:25:48 -06001514 self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
1515
Simon Glass15a587c2018-07-17 13:25:51 -06001516 def testUsesPos(self):
1517 """Test that the 'pos' property cannot be used anymore"""
1518 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001519 data = self._DoReadFile('079_uses_pos.dts')
Simon Glass15a587c2018-07-17 13:25:51 -06001520 self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
1521 "'pos'", str(e.exception))
1522
Simon Glassd178eab2018-09-14 04:57:08 -06001523 def testFillZero(self):
1524 """Test for an fill entry type with a size of 0"""
Simon Glass741f2d62018-10-01 12:22:30 -06001525 data = self._DoReadFile('080_fill_empty.dts')
Simon Glasse6d85ff2019-05-14 15:53:47 -06001526 self.assertEqual(tools.GetBytes(0, 16), data)
Simon Glassd178eab2018-09-14 04:57:08 -06001527
Simon Glass0b489362018-09-14 04:57:09 -06001528 def testTextMissing(self):
1529 """Test for a text entry type where there is no text"""
1530 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001531 self._DoReadFileDtb('066_text.dts',)
Simon Glass0b489362018-09-14 04:57:09 -06001532 self.assertIn("Node '/binman/text': No value provided for text label "
1533 "'test-id'", str(e.exception))
1534
Simon Glass35b384c2018-09-14 04:57:10 -06001535 def testPackStart16Tpl(self):
1536 """Test that an image with an x86 start16 TPL region can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001537 data = self._DoReadFile('081_x86-start16-tpl.dts')
Simon Glass35b384c2018-09-14 04:57:10 -06001538 self.assertEqual(X86_START16_TPL_DATA, data[:len(X86_START16_TPL_DATA)])
1539
Simon Glass0bfa7b02018-09-14 04:57:12 -06001540 def testSelectImage(self):
1541 """Test that we can select which images to build"""
Simon Glasseb833d82019-04-25 21:58:34 -06001542 expected = 'Skipping images: image1'
Simon Glass0bfa7b02018-09-14 04:57:12 -06001543
Simon Glasseb833d82019-04-25 21:58:34 -06001544 # We should only get the expected message in verbose mode
Simon Glassee0c9a72019-07-08 13:18:48 -06001545 for verbosity in (0, 2):
Simon Glasseb833d82019-04-25 21:58:34 -06001546 with test_util.capture_sys_output() as (stdout, stderr):
1547 retcode = self._DoTestFile('006_dual_image.dts',
1548 verbosity=verbosity,
1549 images=['image2'])
1550 self.assertEqual(0, retcode)
1551 if verbosity:
1552 self.assertIn(expected, stdout.getvalue())
1553 else:
1554 self.assertNotIn(expected, stdout.getvalue())
1555
1556 self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
1557 self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
Simon Glass0bfa7b02018-09-14 04:57:12 -06001558
Simon Glass6ed45ba2018-09-14 04:57:24 -06001559 def testUpdateFdtAll(self):
1560 """Test that all device trees are updated with offset/size info"""
Simon Glass3c081312019-07-08 14:25:26 -06001561 data = self._DoReadFileRealDtb('082_fdt_update_all.dts')
Simon Glass6ed45ba2018-09-14 04:57:24 -06001562
1563 base_expected = {
1564 'section:image-pos': 0,
1565 'u-boot-tpl-dtb:size': 513,
1566 'u-boot-spl-dtb:size': 513,
1567 'u-boot-spl-dtb:offset': 493,
1568 'image-pos': 0,
1569 'section/u-boot-dtb:image-pos': 0,
1570 'u-boot-spl-dtb:image-pos': 493,
1571 'section/u-boot-dtb:size': 493,
1572 'u-boot-tpl-dtb:image-pos': 1006,
1573 'section/u-boot-dtb:offset': 0,
1574 'section:size': 493,
1575 'offset': 0,
1576 'section:offset': 0,
1577 'u-boot-tpl-dtb:offset': 1006,
1578 'size': 1519
1579 }
1580
1581 # We expect three device-tree files in the output, one after the other.
1582 # Read them in sequence. We look for an 'spl' property in the SPL tree,
1583 # and 'tpl' in the TPL tree, to make sure they are distinct from the
1584 # main U-Boot tree. All three should have the same postions and offset.
1585 start = 0
1586 for item in ['', 'spl', 'tpl']:
1587 dtb = fdt.Fdt.FromData(data[start:])
1588 dtb.Scan()
1589 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos',
1590 'spl', 'tpl'])
1591 expected = dict(base_expected)
1592 if item:
1593 expected[item] = 0
1594 self.assertEqual(expected, props)
1595 start += dtb._fdt_obj.totalsize()
1596
1597 def testUpdateFdtOutput(self):
1598 """Test that output DTB files are updated"""
1599 try:
Simon Glass741f2d62018-10-01 12:22:30 -06001600 data, dtb_data, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
Simon Glass6ed45ba2018-09-14 04:57:24 -06001601 use_real_dtb=True, update_dtb=True, reset_dtbs=False)
1602
1603 # Unfortunately, compiling a source file always results in a file
1604 # called source.dtb (see fdt_util.EnsureCompiled()). The test
Simon Glass741f2d62018-10-01 12:22:30 -06001605 # source file (e.g. test/075_fdt_update_all.dts) thus does not enter
Simon Glass6ed45ba2018-09-14 04:57:24 -06001606 # binman as a file called u-boot.dtb. To fix this, copy the file
1607 # over to the expected place.
1608 #tools.WriteFile(os.path.join(self._indir, 'u-boot.dtb'),
1609 #tools.ReadFile(tools.GetOutputFilename('source.dtb')))
1610 start = 0
1611 for fname in ['u-boot.dtb.out', 'spl/u-boot-spl.dtb.out',
1612 'tpl/u-boot-tpl.dtb.out']:
1613 dtb = fdt.Fdt.FromData(data[start:])
1614 size = dtb._fdt_obj.totalsize()
1615 pathname = tools.GetOutputFilename(os.path.split(fname)[1])
1616 outdata = tools.ReadFile(pathname)
1617 name = os.path.split(fname)[0]
1618
1619 if name:
1620 orig_indata = self._GetDtbContentsForSplTpl(dtb_data, name)
1621 else:
1622 orig_indata = dtb_data
1623 self.assertNotEqual(outdata, orig_indata,
1624 "Expected output file '%s' be updated" % pathname)
1625 self.assertEqual(outdata, data[start:start + size],
1626 "Expected output file '%s' to match output image" %
1627 pathname)
1628 start += size
1629 finally:
1630 self._ResetDtbs()
1631
Simon Glass83d73c22018-09-14 04:57:26 -06001632 def _decompress(self, data):
Simon Glassff5c7e32019-07-08 13:18:42 -06001633 return tools.Decompress(data, 'lz4')
Simon Glass83d73c22018-09-14 04:57:26 -06001634
1635 def testCompress(self):
1636 """Test compression of blobs"""
Simon Glassac62fba2019-07-08 13:18:53 -06001637 self._CheckLz4()
Simon Glass741f2d62018-10-01 12:22:30 -06001638 data, _, _, out_dtb_fname = self._DoReadFileDtb('083_compress.dts',
Simon Glass83d73c22018-09-14 04:57:26 -06001639 use_real_dtb=True, update_dtb=True)
1640 dtb = fdt.Fdt(out_dtb_fname)
1641 dtb.Scan()
1642 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
1643 orig = self._decompress(data)
1644 self.assertEquals(COMPRESS_DATA, orig)
1645 expected = {
1646 'blob:uncomp-size': len(COMPRESS_DATA),
1647 'blob:size': len(data),
1648 'size': len(data),
1649 }
1650 self.assertEqual(expected, props)
1651
Simon Glass0a98b282018-09-14 04:57:28 -06001652 def testFiles(self):
1653 """Test bringing in multiple files"""
Simon Glass741f2d62018-10-01 12:22:30 -06001654 data = self._DoReadFile('084_files.dts')
Simon Glass0a98b282018-09-14 04:57:28 -06001655 self.assertEqual(FILES_DATA, data)
1656
1657 def testFilesCompress(self):
1658 """Test bringing in multiple files and compressing them"""
Simon Glassac62fba2019-07-08 13:18:53 -06001659 self._CheckLz4()
Simon Glass741f2d62018-10-01 12:22:30 -06001660 data = self._DoReadFile('085_files_compress.dts')
Simon Glass0a98b282018-09-14 04:57:28 -06001661
1662 image = control.images['image']
1663 entries = image.GetEntries()
1664 files = entries['files']
1665 entries = files._section._entries
1666
Simon Glassc6c10e72019-05-17 22:00:46 -06001667 orig = b''
Simon Glass0a98b282018-09-14 04:57:28 -06001668 for i in range(1, 3):
1669 key = '%d.dat' % i
1670 start = entries[key].image_pos
1671 len = entries[key].size
1672 chunk = data[start:start + len]
1673 orig += self._decompress(chunk)
1674
1675 self.assertEqual(FILES_DATA, orig)
1676
1677 def testFilesMissing(self):
1678 """Test missing files"""
1679 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001680 data = self._DoReadFile('086_files_none.dts')
Simon Glass0a98b282018-09-14 04:57:28 -06001681 self.assertIn("Node '/binman/files': Pattern \'files/*.none\' matched "
1682 'no files', str(e.exception))
1683
1684 def testFilesNoPattern(self):
1685 """Test missing files"""
1686 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001687 data = self._DoReadFile('087_files_no_pattern.dts')
Simon Glass0a98b282018-09-14 04:57:28 -06001688 self.assertIn("Node '/binman/files': Missing 'pattern' property",
1689 str(e.exception))
1690
Simon Glassba64a0b2018-09-14 04:57:29 -06001691 def testExpandSize(self):
1692 """Test an expanding entry"""
Simon Glass741f2d62018-10-01 12:22:30 -06001693 data, _, map_data, _ = self._DoReadFileDtb('088_expand_size.dts',
Simon Glassba64a0b2018-09-14 04:57:29 -06001694 map=True)
Simon Glassc6c10e72019-05-17 22:00:46 -06001695 expect = (tools.GetBytes(ord('a'), 8) + U_BOOT_DATA +
1696 MRC_DATA + tools.GetBytes(ord('b'), 1) + U_BOOT_DATA +
1697 tools.GetBytes(ord('c'), 8) + U_BOOT_DATA +
1698 tools.GetBytes(ord('d'), 8))
Simon Glassba64a0b2018-09-14 04:57:29 -06001699 self.assertEqual(expect, data)
1700 self.assertEqual('''ImagePos Offset Size Name
170100000000 00000000 00000028 main-section
170200000000 00000000 00000008 fill
170300000008 00000008 00000004 u-boot
17040000000c 0000000c 00000004 section
17050000000c 00000000 00000003 intel-mrc
170600000010 00000010 00000004 u-boot2
170700000014 00000014 0000000c section2
170800000014 00000000 00000008 fill
17090000001c 00000008 00000004 u-boot
171000000020 00000020 00000008 fill2
1711''', map_data)
1712
1713 def testExpandSizeBad(self):
1714 """Test an expanding entry which fails to provide contents"""
Simon Glass163ed6c2018-09-14 04:57:36 -06001715 with test_util.capture_sys_output() as (stdout, stderr):
1716 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001717 self._DoReadFileDtb('089_expand_size_bad.dts', map=True)
Simon Glassba64a0b2018-09-14 04:57:29 -06001718 self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
1719 'expanding entry', str(e.exception))
1720
Simon Glasse0e5df92018-09-14 04:57:31 -06001721 def testHash(self):
1722 """Test hashing of the contents of an entry"""
Simon Glass741f2d62018-10-01 12:22:30 -06001723 _, _, _, out_dtb_fname = self._DoReadFileDtb('090_hash.dts',
Simon Glasse0e5df92018-09-14 04:57:31 -06001724 use_real_dtb=True, update_dtb=True)
1725 dtb = fdt.Fdt(out_dtb_fname)
1726 dtb.Scan()
1727 hash_node = dtb.GetNode('/binman/u-boot/hash').props['value']
1728 m = hashlib.sha256()
1729 m.update(U_BOOT_DATA)
Simon Glassc6c10e72019-05-17 22:00:46 -06001730 self.assertEqual(m.digest(), b''.join(hash_node.value))
Simon Glasse0e5df92018-09-14 04:57:31 -06001731
1732 def testHashNoAlgo(self):
1733 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001734 self._DoReadFileDtb('091_hash_no_algo.dts', update_dtb=True)
Simon Glasse0e5df92018-09-14 04:57:31 -06001735 self.assertIn("Node \'/binman/u-boot\': Missing \'algo\' property for "
1736 'hash node', str(e.exception))
1737
1738 def testHashBadAlgo(self):
1739 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001740 self._DoReadFileDtb('092_hash_bad_algo.dts', update_dtb=True)
Simon Glasse0e5df92018-09-14 04:57:31 -06001741 self.assertIn("Node '/binman/u-boot': Unknown hash algorithm",
1742 str(e.exception))
1743
1744 def testHashSection(self):
1745 """Test hashing of the contents of an entry"""
Simon Glass741f2d62018-10-01 12:22:30 -06001746 _, _, _, out_dtb_fname = self._DoReadFileDtb('099_hash_section.dts',
Simon Glasse0e5df92018-09-14 04:57:31 -06001747 use_real_dtb=True, update_dtb=True)
1748 dtb = fdt.Fdt(out_dtb_fname)
1749 dtb.Scan()
1750 hash_node = dtb.GetNode('/binman/section/hash').props['value']
1751 m = hashlib.sha256()
1752 m.update(U_BOOT_DATA)
Simon Glassc6c10e72019-05-17 22:00:46 -06001753 m.update(tools.GetBytes(ord('a'), 16))
1754 self.assertEqual(m.digest(), b''.join(hash_node.value))
Simon Glasse0e5df92018-09-14 04:57:31 -06001755
Simon Glassf0253632018-09-14 04:57:32 -06001756 def testPackUBootTplMicrocode(self):
1757 """Test that x86 microcode can be handled correctly in TPL
1758
1759 We expect to see the following in the image, in order:
1760 u-boot-tpl-nodtb.bin with a microcode pointer inserted at the correct
1761 place
1762 u-boot-tpl.dtb with the microcode removed
1763 the microcode
1764 """
Simon Glass1d0ebf72019-05-14 15:53:42 -06001765 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
Simon Glassf0253632018-09-14 04:57:32 -06001766 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
Simon Glass741f2d62018-10-01 12:22:30 -06001767 first, pos_and_size = self._RunMicrocodeTest('093_x86_tpl_ucode.dts',
Simon Glassf0253632018-09-14 04:57:32 -06001768 U_BOOT_TPL_NODTB_DATA)
Simon Glassc6c10e72019-05-17 22:00:46 -06001769 self.assertEqual(b'tplnodtb with microc' + pos_and_size +
1770 b'ter somewhere in here', first)
Simon Glassf0253632018-09-14 04:57:32 -06001771
Simon Glassf8f8df62018-09-14 04:57:34 -06001772 def testFmapX86(self):
1773 """Basic test of generation of a flashrom fmap"""
Simon Glass741f2d62018-10-01 12:22:30 -06001774 data = self._DoReadFile('094_fmap_x86.dts')
Simon Glassf8f8df62018-09-14 04:57:34 -06001775 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
Simon Glassc6c10e72019-05-17 22:00:46 -06001776 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('a'), 32 - 7)
Simon Glassf8f8df62018-09-14 04:57:34 -06001777 self.assertEqual(expected, data[:32])
1778 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1779
1780 self.assertEqual(0x100, fhdr.image_size)
1781
1782 self.assertEqual(0, fentries[0].offset)
1783 self.assertEqual(4, fentries[0].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001784 self.assertEqual(b'U_BOOT', fentries[0].name)
Simon Glassf8f8df62018-09-14 04:57:34 -06001785
1786 self.assertEqual(4, fentries[1].offset)
1787 self.assertEqual(3, fentries[1].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001788 self.assertEqual(b'INTEL_MRC', fentries[1].name)
Simon Glassf8f8df62018-09-14 04:57:34 -06001789
1790 self.assertEqual(32, fentries[2].offset)
1791 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1792 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001793 self.assertEqual(b'FMAP', fentries[2].name)
Simon Glassf8f8df62018-09-14 04:57:34 -06001794
1795 def testFmapX86Section(self):
1796 """Basic test of generation of a flashrom fmap"""
Simon Glass741f2d62018-10-01 12:22:30 -06001797 data = self._DoReadFile('095_fmap_x86_section.dts')
Simon Glassc6c10e72019-05-17 22:00:46 -06001798 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('b'), 32 - 7)
Simon Glassf8f8df62018-09-14 04:57:34 -06001799 self.assertEqual(expected, data[:32])
1800 fhdr, fentries = fmap_util.DecodeFmap(data[36:])
1801
1802 self.assertEqual(0x100, fhdr.image_size)
1803
1804 self.assertEqual(0, fentries[0].offset)
1805 self.assertEqual(4, fentries[0].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001806 self.assertEqual(b'U_BOOT', fentries[0].name)
Simon Glassf8f8df62018-09-14 04:57:34 -06001807
1808 self.assertEqual(4, fentries[1].offset)
1809 self.assertEqual(3, fentries[1].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001810 self.assertEqual(b'INTEL_MRC', fentries[1].name)
Simon Glassf8f8df62018-09-14 04:57:34 -06001811
1812 self.assertEqual(36, fentries[2].offset)
1813 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1814 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001815 self.assertEqual(b'FMAP', fentries[2].name)
Simon Glassf8f8df62018-09-14 04:57:34 -06001816
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001817 def testElf(self):
1818 """Basic test of ELF entries"""
Simon Glass11ae93e2018-10-01 21:12:47 -06001819 self._SetupSplElf()
Simon Glass1d0ebf72019-05-14 15:53:42 -06001820 with open(self.TestFile('bss_data'), 'rb') as fd:
Simon Glass4c650252019-07-08 13:18:46 -06001821 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1822 with open(self.TestFile('bss_data'), 'rb') as fd:
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001823 TestFunctional._MakeInputFile('-boot', fd.read())
Simon Glass741f2d62018-10-01 12:22:30 -06001824 data = self._DoReadFile('096_elf.dts')
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001825
Simon Glass093d1682019-07-08 13:18:25 -06001826 def testElfStrip(self):
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001827 """Basic test of ELF entries"""
Simon Glass11ae93e2018-10-01 21:12:47 -06001828 self._SetupSplElf()
Simon Glass1d0ebf72019-05-14 15:53:42 -06001829 with open(self.TestFile('bss_data'), 'rb') as fd:
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001830 TestFunctional._MakeInputFile('-boot', fd.read())
Simon Glass741f2d62018-10-01 12:22:30 -06001831 data = self._DoReadFile('097_elf_strip.dts')
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001832
Simon Glass163ed6c2018-09-14 04:57:36 -06001833 def testPackOverlapMap(self):
1834 """Test that overlapping regions are detected"""
1835 with test_util.capture_sys_output() as (stdout, stderr):
1836 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001837 self._DoTestFile('014_pack_overlap.dts', map=True)
Simon Glass163ed6c2018-09-14 04:57:36 -06001838 map_fname = tools.GetOutputFilename('image.map')
1839 self.assertEqual("Wrote map file '%s' to show errors\n" % map_fname,
1840 stdout.getvalue())
1841
1842 # We should not get an inmage, but there should be a map file
1843 self.assertFalse(os.path.exists(tools.GetOutputFilename('image.bin')))
1844 self.assertTrue(os.path.exists(map_fname))
Simon Glasseb546ac2019-05-17 22:00:51 -06001845 map_data = tools.ReadFile(map_fname, binary=False)
Simon Glass163ed6c2018-09-14 04:57:36 -06001846 self.assertEqual('''ImagePos Offset Size Name
1847<none> 00000000 00000007 main-section
1848<none> 00000000 00000004 u-boot
1849<none> 00000003 00000004 u-boot-align
1850''', map_data)
1851
Simon Glass093d1682019-07-08 13:18:25 -06001852 def testPackRefCode(self):
Simon Glass3ae192c2018-10-01 12:22:31 -06001853 """Test that an image with an Intel Reference code binary works"""
1854 data = self._DoReadFile('100_intel_refcode.dts')
1855 self.assertEqual(REFCODE_DATA, data[:len(REFCODE_DATA)])
1856
Simon Glass9481c802019-04-25 21:58:39 -06001857 def testSectionOffset(self):
1858 """Tests use of a section with an offset"""
1859 data, _, map_data, _ = self._DoReadFileDtb('101_sections_offset.dts',
1860 map=True)
1861 self.assertEqual('''ImagePos Offset Size Name
186200000000 00000000 00000038 main-section
186300000004 00000004 00000010 section@0
186400000004 00000000 00000004 u-boot
186500000018 00000018 00000010 section@1
186600000018 00000000 00000004 u-boot
18670000002c 0000002c 00000004 section@2
18680000002c 00000000 00000004 u-boot
1869''', map_data)
1870 self.assertEqual(data,
Simon Glasse6d85ff2019-05-14 15:53:47 -06001871 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1872 tools.GetBytes(0x21, 12) +
1873 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1874 tools.GetBytes(0x61, 12) +
1875 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1876 tools.GetBytes(0x26, 8))
Simon Glass9481c802019-04-25 21:58:39 -06001877
Simon Glassac62fba2019-07-08 13:18:53 -06001878 def testCbfsRaw(self):
1879 """Test base handling of a Coreboot Filesystem (CBFS)
1880
1881 The exact contents of the CBFS is verified by similar tests in
1882 cbfs_util_test.py. The tests here merely check that the files added to
1883 the CBFS can be found in the final image.
1884 """
1885 data = self._DoReadFile('102_cbfs_raw.dts')
1886 size = 0xb0
1887
1888 cbfs = cbfs_util.CbfsReader(data)
1889 self.assertEqual(size, cbfs.rom_size)
1890
1891 self.assertIn('u-boot-dtb', cbfs.files)
1892 cfile = cbfs.files['u-boot-dtb']
1893 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
1894
1895 def testCbfsArch(self):
1896 """Test on non-x86 architecture"""
1897 data = self._DoReadFile('103_cbfs_raw_ppc.dts')
1898 size = 0x100
1899
1900 cbfs = cbfs_util.CbfsReader(data)
1901 self.assertEqual(size, cbfs.rom_size)
1902
1903 self.assertIn('u-boot-dtb', cbfs.files)
1904 cfile = cbfs.files['u-boot-dtb']
1905 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
1906
1907 def testCbfsStage(self):
1908 """Tests handling of a Coreboot Filesystem (CBFS)"""
1909 if not elf.ELF_TOOLS:
1910 self.skipTest('Python elftools not available')
1911 elf_fname = os.path.join(self._indir, 'cbfs-stage.elf')
1912 elf.MakeElf(elf_fname, U_BOOT_DATA, U_BOOT_DTB_DATA)
1913 size = 0xb0
1914
1915 data = self._DoReadFile('104_cbfs_stage.dts')
1916 cbfs = cbfs_util.CbfsReader(data)
1917 self.assertEqual(size, cbfs.rom_size)
1918
1919 self.assertIn('u-boot', cbfs.files)
1920 cfile = cbfs.files['u-boot']
1921 self.assertEqual(U_BOOT_DATA + U_BOOT_DTB_DATA, cfile.data)
1922
1923 def testCbfsRawCompress(self):
1924 """Test handling of compressing raw files"""
1925 self._CheckLz4()
1926 data = self._DoReadFile('105_cbfs_raw_compress.dts')
1927 size = 0x140
1928
1929 cbfs = cbfs_util.CbfsReader(data)
1930 self.assertIn('u-boot', cbfs.files)
1931 cfile = cbfs.files['u-boot']
1932 self.assertEqual(COMPRESS_DATA, cfile.data)
1933
1934 def testCbfsBadArch(self):
1935 """Test handling of a bad architecture"""
1936 with self.assertRaises(ValueError) as e:
1937 self._DoReadFile('106_cbfs_bad_arch.dts')
1938 self.assertIn("Invalid architecture 'bad-arch'", str(e.exception))
1939
1940 def testCbfsNoSize(self):
1941 """Test handling of a missing size property"""
1942 with self.assertRaises(ValueError) as e:
1943 self._DoReadFile('107_cbfs_no_size.dts')
1944 self.assertIn('entry must have a size property', str(e.exception))
1945
1946 def testCbfsNoCOntents(self):
1947 """Test handling of a CBFS entry which does not provide contentsy"""
1948 with self.assertRaises(ValueError) as e:
1949 self._DoReadFile('108_cbfs_no_contents.dts')
1950 self.assertIn('Could not complete processing of contents',
1951 str(e.exception))
1952
1953 def testCbfsBadCompress(self):
1954 """Test handling of a bad architecture"""
1955 with self.assertRaises(ValueError) as e:
1956 self._DoReadFile('109_cbfs_bad_compress.dts')
1957 self.assertIn("Invalid compression in 'u-boot': 'invalid-algo'",
1958 str(e.exception))
1959
1960 def testCbfsNamedEntries(self):
1961 """Test handling of named entries"""
1962 data = self._DoReadFile('110_cbfs_name.dts')
1963
1964 cbfs = cbfs_util.CbfsReader(data)
1965 self.assertIn('FRED', cbfs.files)
1966 cfile1 = cbfs.files['FRED']
1967 self.assertEqual(U_BOOT_DATA, cfile1.data)
1968
1969 self.assertIn('hello', cbfs.files)
1970 cfile2 = cbfs.files['hello']
1971 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
1972
Simon Glassc5ac1382019-07-08 13:18:54 -06001973 def _SetupIfwi(self, fname):
1974 """Set up to run an IFWI test
1975
1976 Args:
1977 fname: Filename of input file to provide (fitimage.bin or ifwi.bin)
1978 """
1979 self._SetupSplElf()
1980
1981 # Intel Integrated Firmware Image (IFWI) file
1982 with gzip.open(self.TestFile('%s.gz' % fname), 'rb') as fd:
1983 data = fd.read()
1984 TestFunctional._MakeInputFile(fname,data)
1985
1986 def _CheckIfwi(self, data):
1987 """Check that an image with an IFWI contains the correct output
1988
1989 Args:
1990 data: Conents of output file
1991 """
1992 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
1993 if data[:0x1000] != expected_desc:
1994 self.fail('Expected descriptor binary at start of image')
1995
1996 # We expect to find the TPL wil in subpart IBBP entry IBBL
1997 image_fname = tools.GetOutputFilename('image.bin')
1998 tpl_fname = tools.GetOutputFilename('tpl.out')
1999 tools.RunIfwiTool(image_fname, tools.CMD_EXTRACT, fname=tpl_fname,
2000 subpart='IBBP', entry_name='IBBL')
2001
2002 tpl_data = tools.ReadFile(tpl_fname)
2003 self.assertEqual(tpl_data[:len(U_BOOT_TPL_DATA)], U_BOOT_TPL_DATA)
2004
2005 def testPackX86RomIfwi(self):
2006 """Test that an x86 ROM with Integrated Firmware Image can be created"""
2007 self._SetupIfwi('fitimage.bin')
2008 data = self._DoReadFile('111_x86-rom-ifwi.dts')
2009 self._CheckIfwi(data)
2010
2011 def testPackX86RomIfwiNoDesc(self):
2012 """Test that an x86 ROM with IFWI can be created from an ifwi.bin file"""
2013 self._SetupIfwi('ifwi.bin')
2014 data = self._DoReadFile('112_x86-rom-ifwi-nodesc.dts')
2015 self._CheckIfwi(data)
2016
2017 def testPackX86RomIfwiNoData(self):
2018 """Test that an x86 ROM with IFWI handles missing data"""
2019 self._SetupIfwi('ifwi.bin')
2020 with self.assertRaises(ValueError) as e:
2021 data = self._DoReadFile('113_x86-rom-ifwi-nodata.dts')
2022 self.assertIn('Could not complete processing of contents',
2023 str(e.exception))
Simon Glass53af22a2018-07-17 13:25:32 -06002024
Simon Glasse073d4e2019-07-08 13:18:56 -06002025 def testCbfsOffset(self):
2026 """Test a CBFS with files at particular offsets
2027
2028 Like all CFBS tests, this is just checking the logic that calls
2029 cbfs_util. See cbfs_util_test for fully tests (e.g. test_cbfs_offset()).
2030 """
2031 data = self._DoReadFile('114_cbfs_offset.dts')
2032 size = 0x200
2033
2034 cbfs = cbfs_util.CbfsReader(data)
2035 self.assertEqual(size, cbfs.rom_size)
2036
2037 self.assertIn('u-boot', cbfs.files)
2038 cfile = cbfs.files['u-boot']
2039 self.assertEqual(U_BOOT_DATA, cfile.data)
2040 self.assertEqual(0x40, cfile.cbfs_offset)
2041
2042 self.assertIn('u-boot-dtb', cbfs.files)
2043 cfile2 = cbfs.files['u-boot-dtb']
2044 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
2045 self.assertEqual(0x140, cfile2.cbfs_offset)
2046
Simon Glass086cec92019-07-08 14:25:27 -06002047 def testFdtmap(self):
2048 """Test an FDT map can be inserted in the image"""
2049 data = self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
2050 fdtmap_data = data[len(U_BOOT_DATA):]
2051 magic = fdtmap_data[:8]
2052 self.assertEqual('_FDTMAP_', magic)
2053 self.assertEqual(tools.GetBytes(0, 8), fdtmap_data[8:16])
2054
2055 fdt_data = fdtmap_data[16:]
2056 dtb = fdt.Fdt.FromData(fdt_data)
2057 dtb.Scan()
2058 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'],
2059 prefix='/')
2060 self.assertEqual({
2061 'image-pos': 0,
2062 'offset': 0,
2063 'u-boot:offset': 0,
2064 'u-boot:size': len(U_BOOT_DATA),
2065 'u-boot:image-pos': 0,
2066 'fdtmap:image-pos': 4,
2067 'fdtmap:offset': 4,
2068 'fdtmap:size': len(fdtmap_data),
2069 'size': len(data),
2070 }, props)
2071
2072 def testFdtmapNoMatch(self):
2073 """Check handling of an FDT map when the section cannot be found"""
2074 self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
2075
2076 # Mangle the section name, which should cause a mismatch between the
2077 # correct FDT path and the one expected by the section
2078 image = control.images['image']
Simon Glasscf228942019-07-08 14:25:28 -06002079 image._node.path += '-suffix'
Simon Glass086cec92019-07-08 14:25:27 -06002080 entries = image.GetEntries()
2081 fdtmap = entries['fdtmap']
2082 with self.assertRaises(ValueError) as e:
2083 fdtmap._GetFdtmap()
2084 self.assertIn("Cannot locate node for path '/binman-suffix'",
2085 str(e.exception))
2086
Simon Glasscf228942019-07-08 14:25:28 -06002087 def testFdtmapHeader(self):
2088 """Test an FDT map and image header can be inserted in the image"""
2089 data = self.data = self._DoReadFileRealDtb('116_fdtmap_hdr.dts')
2090 fdtmap_pos = len(U_BOOT_DATA)
2091 fdtmap_data = data[fdtmap_pos:]
2092 fdt_data = fdtmap_data[16:]
2093 dtb = fdt.Fdt.FromData(fdt_data)
2094 fdt_size = dtb.GetFdtObj().totalsize()
2095 hdr_data = data[-8:]
2096 self.assertEqual('BinM', hdr_data[:4])
2097 offset = struct.unpack('<I', hdr_data[4:])[0] & 0xffffffff
2098 self.assertEqual(fdtmap_pos - 0x400, offset - (1 << 32))
2099
2100 def testFdtmapHeaderStart(self):
2101 """Test an image header can be inserted at the image start"""
2102 data = self.data = self._DoReadFileRealDtb('117_fdtmap_hdr_start.dts')
2103 fdtmap_pos = 0x100 + len(U_BOOT_DATA)
2104 hdr_data = data[:8]
2105 self.assertEqual('BinM', hdr_data[:4])
2106 offset = struct.unpack('<I', hdr_data[4:])[0]
2107 self.assertEqual(fdtmap_pos, offset)
2108
2109 def testFdtmapHeaderPos(self):
2110 """Test an image header can be inserted at a chosen position"""
2111 data = self.data = self._DoReadFileRealDtb('118_fdtmap_hdr_pos.dts')
2112 fdtmap_pos = 0x100 + len(U_BOOT_DATA)
2113 hdr_data = data[0x80:0x88]
2114 self.assertEqual('BinM', hdr_data[:4])
2115 offset = struct.unpack('<I', hdr_data[4:])[0]
2116 self.assertEqual(fdtmap_pos, offset)
2117
2118 def testHeaderMissingFdtmap(self):
2119 """Test an image header requires an fdtmap"""
2120 with self.assertRaises(ValueError) as e:
2121 self.data = self._DoReadFileRealDtb('119_fdtmap_hdr_missing.dts')
2122 self.assertIn("'image_header' section must have an 'fdtmap' sibling",
2123 str(e.exception))
2124
2125 def testHeaderNoLocation(self):
2126 """Test an image header with a no specified location is detected"""
2127 with self.assertRaises(ValueError) as e:
2128 self.data = self._DoReadFileRealDtb('120_hdr_no_location.dts')
2129 self.assertIn("Invalid location 'None', expected 'start' or 'end'",
2130 str(e.exception))
2131
Simon Glasse073d4e2019-07-08 13:18:56 -06002132
Simon Glass9fc60b42017-11-12 21:52:22 -07002133if __name__ == "__main__":
2134 unittest.main()