blob: 14abfbf774f9578b10e01e1b276ee8f6dcd69cf1 [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 Glassc55a50f2018-09-14 04:57:19 -060030import state
Simon Glass4f443042016-11-25 20:15:52 -070031import tools
32import tout
33
34# Contents of test files, corresponding to different entry types
Simon Glassc6c10e72019-05-17 22:00:46 -060035U_BOOT_DATA = b'1234'
36U_BOOT_IMG_DATA = b'img'
37U_BOOT_SPL_DATA = b'56780123456789abcde'
38U_BOOT_TPL_DATA = b'tpl'
39BLOB_DATA = b'89'
40ME_DATA = b'0abcd'
41VGA_DATA = b'vga'
42U_BOOT_DTB_DATA = b'udtb'
43U_BOOT_SPL_DTB_DATA = b'spldtb'
44U_BOOT_TPL_DTB_DATA = b'tpldtb'
45X86_START16_DATA = b'start16'
46X86_START16_SPL_DATA = b'start16spl'
47X86_START16_TPL_DATA = b'start16tpl'
48PPC_MPC85XX_BR_DATA = b'ppcmpc85xxbr'
49U_BOOT_NODTB_DATA = b'nodtb with microcode pointer somewhere in here'
50U_BOOT_SPL_NODTB_DATA = b'splnodtb with microcode pointer somewhere in here'
51U_BOOT_TPL_NODTB_DATA = b'tplnodtb with microcode pointer somewhere in here'
52FSP_DATA = b'fsp'
53CMC_DATA = b'cmc'
54VBT_DATA = b'vbt'
55MRC_DATA = b'mrc'
Simon Glassbb748372018-07-17 13:25:33 -060056TEXT_DATA = 'text'
57TEXT_DATA2 = 'text2'
58TEXT_DATA3 = 'text3'
Simon Glassc6c10e72019-05-17 22:00:46 -060059CROS_EC_RW_DATA = b'ecrw'
60GBB_DATA = b'gbbd'
61BMPBLK_DATA = b'bmp'
62VBLOCK_DATA = b'vblk'
63FILES_DATA = (b"sorry I'm late\nOh, don't bother apologising, I'm " +
64 b"sorry you're alive\n")
Simon Glassff5c7e32019-07-08 13:18:42 -060065COMPRESS_DATA = b'compress xxxxxxxxxxxxxxxxxxxxxx data'
Simon Glassc6c10e72019-05-17 22:00:46 -060066REFCODE_DATA = b'refcode'
Simon Glassec127af2018-07-17 13:25:39 -060067
Simon Glass4f443042016-11-25 20:15:52 -070068
69class TestFunctional(unittest.TestCase):
70 """Functional tests for binman
71
72 Most of these use a sample .dts file to build an image and then check
73 that it looks correct. The sample files are in the test/ subdirectory
74 and are numbered.
75
76 For each entry type a very small test file is created using fixed
77 string contents. This makes it easy to test that things look right, and
78 debug problems.
79
80 In some cases a 'real' file must be used - these are also supplied in
81 the test/ diurectory.
82 """
83 @classmethod
84 def setUpClass(self):
Simon Glass4d5994f2017-11-12 21:52:20 -070085 global entry
86 import entry
87
Simon Glass4f443042016-11-25 20:15:52 -070088 # Handle the case where argv[0] is 'python'
89 self._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
90 self._binman_pathname = os.path.join(self._binman_dir, 'binman')
91
92 # Create a temporary directory for input files
93 self._indir = tempfile.mkdtemp(prefix='binmant.')
94
95 # Create some test files
96 TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
97 TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
98 TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
Simon Glassb8ef5b62018-07-17 13:25:48 -060099 TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
Simon Glass4f443042016-11-25 20:15:52 -0700100 TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
Simon Glasse0ff8552016-11-25 20:15:53 -0700101 TestFunctional._MakeInputFile('me.bin', ME_DATA)
102 TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
Simon Glassb8ef5b62018-07-17 13:25:48 -0600103 self._ResetDtbs()
Simon Glasse0ff8552016-11-25 20:15:53 -0700104 TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
Jagdish Gediya9d368f32018-09-03 21:35:08 +0530105 TestFunctional._MakeInputFile('u-boot-br.bin', PPC_MPC85XX_BR_DATA)
Simon Glass87722132017-11-12 21:52:26 -0700106 TestFunctional._MakeInputFile('spl/u-boot-x86-16bit-spl.bin',
107 X86_START16_SPL_DATA)
Simon Glass35b384c2018-09-14 04:57:10 -0600108 TestFunctional._MakeInputFile('tpl/u-boot-x86-16bit-tpl.bin',
109 X86_START16_TPL_DATA)
Simon Glass4f443042016-11-25 20:15:52 -0700110 TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
Simon Glass6b187df2017-11-12 21:52:27 -0700111 TestFunctional._MakeInputFile('spl/u-boot-spl-nodtb.bin',
112 U_BOOT_SPL_NODTB_DATA)
Simon Glassf0253632018-09-14 04:57:32 -0600113 TestFunctional._MakeInputFile('tpl/u-boot-tpl-nodtb.bin',
114 U_BOOT_TPL_NODTB_DATA)
Simon Glassda229092016-11-25 20:15:56 -0700115 TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
116 TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
Bin Meng59ea8c22017-08-15 22:41:54 -0700117 TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
Simon Glassca4f4ff2017-11-12 21:52:28 -0700118 TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
Simon Glassec127af2018-07-17 13:25:39 -0600119 TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
Simon Glass0ef87aa2018-07-17 13:25:44 -0600120 TestFunctional._MakeInputDir('devkeys')
121 TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
Simon Glass3ae192c2018-10-01 12:22:31 -0600122 TestFunctional._MakeInputFile('refcode.bin', REFCODE_DATA)
Simon Glass4f443042016-11-25 20:15:52 -0700123
Simon Glasse0ff8552016-11-25 20:15:53 -0700124 # ELF file with a '_dt_ucode_base_size' symbol
Simon Glass1d0ebf72019-05-14 15:53:42 -0600125 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
Simon Glasse0ff8552016-11-25 20:15:53 -0700126 TestFunctional._MakeInputFile('u-boot', fd.read())
127
128 # Intel flash descriptor file
Simon Glass1d0ebf72019-05-14 15:53:42 -0600129 with open(self.TestFile('descriptor.bin'), 'rb') as fd:
Simon Glasse0ff8552016-11-25 20:15:53 -0700130 TestFunctional._MakeInputFile('descriptor.bin', fd.read())
131
Simon Glass0a98b282018-09-14 04:57:28 -0600132 shutil.copytree(self.TestFile('files'),
133 os.path.join(self._indir, 'files'))
134
Simon Glass83d73c22018-09-14 04:57:26 -0600135 TestFunctional._MakeInputFile('compress', COMPRESS_DATA)
136
Simon Glassac62fba2019-07-08 13:18:53 -0600137 # Travis-CI may have an old lz4
138 self.have_lz4 = True
139 try:
140 tools.Run('lz4', '--no-frame-crc', '-c',
141 os.path.join(self._indir, 'u-boot.bin'))
142 except:
143 self.have_lz4 = False
144
Simon Glass4f443042016-11-25 20:15:52 -0700145 @classmethod
146 def tearDownClass(self):
147 """Remove the temporary input directory and its contents"""
Simon Glassd5164a72019-07-08 13:18:49 -0600148 if self.preserve_indir:
149 print('Preserving input dir: %s' % self._indir)
150 else:
151 if self._indir:
152 shutil.rmtree(self._indir)
Simon Glass4f443042016-11-25 20:15:52 -0700153 self._indir = None
154
Simon Glassd5164a72019-07-08 13:18:49 -0600155 @classmethod
Simon Glass8acce602019-07-08 13:18:50 -0600156 def setup_test_args(cls, preserve_indir=False, preserve_outdirs=False,
157 toolpath=None):
Simon Glassd5164a72019-07-08 13:18:49 -0600158 """Accept arguments controlling test execution
159
160 Args:
161 preserve_indir: Preserve the shared input directory used by all
162 tests in this class.
163 preserve_outdir: Preserve the output directories used by tests. Each
164 test has its own, so this is normally only useful when running a
165 single test.
Simon Glass8acce602019-07-08 13:18:50 -0600166 toolpath: ist of paths to use for tools
Simon Glassd5164a72019-07-08 13:18:49 -0600167 """
168 cls.preserve_indir = preserve_indir
169 cls.preserve_outdirs = preserve_outdirs
Simon Glass8acce602019-07-08 13:18:50 -0600170 cls.toolpath = toolpath
Simon Glassd5164a72019-07-08 13:18:49 -0600171
Simon Glassac62fba2019-07-08 13:18:53 -0600172 def _CheckLz4(self):
173 if not self.have_lz4:
174 self.skipTest('lz4 --no-frame-crc not available')
175
Simon Glass4f443042016-11-25 20:15:52 -0700176 def setUp(self):
177 # Enable this to turn on debugging output
178 # tout.Init(tout.DEBUG)
179 command.test_result = None
180
181 def tearDown(self):
182 """Remove the temporary output directory"""
Simon Glassd5164a72019-07-08 13:18:49 -0600183 if self.preserve_outdirs:
184 print('Preserving output dir: %s' % tools.outdir)
185 else:
186 tools._FinaliseForTest()
Simon Glass4f443042016-11-25 20:15:52 -0700187
Simon Glassb8ef5b62018-07-17 13:25:48 -0600188 @classmethod
189 def _ResetDtbs(self):
190 TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
191 TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
192 TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
193
Simon Glassee0c9a72019-07-08 13:18:48 -0600194 def _GetVerbosity(self):
195 """Check if verbosity should be enabled
196
197 Returns:
198 list containing either:
199 - Verbosity flag (e.g. '-v2') if it is present on the cmd line
200 - nothing if the flag is not present
201 """
202 for arg in sys.argv[1:]:
203 if arg.startswith('-v'):
204 return [arg]
205 return []
206
Simon Glass4f443042016-11-25 20:15:52 -0700207 def _RunBinman(self, *args, **kwargs):
208 """Run binman using the command line
209
210 Args:
211 Arguments to pass, as a list of strings
212 kwargs: Arguments to pass to Command.RunPipe()
213 """
214 result = command.RunPipe([[self._binman_pathname] + list(args)],
215 capture=True, capture_stderr=True, raise_on_error=False)
216 if result.return_code and kwargs.get('raise_on_error', True):
217 raise Exception("Error running '%s': %s" % (' '.join(args),
218 result.stdout + result.stderr))
219 return result
220
221 def _DoBinman(self, *args):
222 """Run binman using directly (in the same process)
223
224 Args:
225 Arguments to pass, as a list of strings
226 Returns:
227 Return value (0 for success)
228 """
Simon Glass7fe91732017-11-13 18:55:00 -0700229 args = list(args)
230 if '-D' in sys.argv:
231 args = args + ['-D']
232 (options, args) = cmdline.ParseArgs(args)
Simon Glass4f443042016-11-25 20:15:52 -0700233 options.pager = 'binman-invalid-pager'
234 options.build_dir = self._indir
235
236 # For testing, you can force an increase in verbosity here
237 # options.verbosity = tout.DEBUG
238 return control.Binman(options, args)
239
Simon Glass53af22a2018-07-17 13:25:32 -0600240 def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
Simon Glasseb833d82019-04-25 21:58:34 -0600241 entry_args=None, images=None, use_real_dtb=False,
242 verbosity=None):
Simon Glass4f443042016-11-25 20:15:52 -0700243 """Run binman with a given test file
244
245 Args:
Simon Glass741f2d62018-10-01 12:22:30 -0600246 fname: Device-tree source filename to use (e.g. 005_simple.dts)
Simon Glass7ae5f312018-06-01 09:38:19 -0600247 debug: True to enable debugging output
Simon Glass3b0c3822018-06-01 09:38:20 -0600248 map: True to output map files for the images
Simon Glass3ab95982018-08-01 15:22:37 -0600249 update_dtb: Update the offset and size of each entry in the device
Simon Glass16b8d6b2018-07-06 10:27:42 -0600250 tree before packing it into the image
Simon Glass0bfa7b02018-09-14 04:57:12 -0600251 entry_args: Dict of entry args to supply to binman
252 key: arg name
253 value: value of that arg
254 images: List of image names to build
Simon Glass4f443042016-11-25 20:15:52 -0700255 """
Simon Glass7fe91732017-11-13 18:55:00 -0700256 args = ['-p', '-I', self._indir, '-d', self.TestFile(fname)]
257 if debug:
258 args.append('-D')
Simon Glass3b0c3822018-06-01 09:38:20 -0600259 if map:
260 args.append('-m')
Simon Glass16b8d6b2018-07-06 10:27:42 -0600261 if update_dtb:
Simon Glass2569e102019-07-08 13:18:47 -0600262 args.append('-u')
Simon Glass93d17412018-09-14 04:57:23 -0600263 if not use_real_dtb:
264 args.append('--fake-dtb')
Simon Glasseb833d82019-04-25 21:58:34 -0600265 if verbosity is not None:
266 args.append('-v%d' % verbosity)
Simon Glassee0c9a72019-07-08 13:18:48 -0600267 else:
268 args += self._GetVerbosity()
Simon Glass53af22a2018-07-17 13:25:32 -0600269 if entry_args:
Simon Glass50979152019-05-14 15:53:41 -0600270 for arg, value in entry_args.items():
Simon Glass53af22a2018-07-17 13:25:32 -0600271 args.append('-a%s=%s' % (arg, value))
Simon Glass0bfa7b02018-09-14 04:57:12 -0600272 if images:
273 for image in images:
274 args += ['-i', image]
Simon Glass8acce602019-07-08 13:18:50 -0600275 if self.toolpath:
276 for path in self.toolpath:
277 args += ['--toolpath', path]
Simon Glass7fe91732017-11-13 18:55:00 -0700278 return self._DoBinman(*args)
Simon Glass4f443042016-11-25 20:15:52 -0700279
280 def _SetupDtb(self, fname, outfile='u-boot.dtb'):
Simon Glasse0ff8552016-11-25 20:15:53 -0700281 """Set up a new test device-tree file
282
283 The given file is compiled and set up as the device tree to be used
284 for ths test.
285
286 Args:
287 fname: Filename of .dts file to read
Simon Glass7ae5f312018-06-01 09:38:19 -0600288 outfile: Output filename for compiled device-tree binary
Simon Glasse0ff8552016-11-25 20:15:53 -0700289
290 Returns:
Simon Glass7ae5f312018-06-01 09:38:19 -0600291 Contents of device-tree binary
Simon Glasse0ff8552016-11-25 20:15:53 -0700292 """
Simon Glasse0e62752018-10-01 21:12:41 -0600293 tools.PrepareOutputDir(None)
Simon Glass4f443042016-11-25 20:15:52 -0700294 dtb = fdt_util.EnsureCompiled(self.TestFile(fname))
Simon Glass1d0ebf72019-05-14 15:53:42 -0600295 with open(dtb, 'rb') as fd:
Simon Glass4f443042016-11-25 20:15:52 -0700296 data = fd.read()
297 TestFunctional._MakeInputFile(outfile, data)
Simon Glasse0e62752018-10-01 21:12:41 -0600298 tools.FinaliseOutputDir()
299 return data
Simon Glass4f443042016-11-25 20:15:52 -0700300
Simon Glass6ed45ba2018-09-14 04:57:24 -0600301 def _GetDtbContentsForSplTpl(self, dtb_data, name):
302 """Create a version of the main DTB for SPL or SPL
303
304 For testing we don't actually have different versions of the DTB. With
305 U-Boot we normally run fdtgrep to remove unwanted nodes, but for tests
306 we don't normally have any unwanted nodes.
307
308 We still want the DTBs for SPL and TPL to be different though, since
309 otherwise it is confusing to know which one we are looking at. So add
310 an 'spl' or 'tpl' property to the top-level node.
311 """
312 dtb = fdt.Fdt.FromData(dtb_data)
313 dtb.Scan()
314 dtb.GetNode('/binman').AddZeroProp(name)
315 dtb.Sync(auto_resize=True)
316 dtb.Pack()
317 return dtb.GetContents()
318
Simon Glass16b8d6b2018-07-06 10:27:42 -0600319 def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
Simon Glass6ed45ba2018-09-14 04:57:24 -0600320 update_dtb=False, entry_args=None, reset_dtbs=True):
Simon Glass4f443042016-11-25 20:15:52 -0700321 """Run binman and return the resulting image
322
323 This runs binman with a given test file and then reads the resulting
324 output file. It is a shortcut function since most tests need to do
325 these steps.
326
327 Raises an assertion failure if binman returns a non-zero exit code.
328
329 Args:
Simon Glass741f2d62018-10-01 12:22:30 -0600330 fname: Device-tree source filename to use (e.g. 005_simple.dts)
Simon Glass4f443042016-11-25 20:15:52 -0700331 use_real_dtb: True to use the test file as the contents of
332 the u-boot-dtb entry. Normally this is not needed and the
333 test contents (the U_BOOT_DTB_DATA string) can be used.
334 But in some test we need the real contents.
Simon Glass3b0c3822018-06-01 09:38:20 -0600335 map: True to output map files for the images
Simon Glass3ab95982018-08-01 15:22:37 -0600336 update_dtb: Update the offset and size of each entry in the device
Simon Glass16b8d6b2018-07-06 10:27:42 -0600337 tree before packing it into the image
Simon Glasse0ff8552016-11-25 20:15:53 -0700338
339 Returns:
340 Tuple:
341 Resulting image contents
342 Device tree contents
Simon Glass3b0c3822018-06-01 09:38:20 -0600343 Map data showing contents of image (or None if none)
Simon Glassea6922e2018-07-17 13:25:27 -0600344 Output device tree binary filename ('u-boot.dtb' path)
Simon Glass4f443042016-11-25 20:15:52 -0700345 """
Simon Glasse0ff8552016-11-25 20:15:53 -0700346 dtb_data = None
Simon Glass4f443042016-11-25 20:15:52 -0700347 # Use the compiled test file as the u-boot-dtb input
348 if use_real_dtb:
Simon Glasse0ff8552016-11-25 20:15:53 -0700349 dtb_data = self._SetupDtb(fname)
Simon Glass6ed45ba2018-09-14 04:57:24 -0600350
351 # For testing purposes, make a copy of the DT for SPL and TPL. Add
352 # a node indicating which it is, so aid verification.
353 for name in ['spl', 'tpl']:
354 dtb_fname = '%s/u-boot-%s.dtb' % (name, name)
355 outfile = os.path.join(self._indir, dtb_fname)
356 TestFunctional._MakeInputFile(dtb_fname,
357 self._GetDtbContentsForSplTpl(dtb_data, name))
Simon Glass4f443042016-11-25 20:15:52 -0700358
359 try:
Simon Glass53af22a2018-07-17 13:25:32 -0600360 retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
Simon Glass6ed45ba2018-09-14 04:57:24 -0600361 entry_args=entry_args, use_real_dtb=use_real_dtb)
Simon Glass4f443042016-11-25 20:15:52 -0700362 self.assertEqual(0, retcode)
Simon Glass6ed45ba2018-09-14 04:57:24 -0600363 out_dtb_fname = tools.GetOutputFilename('u-boot.dtb.out')
Simon Glass4f443042016-11-25 20:15:52 -0700364
365 # Find the (only) image, read it and return its contents
366 image = control.images['image']
Simon Glass16b8d6b2018-07-06 10:27:42 -0600367 image_fname = tools.GetOutputFilename('image.bin')
368 self.assertTrue(os.path.exists(image_fname))
Simon Glass3b0c3822018-06-01 09:38:20 -0600369 if map:
370 map_fname = tools.GetOutputFilename('image.map')
371 with open(map_fname) as fd:
372 map_data = fd.read()
373 else:
374 map_data = None
Simon Glass1d0ebf72019-05-14 15:53:42 -0600375 with open(image_fname, 'rb') as fd:
Simon Glass16b8d6b2018-07-06 10:27:42 -0600376 return fd.read(), dtb_data, map_data, out_dtb_fname
Simon Glass4f443042016-11-25 20:15:52 -0700377 finally:
378 # Put the test file back
Simon Glass6ed45ba2018-09-14 04:57:24 -0600379 if reset_dtbs and use_real_dtb:
Simon Glassb8ef5b62018-07-17 13:25:48 -0600380 self._ResetDtbs()
Simon Glass4f443042016-11-25 20:15:52 -0700381
Simon Glasse0ff8552016-11-25 20:15:53 -0700382 def _DoReadFile(self, fname, use_real_dtb=False):
Simon Glass7ae5f312018-06-01 09:38:19 -0600383 """Helper function which discards the device-tree binary
384
385 Args:
Simon Glass741f2d62018-10-01 12:22:30 -0600386 fname: Device-tree source filename to use (e.g. 005_simple.dts)
Simon Glass7ae5f312018-06-01 09:38:19 -0600387 use_real_dtb: True to use the test file as the contents of
388 the u-boot-dtb entry. Normally this is not needed and the
389 test contents (the U_BOOT_DTB_DATA string) can be used.
390 But in some test we need the real contents.
Simon Glassea6922e2018-07-17 13:25:27 -0600391
392 Returns:
393 Resulting image contents
Simon Glass7ae5f312018-06-01 09:38:19 -0600394 """
Simon Glasse0ff8552016-11-25 20:15:53 -0700395 return self._DoReadFileDtb(fname, use_real_dtb)[0]
396
Simon Glass4f443042016-11-25 20:15:52 -0700397 @classmethod
398 def _MakeInputFile(self, fname, contents):
399 """Create a new test input file, creating directories as needed
400
401 Args:
Simon Glass3ab95982018-08-01 15:22:37 -0600402 fname: Filename to create
Simon Glass4f443042016-11-25 20:15:52 -0700403 contents: File contents to write in to the file
404 Returns:
405 Full pathname of file created
406 """
407 pathname = os.path.join(self._indir, fname)
408 dirname = os.path.dirname(pathname)
409 if dirname and not os.path.exists(dirname):
410 os.makedirs(dirname)
411 with open(pathname, 'wb') as fd:
412 fd.write(contents)
413 return pathname
414
415 @classmethod
Simon Glass0ef87aa2018-07-17 13:25:44 -0600416 def _MakeInputDir(self, dirname):
417 """Create a new test input directory, creating directories as needed
418
419 Args:
420 dirname: Directory name to create
421
422 Returns:
423 Full pathname of directory created
424 """
425 pathname = os.path.join(self._indir, dirname)
426 if not os.path.exists(pathname):
427 os.makedirs(pathname)
428 return pathname
429
430 @classmethod
Simon Glass11ae93e2018-10-01 21:12:47 -0600431 def _SetupSplElf(self, src_fname='bss_data'):
432 """Set up an ELF file with a '_dt_ucode_base_size' symbol
433
434 Args:
435 Filename of ELF file to use as SPL
436 """
Simon Glass1d0ebf72019-05-14 15:53:42 -0600437 with open(self.TestFile(src_fname), 'rb') as fd:
Simon Glass11ae93e2018-10-01 21:12:47 -0600438 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
439
440 @classmethod
Simon Glass4f443042016-11-25 20:15:52 -0700441 def TestFile(self, fname):
442 return os.path.join(self._binman_dir, 'test', fname)
443
444 def AssertInList(self, grep_list, target):
445 """Assert that at least one of a list of things is in a target
446
447 Args:
448 grep_list: List of strings to check
449 target: Target string
450 """
451 for grep in grep_list:
452 if grep in target:
453 return
Simon Glass1fc62de2019-05-17 22:00:50 -0600454 self.fail("Error: '%s' not found in '%s'" % (grep_list, target))
Simon Glass4f443042016-11-25 20:15:52 -0700455
456 def CheckNoGaps(self, entries):
457 """Check that all entries fit together without gaps
458
459 Args:
460 entries: List of entries to check
461 """
Simon Glass3ab95982018-08-01 15:22:37 -0600462 offset = 0
Simon Glass4f443042016-11-25 20:15:52 -0700463 for entry in entries.values():
Simon Glass3ab95982018-08-01 15:22:37 -0600464 self.assertEqual(offset, entry.offset)
465 offset += entry.size
Simon Glass4f443042016-11-25 20:15:52 -0700466
Simon Glasse0ff8552016-11-25 20:15:53 -0700467 def GetFdtLen(self, dtb):
Simon Glass7ae5f312018-06-01 09:38:19 -0600468 """Get the totalsize field from a device-tree binary
Simon Glasse0ff8552016-11-25 20:15:53 -0700469
470 Args:
Simon Glass7ae5f312018-06-01 09:38:19 -0600471 dtb: Device-tree binary contents
Simon Glasse0ff8552016-11-25 20:15:53 -0700472
473 Returns:
Simon Glass7ae5f312018-06-01 09:38:19 -0600474 Total size of device-tree binary, from the header
Simon Glasse0ff8552016-11-25 20:15:53 -0700475 """
476 return struct.unpack('>L', dtb[4:8])[0]
477
Simon Glasscee02e62018-07-17 13:25:52 -0600478 def _GetPropTree(self, dtb, prop_names):
Simon Glass16b8d6b2018-07-06 10:27:42 -0600479 def AddNode(node, path):
480 if node.name != '/':
481 path += '/' + node.name
Simon Glass16b8d6b2018-07-06 10:27:42 -0600482 for subnode in node.subnodes:
483 for prop in subnode.props.values():
Simon Glasscee02e62018-07-17 13:25:52 -0600484 if prop.name in prop_names:
Simon Glass16b8d6b2018-07-06 10:27:42 -0600485 prop_path = path + '/' + subnode.name + ':' + prop.name
486 tree[prop_path[len('/binman/'):]] = fdt_util.fdt32_to_cpu(
487 prop.value)
Simon Glass16b8d6b2018-07-06 10:27:42 -0600488 AddNode(subnode, path)
489
490 tree = {}
Simon Glass16b8d6b2018-07-06 10:27:42 -0600491 AddNode(dtb.GetRoot(), '')
492 return tree
493
Simon Glass4f443042016-11-25 20:15:52 -0700494 def testRun(self):
495 """Test a basic run with valid args"""
496 result = self._RunBinman('-h')
497
498 def testFullHelp(self):
499 """Test that the full help is displayed with -H"""
500 result = self._RunBinman('-H')
501 help_file = os.path.join(self._binman_dir, 'README')
Tom Rini3759df02018-01-16 15:29:50 -0500502 # Remove possible extraneous strings
503 extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
504 gothelp = result.stdout.replace(extra, '')
505 self.assertEqual(len(gothelp), os.path.getsize(help_file))
Simon Glass4f443042016-11-25 20:15:52 -0700506 self.assertEqual(0, len(result.stderr))
507 self.assertEqual(0, result.return_code)
508
509 def testFullHelpInternal(self):
510 """Test that the full help is displayed with -H"""
511 try:
512 command.test_result = command.CommandResult()
513 result = self._DoBinman('-H')
514 help_file = os.path.join(self._binman_dir, 'README')
515 finally:
516 command.test_result = None
517
518 def testHelp(self):
519 """Test that the basic help is displayed with -h"""
520 result = self._RunBinman('-h')
521 self.assertTrue(len(result.stdout) > 200)
522 self.assertEqual(0, len(result.stderr))
523 self.assertEqual(0, result.return_code)
524
Simon Glass4f443042016-11-25 20:15:52 -0700525 def testBoard(self):
526 """Test that we can run it with a specific board"""
Simon Glass741f2d62018-10-01 12:22:30 -0600527 self._SetupDtb('005_simple.dts', 'sandbox/u-boot.dtb')
Simon Glass4f443042016-11-25 20:15:52 -0700528 TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
529 result = self._DoBinman('-b', 'sandbox')
530 self.assertEqual(0, result)
531
532 def testNeedBoard(self):
533 """Test that we get an error when no board ius supplied"""
534 with self.assertRaises(ValueError) as e:
535 result = self._DoBinman()
536 self.assertIn("Must provide a board to process (use -b <board>)",
537 str(e.exception))
538
539 def testMissingDt(self):
Simon Glass7ae5f312018-06-01 09:38:19 -0600540 """Test that an invalid device-tree file generates an error"""
Simon Glass4f443042016-11-25 20:15:52 -0700541 with self.assertRaises(Exception) as e:
542 self._RunBinman('-d', 'missing_file')
543 # We get one error from libfdt, and a different one from fdtget.
544 self.AssertInList(["Couldn't open blob from 'missing_file'",
545 'No such file or directory'], str(e.exception))
546
547 def testBrokenDt(self):
Simon Glass7ae5f312018-06-01 09:38:19 -0600548 """Test that an invalid device-tree source file generates an error
Simon Glass4f443042016-11-25 20:15:52 -0700549
550 Since this is a source file it should be compiled and the error
551 will come from the device-tree compiler (dtc).
552 """
553 with self.assertRaises(Exception) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600554 self._RunBinman('-d', self.TestFile('001_invalid.dts'))
Simon Glass4f443042016-11-25 20:15:52 -0700555 self.assertIn("FATAL ERROR: Unable to parse input tree",
556 str(e.exception))
557
558 def testMissingNode(self):
559 """Test that a device tree without a 'binman' node generates an error"""
560 with self.assertRaises(Exception) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600561 self._DoBinman('-d', self.TestFile('002_missing_node.dts'))
Simon Glass4f443042016-11-25 20:15:52 -0700562 self.assertIn("does not have a 'binman' node", str(e.exception))
563
564 def testEmpty(self):
565 """Test that an empty binman node works OK (i.e. does nothing)"""
Simon Glass741f2d62018-10-01 12:22:30 -0600566 result = self._RunBinman('-d', self.TestFile('003_empty.dts'))
Simon Glass4f443042016-11-25 20:15:52 -0700567 self.assertEqual(0, len(result.stderr))
568 self.assertEqual(0, result.return_code)
569
570 def testInvalidEntry(self):
571 """Test that an invalid entry is flagged"""
572 with self.assertRaises(Exception) as e:
573 result = self._RunBinman('-d',
Simon Glass741f2d62018-10-01 12:22:30 -0600574 self.TestFile('004_invalid_entry.dts'))
Simon Glass4f443042016-11-25 20:15:52 -0700575 self.assertIn("Unknown entry type 'not-a-valid-type' in node "
576 "'/binman/not-a-valid-type'", str(e.exception))
577
578 def testSimple(self):
579 """Test a simple binman with a single file"""
Simon Glass741f2d62018-10-01 12:22:30 -0600580 data = self._DoReadFile('005_simple.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700581 self.assertEqual(U_BOOT_DATA, data)
582
Simon Glass7fe91732017-11-13 18:55:00 -0700583 def testSimpleDebug(self):
584 """Test a simple binman run with debugging enabled"""
Simon Glass741f2d62018-10-01 12:22:30 -0600585 data = self._DoTestFile('005_simple.dts', debug=True)
Simon Glass7fe91732017-11-13 18:55:00 -0700586
Simon Glass4f443042016-11-25 20:15:52 -0700587 def testDual(self):
588 """Test that we can handle creating two images
589
590 This also tests image padding.
591 """
Simon Glass741f2d62018-10-01 12:22:30 -0600592 retcode = self._DoTestFile('006_dual_image.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700593 self.assertEqual(0, retcode)
594
595 image = control.images['image1']
596 self.assertEqual(len(U_BOOT_DATA), image._size)
597 fname = tools.GetOutputFilename('image1.bin')
598 self.assertTrue(os.path.exists(fname))
Simon Glass1d0ebf72019-05-14 15:53:42 -0600599 with open(fname, 'rb') as fd:
Simon Glass4f443042016-11-25 20:15:52 -0700600 data = fd.read()
601 self.assertEqual(U_BOOT_DATA, data)
602
603 image = control.images['image2']
604 self.assertEqual(3 + len(U_BOOT_DATA) + 5, image._size)
605 fname = tools.GetOutputFilename('image2.bin')
606 self.assertTrue(os.path.exists(fname))
Simon Glass1d0ebf72019-05-14 15:53:42 -0600607 with open(fname, 'rb') as fd:
Simon Glass4f443042016-11-25 20:15:52 -0700608 data = fd.read()
609 self.assertEqual(U_BOOT_DATA, data[3:7])
Simon Glasse6d85ff2019-05-14 15:53:47 -0600610 self.assertEqual(tools.GetBytes(0, 3), data[:3])
611 self.assertEqual(tools.GetBytes(0, 5), data[7:])
Simon Glass4f443042016-11-25 20:15:52 -0700612
613 def testBadAlign(self):
614 """Test that an invalid alignment value is detected"""
615 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600616 self._DoTestFile('007_bad_align.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700617 self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
618 "of two", str(e.exception))
619
620 def testPackSimple(self):
621 """Test that packing works as expected"""
Simon Glass741f2d62018-10-01 12:22:30 -0600622 retcode = self._DoTestFile('008_pack.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700623 self.assertEqual(0, retcode)
624 self.assertIn('image', control.images)
625 image = control.images['image']
Simon Glass8f1da502018-06-01 09:38:12 -0600626 entries = image.GetEntries()
Simon Glass4f443042016-11-25 20:15:52 -0700627 self.assertEqual(5, len(entries))
628
629 # First u-boot
630 self.assertIn('u-boot', entries)
631 entry = entries['u-boot']
Simon Glass3ab95982018-08-01 15:22:37 -0600632 self.assertEqual(0, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700633 self.assertEqual(len(U_BOOT_DATA), entry.size)
634
635 # Second u-boot, aligned to 16-byte boundary
636 self.assertIn('u-boot-align', entries)
637 entry = entries['u-boot-align']
Simon Glass3ab95982018-08-01 15:22:37 -0600638 self.assertEqual(16, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700639 self.assertEqual(len(U_BOOT_DATA), entry.size)
640
641 # Third u-boot, size 23 bytes
642 self.assertIn('u-boot-size', entries)
643 entry = entries['u-boot-size']
Simon Glass3ab95982018-08-01 15:22:37 -0600644 self.assertEqual(20, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700645 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
646 self.assertEqual(23, entry.size)
647
648 # Fourth u-boot, placed immediate after the above
649 self.assertIn('u-boot-next', entries)
650 entry = entries['u-boot-next']
Simon Glass3ab95982018-08-01 15:22:37 -0600651 self.assertEqual(43, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700652 self.assertEqual(len(U_BOOT_DATA), entry.size)
653
Simon Glass3ab95982018-08-01 15:22:37 -0600654 # Fifth u-boot, placed at a fixed offset
Simon Glass4f443042016-11-25 20:15:52 -0700655 self.assertIn('u-boot-fixed', entries)
656 entry = entries['u-boot-fixed']
Simon Glass3ab95982018-08-01 15:22:37 -0600657 self.assertEqual(61, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700658 self.assertEqual(len(U_BOOT_DATA), entry.size)
659
660 self.assertEqual(65, image._size)
661
662 def testPackExtra(self):
663 """Test that extra packing feature works as expected"""
Simon Glass741f2d62018-10-01 12:22:30 -0600664 retcode = self._DoTestFile('009_pack_extra.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700665
666 self.assertEqual(0, retcode)
667 self.assertIn('image', control.images)
668 image = control.images['image']
Simon Glass8f1da502018-06-01 09:38:12 -0600669 entries = image.GetEntries()
Simon Glass4f443042016-11-25 20:15:52 -0700670 self.assertEqual(5, len(entries))
671
672 # First u-boot with padding before and after
673 self.assertIn('u-boot', entries)
674 entry = entries['u-boot']
Simon Glass3ab95982018-08-01 15:22:37 -0600675 self.assertEqual(0, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700676 self.assertEqual(3, entry.pad_before)
677 self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
678
679 # Second u-boot has an aligned size, but it has no effect
680 self.assertIn('u-boot-align-size-nop', entries)
681 entry = entries['u-boot-align-size-nop']
Simon Glass3ab95982018-08-01 15:22:37 -0600682 self.assertEqual(12, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700683 self.assertEqual(4, entry.size)
684
685 # Third u-boot has an aligned size too
686 self.assertIn('u-boot-align-size', entries)
687 entry = entries['u-boot-align-size']
Simon Glass3ab95982018-08-01 15:22:37 -0600688 self.assertEqual(16, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700689 self.assertEqual(32, entry.size)
690
691 # Fourth u-boot has an aligned end
692 self.assertIn('u-boot-align-end', entries)
693 entry = entries['u-boot-align-end']
Simon Glass3ab95982018-08-01 15:22:37 -0600694 self.assertEqual(48, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700695 self.assertEqual(16, entry.size)
696
697 # Fifth u-boot immediately afterwards
698 self.assertIn('u-boot-align-both', entries)
699 entry = entries['u-boot-align-both']
Simon Glass3ab95982018-08-01 15:22:37 -0600700 self.assertEqual(64, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700701 self.assertEqual(64, entry.size)
702
703 self.CheckNoGaps(entries)
704 self.assertEqual(128, image._size)
705
706 def testPackAlignPowerOf2(self):
707 """Test that invalid entry alignment is detected"""
708 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600709 self._DoTestFile('010_pack_align_power2.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700710 self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
711 "of two", str(e.exception))
712
713 def testPackAlignSizePowerOf2(self):
714 """Test that invalid entry size alignment is detected"""
715 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600716 self._DoTestFile('011_pack_align_size_power2.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700717 self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
718 "power of two", str(e.exception))
719
720 def testPackInvalidAlign(self):
Simon Glass3ab95982018-08-01 15:22:37 -0600721 """Test detection of an offset that does not match its alignment"""
Simon Glass4f443042016-11-25 20:15:52 -0700722 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600723 self._DoTestFile('012_pack_inv_align.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600724 self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
Simon Glass4f443042016-11-25 20:15:52 -0700725 "align 0x4 (4)", str(e.exception))
726
727 def testPackInvalidSizeAlign(self):
728 """Test that invalid entry size alignment is detected"""
729 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600730 self._DoTestFile('013_pack_inv_size_align.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700731 self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
732 "align-size 0x4 (4)", str(e.exception))
733
734 def testPackOverlap(self):
735 """Test that overlapping regions are detected"""
736 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600737 self._DoTestFile('014_pack_overlap.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600738 self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
Simon Glass4f443042016-11-25 20:15:52 -0700739 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
740 str(e.exception))
741
742 def testPackEntryOverflow(self):
743 """Test that entries that overflow their size are detected"""
744 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600745 self._DoTestFile('015_pack_overflow.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700746 self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
747 "but entry size is 0x3 (3)", str(e.exception))
748
749 def testPackImageOverflow(self):
750 """Test that entries which overflow the image size are detected"""
751 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600752 self._DoTestFile('016_pack_image_overflow.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600753 self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section "
Simon Glass4f443042016-11-25 20:15:52 -0700754 "size 0x3 (3)", str(e.exception))
755
756 def testPackImageSize(self):
757 """Test that the image size can be set"""
Simon Glass741f2d62018-10-01 12:22:30 -0600758 retcode = self._DoTestFile('017_pack_image_size.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700759 self.assertEqual(0, retcode)
760 self.assertIn('image', control.images)
761 image = control.images['image']
762 self.assertEqual(7, image._size)
763
764 def testPackImageSizeAlign(self):
765 """Test that image size alignemnt works as expected"""
Simon Glass741f2d62018-10-01 12:22:30 -0600766 retcode = self._DoTestFile('018_pack_image_align.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700767 self.assertEqual(0, retcode)
768 self.assertIn('image', control.images)
769 image = control.images['image']
770 self.assertEqual(16, image._size)
771
772 def testPackInvalidImageAlign(self):
773 """Test that invalid image alignment is detected"""
774 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600775 self._DoTestFile('019_pack_inv_image_align.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600776 self.assertIn("Section '/binman': Size 0x7 (7) does not match "
Simon Glass4f443042016-11-25 20:15:52 -0700777 "align-size 0x8 (8)", str(e.exception))
778
779 def testPackAlignPowerOf2(self):
780 """Test that invalid image alignment is detected"""
781 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600782 self._DoTestFile('020_pack_inv_image_align_power2.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600783 self.assertIn("Section '/binman': Alignment size 131 must be a power of "
Simon Glass4f443042016-11-25 20:15:52 -0700784 "two", str(e.exception))
785
786 def testImagePadByte(self):
787 """Test that the image pad byte can be specified"""
Simon Glass11ae93e2018-10-01 21:12:47 -0600788 self._SetupSplElf()
Simon Glass741f2d62018-10-01 12:22:30 -0600789 data = self._DoReadFile('021_image_pad.dts')
Simon Glasse6d85ff2019-05-14 15:53:47 -0600790 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0xff, 1) +
791 U_BOOT_DATA, data)
Simon Glass4f443042016-11-25 20:15:52 -0700792
793 def testImageName(self):
794 """Test that image files can be named"""
Simon Glass741f2d62018-10-01 12:22:30 -0600795 retcode = self._DoTestFile('022_image_name.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700796 self.assertEqual(0, retcode)
797 image = control.images['image1']
798 fname = tools.GetOutputFilename('test-name')
799 self.assertTrue(os.path.exists(fname))
800
801 image = control.images['image2']
802 fname = tools.GetOutputFilename('test-name.xx')
803 self.assertTrue(os.path.exists(fname))
804
805 def testBlobFilename(self):
806 """Test that generic blobs can be provided by filename"""
Simon Glass741f2d62018-10-01 12:22:30 -0600807 data = self._DoReadFile('023_blob.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700808 self.assertEqual(BLOB_DATA, data)
809
810 def testPackSorted(self):
811 """Test that entries can be sorted"""
Simon Glass11ae93e2018-10-01 21:12:47 -0600812 self._SetupSplElf()
Simon Glass741f2d62018-10-01 12:22:30 -0600813 data = self._DoReadFile('024_sorted.dts')
Simon Glasse6d85ff2019-05-14 15:53:47 -0600814 self.assertEqual(tools.GetBytes(0, 1) + U_BOOT_SPL_DATA +
815 tools.GetBytes(0, 2) + U_BOOT_DATA, data)
Simon Glass4f443042016-11-25 20:15:52 -0700816
Simon Glass3ab95982018-08-01 15:22:37 -0600817 def testPackZeroOffset(self):
818 """Test that an entry at offset 0 is not given a new offset"""
Simon Glass4f443042016-11-25 20:15:52 -0700819 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600820 self._DoTestFile('025_pack_zero_size.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600821 self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
Simon Glass4f443042016-11-25 20:15:52 -0700822 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
823 str(e.exception))
824
825 def testPackUbootDtb(self):
826 """Test that a device tree can be added to U-Boot"""
Simon Glass741f2d62018-10-01 12:22:30 -0600827 data = self._DoReadFile('026_pack_u_boot_dtb.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700828 self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
Simon Glasse0ff8552016-11-25 20:15:53 -0700829
830 def testPackX86RomNoSize(self):
831 """Test that the end-at-4gb property requires a size property"""
832 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600833 self._DoTestFile('027_pack_4gb_no_size.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600834 self.assertIn("Section '/binman': Section size must be provided when "
Simon Glasse0ff8552016-11-25 20:15:53 -0700835 "using end-at-4gb", str(e.exception))
836
Jagdish Gediya94b57db2018-09-03 21:35:07 +0530837 def test4gbAndSkipAtStartTogether(self):
838 """Test that the end-at-4gb and skip-at-size property can't be used
839 together"""
840 with self.assertRaises(ValueError) as e:
841 self._DoTestFile('80_4gb_and_skip_at_start_together.dts')
842 self.assertIn("Section '/binman': Provide either 'end-at-4gb' or "
843 "'skip-at-start'", str(e.exception))
844
Simon Glasse0ff8552016-11-25 20:15:53 -0700845 def testPackX86RomOutside(self):
Simon Glass3ab95982018-08-01 15:22:37 -0600846 """Test that the end-at-4gb property checks for offset boundaries"""
Simon Glasse0ff8552016-11-25 20:15:53 -0700847 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600848 self._DoTestFile('028_pack_4gb_outside.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600849 self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
Simon Glass8f1da502018-06-01 09:38:12 -0600850 "the section starting at 0xffffffe0 (4294967264)",
Simon Glasse0ff8552016-11-25 20:15:53 -0700851 str(e.exception))
852
853 def testPackX86Rom(self):
854 """Test that a basic x86 ROM can be created"""
Simon Glass11ae93e2018-10-01 21:12:47 -0600855 self._SetupSplElf()
Simon Glass741f2d62018-10-01 12:22:30 -0600856 data = self._DoReadFile('029_x86-rom.dts')
Simon Glasse6d85ff2019-05-14 15:53:47 -0600857 self.assertEqual(U_BOOT_DATA + tools.GetBytes(0, 7) + U_BOOT_SPL_DATA +
858 tools.GetBytes(0, 2), data)
Simon Glasse0ff8552016-11-25 20:15:53 -0700859
860 def testPackX86RomMeNoDesc(self):
861 """Test that an invalid Intel descriptor entry is detected"""
Simon Glassc6c10e72019-05-17 22:00:46 -0600862 TestFunctional._MakeInputFile('descriptor.bin', b'')
Simon Glasse0ff8552016-11-25 20:15:53 -0700863 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600864 self._DoTestFile('031_x86-rom-me.dts')
Simon Glass458be452019-07-08 13:18:32 -0600865 self.assertIn("Node '/binman/intel-descriptor': Cannot find Intel Flash Descriptor (FD) signature",
866 str(e.exception))
Simon Glasse0ff8552016-11-25 20:15:53 -0700867
868 def testPackX86RomBadDesc(self):
869 """Test that the Intel requires a descriptor entry"""
870 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600871 self._DoTestFile('030_x86-rom-me-no-desc.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600872 self.assertIn("Node '/binman/intel-me': No offset set with "
873 "offset-unset: should another entry provide this correct "
874 "offset?", str(e.exception))
Simon Glasse0ff8552016-11-25 20:15:53 -0700875
876 def testPackX86RomMe(self):
877 """Test that an x86 ROM with an ME region can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -0600878 data = self._DoReadFile('031_x86-rom-me.dts')
Simon Glasse0ff8552016-11-25 20:15:53 -0700879 self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
880
881 def testPackVga(self):
882 """Test that an image with a VGA binary can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -0600883 data = self._DoReadFile('032_intel-vga.dts')
Simon Glasse0ff8552016-11-25 20:15:53 -0700884 self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
885
886 def testPackStart16(self):
887 """Test that an image with an x86 start16 region can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -0600888 data = self._DoReadFile('033_x86-start16.dts')
Simon Glasse0ff8552016-11-25 20:15:53 -0700889 self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
890
Jagdish Gediya9d368f32018-09-03 21:35:08 +0530891 def testPackPowerpcMpc85xxBootpgResetvec(self):
892 """Test that an image with powerpc-mpc85xx-bootpg-resetvec can be
893 created"""
894 data = self._DoReadFile('81_powerpc_mpc85xx_bootpg_resetvec.dts')
895 self.assertEqual(PPC_MPC85XX_BR_DATA, data[:len(PPC_MPC85XX_BR_DATA)])
896
Simon Glass736bb0a2018-07-06 10:27:17 -0600897 def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False):
Simon Glassadc57012018-07-06 10:27:16 -0600898 """Handle running a test for insertion of microcode
899
900 Args:
901 dts_fname: Name of test .dts file
902 nodtb_data: Data that we expect in the first section
Simon Glass736bb0a2018-07-06 10:27:17 -0600903 ucode_second: True if the microsecond entry is second instead of
904 third
Simon Glassadc57012018-07-06 10:27:16 -0600905
906 Returns:
907 Tuple:
908 Contents of first region (U-Boot or SPL)
Simon Glass3ab95982018-08-01 15:22:37 -0600909 Offset and size components of microcode pointer, as inserted
Simon Glassadc57012018-07-06 10:27:16 -0600910 in the above (two 4-byte words)
911 """
Simon Glass6b187df2017-11-12 21:52:27 -0700912 data = self._DoReadFile(dts_fname, True)
Simon Glasse0ff8552016-11-25 20:15:53 -0700913
914 # Now check the device tree has no microcode
Simon Glass736bb0a2018-07-06 10:27:17 -0600915 if ucode_second:
916 ucode_content = data[len(nodtb_data):]
917 ucode_pos = len(nodtb_data)
918 dtb_with_ucode = ucode_content[16:]
919 fdt_len = self.GetFdtLen(dtb_with_ucode)
920 else:
921 dtb_with_ucode = data[len(nodtb_data):]
922 fdt_len = self.GetFdtLen(dtb_with_ucode)
923 ucode_content = dtb_with_ucode[fdt_len:]
924 ucode_pos = len(nodtb_data) + fdt_len
Simon Glasse0ff8552016-11-25 20:15:53 -0700925 fname = tools.GetOutputFilename('test.dtb')
926 with open(fname, 'wb') as fd:
Simon Glassadc57012018-07-06 10:27:16 -0600927 fd.write(dtb_with_ucode)
Simon Glassec3f3782017-05-27 07:38:29 -0600928 dtb = fdt.FdtScan(fname)
929 ucode = dtb.GetNode('/microcode')
Simon Glasse0ff8552016-11-25 20:15:53 -0700930 self.assertTrue(ucode)
931 for node in ucode.subnodes:
932 self.assertFalse(node.props.get('data'))
933
Simon Glasse0ff8552016-11-25 20:15:53 -0700934 # Check that the microcode appears immediately after the Fdt
935 # This matches the concatenation of the data properties in
Simon Glass87722132017-11-12 21:52:26 -0700936 # the /microcode/update@xxx nodes in 34_x86_ucode.dts.
Simon Glasse0ff8552016-11-25 20:15:53 -0700937 ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
938 0x78235609)
Simon Glassadc57012018-07-06 10:27:16 -0600939 self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
Simon Glasse0ff8552016-11-25 20:15:53 -0700940
941 # Check that the microcode pointer was inserted. It should match the
Simon Glass3ab95982018-08-01 15:22:37 -0600942 # expected offset and size
Simon Glasse0ff8552016-11-25 20:15:53 -0700943 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
944 len(ucode_data))
Simon Glass736bb0a2018-07-06 10:27:17 -0600945 u_boot = data[:len(nodtb_data)]
946 return u_boot, pos_and_size
Simon Glass6b187df2017-11-12 21:52:27 -0700947
948 def testPackUbootMicrocode(self):
949 """Test that x86 microcode can be handled correctly
950
951 We expect to see the following in the image, in order:
952 u-boot-nodtb.bin with a microcode pointer inserted at the correct
953 place
954 u-boot.dtb with the microcode removed
955 the microcode
956 """
Simon Glass741f2d62018-10-01 12:22:30 -0600957 first, pos_and_size = self._RunMicrocodeTest('034_x86_ucode.dts',
Simon Glass6b187df2017-11-12 21:52:27 -0700958 U_BOOT_NODTB_DATA)
Simon Glassc6c10e72019-05-17 22:00:46 -0600959 self.assertEqual(b'nodtb with microcode' + pos_and_size +
960 b' somewhere in here', first)
Simon Glasse0ff8552016-11-25 20:15:53 -0700961
Simon Glass160a7662017-05-27 07:38:26 -0600962 def _RunPackUbootSingleMicrocode(self):
Simon Glasse0ff8552016-11-25 20:15:53 -0700963 """Test that x86 microcode can be handled correctly
964
965 We expect to see the following in the image, in order:
966 u-boot-nodtb.bin with a microcode pointer inserted at the correct
967 place
968 u-boot.dtb with the microcode
969 an empty microcode region
970 """
971 # We need the libfdt library to run this test since only that allows
972 # finding the offset of a property. This is required by
973 # Entry_u_boot_dtb_with_ucode.ObtainContents().
Simon Glass741f2d62018-10-01 12:22:30 -0600974 data = self._DoReadFile('035_x86_single_ucode.dts', True)
Simon Glasse0ff8552016-11-25 20:15:53 -0700975
976 second = data[len(U_BOOT_NODTB_DATA):]
977
978 fdt_len = self.GetFdtLen(second)
979 third = second[fdt_len:]
980 second = second[:fdt_len]
981
Simon Glass160a7662017-05-27 07:38:26 -0600982 ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
983 self.assertIn(ucode_data, second)
984 ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
Simon Glasse0ff8552016-11-25 20:15:53 -0700985
Simon Glass160a7662017-05-27 07:38:26 -0600986 # Check that the microcode pointer was inserted. It should match the
Simon Glass3ab95982018-08-01 15:22:37 -0600987 # expected offset and size
Simon Glass160a7662017-05-27 07:38:26 -0600988 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
989 len(ucode_data))
990 first = data[:len(U_BOOT_NODTB_DATA)]
Simon Glassc6c10e72019-05-17 22:00:46 -0600991 self.assertEqual(b'nodtb with microcode' + pos_and_size +
992 b' somewhere in here', first)
Simon Glassc49deb82016-11-25 20:15:54 -0700993
Simon Glass75db0862016-11-25 20:15:55 -0700994 def testPackUbootSingleMicrocode(self):
995 """Test that x86 microcode can be handled correctly with fdt_normal.
996 """
Simon Glass160a7662017-05-27 07:38:26 -0600997 self._RunPackUbootSingleMicrocode()
Simon Glass75db0862016-11-25 20:15:55 -0700998
Simon Glassc49deb82016-11-25 20:15:54 -0700999 def testUBootImg(self):
1000 """Test that u-boot.img can be put in a file"""
Simon Glass741f2d62018-10-01 12:22:30 -06001001 data = self._DoReadFile('036_u_boot_img.dts')
Simon Glassc49deb82016-11-25 20:15:54 -07001002 self.assertEqual(U_BOOT_IMG_DATA, data)
Simon Glass75db0862016-11-25 20:15:55 -07001003
1004 def testNoMicrocode(self):
1005 """Test that a missing microcode region is detected"""
1006 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001007 self._DoReadFile('037_x86_no_ucode.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -07001008 self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
1009 "node found in ", str(e.exception))
1010
1011 def testMicrocodeWithoutNode(self):
1012 """Test that a missing u-boot-dtb-with-ucode node is detected"""
1013 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001014 self._DoReadFile('038_x86_ucode_missing_node.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -07001015 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1016 "microcode region u-boot-dtb-with-ucode", str(e.exception))
1017
1018 def testMicrocodeWithoutNode2(self):
1019 """Test that a missing u-boot-ucode node is detected"""
1020 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001021 self._DoReadFile('039_x86_ucode_missing_node2.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -07001022 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1023 "microcode region u-boot-ucode", str(e.exception))
1024
1025 def testMicrocodeWithoutPtrInElf(self):
1026 """Test that a U-Boot binary without the microcode symbol is detected"""
1027 # ELF file without a '_dt_ucode_base_size' symbol
Simon Glass75db0862016-11-25 20:15:55 -07001028 try:
Simon Glass1d0ebf72019-05-14 15:53:42 -06001029 with open(self.TestFile('u_boot_no_ucode_ptr'), 'rb') as fd:
Simon Glass75db0862016-11-25 20:15:55 -07001030 TestFunctional._MakeInputFile('u-boot', fd.read())
1031
1032 with self.assertRaises(ValueError) as e:
Simon Glass160a7662017-05-27 07:38:26 -06001033 self._RunPackUbootSingleMicrocode()
Simon Glass75db0862016-11-25 20:15:55 -07001034 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
1035 "_dt_ucode_base_size symbol in u-boot", str(e.exception))
1036
1037 finally:
1038 # Put the original file back
Simon Glass1d0ebf72019-05-14 15:53:42 -06001039 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
Simon Glass75db0862016-11-25 20:15:55 -07001040 TestFunctional._MakeInputFile('u-boot', fd.read())
1041
1042 def testMicrocodeNotInImage(self):
1043 """Test that microcode must be placed within the image"""
1044 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001045 self._DoReadFile('040_x86_ucode_not_in_image.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -07001046 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
1047 "pointer _dt_ucode_base_size at fffffe14 is outside the "
Simon Glass25ac0e62018-06-01 09:38:14 -06001048 "section ranging from 00000000 to 0000002e", str(e.exception))
Simon Glass75db0862016-11-25 20:15:55 -07001049
1050 def testWithoutMicrocode(self):
1051 """Test that we can cope with an image without microcode (e.g. qemu)"""
Simon Glass1d0ebf72019-05-14 15:53:42 -06001052 with open(self.TestFile('u_boot_no_ucode_ptr'), 'rb') as fd:
Simon Glass75db0862016-11-25 20:15:55 -07001053 TestFunctional._MakeInputFile('u-boot', fd.read())
Simon Glass741f2d62018-10-01 12:22:30 -06001054 data, dtb, _, _ = self._DoReadFileDtb('044_x86_optional_ucode.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -07001055
1056 # Now check the device tree has no microcode
1057 self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
1058 second = data[len(U_BOOT_NODTB_DATA):]
1059
1060 fdt_len = self.GetFdtLen(second)
1061 self.assertEqual(dtb, second[:fdt_len])
1062
1063 used_len = len(U_BOOT_NODTB_DATA) + fdt_len
1064 third = data[used_len:]
Simon Glasse6d85ff2019-05-14 15:53:47 -06001065 self.assertEqual(tools.GetBytes(0, 0x200 - used_len), third)
Simon Glass75db0862016-11-25 20:15:55 -07001066
1067 def testUnknownPosSize(self):
1068 """Test that microcode must be placed within the image"""
1069 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001070 self._DoReadFile('041_unknown_pos_size.dts', True)
Simon Glass3ab95982018-08-01 15:22:37 -06001071 self.assertIn("Section '/binman': Unable to set offset/size for unknown "
Simon Glass75db0862016-11-25 20:15:55 -07001072 "entry 'invalid-entry'", str(e.exception))
Simon Glassda229092016-11-25 20:15:56 -07001073
1074 def testPackFsp(self):
1075 """Test that an image with a FSP binary can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001076 data = self._DoReadFile('042_intel-fsp.dts')
Simon Glassda229092016-11-25 20:15:56 -07001077 self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
1078
1079 def testPackCmc(self):
Bin Meng59ea8c22017-08-15 22:41:54 -07001080 """Test that an image with a CMC binary can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001081 data = self._DoReadFile('043_intel-cmc.dts')
Simon Glassda229092016-11-25 20:15:56 -07001082 self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
Bin Meng59ea8c22017-08-15 22:41:54 -07001083
1084 def testPackVbt(self):
1085 """Test that an image with a VBT binary can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001086 data = self._DoReadFile('046_intel-vbt.dts')
Bin Meng59ea8c22017-08-15 22:41:54 -07001087 self.assertEqual(VBT_DATA, data[:len(VBT_DATA)])
Simon Glass9fc60b42017-11-12 21:52:22 -07001088
Simon Glass56509842017-11-12 21:52:25 -07001089 def testSplBssPad(self):
1090 """Test that we can pad SPL's BSS with zeros"""
Simon Glass6b187df2017-11-12 21:52:27 -07001091 # ELF file with a '__bss_size' symbol
Simon Glass11ae93e2018-10-01 21:12:47 -06001092 self._SetupSplElf()
Simon Glass741f2d62018-10-01 12:22:30 -06001093 data = self._DoReadFile('047_spl_bss_pad.dts')
Simon Glasse6d85ff2019-05-14 15:53:47 -06001094 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0, 10) + U_BOOT_DATA,
1095 data)
Simon Glass56509842017-11-12 21:52:25 -07001096
Simon Glass86af5112018-10-01 21:12:42 -06001097 def testSplBssPadMissing(self):
1098 """Test that a missing symbol is detected"""
Simon Glass11ae93e2018-10-01 21:12:47 -06001099 self._SetupSplElf('u_boot_ucode_ptr')
Simon Glassb50e5612017-11-13 18:54:54 -07001100 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001101 self._DoReadFile('047_spl_bss_pad.dts')
Simon Glassb50e5612017-11-13 18:54:54 -07001102 self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
1103 str(e.exception))
1104
Simon Glass87722132017-11-12 21:52:26 -07001105 def testPackStart16Spl(self):
Simon Glass35b384c2018-09-14 04:57:10 -06001106 """Test that an image with an x86 start16 SPL region can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001107 data = self._DoReadFile('048_x86-start16-spl.dts')
Simon Glass87722132017-11-12 21:52:26 -07001108 self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)])
1109
Simon Glass736bb0a2018-07-06 10:27:17 -06001110 def _PackUbootSplMicrocode(self, dts, ucode_second=False):
1111 """Helper function for microcode tests
Simon Glass6b187df2017-11-12 21:52:27 -07001112
1113 We expect to see the following in the image, in order:
1114 u-boot-spl-nodtb.bin with a microcode pointer inserted at the
1115 correct place
1116 u-boot.dtb with the microcode removed
1117 the microcode
Simon Glass736bb0a2018-07-06 10:27:17 -06001118
1119 Args:
1120 dts: Device tree file to use for test
1121 ucode_second: True if the microsecond entry is second instead of
1122 third
Simon Glass6b187df2017-11-12 21:52:27 -07001123 """
Simon Glass11ae93e2018-10-01 21:12:47 -06001124 self._SetupSplElf('u_boot_ucode_ptr')
Simon Glass736bb0a2018-07-06 10:27:17 -06001125 first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA,
1126 ucode_second=ucode_second)
Simon Glassc6c10e72019-05-17 22:00:46 -06001127 self.assertEqual(b'splnodtb with microc' + pos_and_size +
1128 b'ter somewhere in here', first)
Simon Glass6b187df2017-11-12 21:52:27 -07001129
Simon Glass736bb0a2018-07-06 10:27:17 -06001130 def testPackUbootSplMicrocode(self):
1131 """Test that x86 microcode can be handled correctly in SPL"""
Simon Glass741f2d62018-10-01 12:22:30 -06001132 self._PackUbootSplMicrocode('049_x86_ucode_spl.dts')
Simon Glass736bb0a2018-07-06 10:27:17 -06001133
1134 def testPackUbootSplMicrocodeReorder(self):
1135 """Test that order doesn't matter for microcode entries
1136
1137 This is the same as testPackUbootSplMicrocode but when we process the
1138 u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode
1139 entry, so we reply on binman to try later.
1140 """
Simon Glass741f2d62018-10-01 12:22:30 -06001141 self._PackUbootSplMicrocode('058_x86_ucode_spl_needs_retry.dts',
Simon Glass736bb0a2018-07-06 10:27:17 -06001142 ucode_second=True)
1143
Simon Glassca4f4ff2017-11-12 21:52:28 -07001144 def testPackMrc(self):
1145 """Test that an image with an MRC binary can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001146 data = self._DoReadFile('050_intel_mrc.dts')
Simon Glassca4f4ff2017-11-12 21:52:28 -07001147 self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
1148
Simon Glass47419ea2017-11-13 18:54:55 -07001149 def testSplDtb(self):
1150 """Test that an image with spl/u-boot-spl.dtb can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001151 data = self._DoReadFile('051_u_boot_spl_dtb.dts')
Simon Glass47419ea2017-11-13 18:54:55 -07001152 self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
1153
Simon Glass4e6fdbe2017-11-13 18:54:56 -07001154 def testSplNoDtb(self):
1155 """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001156 data = self._DoReadFile('052_u_boot_spl_nodtb.dts')
Simon Glass4e6fdbe2017-11-13 18:54:56 -07001157 self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
1158
Simon Glass19790632017-11-13 18:55:01 -07001159 def testSymbols(self):
1160 """Test binman can assign symbols embedded in U-Boot"""
1161 elf_fname = self.TestFile('u_boot_binman_syms')
1162 syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
1163 addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
Simon Glass3ab95982018-08-01 15:22:37 -06001164 self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
Simon Glass19790632017-11-13 18:55:01 -07001165
Simon Glass11ae93e2018-10-01 21:12:47 -06001166 self._SetupSplElf('u_boot_binman_syms')
Simon Glass741f2d62018-10-01 12:22:30 -06001167 data = self._DoReadFile('053_symbols.dts')
Simon Glass19790632017-11-13 18:55:01 -07001168 sym_values = struct.pack('<LQL', 0x24 + 0, 0x24 + 24, 0x24 + 20)
Simon Glasse6d85ff2019-05-14 15:53:47 -06001169 expected = (sym_values + U_BOOT_SPL_DATA[16:] +
1170 tools.GetBytes(0xff, 1) + U_BOOT_DATA + sym_values +
1171 U_BOOT_SPL_DATA[16:])
Simon Glass19790632017-11-13 18:55:01 -07001172 self.assertEqual(expected, data)
1173
Simon Glassdd57c132018-06-01 09:38:11 -06001174 def testPackUnitAddress(self):
1175 """Test that we support multiple binaries with the same name"""
Simon Glass741f2d62018-10-01 12:22:30 -06001176 data = self._DoReadFile('054_unit_address.dts')
Simon Glassdd57c132018-06-01 09:38:11 -06001177 self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
1178
Simon Glass18546952018-06-01 09:38:16 -06001179 def testSections(self):
1180 """Basic test of sections"""
Simon Glass741f2d62018-10-01 12:22:30 -06001181 data = self._DoReadFile('055_sections.dts')
Simon Glassc6c10e72019-05-17 22:00:46 -06001182 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1183 U_BOOT_DATA + tools.GetBytes(ord('a'), 12) +
1184 U_BOOT_DATA + tools.GetBytes(ord('&'), 4))
Simon Glass18546952018-06-01 09:38:16 -06001185 self.assertEqual(expected, data)
Simon Glass9fc60b42017-11-12 21:52:22 -07001186
Simon Glass3b0c3822018-06-01 09:38:20 -06001187 def testMap(self):
1188 """Tests outputting a map of the images"""
Simon Glass741f2d62018-10-01 12:22:30 -06001189 _, _, map_data, _ = self._DoReadFileDtb('055_sections.dts', map=True)
Simon Glass1be70d22018-07-17 13:25:49 -06001190 self.assertEqual('''ImagePos Offset Size Name
119100000000 00000000 00000028 main-section
119200000000 00000000 00000010 section@0
119300000000 00000000 00000004 u-boot
119400000010 00000010 00000010 section@1
119500000010 00000000 00000004 u-boot
119600000020 00000020 00000004 section@2
119700000020 00000000 00000004 u-boot
Simon Glass3b0c3822018-06-01 09:38:20 -06001198''', map_data)
1199
Simon Glassc8d48ef2018-06-01 09:38:21 -06001200 def testNamePrefix(self):
1201 """Tests that name prefixes are used"""
Simon Glass741f2d62018-10-01 12:22:30 -06001202 _, _, map_data, _ = self._DoReadFileDtb('056_name_prefix.dts', map=True)
Simon Glass1be70d22018-07-17 13:25:49 -06001203 self.assertEqual('''ImagePos Offset Size Name
120400000000 00000000 00000028 main-section
120500000000 00000000 00000010 section@0
120600000000 00000000 00000004 ro-u-boot
120700000010 00000010 00000010 section@1
120800000010 00000000 00000004 rw-u-boot
Simon Glassc8d48ef2018-06-01 09:38:21 -06001209''', map_data)
1210
Simon Glass736bb0a2018-07-06 10:27:17 -06001211 def testUnknownContents(self):
1212 """Test that obtaining the contents works as expected"""
1213 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001214 self._DoReadFile('057_unknown_contents.dts', True)
Simon Glass736bb0a2018-07-06 10:27:17 -06001215 self.assertIn("Section '/binman': Internal error: Could not complete "
1216 "processing of contents: remaining [<_testing.Entry__testing ",
1217 str(e.exception))
1218
Simon Glass5c890232018-07-06 10:27:19 -06001219 def testBadChangeSize(self):
1220 """Test that trying to change the size of an entry fails"""
1221 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001222 self._DoReadFile('059_change_size.dts', True)
Simon Glass5c890232018-07-06 10:27:19 -06001223 self.assertIn("Node '/binman/_testing': Cannot update entry size from "
1224 '2 to 1', str(e.exception))
1225
Simon Glass16b8d6b2018-07-06 10:27:42 -06001226 def testUpdateFdt(self):
Simon Glass3ab95982018-08-01 15:22:37 -06001227 """Test that we can update the device tree with offset/size info"""
Simon Glass741f2d62018-10-01 12:22:30 -06001228 _, _, _, out_dtb_fname = self._DoReadFileDtb('060_fdt_update.dts',
Simon Glass16b8d6b2018-07-06 10:27:42 -06001229 update_dtb=True)
Simon Glasscee02e62018-07-17 13:25:52 -06001230 dtb = fdt.Fdt(out_dtb_fname)
1231 dtb.Scan()
1232 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'])
Simon Glass16b8d6b2018-07-06 10:27:42 -06001233 self.assertEqual({
Simon Glassdbf6be92018-08-01 15:22:42 -06001234 'image-pos': 0,
Simon Glass8122f392018-07-17 13:25:28 -06001235 'offset': 0,
Simon Glass3ab95982018-08-01 15:22:37 -06001236 '_testing:offset': 32,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001237 '_testing:size': 1,
Simon Glassdbf6be92018-08-01 15:22:42 -06001238 '_testing:image-pos': 32,
Simon Glass3ab95982018-08-01 15:22:37 -06001239 'section@0/u-boot:offset': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001240 'section@0/u-boot:size': len(U_BOOT_DATA),
Simon Glassdbf6be92018-08-01 15:22:42 -06001241 'section@0/u-boot:image-pos': 0,
Simon Glass3ab95982018-08-01 15:22:37 -06001242 'section@0:offset': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001243 'section@0:size': 16,
Simon Glassdbf6be92018-08-01 15:22:42 -06001244 'section@0:image-pos': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001245
Simon Glass3ab95982018-08-01 15:22:37 -06001246 'section@1/u-boot:offset': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001247 'section@1/u-boot:size': len(U_BOOT_DATA),
Simon Glassdbf6be92018-08-01 15:22:42 -06001248 'section@1/u-boot:image-pos': 16,
Simon Glass3ab95982018-08-01 15:22:37 -06001249 'section@1:offset': 16,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001250 'section@1:size': 16,
Simon Glassdbf6be92018-08-01 15:22:42 -06001251 'section@1:image-pos': 16,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001252 'size': 40
1253 }, props)
1254
1255 def testUpdateFdtBad(self):
1256 """Test that we detect when ProcessFdt never completes"""
1257 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001258 self._DoReadFileDtb('061_fdt_update_bad.dts', update_dtb=True)
Simon Glass16b8d6b2018-07-06 10:27:42 -06001259 self.assertIn('Could not complete processing of Fdt: remaining '
1260 '[<_testing.Entry__testing', str(e.exception))
Simon Glass5c890232018-07-06 10:27:19 -06001261
Simon Glass53af22a2018-07-17 13:25:32 -06001262 def testEntryArgs(self):
1263 """Test passing arguments to entries from the command line"""
1264 entry_args = {
1265 'test-str-arg': 'test1',
1266 'test-int-arg': '456',
1267 }
Simon Glass741f2d62018-10-01 12:22:30 -06001268 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
Simon Glass53af22a2018-07-17 13:25:32 -06001269 self.assertIn('image', control.images)
1270 entry = control.images['image'].GetEntries()['_testing']
1271 self.assertEqual('test0', entry.test_str_fdt)
1272 self.assertEqual('test1', entry.test_str_arg)
1273 self.assertEqual(123, entry.test_int_fdt)
1274 self.assertEqual(456, entry.test_int_arg)
1275
1276 def testEntryArgsMissing(self):
1277 """Test missing arguments and properties"""
1278 entry_args = {
1279 'test-int-arg': '456',
1280 }
Simon Glass741f2d62018-10-01 12:22:30 -06001281 self._DoReadFileDtb('063_entry_args_missing.dts', entry_args=entry_args)
Simon Glass53af22a2018-07-17 13:25:32 -06001282 entry = control.images['image'].GetEntries()['_testing']
1283 self.assertEqual('test0', entry.test_str_fdt)
1284 self.assertEqual(None, entry.test_str_arg)
1285 self.assertEqual(None, entry.test_int_fdt)
1286 self.assertEqual(456, entry.test_int_arg)
1287
1288 def testEntryArgsRequired(self):
1289 """Test missing arguments and properties"""
1290 entry_args = {
1291 'test-int-arg': '456',
1292 }
1293 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001294 self._DoReadFileDtb('064_entry_args_required.dts')
Simon Glass53af22a2018-07-17 13:25:32 -06001295 self.assertIn("Node '/binman/_testing': Missing required "
1296 'properties/entry args: test-str-arg, test-int-fdt, test-int-arg',
1297 str(e.exception))
1298
1299 def testEntryArgsInvalidFormat(self):
1300 """Test that an invalid entry-argument format is detected"""
Simon Glass741f2d62018-10-01 12:22:30 -06001301 args = ['-d', self.TestFile('064_entry_args_required.dts'), '-ano-value']
Simon Glass53af22a2018-07-17 13:25:32 -06001302 with self.assertRaises(ValueError) as e:
1303 self._DoBinman(*args)
1304 self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
1305
1306 def testEntryArgsInvalidInteger(self):
1307 """Test that an invalid entry-argument integer is detected"""
1308 entry_args = {
1309 'test-int-arg': 'abc',
1310 }
1311 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001312 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
Simon Glass53af22a2018-07-17 13:25:32 -06001313 self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
1314 "'test-int-arg' (value 'abc') to integer",
1315 str(e.exception))
1316
1317 def testEntryArgsInvalidDatatype(self):
1318 """Test that an invalid entry-argument datatype is detected
1319
1320 This test could be written in entry_test.py except that it needs
1321 access to control.entry_args, which seems more than that module should
1322 be able to see.
1323 """
1324 entry_args = {
1325 'test-bad-datatype-arg': '12',
1326 }
1327 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001328 self._DoReadFileDtb('065_entry_args_unknown_datatype.dts',
Simon Glass53af22a2018-07-17 13:25:32 -06001329 entry_args=entry_args)
1330 self.assertIn('GetArg() internal error: Unknown data type ',
1331 str(e.exception))
1332
Simon Glassbb748372018-07-17 13:25:33 -06001333 def testText(self):
1334 """Test for a text entry type"""
1335 entry_args = {
1336 'test-id': TEXT_DATA,
1337 'test-id2': TEXT_DATA2,
1338 'test-id3': TEXT_DATA3,
1339 }
Simon Glass741f2d62018-10-01 12:22:30 -06001340 data, _, _, _ = self._DoReadFileDtb('066_text.dts',
Simon Glassbb748372018-07-17 13:25:33 -06001341 entry_args=entry_args)
Simon Glassc6c10e72019-05-17 22:00:46 -06001342 expected = (tools.ToBytes(TEXT_DATA) +
1343 tools.GetBytes(0, 8 - len(TEXT_DATA)) +
1344 tools.ToBytes(TEXT_DATA2) + tools.ToBytes(TEXT_DATA3) +
Simon Glassaa88b502019-07-08 13:18:40 -06001345 b'some text' + b'more text')
Simon Glassbb748372018-07-17 13:25:33 -06001346 self.assertEqual(expected, data)
1347
Simon Glassfd8d1f72018-07-17 13:25:36 -06001348 def testEntryDocs(self):
1349 """Test for creation of entry documentation"""
1350 with test_util.capture_sys_output() as (stdout, stderr):
1351 control.WriteEntryDocs(binman.GetEntryModules())
1352 self.assertTrue(len(stdout.getvalue()) > 0)
1353
1354 def testEntryDocsMissing(self):
1355 """Test handling of missing entry documentation"""
1356 with self.assertRaises(ValueError) as e:
1357 with test_util.capture_sys_output() as (stdout, stderr):
1358 control.WriteEntryDocs(binman.GetEntryModules(), 'u_boot')
1359 self.assertIn('Documentation is missing for modules: u_boot',
1360 str(e.exception))
1361
Simon Glass11e36cc2018-07-17 13:25:38 -06001362 def testFmap(self):
1363 """Basic test of generation of a flashrom fmap"""
Simon Glass741f2d62018-10-01 12:22:30 -06001364 data = self._DoReadFile('067_fmap.dts')
Simon Glass11e36cc2018-07-17 13:25:38 -06001365 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
Simon Glassc6c10e72019-05-17 22:00:46 -06001366 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1367 U_BOOT_DATA + tools.GetBytes(ord('a'), 12))
Simon Glass11e36cc2018-07-17 13:25:38 -06001368 self.assertEqual(expected, data[:32])
Simon Glassc6c10e72019-05-17 22:00:46 -06001369 self.assertEqual(b'__FMAP__', fhdr.signature)
Simon Glass11e36cc2018-07-17 13:25:38 -06001370 self.assertEqual(1, fhdr.ver_major)
1371 self.assertEqual(0, fhdr.ver_minor)
1372 self.assertEqual(0, fhdr.base)
1373 self.assertEqual(16 + 16 +
1374 fmap_util.FMAP_HEADER_LEN +
1375 fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001376 self.assertEqual(b'FMAP', fhdr.name)
Simon Glass11e36cc2018-07-17 13:25:38 -06001377 self.assertEqual(3, fhdr.nareas)
1378 for fentry in fentries:
1379 self.assertEqual(0, fentry.flags)
1380
1381 self.assertEqual(0, fentries[0].offset)
1382 self.assertEqual(4, fentries[0].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001383 self.assertEqual(b'RO_U_BOOT', fentries[0].name)
Simon Glass11e36cc2018-07-17 13:25:38 -06001384
1385 self.assertEqual(16, fentries[1].offset)
1386 self.assertEqual(4, fentries[1].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001387 self.assertEqual(b'RW_U_BOOT', fentries[1].name)
Simon Glass11e36cc2018-07-17 13:25:38 -06001388
1389 self.assertEqual(32, fentries[2].offset)
1390 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1391 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001392 self.assertEqual(b'FMAP', fentries[2].name)
Simon Glass11e36cc2018-07-17 13:25:38 -06001393
Simon Glassec127af2018-07-17 13:25:39 -06001394 def testBlobNamedByArg(self):
1395 """Test we can add a blob with the filename coming from an entry arg"""
1396 entry_args = {
1397 'cros-ec-rw-path': 'ecrw.bin',
1398 }
Simon Glass741f2d62018-10-01 12:22:30 -06001399 data, _, _, _ = self._DoReadFileDtb('068_blob_named_by_arg.dts',
Simon Glassec127af2018-07-17 13:25:39 -06001400 entry_args=entry_args)
1401
Simon Glass3af8e492018-07-17 13:25:40 -06001402 def testFill(self):
1403 """Test for an fill entry type"""
Simon Glass741f2d62018-10-01 12:22:30 -06001404 data = self._DoReadFile('069_fill.dts')
Simon Glasse6d85ff2019-05-14 15:53:47 -06001405 expected = tools.GetBytes(0xff, 8) + tools.GetBytes(0, 8)
Simon Glass3af8e492018-07-17 13:25:40 -06001406 self.assertEqual(expected, data)
1407
1408 def testFillNoSize(self):
1409 """Test for an fill entry type with no size"""
1410 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001411 self._DoReadFile('070_fill_no_size.dts')
Simon Glass3af8e492018-07-17 13:25:40 -06001412 self.assertIn("'fill' entry must have a size property",
1413 str(e.exception))
1414
Simon Glass0ef87aa2018-07-17 13:25:44 -06001415 def _HandleGbbCommand(self, pipe_list):
1416 """Fake calls to the futility utility"""
1417 if pipe_list[0][0] == 'futility':
1418 fname = pipe_list[0][-1]
1419 # Append our GBB data to the file, which will happen every time the
1420 # futility command is called.
Simon Glass1d0ebf72019-05-14 15:53:42 -06001421 with open(fname, 'ab') as fd:
Simon Glass0ef87aa2018-07-17 13:25:44 -06001422 fd.write(GBB_DATA)
1423 return command.CommandResult()
1424
1425 def testGbb(self):
1426 """Test for the Chromium OS Google Binary Block"""
1427 command.test_result = self._HandleGbbCommand
1428 entry_args = {
1429 'keydir': 'devkeys',
1430 'bmpblk': 'bmpblk.bin',
1431 }
Simon Glass741f2d62018-10-01 12:22:30 -06001432 data, _, _, _ = self._DoReadFileDtb('071_gbb.dts', entry_args=entry_args)
Simon Glass0ef87aa2018-07-17 13:25:44 -06001433
1434 # Since futility
Simon Glasse6d85ff2019-05-14 15:53:47 -06001435 expected = (GBB_DATA + GBB_DATA + tools.GetBytes(0, 8) +
1436 tools.GetBytes(0, 0x2180 - 16))
Simon Glass0ef87aa2018-07-17 13:25:44 -06001437 self.assertEqual(expected, data)
1438
1439 def testGbbTooSmall(self):
1440 """Test for the Chromium OS Google Binary Block being large enough"""
1441 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001442 self._DoReadFileDtb('072_gbb_too_small.dts')
Simon Glass0ef87aa2018-07-17 13:25:44 -06001443 self.assertIn("Node '/binman/gbb': GBB is too small",
1444 str(e.exception))
1445
1446 def testGbbNoSize(self):
1447 """Test for the Chromium OS Google Binary Block having a size"""
1448 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001449 self._DoReadFileDtb('073_gbb_no_size.dts')
Simon Glass0ef87aa2018-07-17 13:25:44 -06001450 self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
1451 str(e.exception))
1452
Simon Glass24d0d3c2018-07-17 13:25:47 -06001453 def _HandleVblockCommand(self, pipe_list):
1454 """Fake calls to the futility utility"""
1455 if pipe_list[0][0] == 'futility':
1456 fname = pipe_list[0][3]
Simon Glassa326b492018-09-14 04:57:11 -06001457 with open(fname, 'wb') as fd:
Simon Glass24d0d3c2018-07-17 13:25:47 -06001458 fd.write(VBLOCK_DATA)
1459 return command.CommandResult()
1460
1461 def testVblock(self):
1462 """Test for the Chromium OS Verified Boot Block"""
1463 command.test_result = self._HandleVblockCommand
1464 entry_args = {
1465 'keydir': 'devkeys',
1466 }
Simon Glass741f2d62018-10-01 12:22:30 -06001467 data, _, _, _ = self._DoReadFileDtb('074_vblock.dts',
Simon Glass24d0d3c2018-07-17 13:25:47 -06001468 entry_args=entry_args)
1469 expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
1470 self.assertEqual(expected, data)
1471
1472 def testVblockNoContent(self):
1473 """Test we detect a vblock which has no content to sign"""
1474 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001475 self._DoReadFile('075_vblock_no_content.dts')
Simon Glass24d0d3c2018-07-17 13:25:47 -06001476 self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
1477 'property', str(e.exception))
1478
1479 def testVblockBadPhandle(self):
1480 """Test that we detect a vblock with an invalid phandle in contents"""
1481 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001482 self._DoReadFile('076_vblock_bad_phandle.dts')
Simon Glass24d0d3c2018-07-17 13:25:47 -06001483 self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
1484 '1000', str(e.exception))
1485
1486 def testVblockBadEntry(self):
1487 """Test that we detect an entry that points to a non-entry"""
1488 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001489 self._DoReadFile('077_vblock_bad_entry.dts')
Simon Glass24d0d3c2018-07-17 13:25:47 -06001490 self.assertIn("Node '/binman/vblock': Cannot find entry for node "
1491 "'other'", str(e.exception))
1492
Simon Glassb8ef5b62018-07-17 13:25:48 -06001493 def testTpl(self):
1494 """Test that an image with TPL and ots device tree can be created"""
1495 # ELF file with a '__bss_size' symbol
Simon Glass1d0ebf72019-05-14 15:53:42 -06001496 with open(self.TestFile('bss_data'), 'rb') as fd:
Simon Glassb8ef5b62018-07-17 13:25:48 -06001497 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
Simon Glass741f2d62018-10-01 12:22:30 -06001498 data = self._DoReadFile('078_u_boot_tpl.dts')
Simon Glassb8ef5b62018-07-17 13:25:48 -06001499 self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
1500
Simon Glass15a587c2018-07-17 13:25:51 -06001501 def testUsesPos(self):
1502 """Test that the 'pos' property cannot be used anymore"""
1503 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001504 data = self._DoReadFile('079_uses_pos.dts')
Simon Glass15a587c2018-07-17 13:25:51 -06001505 self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
1506 "'pos'", str(e.exception))
1507
Simon Glassd178eab2018-09-14 04:57:08 -06001508 def testFillZero(self):
1509 """Test for an fill entry type with a size of 0"""
Simon Glass741f2d62018-10-01 12:22:30 -06001510 data = self._DoReadFile('080_fill_empty.dts')
Simon Glasse6d85ff2019-05-14 15:53:47 -06001511 self.assertEqual(tools.GetBytes(0, 16), data)
Simon Glassd178eab2018-09-14 04:57:08 -06001512
Simon Glass0b489362018-09-14 04:57:09 -06001513 def testTextMissing(self):
1514 """Test for a text entry type where there is no text"""
1515 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001516 self._DoReadFileDtb('066_text.dts',)
Simon Glass0b489362018-09-14 04:57:09 -06001517 self.assertIn("Node '/binman/text': No value provided for text label "
1518 "'test-id'", str(e.exception))
1519
Simon Glass35b384c2018-09-14 04:57:10 -06001520 def testPackStart16Tpl(self):
1521 """Test that an image with an x86 start16 TPL region can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001522 data = self._DoReadFile('081_x86-start16-tpl.dts')
Simon Glass35b384c2018-09-14 04:57:10 -06001523 self.assertEqual(X86_START16_TPL_DATA, data[:len(X86_START16_TPL_DATA)])
1524
Simon Glass0bfa7b02018-09-14 04:57:12 -06001525 def testSelectImage(self):
1526 """Test that we can select which images to build"""
Simon Glasseb833d82019-04-25 21:58:34 -06001527 expected = 'Skipping images: image1'
Simon Glass0bfa7b02018-09-14 04:57:12 -06001528
Simon Glasseb833d82019-04-25 21:58:34 -06001529 # We should only get the expected message in verbose mode
Simon Glassee0c9a72019-07-08 13:18:48 -06001530 for verbosity in (0, 2):
Simon Glasseb833d82019-04-25 21:58:34 -06001531 with test_util.capture_sys_output() as (stdout, stderr):
1532 retcode = self._DoTestFile('006_dual_image.dts',
1533 verbosity=verbosity,
1534 images=['image2'])
1535 self.assertEqual(0, retcode)
1536 if verbosity:
1537 self.assertIn(expected, stdout.getvalue())
1538 else:
1539 self.assertNotIn(expected, stdout.getvalue())
1540
1541 self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
1542 self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
Simon Glass0bfa7b02018-09-14 04:57:12 -06001543
Simon Glass6ed45ba2018-09-14 04:57:24 -06001544 def testUpdateFdtAll(self):
1545 """Test that all device trees are updated with offset/size info"""
Simon Glass741f2d62018-10-01 12:22:30 -06001546 data, _, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
Simon Glass6ed45ba2018-09-14 04:57:24 -06001547 use_real_dtb=True, update_dtb=True)
1548
1549 base_expected = {
1550 'section:image-pos': 0,
1551 'u-boot-tpl-dtb:size': 513,
1552 'u-boot-spl-dtb:size': 513,
1553 'u-boot-spl-dtb:offset': 493,
1554 'image-pos': 0,
1555 'section/u-boot-dtb:image-pos': 0,
1556 'u-boot-spl-dtb:image-pos': 493,
1557 'section/u-boot-dtb:size': 493,
1558 'u-boot-tpl-dtb:image-pos': 1006,
1559 'section/u-boot-dtb:offset': 0,
1560 'section:size': 493,
1561 'offset': 0,
1562 'section:offset': 0,
1563 'u-boot-tpl-dtb:offset': 1006,
1564 'size': 1519
1565 }
1566
1567 # We expect three device-tree files in the output, one after the other.
1568 # Read them in sequence. We look for an 'spl' property in the SPL tree,
1569 # and 'tpl' in the TPL tree, to make sure they are distinct from the
1570 # main U-Boot tree. All three should have the same postions and offset.
1571 start = 0
1572 for item in ['', 'spl', 'tpl']:
1573 dtb = fdt.Fdt.FromData(data[start:])
1574 dtb.Scan()
1575 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos',
1576 'spl', 'tpl'])
1577 expected = dict(base_expected)
1578 if item:
1579 expected[item] = 0
1580 self.assertEqual(expected, props)
1581 start += dtb._fdt_obj.totalsize()
1582
1583 def testUpdateFdtOutput(self):
1584 """Test that output DTB files are updated"""
1585 try:
Simon Glass741f2d62018-10-01 12:22:30 -06001586 data, dtb_data, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
Simon Glass6ed45ba2018-09-14 04:57:24 -06001587 use_real_dtb=True, update_dtb=True, reset_dtbs=False)
1588
1589 # Unfortunately, compiling a source file always results in a file
1590 # called source.dtb (see fdt_util.EnsureCompiled()). The test
Simon Glass741f2d62018-10-01 12:22:30 -06001591 # source file (e.g. test/075_fdt_update_all.dts) thus does not enter
Simon Glass6ed45ba2018-09-14 04:57:24 -06001592 # binman as a file called u-boot.dtb. To fix this, copy the file
1593 # over to the expected place.
1594 #tools.WriteFile(os.path.join(self._indir, 'u-boot.dtb'),
1595 #tools.ReadFile(tools.GetOutputFilename('source.dtb')))
1596 start = 0
1597 for fname in ['u-boot.dtb.out', 'spl/u-boot-spl.dtb.out',
1598 'tpl/u-boot-tpl.dtb.out']:
1599 dtb = fdt.Fdt.FromData(data[start:])
1600 size = dtb._fdt_obj.totalsize()
1601 pathname = tools.GetOutputFilename(os.path.split(fname)[1])
1602 outdata = tools.ReadFile(pathname)
1603 name = os.path.split(fname)[0]
1604
1605 if name:
1606 orig_indata = self._GetDtbContentsForSplTpl(dtb_data, name)
1607 else:
1608 orig_indata = dtb_data
1609 self.assertNotEqual(outdata, orig_indata,
1610 "Expected output file '%s' be updated" % pathname)
1611 self.assertEqual(outdata, data[start:start + size],
1612 "Expected output file '%s' to match output image" %
1613 pathname)
1614 start += size
1615 finally:
1616 self._ResetDtbs()
1617
Simon Glass83d73c22018-09-14 04:57:26 -06001618 def _decompress(self, data):
Simon Glassff5c7e32019-07-08 13:18:42 -06001619 return tools.Decompress(data, 'lz4')
Simon Glass83d73c22018-09-14 04:57:26 -06001620
1621 def testCompress(self):
1622 """Test compression of blobs"""
Simon Glassac62fba2019-07-08 13:18:53 -06001623 self._CheckLz4()
Simon Glass741f2d62018-10-01 12:22:30 -06001624 data, _, _, out_dtb_fname = self._DoReadFileDtb('083_compress.dts',
Simon Glass83d73c22018-09-14 04:57:26 -06001625 use_real_dtb=True, update_dtb=True)
1626 dtb = fdt.Fdt(out_dtb_fname)
1627 dtb.Scan()
1628 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
1629 orig = self._decompress(data)
1630 self.assertEquals(COMPRESS_DATA, orig)
1631 expected = {
1632 'blob:uncomp-size': len(COMPRESS_DATA),
1633 'blob:size': len(data),
1634 'size': len(data),
1635 }
1636 self.assertEqual(expected, props)
1637
Simon Glass0a98b282018-09-14 04:57:28 -06001638 def testFiles(self):
1639 """Test bringing in multiple files"""
Simon Glass741f2d62018-10-01 12:22:30 -06001640 data = self._DoReadFile('084_files.dts')
Simon Glass0a98b282018-09-14 04:57:28 -06001641 self.assertEqual(FILES_DATA, data)
1642
1643 def testFilesCompress(self):
1644 """Test bringing in multiple files and compressing them"""
Simon Glassac62fba2019-07-08 13:18:53 -06001645 self._CheckLz4()
Simon Glass741f2d62018-10-01 12:22:30 -06001646 data = self._DoReadFile('085_files_compress.dts')
Simon Glass0a98b282018-09-14 04:57:28 -06001647
1648 image = control.images['image']
1649 entries = image.GetEntries()
1650 files = entries['files']
1651 entries = files._section._entries
1652
Simon Glassc6c10e72019-05-17 22:00:46 -06001653 orig = b''
Simon Glass0a98b282018-09-14 04:57:28 -06001654 for i in range(1, 3):
1655 key = '%d.dat' % i
1656 start = entries[key].image_pos
1657 len = entries[key].size
1658 chunk = data[start:start + len]
1659 orig += self._decompress(chunk)
1660
1661 self.assertEqual(FILES_DATA, orig)
1662
1663 def testFilesMissing(self):
1664 """Test missing files"""
1665 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001666 data = self._DoReadFile('086_files_none.dts')
Simon Glass0a98b282018-09-14 04:57:28 -06001667 self.assertIn("Node '/binman/files': Pattern \'files/*.none\' matched "
1668 'no files', str(e.exception))
1669
1670 def testFilesNoPattern(self):
1671 """Test missing files"""
1672 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001673 data = self._DoReadFile('087_files_no_pattern.dts')
Simon Glass0a98b282018-09-14 04:57:28 -06001674 self.assertIn("Node '/binman/files': Missing 'pattern' property",
1675 str(e.exception))
1676
Simon Glassba64a0b2018-09-14 04:57:29 -06001677 def testExpandSize(self):
1678 """Test an expanding entry"""
Simon Glass741f2d62018-10-01 12:22:30 -06001679 data, _, map_data, _ = self._DoReadFileDtb('088_expand_size.dts',
Simon Glassba64a0b2018-09-14 04:57:29 -06001680 map=True)
Simon Glassc6c10e72019-05-17 22:00:46 -06001681 expect = (tools.GetBytes(ord('a'), 8) + U_BOOT_DATA +
1682 MRC_DATA + tools.GetBytes(ord('b'), 1) + U_BOOT_DATA +
1683 tools.GetBytes(ord('c'), 8) + U_BOOT_DATA +
1684 tools.GetBytes(ord('d'), 8))
Simon Glassba64a0b2018-09-14 04:57:29 -06001685 self.assertEqual(expect, data)
1686 self.assertEqual('''ImagePos Offset Size Name
168700000000 00000000 00000028 main-section
168800000000 00000000 00000008 fill
168900000008 00000008 00000004 u-boot
16900000000c 0000000c 00000004 section
16910000000c 00000000 00000003 intel-mrc
169200000010 00000010 00000004 u-boot2
169300000014 00000014 0000000c section2
169400000014 00000000 00000008 fill
16950000001c 00000008 00000004 u-boot
169600000020 00000020 00000008 fill2
1697''', map_data)
1698
1699 def testExpandSizeBad(self):
1700 """Test an expanding entry which fails to provide contents"""
Simon Glass163ed6c2018-09-14 04:57:36 -06001701 with test_util.capture_sys_output() as (stdout, stderr):
1702 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001703 self._DoReadFileDtb('089_expand_size_bad.dts', map=True)
Simon Glassba64a0b2018-09-14 04:57:29 -06001704 self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
1705 'expanding entry', str(e.exception))
1706
Simon Glasse0e5df92018-09-14 04:57:31 -06001707 def testHash(self):
1708 """Test hashing of the contents of an entry"""
Simon Glass741f2d62018-10-01 12:22:30 -06001709 _, _, _, out_dtb_fname = self._DoReadFileDtb('090_hash.dts',
Simon Glasse0e5df92018-09-14 04:57:31 -06001710 use_real_dtb=True, update_dtb=True)
1711 dtb = fdt.Fdt(out_dtb_fname)
1712 dtb.Scan()
1713 hash_node = dtb.GetNode('/binman/u-boot/hash').props['value']
1714 m = hashlib.sha256()
1715 m.update(U_BOOT_DATA)
Simon Glassc6c10e72019-05-17 22:00:46 -06001716 self.assertEqual(m.digest(), b''.join(hash_node.value))
Simon Glasse0e5df92018-09-14 04:57:31 -06001717
1718 def testHashNoAlgo(self):
1719 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001720 self._DoReadFileDtb('091_hash_no_algo.dts', update_dtb=True)
Simon Glasse0e5df92018-09-14 04:57:31 -06001721 self.assertIn("Node \'/binman/u-boot\': Missing \'algo\' property for "
1722 'hash node', str(e.exception))
1723
1724 def testHashBadAlgo(self):
1725 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001726 self._DoReadFileDtb('092_hash_bad_algo.dts', update_dtb=True)
Simon Glasse0e5df92018-09-14 04:57:31 -06001727 self.assertIn("Node '/binman/u-boot': Unknown hash algorithm",
1728 str(e.exception))
1729
1730 def testHashSection(self):
1731 """Test hashing of the contents of an entry"""
Simon Glass741f2d62018-10-01 12:22:30 -06001732 _, _, _, out_dtb_fname = self._DoReadFileDtb('099_hash_section.dts',
Simon Glasse0e5df92018-09-14 04:57:31 -06001733 use_real_dtb=True, update_dtb=True)
1734 dtb = fdt.Fdt(out_dtb_fname)
1735 dtb.Scan()
1736 hash_node = dtb.GetNode('/binman/section/hash').props['value']
1737 m = hashlib.sha256()
1738 m.update(U_BOOT_DATA)
Simon Glassc6c10e72019-05-17 22:00:46 -06001739 m.update(tools.GetBytes(ord('a'), 16))
1740 self.assertEqual(m.digest(), b''.join(hash_node.value))
Simon Glasse0e5df92018-09-14 04:57:31 -06001741
Simon Glassf0253632018-09-14 04:57:32 -06001742 def testPackUBootTplMicrocode(self):
1743 """Test that x86 microcode can be handled correctly in TPL
1744
1745 We expect to see the following in the image, in order:
1746 u-boot-tpl-nodtb.bin with a microcode pointer inserted at the correct
1747 place
1748 u-boot-tpl.dtb with the microcode removed
1749 the microcode
1750 """
Simon Glass1d0ebf72019-05-14 15:53:42 -06001751 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
Simon Glassf0253632018-09-14 04:57:32 -06001752 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
Simon Glass741f2d62018-10-01 12:22:30 -06001753 first, pos_and_size = self._RunMicrocodeTest('093_x86_tpl_ucode.dts',
Simon Glassf0253632018-09-14 04:57:32 -06001754 U_BOOT_TPL_NODTB_DATA)
Simon Glassc6c10e72019-05-17 22:00:46 -06001755 self.assertEqual(b'tplnodtb with microc' + pos_and_size +
1756 b'ter somewhere in here', first)
Simon Glassf0253632018-09-14 04:57:32 -06001757
Simon Glassf8f8df62018-09-14 04:57:34 -06001758 def testFmapX86(self):
1759 """Basic test of generation of a flashrom fmap"""
Simon Glass741f2d62018-10-01 12:22:30 -06001760 data = self._DoReadFile('094_fmap_x86.dts')
Simon Glassf8f8df62018-09-14 04:57:34 -06001761 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
Simon Glassc6c10e72019-05-17 22:00:46 -06001762 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('a'), 32 - 7)
Simon Glassf8f8df62018-09-14 04:57:34 -06001763 self.assertEqual(expected, data[:32])
1764 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1765
1766 self.assertEqual(0x100, fhdr.image_size)
1767
1768 self.assertEqual(0, fentries[0].offset)
1769 self.assertEqual(4, fentries[0].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001770 self.assertEqual(b'U_BOOT', fentries[0].name)
Simon Glassf8f8df62018-09-14 04:57:34 -06001771
1772 self.assertEqual(4, fentries[1].offset)
1773 self.assertEqual(3, fentries[1].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001774 self.assertEqual(b'INTEL_MRC', fentries[1].name)
Simon Glassf8f8df62018-09-14 04:57:34 -06001775
1776 self.assertEqual(32, fentries[2].offset)
1777 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1778 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001779 self.assertEqual(b'FMAP', fentries[2].name)
Simon Glassf8f8df62018-09-14 04:57:34 -06001780
1781 def testFmapX86Section(self):
1782 """Basic test of generation of a flashrom fmap"""
Simon Glass741f2d62018-10-01 12:22:30 -06001783 data = self._DoReadFile('095_fmap_x86_section.dts')
Simon Glassc6c10e72019-05-17 22:00:46 -06001784 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('b'), 32 - 7)
Simon Glassf8f8df62018-09-14 04:57:34 -06001785 self.assertEqual(expected, data[:32])
1786 fhdr, fentries = fmap_util.DecodeFmap(data[36:])
1787
1788 self.assertEqual(0x100, fhdr.image_size)
1789
1790 self.assertEqual(0, fentries[0].offset)
1791 self.assertEqual(4, fentries[0].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001792 self.assertEqual(b'U_BOOT', fentries[0].name)
Simon Glassf8f8df62018-09-14 04:57:34 -06001793
1794 self.assertEqual(4, fentries[1].offset)
1795 self.assertEqual(3, fentries[1].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001796 self.assertEqual(b'INTEL_MRC', fentries[1].name)
Simon Glassf8f8df62018-09-14 04:57:34 -06001797
1798 self.assertEqual(36, fentries[2].offset)
1799 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1800 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001801 self.assertEqual(b'FMAP', fentries[2].name)
Simon Glassf8f8df62018-09-14 04:57:34 -06001802
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001803 def testElf(self):
1804 """Basic test of ELF entries"""
Simon Glass11ae93e2018-10-01 21:12:47 -06001805 self._SetupSplElf()
Simon Glass1d0ebf72019-05-14 15:53:42 -06001806 with open(self.TestFile('bss_data'), 'rb') as fd:
Simon Glass4c650252019-07-08 13:18:46 -06001807 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1808 with open(self.TestFile('bss_data'), 'rb') as fd:
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001809 TestFunctional._MakeInputFile('-boot', fd.read())
Simon Glass741f2d62018-10-01 12:22:30 -06001810 data = self._DoReadFile('096_elf.dts')
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001811
Simon Glass093d1682019-07-08 13:18:25 -06001812 def testElfStrip(self):
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001813 """Basic test of ELF entries"""
Simon Glass11ae93e2018-10-01 21:12:47 -06001814 self._SetupSplElf()
Simon Glass1d0ebf72019-05-14 15:53:42 -06001815 with open(self.TestFile('bss_data'), 'rb') as fd:
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001816 TestFunctional._MakeInputFile('-boot', fd.read())
Simon Glass741f2d62018-10-01 12:22:30 -06001817 data = self._DoReadFile('097_elf_strip.dts')
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001818
Simon Glass163ed6c2018-09-14 04:57:36 -06001819 def testPackOverlapMap(self):
1820 """Test that overlapping regions are detected"""
1821 with test_util.capture_sys_output() as (stdout, stderr):
1822 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001823 self._DoTestFile('014_pack_overlap.dts', map=True)
Simon Glass163ed6c2018-09-14 04:57:36 -06001824 map_fname = tools.GetOutputFilename('image.map')
1825 self.assertEqual("Wrote map file '%s' to show errors\n" % map_fname,
1826 stdout.getvalue())
1827
1828 # We should not get an inmage, but there should be a map file
1829 self.assertFalse(os.path.exists(tools.GetOutputFilename('image.bin')))
1830 self.assertTrue(os.path.exists(map_fname))
Simon Glasseb546ac2019-05-17 22:00:51 -06001831 map_data = tools.ReadFile(map_fname, binary=False)
Simon Glass163ed6c2018-09-14 04:57:36 -06001832 self.assertEqual('''ImagePos Offset Size Name
1833<none> 00000000 00000007 main-section
1834<none> 00000000 00000004 u-boot
1835<none> 00000003 00000004 u-boot-align
1836''', map_data)
1837
Simon Glass093d1682019-07-08 13:18:25 -06001838 def testPackRefCode(self):
Simon Glass3ae192c2018-10-01 12:22:31 -06001839 """Test that an image with an Intel Reference code binary works"""
1840 data = self._DoReadFile('100_intel_refcode.dts')
1841 self.assertEqual(REFCODE_DATA, data[:len(REFCODE_DATA)])
1842
Simon Glass9481c802019-04-25 21:58:39 -06001843 def testSectionOffset(self):
1844 """Tests use of a section with an offset"""
1845 data, _, map_data, _ = self._DoReadFileDtb('101_sections_offset.dts',
1846 map=True)
1847 self.assertEqual('''ImagePos Offset Size Name
184800000000 00000000 00000038 main-section
184900000004 00000004 00000010 section@0
185000000004 00000000 00000004 u-boot
185100000018 00000018 00000010 section@1
185200000018 00000000 00000004 u-boot
18530000002c 0000002c 00000004 section@2
18540000002c 00000000 00000004 u-boot
1855''', map_data)
1856 self.assertEqual(data,
Simon Glasse6d85ff2019-05-14 15:53:47 -06001857 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1858 tools.GetBytes(0x21, 12) +
1859 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1860 tools.GetBytes(0x61, 12) +
1861 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1862 tools.GetBytes(0x26, 8))
Simon Glass9481c802019-04-25 21:58:39 -06001863
Simon Glassac62fba2019-07-08 13:18:53 -06001864 def testCbfsRaw(self):
1865 """Test base handling of a Coreboot Filesystem (CBFS)
1866
1867 The exact contents of the CBFS is verified by similar tests in
1868 cbfs_util_test.py. The tests here merely check that the files added to
1869 the CBFS can be found in the final image.
1870 """
1871 data = self._DoReadFile('102_cbfs_raw.dts')
1872 size = 0xb0
1873
1874 cbfs = cbfs_util.CbfsReader(data)
1875 self.assertEqual(size, cbfs.rom_size)
1876
1877 self.assertIn('u-boot-dtb', cbfs.files)
1878 cfile = cbfs.files['u-boot-dtb']
1879 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
1880
1881 def testCbfsArch(self):
1882 """Test on non-x86 architecture"""
1883 data = self._DoReadFile('103_cbfs_raw_ppc.dts')
1884 size = 0x100
1885
1886 cbfs = cbfs_util.CbfsReader(data)
1887 self.assertEqual(size, cbfs.rom_size)
1888
1889 self.assertIn('u-boot-dtb', cbfs.files)
1890 cfile = cbfs.files['u-boot-dtb']
1891 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
1892
1893 def testCbfsStage(self):
1894 """Tests handling of a Coreboot Filesystem (CBFS)"""
1895 if not elf.ELF_TOOLS:
1896 self.skipTest('Python elftools not available')
1897 elf_fname = os.path.join(self._indir, 'cbfs-stage.elf')
1898 elf.MakeElf(elf_fname, U_BOOT_DATA, U_BOOT_DTB_DATA)
1899 size = 0xb0
1900
1901 data = self._DoReadFile('104_cbfs_stage.dts')
1902 cbfs = cbfs_util.CbfsReader(data)
1903 self.assertEqual(size, cbfs.rom_size)
1904
1905 self.assertIn('u-boot', cbfs.files)
1906 cfile = cbfs.files['u-boot']
1907 self.assertEqual(U_BOOT_DATA + U_BOOT_DTB_DATA, cfile.data)
1908
1909 def testCbfsRawCompress(self):
1910 """Test handling of compressing raw files"""
1911 self._CheckLz4()
1912 data = self._DoReadFile('105_cbfs_raw_compress.dts')
1913 size = 0x140
1914
1915 cbfs = cbfs_util.CbfsReader(data)
1916 self.assertIn('u-boot', cbfs.files)
1917 cfile = cbfs.files['u-boot']
1918 self.assertEqual(COMPRESS_DATA, cfile.data)
1919
1920 def testCbfsBadArch(self):
1921 """Test handling of a bad architecture"""
1922 with self.assertRaises(ValueError) as e:
1923 self._DoReadFile('106_cbfs_bad_arch.dts')
1924 self.assertIn("Invalid architecture 'bad-arch'", str(e.exception))
1925
1926 def testCbfsNoSize(self):
1927 """Test handling of a missing size property"""
1928 with self.assertRaises(ValueError) as e:
1929 self._DoReadFile('107_cbfs_no_size.dts')
1930 self.assertIn('entry must have a size property', str(e.exception))
1931
1932 def testCbfsNoCOntents(self):
1933 """Test handling of a CBFS entry which does not provide contentsy"""
1934 with self.assertRaises(ValueError) as e:
1935 self._DoReadFile('108_cbfs_no_contents.dts')
1936 self.assertIn('Could not complete processing of contents',
1937 str(e.exception))
1938
1939 def testCbfsBadCompress(self):
1940 """Test handling of a bad architecture"""
1941 with self.assertRaises(ValueError) as e:
1942 self._DoReadFile('109_cbfs_bad_compress.dts')
1943 self.assertIn("Invalid compression in 'u-boot': 'invalid-algo'",
1944 str(e.exception))
1945
1946 def testCbfsNamedEntries(self):
1947 """Test handling of named entries"""
1948 data = self._DoReadFile('110_cbfs_name.dts')
1949
1950 cbfs = cbfs_util.CbfsReader(data)
1951 self.assertIn('FRED', cbfs.files)
1952 cfile1 = cbfs.files['FRED']
1953 self.assertEqual(U_BOOT_DATA, cfile1.data)
1954
1955 self.assertIn('hello', cbfs.files)
1956 cfile2 = cbfs.files['hello']
1957 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
1958
Simon Glass53af22a2018-07-17 13:25:32 -06001959
Simon Glass9fc60b42017-11-12 21:52:22 -07001960if __name__ == "__main__":
1961 unittest.main()