blob: f3a8e64ad13e8a1ffb88d458ca857333a7855197 [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 Glasse1925fa2019-07-08 14:25:44 -060027from etype import fdtmap
Simon Glass2d260032019-07-08 14:25:45 -060028from etype import image_header
Simon Glass4f443042016-11-25 20:15:52 -070029import fdt_util
Simon Glass11e36cc2018-07-17 13:25:38 -060030import fmap_util
Simon Glassfd8d1f72018-07-17 13:25:36 -060031import test_util
Simon Glassc5ac1382019-07-08 13:18:54 -060032import gzip
Simon Glassffded752019-07-08 14:25:46 -060033from image import Image
Simon Glassc55a50f2018-09-14 04:57:19 -060034import state
Simon Glass4f443042016-11-25 20:15:52 -070035import tools
36import tout
37
38# Contents of test files, corresponding to different entry types
Simon Glassc6c10e72019-05-17 22:00:46 -060039U_BOOT_DATA = b'1234'
40U_BOOT_IMG_DATA = b'img'
41U_BOOT_SPL_DATA = b'56780123456789abcde'
42U_BOOT_TPL_DATA = b'tpl'
43BLOB_DATA = b'89'
44ME_DATA = b'0abcd'
45VGA_DATA = b'vga'
46U_BOOT_DTB_DATA = b'udtb'
47U_BOOT_SPL_DTB_DATA = b'spldtb'
48U_BOOT_TPL_DTB_DATA = b'tpldtb'
49X86_START16_DATA = b'start16'
50X86_START16_SPL_DATA = b'start16spl'
51X86_START16_TPL_DATA = b'start16tpl'
52PPC_MPC85XX_BR_DATA = b'ppcmpc85xxbr'
53U_BOOT_NODTB_DATA = b'nodtb with microcode pointer somewhere in here'
54U_BOOT_SPL_NODTB_DATA = b'splnodtb with microcode pointer somewhere in here'
55U_BOOT_TPL_NODTB_DATA = b'tplnodtb with microcode pointer somewhere in here'
56FSP_DATA = b'fsp'
57CMC_DATA = b'cmc'
58VBT_DATA = b'vbt'
59MRC_DATA = b'mrc'
Simon Glassbb748372018-07-17 13:25:33 -060060TEXT_DATA = 'text'
61TEXT_DATA2 = 'text2'
62TEXT_DATA3 = 'text3'
Simon Glassc6c10e72019-05-17 22:00:46 -060063CROS_EC_RW_DATA = b'ecrw'
64GBB_DATA = b'gbbd'
65BMPBLK_DATA = b'bmp'
66VBLOCK_DATA = b'vblk'
67FILES_DATA = (b"sorry I'm late\nOh, don't bother apologising, I'm " +
68 b"sorry you're alive\n")
Simon Glassff5c7e32019-07-08 13:18:42 -060069COMPRESS_DATA = b'compress xxxxxxxxxxxxxxxxxxxxxx data'
Simon Glassc6c10e72019-05-17 22:00:46 -060070REFCODE_DATA = b'refcode'
Simon Glassec127af2018-07-17 13:25:39 -060071
Simon Glass4f443042016-11-25 20:15:52 -070072
73class TestFunctional(unittest.TestCase):
74 """Functional tests for binman
75
76 Most of these use a sample .dts file to build an image and then check
77 that it looks correct. The sample files are in the test/ subdirectory
78 and are numbered.
79
80 For each entry type a very small test file is created using fixed
81 string contents. This makes it easy to test that things look right, and
82 debug problems.
83
84 In some cases a 'real' file must be used - these are also supplied in
85 the test/ diurectory.
86 """
87 @classmethod
88 def setUpClass(self):
Simon Glass4d5994f2017-11-12 21:52:20 -070089 global entry
90 import entry
91
Simon Glass4f443042016-11-25 20:15:52 -070092 # Handle the case where argv[0] is 'python'
93 self._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
94 self._binman_pathname = os.path.join(self._binman_dir, 'binman')
95
96 # Create a temporary directory for input files
97 self._indir = tempfile.mkdtemp(prefix='binmant.')
98
99 # Create some test files
100 TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
101 TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
102 TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
Simon Glassb8ef5b62018-07-17 13:25:48 -0600103 TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
Simon Glass4f443042016-11-25 20:15:52 -0700104 TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
Simon Glasse0ff8552016-11-25 20:15:53 -0700105 TestFunctional._MakeInputFile('me.bin', ME_DATA)
106 TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
Simon Glassb8ef5b62018-07-17 13:25:48 -0600107 self._ResetDtbs()
Simon Glasse0ff8552016-11-25 20:15:53 -0700108 TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
Jagdish Gediya9d368f32018-09-03 21:35:08 +0530109 TestFunctional._MakeInputFile('u-boot-br.bin', PPC_MPC85XX_BR_DATA)
Simon Glass87722132017-11-12 21:52:26 -0700110 TestFunctional._MakeInputFile('spl/u-boot-x86-16bit-spl.bin',
111 X86_START16_SPL_DATA)
Simon Glass35b384c2018-09-14 04:57:10 -0600112 TestFunctional._MakeInputFile('tpl/u-boot-x86-16bit-tpl.bin',
113 X86_START16_TPL_DATA)
Simon Glass4f443042016-11-25 20:15:52 -0700114 TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
Simon Glass6b187df2017-11-12 21:52:27 -0700115 TestFunctional._MakeInputFile('spl/u-boot-spl-nodtb.bin',
116 U_BOOT_SPL_NODTB_DATA)
Simon Glassf0253632018-09-14 04:57:32 -0600117 TestFunctional._MakeInputFile('tpl/u-boot-tpl-nodtb.bin',
118 U_BOOT_TPL_NODTB_DATA)
Simon Glassda229092016-11-25 20:15:56 -0700119 TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
120 TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
Bin Meng59ea8c22017-08-15 22:41:54 -0700121 TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
Simon Glassca4f4ff2017-11-12 21:52:28 -0700122 TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
Simon Glassec127af2018-07-17 13:25:39 -0600123 TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
Simon Glass0ef87aa2018-07-17 13:25:44 -0600124 TestFunctional._MakeInputDir('devkeys')
125 TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
Simon Glass3ae192c2018-10-01 12:22:31 -0600126 TestFunctional._MakeInputFile('refcode.bin', REFCODE_DATA)
Simon Glass4f443042016-11-25 20:15:52 -0700127
Simon Glasse0ff8552016-11-25 20:15:53 -0700128 # ELF file with a '_dt_ucode_base_size' symbol
Simon Glass1d0ebf72019-05-14 15:53:42 -0600129 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
Simon Glasse0ff8552016-11-25 20:15:53 -0700130 TestFunctional._MakeInputFile('u-boot', fd.read())
131
132 # Intel flash descriptor file
Simon Glass1d0ebf72019-05-14 15:53:42 -0600133 with open(self.TestFile('descriptor.bin'), 'rb') as fd:
Simon Glasse0ff8552016-11-25 20:15:53 -0700134 TestFunctional._MakeInputFile('descriptor.bin', fd.read())
135
Simon Glass0a98b282018-09-14 04:57:28 -0600136 shutil.copytree(self.TestFile('files'),
137 os.path.join(self._indir, 'files'))
138
Simon Glass83d73c22018-09-14 04:57:26 -0600139 TestFunctional._MakeInputFile('compress', COMPRESS_DATA)
140
Simon Glassac62fba2019-07-08 13:18:53 -0600141 # Travis-CI may have an old lz4
142 self.have_lz4 = True
143 try:
144 tools.Run('lz4', '--no-frame-crc', '-c',
145 os.path.join(self._indir, 'u-boot.bin'))
146 except:
147 self.have_lz4 = False
148
Simon Glass4f443042016-11-25 20:15:52 -0700149 @classmethod
150 def tearDownClass(self):
151 """Remove the temporary input directory and its contents"""
Simon Glassd5164a72019-07-08 13:18:49 -0600152 if self.preserve_indir:
153 print('Preserving input dir: %s' % self._indir)
154 else:
155 if self._indir:
156 shutil.rmtree(self._indir)
Simon Glass4f443042016-11-25 20:15:52 -0700157 self._indir = None
158
Simon Glassd5164a72019-07-08 13:18:49 -0600159 @classmethod
Simon Glass8acce602019-07-08 13:18:50 -0600160 def setup_test_args(cls, preserve_indir=False, preserve_outdirs=False,
Simon Glass53cd5d92019-07-08 14:25:29 -0600161 toolpath=None, verbosity=None):
Simon Glassd5164a72019-07-08 13:18:49 -0600162 """Accept arguments controlling test execution
163
164 Args:
165 preserve_indir: Preserve the shared input directory used by all
166 tests in this class.
167 preserve_outdir: Preserve the output directories used by tests. Each
168 test has its own, so this is normally only useful when running a
169 single test.
Simon Glass8acce602019-07-08 13:18:50 -0600170 toolpath: ist of paths to use for tools
Simon Glassd5164a72019-07-08 13:18:49 -0600171 """
172 cls.preserve_indir = preserve_indir
173 cls.preserve_outdirs = preserve_outdirs
Simon Glass8acce602019-07-08 13:18:50 -0600174 cls.toolpath = toolpath
Simon Glass53cd5d92019-07-08 14:25:29 -0600175 cls.verbosity = verbosity
Simon Glassd5164a72019-07-08 13:18:49 -0600176
Simon Glassac62fba2019-07-08 13:18:53 -0600177 def _CheckLz4(self):
178 if not self.have_lz4:
179 self.skipTest('lz4 --no-frame-crc not available')
180
Simon Glass4f443042016-11-25 20:15:52 -0700181 def setUp(self):
182 # Enable this to turn on debugging output
183 # tout.Init(tout.DEBUG)
184 command.test_result = None
185
186 def tearDown(self):
187 """Remove the temporary output directory"""
Simon Glassd5164a72019-07-08 13:18:49 -0600188 if self.preserve_outdirs:
189 print('Preserving output dir: %s' % tools.outdir)
190 else:
191 tools._FinaliseForTest()
Simon Glass4f443042016-11-25 20:15:52 -0700192
Simon Glassb8ef5b62018-07-17 13:25:48 -0600193 @classmethod
194 def _ResetDtbs(self):
195 TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
196 TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
197 TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
198
Simon Glass4f443042016-11-25 20:15:52 -0700199 def _RunBinman(self, *args, **kwargs):
200 """Run binman using the command line
201
202 Args:
203 Arguments to pass, as a list of strings
204 kwargs: Arguments to pass to Command.RunPipe()
205 """
206 result = command.RunPipe([[self._binman_pathname] + list(args)],
207 capture=True, capture_stderr=True, raise_on_error=False)
208 if result.return_code and kwargs.get('raise_on_error', True):
209 raise Exception("Error running '%s': %s" % (' '.join(args),
210 result.stdout + result.stderr))
211 return result
212
Simon Glass53cd5d92019-07-08 14:25:29 -0600213 def _DoBinman(self, *argv):
Simon Glass4f443042016-11-25 20:15:52 -0700214 """Run binman using directly (in the same process)
215
216 Args:
217 Arguments to pass, as a list of strings
218 Returns:
219 Return value (0 for success)
220 """
Simon Glass53cd5d92019-07-08 14:25:29 -0600221 argv = list(argv)
222 args = cmdline.ParseArgs(argv)
223 args.pager = 'binman-invalid-pager'
224 args.build_dir = self._indir
Simon Glass4f443042016-11-25 20:15:52 -0700225
226 # For testing, you can force an increase in verbosity here
Simon Glass53cd5d92019-07-08 14:25:29 -0600227 # args.verbosity = tout.DEBUG
228 return control.Binman(args)
Simon Glass4f443042016-11-25 20:15:52 -0700229
Simon Glass53af22a2018-07-17 13:25:32 -0600230 def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
Simon Glasseb833d82019-04-25 21:58:34 -0600231 entry_args=None, images=None, use_real_dtb=False,
232 verbosity=None):
Simon Glass4f443042016-11-25 20:15:52 -0700233 """Run binman with a given test file
234
235 Args:
Simon Glass741f2d62018-10-01 12:22:30 -0600236 fname: Device-tree source filename to use (e.g. 005_simple.dts)
Simon Glass7ae5f312018-06-01 09:38:19 -0600237 debug: True to enable debugging output
Simon Glass3b0c3822018-06-01 09:38:20 -0600238 map: True to output map files for the images
Simon Glass3ab95982018-08-01 15:22:37 -0600239 update_dtb: Update the offset and size of each entry in the device
Simon Glass16b8d6b2018-07-06 10:27:42 -0600240 tree before packing it into the image
Simon Glass0bfa7b02018-09-14 04:57:12 -0600241 entry_args: Dict of entry args to supply to binman
242 key: arg name
243 value: value of that arg
244 images: List of image names to build
Simon Glass4f443042016-11-25 20:15:52 -0700245 """
Simon Glass53cd5d92019-07-08 14:25:29 -0600246 args = []
Simon Glass7fe91732017-11-13 18:55:00 -0700247 if debug:
248 args.append('-D')
Simon Glass53cd5d92019-07-08 14:25:29 -0600249 if verbosity is not None:
250 args.append('-v%d' % verbosity)
251 elif self.verbosity:
252 args.append('-v%d' % self.verbosity)
253 if self.toolpath:
254 for path in self.toolpath:
255 args += ['--toolpath', path]
256 args += ['build', '-p', '-I', self._indir, '-d', self.TestFile(fname)]
Simon Glass3b0c3822018-06-01 09:38:20 -0600257 if map:
258 args.append('-m')
Simon Glass16b8d6b2018-07-06 10:27:42 -0600259 if update_dtb:
Simon Glass2569e102019-07-08 13:18:47 -0600260 args.append('-u')
Simon Glass93d17412018-09-14 04:57:23 -0600261 if not use_real_dtb:
262 args.append('--fake-dtb')
Simon Glass53af22a2018-07-17 13:25:32 -0600263 if entry_args:
Simon Glass50979152019-05-14 15:53:41 -0600264 for arg, value in entry_args.items():
Simon Glass53af22a2018-07-17 13:25:32 -0600265 args.append('-a%s=%s' % (arg, value))
Simon Glass0bfa7b02018-09-14 04:57:12 -0600266 if images:
267 for image in images:
268 args += ['-i', image]
Simon Glass7fe91732017-11-13 18:55:00 -0700269 return self._DoBinman(*args)
Simon Glass4f443042016-11-25 20:15:52 -0700270
271 def _SetupDtb(self, fname, outfile='u-boot.dtb'):
Simon Glasse0ff8552016-11-25 20:15:53 -0700272 """Set up a new test device-tree file
273
274 The given file is compiled and set up as the device tree to be used
275 for ths test.
276
277 Args:
278 fname: Filename of .dts file to read
Simon Glass7ae5f312018-06-01 09:38:19 -0600279 outfile: Output filename for compiled device-tree binary
Simon Glasse0ff8552016-11-25 20:15:53 -0700280
281 Returns:
Simon Glass7ae5f312018-06-01 09:38:19 -0600282 Contents of device-tree binary
Simon Glasse0ff8552016-11-25 20:15:53 -0700283 """
Simon Glasse0e62752018-10-01 21:12:41 -0600284 tools.PrepareOutputDir(None)
Simon Glass4f443042016-11-25 20:15:52 -0700285 dtb = fdt_util.EnsureCompiled(self.TestFile(fname))
Simon Glass1d0ebf72019-05-14 15:53:42 -0600286 with open(dtb, 'rb') as fd:
Simon Glass4f443042016-11-25 20:15:52 -0700287 data = fd.read()
288 TestFunctional._MakeInputFile(outfile, data)
Simon Glasse0e62752018-10-01 21:12:41 -0600289 tools.FinaliseOutputDir()
290 return data
Simon Glass4f443042016-11-25 20:15:52 -0700291
Simon Glass6ed45ba2018-09-14 04:57:24 -0600292 def _GetDtbContentsForSplTpl(self, dtb_data, name):
293 """Create a version of the main DTB for SPL or SPL
294
295 For testing we don't actually have different versions of the DTB. With
296 U-Boot we normally run fdtgrep to remove unwanted nodes, but for tests
297 we don't normally have any unwanted nodes.
298
299 We still want the DTBs for SPL and TPL to be different though, since
300 otherwise it is confusing to know which one we are looking at. So add
301 an 'spl' or 'tpl' property to the top-level node.
302 """
303 dtb = fdt.Fdt.FromData(dtb_data)
304 dtb.Scan()
305 dtb.GetNode('/binman').AddZeroProp(name)
306 dtb.Sync(auto_resize=True)
307 dtb.Pack()
308 return dtb.GetContents()
309
Simon Glass16b8d6b2018-07-06 10:27:42 -0600310 def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
Simon Glass6ed45ba2018-09-14 04:57:24 -0600311 update_dtb=False, entry_args=None, reset_dtbs=True):
Simon Glass4f443042016-11-25 20:15:52 -0700312 """Run binman and return the resulting image
313
314 This runs binman with a given test file and then reads the resulting
315 output file. It is a shortcut function since most tests need to do
316 these steps.
317
318 Raises an assertion failure if binman returns a non-zero exit code.
319
320 Args:
Simon Glass741f2d62018-10-01 12:22:30 -0600321 fname: Device-tree source filename to use (e.g. 005_simple.dts)
Simon Glass4f443042016-11-25 20:15:52 -0700322 use_real_dtb: True to use the test file as the contents of
323 the u-boot-dtb entry. Normally this is not needed and the
324 test contents (the U_BOOT_DTB_DATA string) can be used.
325 But in some test we need the real contents.
Simon Glass3b0c3822018-06-01 09:38:20 -0600326 map: True to output map files for the images
Simon Glass3ab95982018-08-01 15:22:37 -0600327 update_dtb: Update the offset and size of each entry in the device
Simon Glass16b8d6b2018-07-06 10:27:42 -0600328 tree before packing it into the image
Simon Glasse0ff8552016-11-25 20:15:53 -0700329
330 Returns:
331 Tuple:
332 Resulting image contents
333 Device tree contents
Simon Glass3b0c3822018-06-01 09:38:20 -0600334 Map data showing contents of image (or None if none)
Simon Glassea6922e2018-07-17 13:25:27 -0600335 Output device tree binary filename ('u-boot.dtb' path)
Simon Glass4f443042016-11-25 20:15:52 -0700336 """
Simon Glasse0ff8552016-11-25 20:15:53 -0700337 dtb_data = None
Simon Glass4f443042016-11-25 20:15:52 -0700338 # Use the compiled test file as the u-boot-dtb input
339 if use_real_dtb:
Simon Glasse0ff8552016-11-25 20:15:53 -0700340 dtb_data = self._SetupDtb(fname)
Simon Glass6ed45ba2018-09-14 04:57:24 -0600341
342 # For testing purposes, make a copy of the DT for SPL and TPL. Add
343 # a node indicating which it is, so aid verification.
344 for name in ['spl', 'tpl']:
345 dtb_fname = '%s/u-boot-%s.dtb' % (name, name)
346 outfile = os.path.join(self._indir, dtb_fname)
347 TestFunctional._MakeInputFile(dtb_fname,
348 self._GetDtbContentsForSplTpl(dtb_data, name))
Simon Glass4f443042016-11-25 20:15:52 -0700349
350 try:
Simon Glass53af22a2018-07-17 13:25:32 -0600351 retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
Simon Glass6ed45ba2018-09-14 04:57:24 -0600352 entry_args=entry_args, use_real_dtb=use_real_dtb)
Simon Glass4f443042016-11-25 20:15:52 -0700353 self.assertEqual(0, retcode)
Simon Glass6ed45ba2018-09-14 04:57:24 -0600354 out_dtb_fname = tools.GetOutputFilename('u-boot.dtb.out')
Simon Glass4f443042016-11-25 20:15:52 -0700355
356 # Find the (only) image, read it and return its contents
357 image = control.images['image']
Simon Glass16b8d6b2018-07-06 10:27:42 -0600358 image_fname = tools.GetOutputFilename('image.bin')
359 self.assertTrue(os.path.exists(image_fname))
Simon Glass3b0c3822018-06-01 09:38:20 -0600360 if map:
361 map_fname = tools.GetOutputFilename('image.map')
362 with open(map_fname) as fd:
363 map_data = fd.read()
364 else:
365 map_data = None
Simon Glass1d0ebf72019-05-14 15:53:42 -0600366 with open(image_fname, 'rb') as fd:
Simon Glass16b8d6b2018-07-06 10:27:42 -0600367 return fd.read(), dtb_data, map_data, out_dtb_fname
Simon Glass4f443042016-11-25 20:15:52 -0700368 finally:
369 # Put the test file back
Simon Glass6ed45ba2018-09-14 04:57:24 -0600370 if reset_dtbs and use_real_dtb:
Simon Glassb8ef5b62018-07-17 13:25:48 -0600371 self._ResetDtbs()
Simon Glass4f443042016-11-25 20:15:52 -0700372
Simon Glass3c081312019-07-08 14:25:26 -0600373 def _DoReadFileRealDtb(self, fname):
374 """Run binman with a real .dtb file and return the resulting data
375
376 Args:
377 fname: DT source filename to use (e.g. 082_fdt_update_all.dts)
378
379 Returns:
380 Resulting image contents
381 """
382 return self._DoReadFileDtb(fname, use_real_dtb=True, update_dtb=True)[0]
383
Simon Glasse0ff8552016-11-25 20:15:53 -0700384 def _DoReadFile(self, fname, use_real_dtb=False):
Simon Glass7ae5f312018-06-01 09:38:19 -0600385 """Helper function which discards the device-tree binary
386
387 Args:
Simon Glass741f2d62018-10-01 12:22:30 -0600388 fname: Device-tree source filename to use (e.g. 005_simple.dts)
Simon Glass7ae5f312018-06-01 09:38:19 -0600389 use_real_dtb: True to use the test file as the contents of
390 the u-boot-dtb entry. Normally this is not needed and the
391 test contents (the U_BOOT_DTB_DATA string) can be used.
392 But in some test we need the real contents.
Simon Glassea6922e2018-07-17 13:25:27 -0600393
394 Returns:
395 Resulting image contents
Simon Glass7ae5f312018-06-01 09:38:19 -0600396 """
Simon Glasse0ff8552016-11-25 20:15:53 -0700397 return self._DoReadFileDtb(fname, use_real_dtb)[0]
398
Simon Glass4f443042016-11-25 20:15:52 -0700399 @classmethod
400 def _MakeInputFile(self, fname, contents):
401 """Create a new test input file, creating directories as needed
402
403 Args:
Simon Glass3ab95982018-08-01 15:22:37 -0600404 fname: Filename to create
Simon Glass4f443042016-11-25 20:15:52 -0700405 contents: File contents to write in to the file
406 Returns:
407 Full pathname of file created
408 """
409 pathname = os.path.join(self._indir, fname)
410 dirname = os.path.dirname(pathname)
411 if dirname and not os.path.exists(dirname):
412 os.makedirs(dirname)
413 with open(pathname, 'wb') as fd:
414 fd.write(contents)
415 return pathname
416
417 @classmethod
Simon Glass0ef87aa2018-07-17 13:25:44 -0600418 def _MakeInputDir(self, dirname):
419 """Create a new test input directory, creating directories as needed
420
421 Args:
422 dirname: Directory name to create
423
424 Returns:
425 Full pathname of directory created
426 """
427 pathname = os.path.join(self._indir, dirname)
428 if not os.path.exists(pathname):
429 os.makedirs(pathname)
430 return pathname
431
432 @classmethod
Simon Glass11ae93e2018-10-01 21:12:47 -0600433 def _SetupSplElf(self, src_fname='bss_data'):
434 """Set up an ELF file with a '_dt_ucode_base_size' symbol
435
436 Args:
437 Filename of ELF file to use as SPL
438 """
Simon Glass1d0ebf72019-05-14 15:53:42 -0600439 with open(self.TestFile(src_fname), 'rb') as fd:
Simon Glass11ae93e2018-10-01 21:12:47 -0600440 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
441
442 @classmethod
Simon Glass4f443042016-11-25 20:15:52 -0700443 def TestFile(self, fname):
444 return os.path.join(self._binman_dir, 'test', fname)
445
446 def AssertInList(self, grep_list, target):
447 """Assert that at least one of a list of things is in a target
448
449 Args:
450 grep_list: List of strings to check
451 target: Target string
452 """
453 for grep in grep_list:
454 if grep in target:
455 return
Simon Glass1fc62de2019-05-17 22:00:50 -0600456 self.fail("Error: '%s' not found in '%s'" % (grep_list, target))
Simon Glass4f443042016-11-25 20:15:52 -0700457
458 def CheckNoGaps(self, entries):
459 """Check that all entries fit together without gaps
460
461 Args:
462 entries: List of entries to check
463 """
Simon Glass3ab95982018-08-01 15:22:37 -0600464 offset = 0
Simon Glass4f443042016-11-25 20:15:52 -0700465 for entry in entries.values():
Simon Glass3ab95982018-08-01 15:22:37 -0600466 self.assertEqual(offset, entry.offset)
467 offset += entry.size
Simon Glass4f443042016-11-25 20:15:52 -0700468
Simon Glasse0ff8552016-11-25 20:15:53 -0700469 def GetFdtLen(self, dtb):
Simon Glass7ae5f312018-06-01 09:38:19 -0600470 """Get the totalsize field from a device-tree binary
Simon Glasse0ff8552016-11-25 20:15:53 -0700471
472 Args:
Simon Glass7ae5f312018-06-01 09:38:19 -0600473 dtb: Device-tree binary contents
Simon Glasse0ff8552016-11-25 20:15:53 -0700474
475 Returns:
Simon Glass7ae5f312018-06-01 09:38:19 -0600476 Total size of device-tree binary, from the header
Simon Glasse0ff8552016-11-25 20:15:53 -0700477 """
478 return struct.unpack('>L', dtb[4:8])[0]
479
Simon Glass086cec92019-07-08 14:25:27 -0600480 def _GetPropTree(self, dtb, prop_names, prefix='/binman/'):
Simon Glass16b8d6b2018-07-06 10:27:42 -0600481 def AddNode(node, path):
482 if node.name != '/':
483 path += '/' + node.name
Simon Glass086cec92019-07-08 14:25:27 -0600484 for prop in node.props.values():
485 if prop.name in prop_names:
486 prop_path = path + ':' + prop.name
487 tree[prop_path[len(prefix):]] = fdt_util.fdt32_to_cpu(
488 prop.value)
Simon Glass16b8d6b2018-07-06 10:27:42 -0600489 for subnode in node.subnodes:
Simon Glass16b8d6b2018-07-06 10:27:42 -0600490 AddNode(subnode, path)
491
492 tree = {}
Simon Glass16b8d6b2018-07-06 10:27:42 -0600493 AddNode(dtb.GetRoot(), '')
494 return tree
495
Simon Glass4f443042016-11-25 20:15:52 -0700496 def testRun(self):
497 """Test a basic run with valid args"""
498 result = self._RunBinman('-h')
499
500 def testFullHelp(self):
501 """Test that the full help is displayed with -H"""
502 result = self._RunBinman('-H')
503 help_file = os.path.join(self._binman_dir, 'README')
Tom Rini3759df02018-01-16 15:29:50 -0500504 # Remove possible extraneous strings
505 extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
506 gothelp = result.stdout.replace(extra, '')
507 self.assertEqual(len(gothelp), os.path.getsize(help_file))
Simon Glass4f443042016-11-25 20:15:52 -0700508 self.assertEqual(0, len(result.stderr))
509 self.assertEqual(0, result.return_code)
510
511 def testFullHelpInternal(self):
512 """Test that the full help is displayed with -H"""
513 try:
514 command.test_result = command.CommandResult()
515 result = self._DoBinman('-H')
516 help_file = os.path.join(self._binman_dir, 'README')
517 finally:
518 command.test_result = None
519
520 def testHelp(self):
521 """Test that the basic help is displayed with -h"""
522 result = self._RunBinman('-h')
523 self.assertTrue(len(result.stdout) > 200)
524 self.assertEqual(0, len(result.stderr))
525 self.assertEqual(0, result.return_code)
526
Simon Glass4f443042016-11-25 20:15:52 -0700527 def testBoard(self):
528 """Test that we can run it with a specific board"""
Simon Glass741f2d62018-10-01 12:22:30 -0600529 self._SetupDtb('005_simple.dts', 'sandbox/u-boot.dtb')
Simon Glass4f443042016-11-25 20:15:52 -0700530 TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
Simon Glass53cd5d92019-07-08 14:25:29 -0600531 result = self._DoBinman('build', '-b', 'sandbox')
Simon Glass4f443042016-11-25 20:15:52 -0700532 self.assertEqual(0, result)
533
534 def testNeedBoard(self):
535 """Test that we get an error when no board ius supplied"""
536 with self.assertRaises(ValueError) as e:
Simon Glass53cd5d92019-07-08 14:25:29 -0600537 result = self._DoBinman('build')
Simon Glass4f443042016-11-25 20:15:52 -0700538 self.assertIn("Must provide a board to process (use -b <board>)",
539 str(e.exception))
540
541 def testMissingDt(self):
Simon Glass7ae5f312018-06-01 09:38:19 -0600542 """Test that an invalid device-tree file generates an error"""
Simon Glass4f443042016-11-25 20:15:52 -0700543 with self.assertRaises(Exception) as e:
Simon Glass53cd5d92019-07-08 14:25:29 -0600544 self._RunBinman('build', '-d', 'missing_file')
Simon Glass4f443042016-11-25 20:15:52 -0700545 # We get one error from libfdt, and a different one from fdtget.
546 self.AssertInList(["Couldn't open blob from 'missing_file'",
547 'No such file or directory'], str(e.exception))
548
549 def testBrokenDt(self):
Simon Glass7ae5f312018-06-01 09:38:19 -0600550 """Test that an invalid device-tree source file generates an error
Simon Glass4f443042016-11-25 20:15:52 -0700551
552 Since this is a source file it should be compiled and the error
553 will come from the device-tree compiler (dtc).
554 """
555 with self.assertRaises(Exception) as e:
Simon Glass53cd5d92019-07-08 14:25:29 -0600556 self._RunBinman('build', '-d', self.TestFile('001_invalid.dts'))
Simon Glass4f443042016-11-25 20:15:52 -0700557 self.assertIn("FATAL ERROR: Unable to parse input tree",
558 str(e.exception))
559
560 def testMissingNode(self):
561 """Test that a device tree without a 'binman' node generates an error"""
562 with self.assertRaises(Exception) as e:
Simon Glass53cd5d92019-07-08 14:25:29 -0600563 self._DoBinman('build', '-d', self.TestFile('002_missing_node.dts'))
Simon Glass4f443042016-11-25 20:15:52 -0700564 self.assertIn("does not have a 'binman' node", str(e.exception))
565
566 def testEmpty(self):
567 """Test that an empty binman node works OK (i.e. does nothing)"""
Simon Glass53cd5d92019-07-08 14:25:29 -0600568 result = self._RunBinman('build', '-d', self.TestFile('003_empty.dts'))
Simon Glass4f443042016-11-25 20:15:52 -0700569 self.assertEqual(0, len(result.stderr))
570 self.assertEqual(0, result.return_code)
571
572 def testInvalidEntry(self):
573 """Test that an invalid entry is flagged"""
574 with self.assertRaises(Exception) as e:
Simon Glass53cd5d92019-07-08 14:25:29 -0600575 result = self._RunBinman('build', '-d',
Simon Glass741f2d62018-10-01 12:22:30 -0600576 self.TestFile('004_invalid_entry.dts'))
Simon Glass4f443042016-11-25 20:15:52 -0700577 self.assertIn("Unknown entry type 'not-a-valid-type' in node "
578 "'/binman/not-a-valid-type'", str(e.exception))
579
580 def testSimple(self):
581 """Test a simple binman with a single file"""
Simon Glass741f2d62018-10-01 12:22:30 -0600582 data = self._DoReadFile('005_simple.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700583 self.assertEqual(U_BOOT_DATA, data)
584
Simon Glass7fe91732017-11-13 18:55:00 -0700585 def testSimpleDebug(self):
586 """Test a simple binman run with debugging enabled"""
Simon Glass741f2d62018-10-01 12:22:30 -0600587 data = self._DoTestFile('005_simple.dts', debug=True)
Simon Glass7fe91732017-11-13 18:55:00 -0700588
Simon Glass4f443042016-11-25 20:15:52 -0700589 def testDual(self):
590 """Test that we can handle creating two images
591
592 This also tests image padding.
593 """
Simon Glass741f2d62018-10-01 12:22:30 -0600594 retcode = self._DoTestFile('006_dual_image.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700595 self.assertEqual(0, retcode)
596
597 image = control.images['image1']
598 self.assertEqual(len(U_BOOT_DATA), image._size)
599 fname = tools.GetOutputFilename('image1.bin')
600 self.assertTrue(os.path.exists(fname))
Simon Glass1d0ebf72019-05-14 15:53:42 -0600601 with open(fname, 'rb') as fd:
Simon Glass4f443042016-11-25 20:15:52 -0700602 data = fd.read()
603 self.assertEqual(U_BOOT_DATA, data)
604
605 image = control.images['image2']
606 self.assertEqual(3 + len(U_BOOT_DATA) + 5, image._size)
607 fname = tools.GetOutputFilename('image2.bin')
608 self.assertTrue(os.path.exists(fname))
Simon Glass1d0ebf72019-05-14 15:53:42 -0600609 with open(fname, 'rb') as fd:
Simon Glass4f443042016-11-25 20:15:52 -0700610 data = fd.read()
611 self.assertEqual(U_BOOT_DATA, data[3:7])
Simon Glasse6d85ff2019-05-14 15:53:47 -0600612 self.assertEqual(tools.GetBytes(0, 3), data[:3])
613 self.assertEqual(tools.GetBytes(0, 5), data[7:])
Simon Glass4f443042016-11-25 20:15:52 -0700614
615 def testBadAlign(self):
616 """Test that an invalid alignment value is detected"""
617 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600618 self._DoTestFile('007_bad_align.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700619 self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
620 "of two", str(e.exception))
621
622 def testPackSimple(self):
623 """Test that packing works as expected"""
Simon Glass741f2d62018-10-01 12:22:30 -0600624 retcode = self._DoTestFile('008_pack.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700625 self.assertEqual(0, retcode)
626 self.assertIn('image', control.images)
627 image = control.images['image']
Simon Glass8f1da502018-06-01 09:38:12 -0600628 entries = image.GetEntries()
Simon Glass4f443042016-11-25 20:15:52 -0700629 self.assertEqual(5, len(entries))
630
631 # First u-boot
632 self.assertIn('u-boot', entries)
633 entry = entries['u-boot']
Simon Glass3ab95982018-08-01 15:22:37 -0600634 self.assertEqual(0, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700635 self.assertEqual(len(U_BOOT_DATA), entry.size)
636
637 # Second u-boot, aligned to 16-byte boundary
638 self.assertIn('u-boot-align', entries)
639 entry = entries['u-boot-align']
Simon Glass3ab95982018-08-01 15:22:37 -0600640 self.assertEqual(16, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700641 self.assertEqual(len(U_BOOT_DATA), entry.size)
642
643 # Third u-boot, size 23 bytes
644 self.assertIn('u-boot-size', entries)
645 entry = entries['u-boot-size']
Simon Glass3ab95982018-08-01 15:22:37 -0600646 self.assertEqual(20, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700647 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
648 self.assertEqual(23, entry.size)
649
650 # Fourth u-boot, placed immediate after the above
651 self.assertIn('u-boot-next', entries)
652 entry = entries['u-boot-next']
Simon Glass3ab95982018-08-01 15:22:37 -0600653 self.assertEqual(43, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700654 self.assertEqual(len(U_BOOT_DATA), entry.size)
655
Simon Glass3ab95982018-08-01 15:22:37 -0600656 # Fifth u-boot, placed at a fixed offset
Simon Glass4f443042016-11-25 20:15:52 -0700657 self.assertIn('u-boot-fixed', entries)
658 entry = entries['u-boot-fixed']
Simon Glass3ab95982018-08-01 15:22:37 -0600659 self.assertEqual(61, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700660 self.assertEqual(len(U_BOOT_DATA), entry.size)
661
662 self.assertEqual(65, image._size)
663
664 def testPackExtra(self):
665 """Test that extra packing feature works as expected"""
Simon Glass741f2d62018-10-01 12:22:30 -0600666 retcode = self._DoTestFile('009_pack_extra.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700667
668 self.assertEqual(0, retcode)
669 self.assertIn('image', control.images)
670 image = control.images['image']
Simon Glass8f1da502018-06-01 09:38:12 -0600671 entries = image.GetEntries()
Simon Glass4f443042016-11-25 20:15:52 -0700672 self.assertEqual(5, len(entries))
673
674 # First u-boot with padding before and after
675 self.assertIn('u-boot', entries)
676 entry = entries['u-boot']
Simon Glass3ab95982018-08-01 15:22:37 -0600677 self.assertEqual(0, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700678 self.assertEqual(3, entry.pad_before)
679 self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
680
681 # Second u-boot has an aligned size, but it has no effect
682 self.assertIn('u-boot-align-size-nop', entries)
683 entry = entries['u-boot-align-size-nop']
Simon Glass3ab95982018-08-01 15:22:37 -0600684 self.assertEqual(12, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700685 self.assertEqual(4, entry.size)
686
687 # Third u-boot has an aligned size too
688 self.assertIn('u-boot-align-size', entries)
689 entry = entries['u-boot-align-size']
Simon Glass3ab95982018-08-01 15:22:37 -0600690 self.assertEqual(16, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700691 self.assertEqual(32, entry.size)
692
693 # Fourth u-boot has an aligned end
694 self.assertIn('u-boot-align-end', entries)
695 entry = entries['u-boot-align-end']
Simon Glass3ab95982018-08-01 15:22:37 -0600696 self.assertEqual(48, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700697 self.assertEqual(16, entry.size)
698
699 # Fifth u-boot immediately afterwards
700 self.assertIn('u-boot-align-both', entries)
701 entry = entries['u-boot-align-both']
Simon Glass3ab95982018-08-01 15:22:37 -0600702 self.assertEqual(64, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700703 self.assertEqual(64, entry.size)
704
705 self.CheckNoGaps(entries)
706 self.assertEqual(128, image._size)
707
708 def testPackAlignPowerOf2(self):
709 """Test that invalid entry alignment is detected"""
710 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600711 self._DoTestFile('010_pack_align_power2.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700712 self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
713 "of two", str(e.exception))
714
715 def testPackAlignSizePowerOf2(self):
716 """Test that invalid entry size alignment is detected"""
717 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600718 self._DoTestFile('011_pack_align_size_power2.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700719 self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
720 "power of two", str(e.exception))
721
722 def testPackInvalidAlign(self):
Simon Glass3ab95982018-08-01 15:22:37 -0600723 """Test detection of an offset that does not match its alignment"""
Simon Glass4f443042016-11-25 20:15:52 -0700724 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600725 self._DoTestFile('012_pack_inv_align.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600726 self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
Simon Glass4f443042016-11-25 20:15:52 -0700727 "align 0x4 (4)", str(e.exception))
728
729 def testPackInvalidSizeAlign(self):
730 """Test that invalid entry size alignment is detected"""
731 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600732 self._DoTestFile('013_pack_inv_size_align.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700733 self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
734 "align-size 0x4 (4)", str(e.exception))
735
736 def testPackOverlap(self):
737 """Test that overlapping regions are detected"""
738 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600739 self._DoTestFile('014_pack_overlap.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600740 self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
Simon Glass4f443042016-11-25 20:15:52 -0700741 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
742 str(e.exception))
743
744 def testPackEntryOverflow(self):
745 """Test that entries that overflow their size are detected"""
746 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600747 self._DoTestFile('015_pack_overflow.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700748 self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
749 "but entry size is 0x3 (3)", str(e.exception))
750
751 def testPackImageOverflow(self):
752 """Test that entries which overflow the image size are detected"""
753 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600754 self._DoTestFile('016_pack_image_overflow.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600755 self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section "
Simon Glass4f443042016-11-25 20:15:52 -0700756 "size 0x3 (3)", str(e.exception))
757
758 def testPackImageSize(self):
759 """Test that the image size can be set"""
Simon Glass741f2d62018-10-01 12:22:30 -0600760 retcode = self._DoTestFile('017_pack_image_size.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700761 self.assertEqual(0, retcode)
762 self.assertIn('image', control.images)
763 image = control.images['image']
764 self.assertEqual(7, image._size)
765
766 def testPackImageSizeAlign(self):
767 """Test that image size alignemnt works as expected"""
Simon Glass741f2d62018-10-01 12:22:30 -0600768 retcode = self._DoTestFile('018_pack_image_align.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700769 self.assertEqual(0, retcode)
770 self.assertIn('image', control.images)
771 image = control.images['image']
772 self.assertEqual(16, image._size)
773
774 def testPackInvalidImageAlign(self):
775 """Test that invalid image alignment is detected"""
776 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600777 self._DoTestFile('019_pack_inv_image_align.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600778 self.assertIn("Section '/binman': Size 0x7 (7) does not match "
Simon Glass4f443042016-11-25 20:15:52 -0700779 "align-size 0x8 (8)", str(e.exception))
780
781 def testPackAlignPowerOf2(self):
782 """Test that invalid image alignment is detected"""
783 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600784 self._DoTestFile('020_pack_inv_image_align_power2.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600785 self.assertIn("Section '/binman': Alignment size 131 must be a power of "
Simon Glass4f443042016-11-25 20:15:52 -0700786 "two", str(e.exception))
787
788 def testImagePadByte(self):
789 """Test that the image pad byte can be specified"""
Simon Glass11ae93e2018-10-01 21:12:47 -0600790 self._SetupSplElf()
Simon Glass741f2d62018-10-01 12:22:30 -0600791 data = self._DoReadFile('021_image_pad.dts')
Simon Glasse6d85ff2019-05-14 15:53:47 -0600792 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0xff, 1) +
793 U_BOOT_DATA, data)
Simon Glass4f443042016-11-25 20:15:52 -0700794
795 def testImageName(self):
796 """Test that image files can be named"""
Simon Glass741f2d62018-10-01 12:22:30 -0600797 retcode = self._DoTestFile('022_image_name.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700798 self.assertEqual(0, retcode)
799 image = control.images['image1']
800 fname = tools.GetOutputFilename('test-name')
801 self.assertTrue(os.path.exists(fname))
802
803 image = control.images['image2']
804 fname = tools.GetOutputFilename('test-name.xx')
805 self.assertTrue(os.path.exists(fname))
806
807 def testBlobFilename(self):
808 """Test that generic blobs can be provided by filename"""
Simon Glass741f2d62018-10-01 12:22:30 -0600809 data = self._DoReadFile('023_blob.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700810 self.assertEqual(BLOB_DATA, data)
811
812 def testPackSorted(self):
813 """Test that entries can be sorted"""
Simon Glass11ae93e2018-10-01 21:12:47 -0600814 self._SetupSplElf()
Simon Glass741f2d62018-10-01 12:22:30 -0600815 data = self._DoReadFile('024_sorted.dts')
Simon Glasse6d85ff2019-05-14 15:53:47 -0600816 self.assertEqual(tools.GetBytes(0, 1) + U_BOOT_SPL_DATA +
817 tools.GetBytes(0, 2) + U_BOOT_DATA, data)
Simon Glass4f443042016-11-25 20:15:52 -0700818
Simon Glass3ab95982018-08-01 15:22:37 -0600819 def testPackZeroOffset(self):
820 """Test that an entry at offset 0 is not given a new offset"""
Simon Glass4f443042016-11-25 20:15:52 -0700821 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600822 self._DoTestFile('025_pack_zero_size.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600823 self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
Simon Glass4f443042016-11-25 20:15:52 -0700824 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
825 str(e.exception))
826
827 def testPackUbootDtb(self):
828 """Test that a device tree can be added to U-Boot"""
Simon Glass741f2d62018-10-01 12:22:30 -0600829 data = self._DoReadFile('026_pack_u_boot_dtb.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700830 self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
Simon Glasse0ff8552016-11-25 20:15:53 -0700831
832 def testPackX86RomNoSize(self):
833 """Test that the end-at-4gb property requires a size property"""
834 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600835 self._DoTestFile('027_pack_4gb_no_size.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600836 self.assertIn("Section '/binman': Section size must be provided when "
Simon Glasse0ff8552016-11-25 20:15:53 -0700837 "using end-at-4gb", str(e.exception))
838
Jagdish Gediya94b57db2018-09-03 21:35:07 +0530839 def test4gbAndSkipAtStartTogether(self):
840 """Test that the end-at-4gb and skip-at-size property can't be used
841 together"""
842 with self.assertRaises(ValueError) as e:
843 self._DoTestFile('80_4gb_and_skip_at_start_together.dts')
844 self.assertIn("Section '/binman': Provide either 'end-at-4gb' or "
845 "'skip-at-start'", str(e.exception))
846
Simon Glasse0ff8552016-11-25 20:15:53 -0700847 def testPackX86RomOutside(self):
Simon Glass3ab95982018-08-01 15:22:37 -0600848 """Test that the end-at-4gb property checks for offset boundaries"""
Simon Glasse0ff8552016-11-25 20:15:53 -0700849 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600850 self._DoTestFile('028_pack_4gb_outside.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600851 self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
Simon Glass8f1da502018-06-01 09:38:12 -0600852 "the section starting at 0xffffffe0 (4294967264)",
Simon Glasse0ff8552016-11-25 20:15:53 -0700853 str(e.exception))
854
855 def testPackX86Rom(self):
856 """Test that a basic x86 ROM can be created"""
Simon Glass11ae93e2018-10-01 21:12:47 -0600857 self._SetupSplElf()
Simon Glass741f2d62018-10-01 12:22:30 -0600858 data = self._DoReadFile('029_x86-rom.dts')
Simon Glasse6d85ff2019-05-14 15:53:47 -0600859 self.assertEqual(U_BOOT_DATA + tools.GetBytes(0, 7) + U_BOOT_SPL_DATA +
860 tools.GetBytes(0, 2), data)
Simon Glasse0ff8552016-11-25 20:15:53 -0700861
862 def testPackX86RomMeNoDesc(self):
863 """Test that an invalid Intel descriptor entry is detected"""
Simon Glassc6c10e72019-05-17 22:00:46 -0600864 TestFunctional._MakeInputFile('descriptor.bin', b'')
Simon Glasse0ff8552016-11-25 20:15:53 -0700865 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600866 self._DoTestFile('031_x86-rom-me.dts')
Simon Glass458be452019-07-08 13:18:32 -0600867 self.assertIn("Node '/binman/intel-descriptor': Cannot find Intel Flash Descriptor (FD) signature",
868 str(e.exception))
Simon Glasse0ff8552016-11-25 20:15:53 -0700869
870 def testPackX86RomBadDesc(self):
871 """Test that the Intel requires a descriptor entry"""
872 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600873 self._DoTestFile('030_x86-rom-me-no-desc.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600874 self.assertIn("Node '/binman/intel-me': No offset set with "
875 "offset-unset: should another entry provide this correct "
876 "offset?", str(e.exception))
Simon Glasse0ff8552016-11-25 20:15:53 -0700877
878 def testPackX86RomMe(self):
879 """Test that an x86 ROM with an ME region can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -0600880 data = self._DoReadFile('031_x86-rom-me.dts')
Simon Glassc5ac1382019-07-08 13:18:54 -0600881 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
882 if data[:0x1000] != expected_desc:
883 self.fail('Expected descriptor binary at start of image')
Simon Glasse0ff8552016-11-25 20:15:53 -0700884 self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
885
886 def testPackVga(self):
887 """Test that an image with a VGA binary can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -0600888 data = self._DoReadFile('032_intel-vga.dts')
Simon Glasse0ff8552016-11-25 20:15:53 -0700889 self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
890
891 def testPackStart16(self):
892 """Test that an image with an x86 start16 region can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -0600893 data = self._DoReadFile('033_x86-start16.dts')
Simon Glasse0ff8552016-11-25 20:15:53 -0700894 self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
895
Jagdish Gediya9d368f32018-09-03 21:35:08 +0530896 def testPackPowerpcMpc85xxBootpgResetvec(self):
897 """Test that an image with powerpc-mpc85xx-bootpg-resetvec can be
898 created"""
899 data = self._DoReadFile('81_powerpc_mpc85xx_bootpg_resetvec.dts')
900 self.assertEqual(PPC_MPC85XX_BR_DATA, data[:len(PPC_MPC85XX_BR_DATA)])
901
Simon Glass736bb0a2018-07-06 10:27:17 -0600902 def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False):
Simon Glassadc57012018-07-06 10:27:16 -0600903 """Handle running a test for insertion of microcode
904
905 Args:
906 dts_fname: Name of test .dts file
907 nodtb_data: Data that we expect in the first section
Simon Glass736bb0a2018-07-06 10:27:17 -0600908 ucode_second: True if the microsecond entry is second instead of
909 third
Simon Glassadc57012018-07-06 10:27:16 -0600910
911 Returns:
912 Tuple:
913 Contents of first region (U-Boot or SPL)
Simon Glass3ab95982018-08-01 15:22:37 -0600914 Offset and size components of microcode pointer, as inserted
Simon Glassadc57012018-07-06 10:27:16 -0600915 in the above (two 4-byte words)
916 """
Simon Glass6b187df2017-11-12 21:52:27 -0700917 data = self._DoReadFile(dts_fname, True)
Simon Glasse0ff8552016-11-25 20:15:53 -0700918
919 # Now check the device tree has no microcode
Simon Glass736bb0a2018-07-06 10:27:17 -0600920 if ucode_second:
921 ucode_content = data[len(nodtb_data):]
922 ucode_pos = len(nodtb_data)
923 dtb_with_ucode = ucode_content[16:]
924 fdt_len = self.GetFdtLen(dtb_with_ucode)
925 else:
926 dtb_with_ucode = data[len(nodtb_data):]
927 fdt_len = self.GetFdtLen(dtb_with_ucode)
928 ucode_content = dtb_with_ucode[fdt_len:]
929 ucode_pos = len(nodtb_data) + fdt_len
Simon Glasse0ff8552016-11-25 20:15:53 -0700930 fname = tools.GetOutputFilename('test.dtb')
931 with open(fname, 'wb') as fd:
Simon Glassadc57012018-07-06 10:27:16 -0600932 fd.write(dtb_with_ucode)
Simon Glassec3f3782017-05-27 07:38:29 -0600933 dtb = fdt.FdtScan(fname)
934 ucode = dtb.GetNode('/microcode')
Simon Glasse0ff8552016-11-25 20:15:53 -0700935 self.assertTrue(ucode)
936 for node in ucode.subnodes:
937 self.assertFalse(node.props.get('data'))
938
Simon Glasse0ff8552016-11-25 20:15:53 -0700939 # Check that the microcode appears immediately after the Fdt
940 # This matches the concatenation of the data properties in
Simon Glass87722132017-11-12 21:52:26 -0700941 # the /microcode/update@xxx nodes in 34_x86_ucode.dts.
Simon Glasse0ff8552016-11-25 20:15:53 -0700942 ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
943 0x78235609)
Simon Glassadc57012018-07-06 10:27:16 -0600944 self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
Simon Glasse0ff8552016-11-25 20:15:53 -0700945
946 # Check that the microcode pointer was inserted. It should match the
Simon Glass3ab95982018-08-01 15:22:37 -0600947 # expected offset and size
Simon Glasse0ff8552016-11-25 20:15:53 -0700948 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
949 len(ucode_data))
Simon Glass736bb0a2018-07-06 10:27:17 -0600950 u_boot = data[:len(nodtb_data)]
951 return u_boot, pos_and_size
Simon Glass6b187df2017-11-12 21:52:27 -0700952
953 def testPackUbootMicrocode(self):
954 """Test that x86 microcode can be handled correctly
955
956 We expect to see the following in the image, in order:
957 u-boot-nodtb.bin with a microcode pointer inserted at the correct
958 place
959 u-boot.dtb with the microcode removed
960 the microcode
961 """
Simon Glass741f2d62018-10-01 12:22:30 -0600962 first, pos_and_size = self._RunMicrocodeTest('034_x86_ucode.dts',
Simon Glass6b187df2017-11-12 21:52:27 -0700963 U_BOOT_NODTB_DATA)
Simon Glassc6c10e72019-05-17 22:00:46 -0600964 self.assertEqual(b'nodtb with microcode' + pos_and_size +
965 b' somewhere in here', first)
Simon Glasse0ff8552016-11-25 20:15:53 -0700966
Simon Glass160a7662017-05-27 07:38:26 -0600967 def _RunPackUbootSingleMicrocode(self):
Simon Glasse0ff8552016-11-25 20:15:53 -0700968 """Test that x86 microcode can be handled correctly
969
970 We expect to see the following in the image, in order:
971 u-boot-nodtb.bin with a microcode pointer inserted at the correct
972 place
973 u-boot.dtb with the microcode
974 an empty microcode region
975 """
976 # We need the libfdt library to run this test since only that allows
977 # finding the offset of a property. This is required by
978 # Entry_u_boot_dtb_with_ucode.ObtainContents().
Simon Glass741f2d62018-10-01 12:22:30 -0600979 data = self._DoReadFile('035_x86_single_ucode.dts', True)
Simon Glasse0ff8552016-11-25 20:15:53 -0700980
981 second = data[len(U_BOOT_NODTB_DATA):]
982
983 fdt_len = self.GetFdtLen(second)
984 third = second[fdt_len:]
985 second = second[:fdt_len]
986
Simon Glass160a7662017-05-27 07:38:26 -0600987 ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
988 self.assertIn(ucode_data, second)
989 ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
Simon Glasse0ff8552016-11-25 20:15:53 -0700990
Simon Glass160a7662017-05-27 07:38:26 -0600991 # Check that the microcode pointer was inserted. It should match the
Simon Glass3ab95982018-08-01 15:22:37 -0600992 # expected offset and size
Simon Glass160a7662017-05-27 07:38:26 -0600993 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
994 len(ucode_data))
995 first = data[:len(U_BOOT_NODTB_DATA)]
Simon Glassc6c10e72019-05-17 22:00:46 -0600996 self.assertEqual(b'nodtb with microcode' + pos_and_size +
997 b' somewhere in here', first)
Simon Glassc49deb82016-11-25 20:15:54 -0700998
Simon Glass75db0862016-11-25 20:15:55 -0700999 def testPackUbootSingleMicrocode(self):
1000 """Test that x86 microcode can be handled correctly with fdt_normal.
1001 """
Simon Glass160a7662017-05-27 07:38:26 -06001002 self._RunPackUbootSingleMicrocode()
Simon Glass75db0862016-11-25 20:15:55 -07001003
Simon Glassc49deb82016-11-25 20:15:54 -07001004 def testUBootImg(self):
1005 """Test that u-boot.img can be put in a file"""
Simon Glass741f2d62018-10-01 12:22:30 -06001006 data = self._DoReadFile('036_u_boot_img.dts')
Simon Glassc49deb82016-11-25 20:15:54 -07001007 self.assertEqual(U_BOOT_IMG_DATA, data)
Simon Glass75db0862016-11-25 20:15:55 -07001008
1009 def testNoMicrocode(self):
1010 """Test that a missing microcode region is detected"""
1011 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001012 self._DoReadFile('037_x86_no_ucode.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -07001013 self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
1014 "node found in ", str(e.exception))
1015
1016 def testMicrocodeWithoutNode(self):
1017 """Test that a missing u-boot-dtb-with-ucode node is detected"""
1018 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001019 self._DoReadFile('038_x86_ucode_missing_node.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -07001020 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1021 "microcode region u-boot-dtb-with-ucode", str(e.exception))
1022
1023 def testMicrocodeWithoutNode2(self):
1024 """Test that a missing u-boot-ucode node is detected"""
1025 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001026 self._DoReadFile('039_x86_ucode_missing_node2.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -07001027 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1028 "microcode region u-boot-ucode", str(e.exception))
1029
1030 def testMicrocodeWithoutPtrInElf(self):
1031 """Test that a U-Boot binary without the microcode symbol is detected"""
1032 # ELF file without a '_dt_ucode_base_size' symbol
Simon Glass75db0862016-11-25 20:15:55 -07001033 try:
Simon Glass1d0ebf72019-05-14 15:53:42 -06001034 with open(self.TestFile('u_boot_no_ucode_ptr'), 'rb') as fd:
Simon Glass75db0862016-11-25 20:15:55 -07001035 TestFunctional._MakeInputFile('u-boot', fd.read())
1036
1037 with self.assertRaises(ValueError) as e:
Simon Glass160a7662017-05-27 07:38:26 -06001038 self._RunPackUbootSingleMicrocode()
Simon Glass75db0862016-11-25 20:15:55 -07001039 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
1040 "_dt_ucode_base_size symbol in u-boot", str(e.exception))
1041
1042 finally:
1043 # Put the original file back
Simon Glass1d0ebf72019-05-14 15:53:42 -06001044 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
Simon Glass75db0862016-11-25 20:15:55 -07001045 TestFunctional._MakeInputFile('u-boot', fd.read())
1046
1047 def testMicrocodeNotInImage(self):
1048 """Test that microcode must be placed within the image"""
1049 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001050 self._DoReadFile('040_x86_ucode_not_in_image.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -07001051 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
1052 "pointer _dt_ucode_base_size at fffffe14 is outside the "
Simon Glass25ac0e62018-06-01 09:38:14 -06001053 "section ranging from 00000000 to 0000002e", str(e.exception))
Simon Glass75db0862016-11-25 20:15:55 -07001054
1055 def testWithoutMicrocode(self):
1056 """Test that we can cope with an image without microcode (e.g. qemu)"""
Simon Glass1d0ebf72019-05-14 15:53:42 -06001057 with open(self.TestFile('u_boot_no_ucode_ptr'), 'rb') as fd:
Simon Glass75db0862016-11-25 20:15:55 -07001058 TestFunctional._MakeInputFile('u-boot', fd.read())
Simon Glass741f2d62018-10-01 12:22:30 -06001059 data, dtb, _, _ = self._DoReadFileDtb('044_x86_optional_ucode.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -07001060
1061 # Now check the device tree has no microcode
1062 self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
1063 second = data[len(U_BOOT_NODTB_DATA):]
1064
1065 fdt_len = self.GetFdtLen(second)
1066 self.assertEqual(dtb, second[:fdt_len])
1067
1068 used_len = len(U_BOOT_NODTB_DATA) + fdt_len
1069 third = data[used_len:]
Simon Glasse6d85ff2019-05-14 15:53:47 -06001070 self.assertEqual(tools.GetBytes(0, 0x200 - used_len), third)
Simon Glass75db0862016-11-25 20:15:55 -07001071
1072 def testUnknownPosSize(self):
1073 """Test that microcode must be placed within the image"""
1074 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001075 self._DoReadFile('041_unknown_pos_size.dts', True)
Simon Glass3ab95982018-08-01 15:22:37 -06001076 self.assertIn("Section '/binman': Unable to set offset/size for unknown "
Simon Glass75db0862016-11-25 20:15:55 -07001077 "entry 'invalid-entry'", str(e.exception))
Simon Glassda229092016-11-25 20:15:56 -07001078
1079 def testPackFsp(self):
1080 """Test that an image with a FSP binary can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001081 data = self._DoReadFile('042_intel-fsp.dts')
Simon Glassda229092016-11-25 20:15:56 -07001082 self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
1083
1084 def testPackCmc(self):
Bin Meng59ea8c22017-08-15 22:41:54 -07001085 """Test that an image with a CMC binary can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001086 data = self._DoReadFile('043_intel-cmc.dts')
Simon Glassda229092016-11-25 20:15:56 -07001087 self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
Bin Meng59ea8c22017-08-15 22:41:54 -07001088
1089 def testPackVbt(self):
1090 """Test that an image with a VBT binary can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001091 data = self._DoReadFile('046_intel-vbt.dts')
Bin Meng59ea8c22017-08-15 22:41:54 -07001092 self.assertEqual(VBT_DATA, data[:len(VBT_DATA)])
Simon Glass9fc60b42017-11-12 21:52:22 -07001093
Simon Glass56509842017-11-12 21:52:25 -07001094 def testSplBssPad(self):
1095 """Test that we can pad SPL's BSS with zeros"""
Simon Glass6b187df2017-11-12 21:52:27 -07001096 # ELF file with a '__bss_size' symbol
Simon Glass11ae93e2018-10-01 21:12:47 -06001097 self._SetupSplElf()
Simon Glass741f2d62018-10-01 12:22:30 -06001098 data = self._DoReadFile('047_spl_bss_pad.dts')
Simon Glasse6d85ff2019-05-14 15:53:47 -06001099 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0, 10) + U_BOOT_DATA,
1100 data)
Simon Glass56509842017-11-12 21:52:25 -07001101
Simon Glass86af5112018-10-01 21:12:42 -06001102 def testSplBssPadMissing(self):
1103 """Test that a missing symbol is detected"""
Simon Glass11ae93e2018-10-01 21:12:47 -06001104 self._SetupSplElf('u_boot_ucode_ptr')
Simon Glassb50e5612017-11-13 18:54:54 -07001105 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001106 self._DoReadFile('047_spl_bss_pad.dts')
Simon Glassb50e5612017-11-13 18:54:54 -07001107 self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
1108 str(e.exception))
1109
Simon Glass87722132017-11-12 21:52:26 -07001110 def testPackStart16Spl(self):
Simon Glass35b384c2018-09-14 04:57:10 -06001111 """Test that an image with an x86 start16 SPL region can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001112 data = self._DoReadFile('048_x86-start16-spl.dts')
Simon Glass87722132017-11-12 21:52:26 -07001113 self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)])
1114
Simon Glass736bb0a2018-07-06 10:27:17 -06001115 def _PackUbootSplMicrocode(self, dts, ucode_second=False):
1116 """Helper function for microcode tests
Simon Glass6b187df2017-11-12 21:52:27 -07001117
1118 We expect to see the following in the image, in order:
1119 u-boot-spl-nodtb.bin with a microcode pointer inserted at the
1120 correct place
1121 u-boot.dtb with the microcode removed
1122 the microcode
Simon Glass736bb0a2018-07-06 10:27:17 -06001123
1124 Args:
1125 dts: Device tree file to use for test
1126 ucode_second: True if the microsecond entry is second instead of
1127 third
Simon Glass6b187df2017-11-12 21:52:27 -07001128 """
Simon Glass11ae93e2018-10-01 21:12:47 -06001129 self._SetupSplElf('u_boot_ucode_ptr')
Simon Glass736bb0a2018-07-06 10:27:17 -06001130 first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA,
1131 ucode_second=ucode_second)
Simon Glassc6c10e72019-05-17 22:00:46 -06001132 self.assertEqual(b'splnodtb with microc' + pos_and_size +
1133 b'ter somewhere in here', first)
Simon Glass6b187df2017-11-12 21:52:27 -07001134
Simon Glass736bb0a2018-07-06 10:27:17 -06001135 def testPackUbootSplMicrocode(self):
1136 """Test that x86 microcode can be handled correctly in SPL"""
Simon Glass741f2d62018-10-01 12:22:30 -06001137 self._PackUbootSplMicrocode('049_x86_ucode_spl.dts')
Simon Glass736bb0a2018-07-06 10:27:17 -06001138
1139 def testPackUbootSplMicrocodeReorder(self):
1140 """Test that order doesn't matter for microcode entries
1141
1142 This is the same as testPackUbootSplMicrocode but when we process the
1143 u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode
1144 entry, so we reply on binman to try later.
1145 """
Simon Glass741f2d62018-10-01 12:22:30 -06001146 self._PackUbootSplMicrocode('058_x86_ucode_spl_needs_retry.dts',
Simon Glass736bb0a2018-07-06 10:27:17 -06001147 ucode_second=True)
1148
Simon Glassca4f4ff2017-11-12 21:52:28 -07001149 def testPackMrc(self):
1150 """Test that an image with an MRC binary can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001151 data = self._DoReadFile('050_intel_mrc.dts')
Simon Glassca4f4ff2017-11-12 21:52:28 -07001152 self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
1153
Simon Glass47419ea2017-11-13 18:54:55 -07001154 def testSplDtb(self):
1155 """Test that an image with spl/u-boot-spl.dtb can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001156 data = self._DoReadFile('051_u_boot_spl_dtb.dts')
Simon Glass47419ea2017-11-13 18:54:55 -07001157 self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
1158
Simon Glass4e6fdbe2017-11-13 18:54:56 -07001159 def testSplNoDtb(self):
1160 """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001161 data = self._DoReadFile('052_u_boot_spl_nodtb.dts')
Simon Glass4e6fdbe2017-11-13 18:54:56 -07001162 self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
1163
Simon Glass19790632017-11-13 18:55:01 -07001164 def testSymbols(self):
1165 """Test binman can assign symbols embedded in U-Boot"""
1166 elf_fname = self.TestFile('u_boot_binman_syms')
1167 syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
1168 addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
Simon Glass3ab95982018-08-01 15:22:37 -06001169 self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
Simon Glass19790632017-11-13 18:55:01 -07001170
Simon Glass11ae93e2018-10-01 21:12:47 -06001171 self._SetupSplElf('u_boot_binman_syms')
Simon Glass741f2d62018-10-01 12:22:30 -06001172 data = self._DoReadFile('053_symbols.dts')
Simon Glass19790632017-11-13 18:55:01 -07001173 sym_values = struct.pack('<LQL', 0x24 + 0, 0x24 + 24, 0x24 + 20)
Simon Glasse6d85ff2019-05-14 15:53:47 -06001174 expected = (sym_values + U_BOOT_SPL_DATA[16:] +
1175 tools.GetBytes(0xff, 1) + U_BOOT_DATA + sym_values +
1176 U_BOOT_SPL_DATA[16:])
Simon Glass19790632017-11-13 18:55:01 -07001177 self.assertEqual(expected, data)
1178
Simon Glassdd57c132018-06-01 09:38:11 -06001179 def testPackUnitAddress(self):
1180 """Test that we support multiple binaries with the same name"""
Simon Glass741f2d62018-10-01 12:22:30 -06001181 data = self._DoReadFile('054_unit_address.dts')
Simon Glassdd57c132018-06-01 09:38:11 -06001182 self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
1183
Simon Glass18546952018-06-01 09:38:16 -06001184 def testSections(self):
1185 """Basic test of sections"""
Simon Glass741f2d62018-10-01 12:22:30 -06001186 data = self._DoReadFile('055_sections.dts')
Simon Glassc6c10e72019-05-17 22:00:46 -06001187 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1188 U_BOOT_DATA + tools.GetBytes(ord('a'), 12) +
1189 U_BOOT_DATA + tools.GetBytes(ord('&'), 4))
Simon Glass18546952018-06-01 09:38:16 -06001190 self.assertEqual(expected, data)
Simon Glass9fc60b42017-11-12 21:52:22 -07001191
Simon Glass3b0c3822018-06-01 09:38:20 -06001192 def testMap(self):
1193 """Tests outputting a map of the images"""
Simon Glass741f2d62018-10-01 12:22:30 -06001194 _, _, map_data, _ = self._DoReadFileDtb('055_sections.dts', map=True)
Simon Glass1be70d22018-07-17 13:25:49 -06001195 self.assertEqual('''ImagePos Offset Size Name
119600000000 00000000 00000028 main-section
119700000000 00000000 00000010 section@0
119800000000 00000000 00000004 u-boot
119900000010 00000010 00000010 section@1
120000000010 00000000 00000004 u-boot
120100000020 00000020 00000004 section@2
120200000020 00000000 00000004 u-boot
Simon Glass3b0c3822018-06-01 09:38:20 -06001203''', map_data)
1204
Simon Glassc8d48ef2018-06-01 09:38:21 -06001205 def testNamePrefix(self):
1206 """Tests that name prefixes are used"""
Simon Glass741f2d62018-10-01 12:22:30 -06001207 _, _, map_data, _ = self._DoReadFileDtb('056_name_prefix.dts', map=True)
Simon Glass1be70d22018-07-17 13:25:49 -06001208 self.assertEqual('''ImagePos Offset Size Name
120900000000 00000000 00000028 main-section
121000000000 00000000 00000010 section@0
121100000000 00000000 00000004 ro-u-boot
121200000010 00000010 00000010 section@1
121300000010 00000000 00000004 rw-u-boot
Simon Glassc8d48ef2018-06-01 09:38:21 -06001214''', map_data)
1215
Simon Glass736bb0a2018-07-06 10:27:17 -06001216 def testUnknownContents(self):
1217 """Test that obtaining the contents works as expected"""
1218 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001219 self._DoReadFile('057_unknown_contents.dts', True)
Simon Glass736bb0a2018-07-06 10:27:17 -06001220 self.assertIn("Section '/binman': Internal error: Could not complete "
1221 "processing of contents: remaining [<_testing.Entry__testing ",
1222 str(e.exception))
1223
Simon Glass5c890232018-07-06 10:27:19 -06001224 def testBadChangeSize(self):
1225 """Test that trying to change the size of an entry fails"""
Simon Glassc52c9e72019-07-08 14:25:37 -06001226 try:
1227 state.SetAllowEntryExpansion(False)
1228 with self.assertRaises(ValueError) as e:
1229 self._DoReadFile('059_change_size.dts', True)
1230 self.assertIn("Node '/binman/_testing': Cannot update entry size from 1 to 2",
1231 str(e.exception))
1232 finally:
1233 state.SetAllowEntryExpansion(True)
Simon Glass5c890232018-07-06 10:27:19 -06001234
Simon Glass16b8d6b2018-07-06 10:27:42 -06001235 def testUpdateFdt(self):
Simon Glass3ab95982018-08-01 15:22:37 -06001236 """Test that we can update the device tree with offset/size info"""
Simon Glass741f2d62018-10-01 12:22:30 -06001237 _, _, _, out_dtb_fname = self._DoReadFileDtb('060_fdt_update.dts',
Simon Glass16b8d6b2018-07-06 10:27:42 -06001238 update_dtb=True)
Simon Glasscee02e62018-07-17 13:25:52 -06001239 dtb = fdt.Fdt(out_dtb_fname)
1240 dtb.Scan()
1241 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'])
Simon Glass16b8d6b2018-07-06 10:27:42 -06001242 self.assertEqual({
Simon Glassdbf6be92018-08-01 15:22:42 -06001243 'image-pos': 0,
Simon Glass8122f392018-07-17 13:25:28 -06001244 'offset': 0,
Simon Glass3ab95982018-08-01 15:22:37 -06001245 '_testing:offset': 32,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001246 '_testing:size': 1,
Simon Glassdbf6be92018-08-01 15:22:42 -06001247 '_testing:image-pos': 32,
Simon Glass3ab95982018-08-01 15:22:37 -06001248 'section@0/u-boot:offset': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001249 'section@0/u-boot:size': len(U_BOOT_DATA),
Simon Glassdbf6be92018-08-01 15:22:42 -06001250 'section@0/u-boot:image-pos': 0,
Simon Glass3ab95982018-08-01 15:22:37 -06001251 'section@0:offset': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001252 'section@0:size': 16,
Simon Glassdbf6be92018-08-01 15:22:42 -06001253 'section@0:image-pos': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001254
Simon Glass3ab95982018-08-01 15:22:37 -06001255 'section@1/u-boot:offset': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001256 'section@1/u-boot:size': len(U_BOOT_DATA),
Simon Glassdbf6be92018-08-01 15:22:42 -06001257 'section@1/u-boot:image-pos': 16,
Simon Glass3ab95982018-08-01 15:22:37 -06001258 'section@1:offset': 16,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001259 'section@1:size': 16,
Simon Glassdbf6be92018-08-01 15:22:42 -06001260 'section@1:image-pos': 16,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001261 'size': 40
1262 }, props)
1263
1264 def testUpdateFdtBad(self):
1265 """Test that we detect when ProcessFdt never completes"""
1266 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001267 self._DoReadFileDtb('061_fdt_update_bad.dts', update_dtb=True)
Simon Glass16b8d6b2018-07-06 10:27:42 -06001268 self.assertIn('Could not complete processing of Fdt: remaining '
1269 '[<_testing.Entry__testing', str(e.exception))
Simon Glass5c890232018-07-06 10:27:19 -06001270
Simon Glass53af22a2018-07-17 13:25:32 -06001271 def testEntryArgs(self):
1272 """Test passing arguments to entries from the command line"""
1273 entry_args = {
1274 'test-str-arg': 'test1',
1275 'test-int-arg': '456',
1276 }
Simon Glass741f2d62018-10-01 12:22:30 -06001277 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
Simon Glass53af22a2018-07-17 13:25:32 -06001278 self.assertIn('image', control.images)
1279 entry = control.images['image'].GetEntries()['_testing']
1280 self.assertEqual('test0', entry.test_str_fdt)
1281 self.assertEqual('test1', entry.test_str_arg)
1282 self.assertEqual(123, entry.test_int_fdt)
1283 self.assertEqual(456, entry.test_int_arg)
1284
1285 def testEntryArgsMissing(self):
1286 """Test missing arguments and properties"""
1287 entry_args = {
1288 'test-int-arg': '456',
1289 }
Simon Glass741f2d62018-10-01 12:22:30 -06001290 self._DoReadFileDtb('063_entry_args_missing.dts', entry_args=entry_args)
Simon Glass53af22a2018-07-17 13:25:32 -06001291 entry = control.images['image'].GetEntries()['_testing']
1292 self.assertEqual('test0', entry.test_str_fdt)
1293 self.assertEqual(None, entry.test_str_arg)
1294 self.assertEqual(None, entry.test_int_fdt)
1295 self.assertEqual(456, entry.test_int_arg)
1296
1297 def testEntryArgsRequired(self):
1298 """Test missing arguments and properties"""
1299 entry_args = {
1300 'test-int-arg': '456',
1301 }
1302 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001303 self._DoReadFileDtb('064_entry_args_required.dts')
Simon Glass53af22a2018-07-17 13:25:32 -06001304 self.assertIn("Node '/binman/_testing': Missing required "
1305 'properties/entry args: test-str-arg, test-int-fdt, test-int-arg',
1306 str(e.exception))
1307
1308 def testEntryArgsInvalidFormat(self):
1309 """Test that an invalid entry-argument format is detected"""
Simon Glass53cd5d92019-07-08 14:25:29 -06001310 args = ['build', '-d', self.TestFile('064_entry_args_required.dts'),
1311 '-ano-value']
Simon Glass53af22a2018-07-17 13:25:32 -06001312 with self.assertRaises(ValueError) as e:
1313 self._DoBinman(*args)
1314 self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
1315
1316 def testEntryArgsInvalidInteger(self):
1317 """Test that an invalid entry-argument integer is detected"""
1318 entry_args = {
1319 'test-int-arg': 'abc',
1320 }
1321 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001322 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
Simon Glass53af22a2018-07-17 13:25:32 -06001323 self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
1324 "'test-int-arg' (value 'abc') to integer",
1325 str(e.exception))
1326
1327 def testEntryArgsInvalidDatatype(self):
1328 """Test that an invalid entry-argument datatype is detected
1329
1330 This test could be written in entry_test.py except that it needs
1331 access to control.entry_args, which seems more than that module should
1332 be able to see.
1333 """
1334 entry_args = {
1335 'test-bad-datatype-arg': '12',
1336 }
1337 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001338 self._DoReadFileDtb('065_entry_args_unknown_datatype.dts',
Simon Glass53af22a2018-07-17 13:25:32 -06001339 entry_args=entry_args)
1340 self.assertIn('GetArg() internal error: Unknown data type ',
1341 str(e.exception))
1342
Simon Glassbb748372018-07-17 13:25:33 -06001343 def testText(self):
1344 """Test for a text entry type"""
1345 entry_args = {
1346 'test-id': TEXT_DATA,
1347 'test-id2': TEXT_DATA2,
1348 'test-id3': TEXT_DATA3,
1349 }
Simon Glass741f2d62018-10-01 12:22:30 -06001350 data, _, _, _ = self._DoReadFileDtb('066_text.dts',
Simon Glassbb748372018-07-17 13:25:33 -06001351 entry_args=entry_args)
Simon Glassc6c10e72019-05-17 22:00:46 -06001352 expected = (tools.ToBytes(TEXT_DATA) +
1353 tools.GetBytes(0, 8 - len(TEXT_DATA)) +
1354 tools.ToBytes(TEXT_DATA2) + tools.ToBytes(TEXT_DATA3) +
Simon Glassaa88b502019-07-08 13:18:40 -06001355 b'some text' + b'more text')
Simon Glassbb748372018-07-17 13:25:33 -06001356 self.assertEqual(expected, data)
1357
Simon Glassfd8d1f72018-07-17 13:25:36 -06001358 def testEntryDocs(self):
1359 """Test for creation of entry documentation"""
1360 with test_util.capture_sys_output() as (stdout, stderr):
1361 control.WriteEntryDocs(binman.GetEntryModules())
1362 self.assertTrue(len(stdout.getvalue()) > 0)
1363
1364 def testEntryDocsMissing(self):
1365 """Test handling of missing entry documentation"""
1366 with self.assertRaises(ValueError) as e:
1367 with test_util.capture_sys_output() as (stdout, stderr):
1368 control.WriteEntryDocs(binman.GetEntryModules(), 'u_boot')
1369 self.assertIn('Documentation is missing for modules: u_boot',
1370 str(e.exception))
1371
Simon Glass11e36cc2018-07-17 13:25:38 -06001372 def testFmap(self):
1373 """Basic test of generation of a flashrom fmap"""
Simon Glass741f2d62018-10-01 12:22:30 -06001374 data = self._DoReadFile('067_fmap.dts')
Simon Glass11e36cc2018-07-17 13:25:38 -06001375 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
Simon Glassc6c10e72019-05-17 22:00:46 -06001376 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1377 U_BOOT_DATA + tools.GetBytes(ord('a'), 12))
Simon Glass11e36cc2018-07-17 13:25:38 -06001378 self.assertEqual(expected, data[:32])
Simon Glassc6c10e72019-05-17 22:00:46 -06001379 self.assertEqual(b'__FMAP__', fhdr.signature)
Simon Glass11e36cc2018-07-17 13:25:38 -06001380 self.assertEqual(1, fhdr.ver_major)
1381 self.assertEqual(0, fhdr.ver_minor)
1382 self.assertEqual(0, fhdr.base)
1383 self.assertEqual(16 + 16 +
1384 fmap_util.FMAP_HEADER_LEN +
1385 fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001386 self.assertEqual(b'FMAP', fhdr.name)
Simon Glass11e36cc2018-07-17 13:25:38 -06001387 self.assertEqual(3, fhdr.nareas)
1388 for fentry in fentries:
1389 self.assertEqual(0, fentry.flags)
1390
1391 self.assertEqual(0, fentries[0].offset)
1392 self.assertEqual(4, fentries[0].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001393 self.assertEqual(b'RO_U_BOOT', fentries[0].name)
Simon Glass11e36cc2018-07-17 13:25:38 -06001394
1395 self.assertEqual(16, fentries[1].offset)
1396 self.assertEqual(4, fentries[1].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001397 self.assertEqual(b'RW_U_BOOT', fentries[1].name)
Simon Glass11e36cc2018-07-17 13:25:38 -06001398
1399 self.assertEqual(32, fentries[2].offset)
1400 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1401 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001402 self.assertEqual(b'FMAP', fentries[2].name)
Simon Glass11e36cc2018-07-17 13:25:38 -06001403
Simon Glassec127af2018-07-17 13:25:39 -06001404 def testBlobNamedByArg(self):
1405 """Test we can add a blob with the filename coming from an entry arg"""
1406 entry_args = {
1407 'cros-ec-rw-path': 'ecrw.bin',
1408 }
Simon Glass741f2d62018-10-01 12:22:30 -06001409 data, _, _, _ = self._DoReadFileDtb('068_blob_named_by_arg.dts',
Simon Glassec127af2018-07-17 13:25:39 -06001410 entry_args=entry_args)
1411
Simon Glass3af8e492018-07-17 13:25:40 -06001412 def testFill(self):
1413 """Test for an fill entry type"""
Simon Glass741f2d62018-10-01 12:22:30 -06001414 data = self._DoReadFile('069_fill.dts')
Simon Glasse6d85ff2019-05-14 15:53:47 -06001415 expected = tools.GetBytes(0xff, 8) + tools.GetBytes(0, 8)
Simon Glass3af8e492018-07-17 13:25:40 -06001416 self.assertEqual(expected, data)
1417
1418 def testFillNoSize(self):
1419 """Test for an fill entry type with no size"""
1420 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001421 self._DoReadFile('070_fill_no_size.dts')
Simon Glass3af8e492018-07-17 13:25:40 -06001422 self.assertIn("'fill' entry must have a size property",
1423 str(e.exception))
1424
Simon Glass0ef87aa2018-07-17 13:25:44 -06001425 def _HandleGbbCommand(self, pipe_list):
1426 """Fake calls to the futility utility"""
1427 if pipe_list[0][0] == 'futility':
1428 fname = pipe_list[0][-1]
1429 # Append our GBB data to the file, which will happen every time the
1430 # futility command is called.
Simon Glass1d0ebf72019-05-14 15:53:42 -06001431 with open(fname, 'ab') as fd:
Simon Glass0ef87aa2018-07-17 13:25:44 -06001432 fd.write(GBB_DATA)
1433 return command.CommandResult()
1434
1435 def testGbb(self):
1436 """Test for the Chromium OS Google Binary Block"""
1437 command.test_result = self._HandleGbbCommand
1438 entry_args = {
1439 'keydir': 'devkeys',
1440 'bmpblk': 'bmpblk.bin',
1441 }
Simon Glass741f2d62018-10-01 12:22:30 -06001442 data, _, _, _ = self._DoReadFileDtb('071_gbb.dts', entry_args=entry_args)
Simon Glass0ef87aa2018-07-17 13:25:44 -06001443
1444 # Since futility
Simon Glasse6d85ff2019-05-14 15:53:47 -06001445 expected = (GBB_DATA + GBB_DATA + tools.GetBytes(0, 8) +
1446 tools.GetBytes(0, 0x2180 - 16))
Simon Glass0ef87aa2018-07-17 13:25:44 -06001447 self.assertEqual(expected, data)
1448
1449 def testGbbTooSmall(self):
1450 """Test for the Chromium OS Google Binary Block being large enough"""
1451 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001452 self._DoReadFileDtb('072_gbb_too_small.dts')
Simon Glass0ef87aa2018-07-17 13:25:44 -06001453 self.assertIn("Node '/binman/gbb': GBB is too small",
1454 str(e.exception))
1455
1456 def testGbbNoSize(self):
1457 """Test for the Chromium OS Google Binary Block having a size"""
1458 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001459 self._DoReadFileDtb('073_gbb_no_size.dts')
Simon Glass0ef87aa2018-07-17 13:25:44 -06001460 self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
1461 str(e.exception))
1462
Simon Glass24d0d3c2018-07-17 13:25:47 -06001463 def _HandleVblockCommand(self, pipe_list):
1464 """Fake calls to the futility utility"""
1465 if pipe_list[0][0] == 'futility':
1466 fname = pipe_list[0][3]
Simon Glassa326b492018-09-14 04:57:11 -06001467 with open(fname, 'wb') as fd:
Simon Glass24d0d3c2018-07-17 13:25:47 -06001468 fd.write(VBLOCK_DATA)
1469 return command.CommandResult()
1470
1471 def testVblock(self):
1472 """Test for the Chromium OS Verified Boot Block"""
1473 command.test_result = self._HandleVblockCommand
1474 entry_args = {
1475 'keydir': 'devkeys',
1476 }
Simon Glass741f2d62018-10-01 12:22:30 -06001477 data, _, _, _ = self._DoReadFileDtb('074_vblock.dts',
Simon Glass24d0d3c2018-07-17 13:25:47 -06001478 entry_args=entry_args)
1479 expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
1480 self.assertEqual(expected, data)
1481
1482 def testVblockNoContent(self):
1483 """Test we detect a vblock which has no content to sign"""
1484 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001485 self._DoReadFile('075_vblock_no_content.dts')
Simon Glass24d0d3c2018-07-17 13:25:47 -06001486 self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
1487 'property', str(e.exception))
1488
1489 def testVblockBadPhandle(self):
1490 """Test that we detect a vblock with an invalid phandle in contents"""
1491 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001492 self._DoReadFile('076_vblock_bad_phandle.dts')
Simon Glass24d0d3c2018-07-17 13:25:47 -06001493 self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
1494 '1000', str(e.exception))
1495
1496 def testVblockBadEntry(self):
1497 """Test that we detect an entry that points to a non-entry"""
1498 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001499 self._DoReadFile('077_vblock_bad_entry.dts')
Simon Glass24d0d3c2018-07-17 13:25:47 -06001500 self.assertIn("Node '/binman/vblock': Cannot find entry for node "
1501 "'other'", str(e.exception))
1502
Simon Glassb8ef5b62018-07-17 13:25:48 -06001503 def testTpl(self):
1504 """Test that an image with TPL and ots device tree can be created"""
1505 # ELF file with a '__bss_size' symbol
Simon Glass1d0ebf72019-05-14 15:53:42 -06001506 with open(self.TestFile('bss_data'), 'rb') as fd:
Simon Glassb8ef5b62018-07-17 13:25:48 -06001507 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
Simon Glass741f2d62018-10-01 12:22:30 -06001508 data = self._DoReadFile('078_u_boot_tpl.dts')
Simon Glassb8ef5b62018-07-17 13:25:48 -06001509 self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
1510
Simon Glass15a587c2018-07-17 13:25:51 -06001511 def testUsesPos(self):
1512 """Test that the 'pos' property cannot be used anymore"""
1513 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001514 data = self._DoReadFile('079_uses_pos.dts')
Simon Glass15a587c2018-07-17 13:25:51 -06001515 self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
1516 "'pos'", str(e.exception))
1517
Simon Glassd178eab2018-09-14 04:57:08 -06001518 def testFillZero(self):
1519 """Test for an fill entry type with a size of 0"""
Simon Glass741f2d62018-10-01 12:22:30 -06001520 data = self._DoReadFile('080_fill_empty.dts')
Simon Glasse6d85ff2019-05-14 15:53:47 -06001521 self.assertEqual(tools.GetBytes(0, 16), data)
Simon Glassd178eab2018-09-14 04:57:08 -06001522
Simon Glass0b489362018-09-14 04:57:09 -06001523 def testTextMissing(self):
1524 """Test for a text entry type where there is no text"""
1525 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001526 self._DoReadFileDtb('066_text.dts',)
Simon Glass0b489362018-09-14 04:57:09 -06001527 self.assertIn("Node '/binman/text': No value provided for text label "
1528 "'test-id'", str(e.exception))
1529
Simon Glass35b384c2018-09-14 04:57:10 -06001530 def testPackStart16Tpl(self):
1531 """Test that an image with an x86 start16 TPL region can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001532 data = self._DoReadFile('081_x86-start16-tpl.dts')
Simon Glass35b384c2018-09-14 04:57:10 -06001533 self.assertEqual(X86_START16_TPL_DATA, data[:len(X86_START16_TPL_DATA)])
1534
Simon Glass0bfa7b02018-09-14 04:57:12 -06001535 def testSelectImage(self):
1536 """Test that we can select which images to build"""
Simon Glasseb833d82019-04-25 21:58:34 -06001537 expected = 'Skipping images: image1'
Simon Glass0bfa7b02018-09-14 04:57:12 -06001538
Simon Glasseb833d82019-04-25 21:58:34 -06001539 # We should only get the expected message in verbose mode
Simon Glassee0c9a72019-07-08 13:18:48 -06001540 for verbosity in (0, 2):
Simon Glasseb833d82019-04-25 21:58:34 -06001541 with test_util.capture_sys_output() as (stdout, stderr):
1542 retcode = self._DoTestFile('006_dual_image.dts',
1543 verbosity=verbosity,
1544 images=['image2'])
1545 self.assertEqual(0, retcode)
1546 if verbosity:
1547 self.assertIn(expected, stdout.getvalue())
1548 else:
1549 self.assertNotIn(expected, stdout.getvalue())
1550
1551 self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
1552 self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
Simon Glass0bfa7b02018-09-14 04:57:12 -06001553
Simon Glass6ed45ba2018-09-14 04:57:24 -06001554 def testUpdateFdtAll(self):
1555 """Test that all device trees are updated with offset/size info"""
Simon Glass3c081312019-07-08 14:25:26 -06001556 data = self._DoReadFileRealDtb('082_fdt_update_all.dts')
Simon Glass6ed45ba2018-09-14 04:57:24 -06001557
1558 base_expected = {
1559 'section:image-pos': 0,
1560 'u-boot-tpl-dtb:size': 513,
1561 'u-boot-spl-dtb:size': 513,
1562 'u-boot-spl-dtb:offset': 493,
1563 'image-pos': 0,
1564 'section/u-boot-dtb:image-pos': 0,
1565 'u-boot-spl-dtb:image-pos': 493,
1566 'section/u-boot-dtb:size': 493,
1567 'u-boot-tpl-dtb:image-pos': 1006,
1568 'section/u-boot-dtb:offset': 0,
1569 'section:size': 493,
1570 'offset': 0,
1571 'section:offset': 0,
1572 'u-boot-tpl-dtb:offset': 1006,
1573 'size': 1519
1574 }
1575
1576 # We expect three device-tree files in the output, one after the other.
1577 # Read them in sequence. We look for an 'spl' property in the SPL tree,
1578 # and 'tpl' in the TPL tree, to make sure they are distinct from the
1579 # main U-Boot tree. All three should have the same postions and offset.
1580 start = 0
1581 for item in ['', 'spl', 'tpl']:
1582 dtb = fdt.Fdt.FromData(data[start:])
1583 dtb.Scan()
1584 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos',
1585 'spl', 'tpl'])
1586 expected = dict(base_expected)
1587 if item:
1588 expected[item] = 0
1589 self.assertEqual(expected, props)
1590 start += dtb._fdt_obj.totalsize()
1591
1592 def testUpdateFdtOutput(self):
1593 """Test that output DTB files are updated"""
1594 try:
Simon Glass741f2d62018-10-01 12:22:30 -06001595 data, dtb_data, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
Simon Glass6ed45ba2018-09-14 04:57:24 -06001596 use_real_dtb=True, update_dtb=True, reset_dtbs=False)
1597
1598 # Unfortunately, compiling a source file always results in a file
1599 # called source.dtb (see fdt_util.EnsureCompiled()). The test
Simon Glass741f2d62018-10-01 12:22:30 -06001600 # source file (e.g. test/075_fdt_update_all.dts) thus does not enter
Simon Glass6ed45ba2018-09-14 04:57:24 -06001601 # binman as a file called u-boot.dtb. To fix this, copy the file
1602 # over to the expected place.
1603 #tools.WriteFile(os.path.join(self._indir, 'u-boot.dtb'),
1604 #tools.ReadFile(tools.GetOutputFilename('source.dtb')))
1605 start = 0
1606 for fname in ['u-boot.dtb.out', 'spl/u-boot-spl.dtb.out',
1607 'tpl/u-boot-tpl.dtb.out']:
1608 dtb = fdt.Fdt.FromData(data[start:])
1609 size = dtb._fdt_obj.totalsize()
1610 pathname = tools.GetOutputFilename(os.path.split(fname)[1])
1611 outdata = tools.ReadFile(pathname)
1612 name = os.path.split(fname)[0]
1613
1614 if name:
1615 orig_indata = self._GetDtbContentsForSplTpl(dtb_data, name)
1616 else:
1617 orig_indata = dtb_data
1618 self.assertNotEqual(outdata, orig_indata,
1619 "Expected output file '%s' be updated" % pathname)
1620 self.assertEqual(outdata, data[start:start + size],
1621 "Expected output file '%s' to match output image" %
1622 pathname)
1623 start += size
1624 finally:
1625 self._ResetDtbs()
1626
Simon Glass83d73c22018-09-14 04:57:26 -06001627 def _decompress(self, data):
Simon Glassff5c7e32019-07-08 13:18:42 -06001628 return tools.Decompress(data, 'lz4')
Simon Glass83d73c22018-09-14 04:57:26 -06001629
1630 def testCompress(self):
1631 """Test compression of blobs"""
Simon Glassac62fba2019-07-08 13:18:53 -06001632 self._CheckLz4()
Simon Glass741f2d62018-10-01 12:22:30 -06001633 data, _, _, out_dtb_fname = self._DoReadFileDtb('083_compress.dts',
Simon Glass83d73c22018-09-14 04:57:26 -06001634 use_real_dtb=True, update_dtb=True)
1635 dtb = fdt.Fdt(out_dtb_fname)
1636 dtb.Scan()
1637 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
1638 orig = self._decompress(data)
1639 self.assertEquals(COMPRESS_DATA, orig)
1640 expected = {
1641 'blob:uncomp-size': len(COMPRESS_DATA),
1642 'blob:size': len(data),
1643 'size': len(data),
1644 }
1645 self.assertEqual(expected, props)
1646
Simon Glass0a98b282018-09-14 04:57:28 -06001647 def testFiles(self):
1648 """Test bringing in multiple files"""
Simon Glass741f2d62018-10-01 12:22:30 -06001649 data = self._DoReadFile('084_files.dts')
Simon Glass0a98b282018-09-14 04:57:28 -06001650 self.assertEqual(FILES_DATA, data)
1651
1652 def testFilesCompress(self):
1653 """Test bringing in multiple files and compressing them"""
Simon Glassac62fba2019-07-08 13:18:53 -06001654 self._CheckLz4()
Simon Glass741f2d62018-10-01 12:22:30 -06001655 data = self._DoReadFile('085_files_compress.dts')
Simon Glass0a98b282018-09-14 04:57:28 -06001656
1657 image = control.images['image']
1658 entries = image.GetEntries()
1659 files = entries['files']
1660 entries = files._section._entries
1661
Simon Glassc6c10e72019-05-17 22:00:46 -06001662 orig = b''
Simon Glass0a98b282018-09-14 04:57:28 -06001663 for i in range(1, 3):
1664 key = '%d.dat' % i
1665 start = entries[key].image_pos
1666 len = entries[key].size
1667 chunk = data[start:start + len]
1668 orig += self._decompress(chunk)
1669
1670 self.assertEqual(FILES_DATA, orig)
1671
1672 def testFilesMissing(self):
1673 """Test missing files"""
1674 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001675 data = self._DoReadFile('086_files_none.dts')
Simon Glass0a98b282018-09-14 04:57:28 -06001676 self.assertIn("Node '/binman/files': Pattern \'files/*.none\' matched "
1677 'no files', str(e.exception))
1678
1679 def testFilesNoPattern(self):
1680 """Test missing files"""
1681 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001682 data = self._DoReadFile('087_files_no_pattern.dts')
Simon Glass0a98b282018-09-14 04:57:28 -06001683 self.assertIn("Node '/binman/files': Missing 'pattern' property",
1684 str(e.exception))
1685
Simon Glassba64a0b2018-09-14 04:57:29 -06001686 def testExpandSize(self):
1687 """Test an expanding entry"""
Simon Glass741f2d62018-10-01 12:22:30 -06001688 data, _, map_data, _ = self._DoReadFileDtb('088_expand_size.dts',
Simon Glassba64a0b2018-09-14 04:57:29 -06001689 map=True)
Simon Glassc6c10e72019-05-17 22:00:46 -06001690 expect = (tools.GetBytes(ord('a'), 8) + U_BOOT_DATA +
1691 MRC_DATA + tools.GetBytes(ord('b'), 1) + U_BOOT_DATA +
1692 tools.GetBytes(ord('c'), 8) + U_BOOT_DATA +
1693 tools.GetBytes(ord('d'), 8))
Simon Glassba64a0b2018-09-14 04:57:29 -06001694 self.assertEqual(expect, data)
1695 self.assertEqual('''ImagePos Offset Size Name
169600000000 00000000 00000028 main-section
169700000000 00000000 00000008 fill
169800000008 00000008 00000004 u-boot
16990000000c 0000000c 00000004 section
17000000000c 00000000 00000003 intel-mrc
170100000010 00000010 00000004 u-boot2
170200000014 00000014 0000000c section2
170300000014 00000000 00000008 fill
17040000001c 00000008 00000004 u-boot
170500000020 00000020 00000008 fill2
1706''', map_data)
1707
1708 def testExpandSizeBad(self):
1709 """Test an expanding entry which fails to provide contents"""
Simon Glass163ed6c2018-09-14 04:57:36 -06001710 with test_util.capture_sys_output() as (stdout, stderr):
1711 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001712 self._DoReadFileDtb('089_expand_size_bad.dts', map=True)
Simon Glassba64a0b2018-09-14 04:57:29 -06001713 self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
1714 'expanding entry', str(e.exception))
1715
Simon Glasse0e5df92018-09-14 04:57:31 -06001716 def testHash(self):
1717 """Test hashing of the contents of an entry"""
Simon Glass741f2d62018-10-01 12:22:30 -06001718 _, _, _, out_dtb_fname = self._DoReadFileDtb('090_hash.dts',
Simon Glasse0e5df92018-09-14 04:57:31 -06001719 use_real_dtb=True, update_dtb=True)
1720 dtb = fdt.Fdt(out_dtb_fname)
1721 dtb.Scan()
1722 hash_node = dtb.GetNode('/binman/u-boot/hash').props['value']
1723 m = hashlib.sha256()
1724 m.update(U_BOOT_DATA)
Simon Glassc6c10e72019-05-17 22:00:46 -06001725 self.assertEqual(m.digest(), b''.join(hash_node.value))
Simon Glasse0e5df92018-09-14 04:57:31 -06001726
1727 def testHashNoAlgo(self):
1728 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001729 self._DoReadFileDtb('091_hash_no_algo.dts', update_dtb=True)
Simon Glasse0e5df92018-09-14 04:57:31 -06001730 self.assertIn("Node \'/binman/u-boot\': Missing \'algo\' property for "
1731 'hash node', str(e.exception))
1732
1733 def testHashBadAlgo(self):
1734 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001735 self._DoReadFileDtb('092_hash_bad_algo.dts', update_dtb=True)
Simon Glasse0e5df92018-09-14 04:57:31 -06001736 self.assertIn("Node '/binman/u-boot': Unknown hash algorithm",
1737 str(e.exception))
1738
1739 def testHashSection(self):
1740 """Test hashing of the contents of an entry"""
Simon Glass741f2d62018-10-01 12:22:30 -06001741 _, _, _, out_dtb_fname = self._DoReadFileDtb('099_hash_section.dts',
Simon Glasse0e5df92018-09-14 04:57:31 -06001742 use_real_dtb=True, update_dtb=True)
1743 dtb = fdt.Fdt(out_dtb_fname)
1744 dtb.Scan()
1745 hash_node = dtb.GetNode('/binman/section/hash').props['value']
1746 m = hashlib.sha256()
1747 m.update(U_BOOT_DATA)
Simon Glassc6c10e72019-05-17 22:00:46 -06001748 m.update(tools.GetBytes(ord('a'), 16))
1749 self.assertEqual(m.digest(), b''.join(hash_node.value))
Simon Glasse0e5df92018-09-14 04:57:31 -06001750
Simon Glassf0253632018-09-14 04:57:32 -06001751 def testPackUBootTplMicrocode(self):
1752 """Test that x86 microcode can be handled correctly in TPL
1753
1754 We expect to see the following in the image, in order:
1755 u-boot-tpl-nodtb.bin with a microcode pointer inserted at the correct
1756 place
1757 u-boot-tpl.dtb with the microcode removed
1758 the microcode
1759 """
Simon Glass1d0ebf72019-05-14 15:53:42 -06001760 with open(self.TestFile('u_boot_ucode_ptr'), 'rb') as fd:
Simon Glassf0253632018-09-14 04:57:32 -06001761 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
Simon Glass741f2d62018-10-01 12:22:30 -06001762 first, pos_and_size = self._RunMicrocodeTest('093_x86_tpl_ucode.dts',
Simon Glassf0253632018-09-14 04:57:32 -06001763 U_BOOT_TPL_NODTB_DATA)
Simon Glassc6c10e72019-05-17 22:00:46 -06001764 self.assertEqual(b'tplnodtb with microc' + pos_and_size +
1765 b'ter somewhere in here', first)
Simon Glassf0253632018-09-14 04:57:32 -06001766
Simon Glassf8f8df62018-09-14 04:57:34 -06001767 def testFmapX86(self):
1768 """Basic test of generation of a flashrom fmap"""
Simon Glass741f2d62018-10-01 12:22:30 -06001769 data = self._DoReadFile('094_fmap_x86.dts')
Simon Glassf8f8df62018-09-14 04:57:34 -06001770 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
Simon Glassc6c10e72019-05-17 22:00:46 -06001771 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('a'), 32 - 7)
Simon Glassf8f8df62018-09-14 04:57:34 -06001772 self.assertEqual(expected, data[:32])
1773 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1774
1775 self.assertEqual(0x100, fhdr.image_size)
1776
1777 self.assertEqual(0, fentries[0].offset)
1778 self.assertEqual(4, fentries[0].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001779 self.assertEqual(b'U_BOOT', fentries[0].name)
Simon Glassf8f8df62018-09-14 04:57:34 -06001780
1781 self.assertEqual(4, fentries[1].offset)
1782 self.assertEqual(3, fentries[1].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001783 self.assertEqual(b'INTEL_MRC', fentries[1].name)
Simon Glassf8f8df62018-09-14 04:57:34 -06001784
1785 self.assertEqual(32, fentries[2].offset)
1786 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1787 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001788 self.assertEqual(b'FMAP', fentries[2].name)
Simon Glassf8f8df62018-09-14 04:57:34 -06001789
1790 def testFmapX86Section(self):
1791 """Basic test of generation of a flashrom fmap"""
Simon Glass741f2d62018-10-01 12:22:30 -06001792 data = self._DoReadFile('095_fmap_x86_section.dts')
Simon Glassc6c10e72019-05-17 22:00:46 -06001793 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('b'), 32 - 7)
Simon Glassf8f8df62018-09-14 04:57:34 -06001794 self.assertEqual(expected, data[:32])
1795 fhdr, fentries = fmap_util.DecodeFmap(data[36:])
1796
1797 self.assertEqual(0x100, fhdr.image_size)
1798
1799 self.assertEqual(0, fentries[0].offset)
1800 self.assertEqual(4, fentries[0].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001801 self.assertEqual(b'U_BOOT', fentries[0].name)
Simon Glassf8f8df62018-09-14 04:57:34 -06001802
1803 self.assertEqual(4, fentries[1].offset)
1804 self.assertEqual(3, fentries[1].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001805 self.assertEqual(b'INTEL_MRC', fentries[1].name)
Simon Glassf8f8df62018-09-14 04:57:34 -06001806
1807 self.assertEqual(36, fentries[2].offset)
1808 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1809 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
Simon Glassc6c10e72019-05-17 22:00:46 -06001810 self.assertEqual(b'FMAP', fentries[2].name)
Simon Glassf8f8df62018-09-14 04:57:34 -06001811
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001812 def testElf(self):
1813 """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 Glass4c650252019-07-08 13:18:46 -06001816 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1817 with open(self.TestFile('bss_data'), 'rb') as fd:
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001818 TestFunctional._MakeInputFile('-boot', fd.read())
Simon Glass741f2d62018-10-01 12:22:30 -06001819 data = self._DoReadFile('096_elf.dts')
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001820
Simon Glass093d1682019-07-08 13:18:25 -06001821 def testElfStrip(self):
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001822 """Basic test of ELF entries"""
Simon Glass11ae93e2018-10-01 21:12:47 -06001823 self._SetupSplElf()
Simon Glass1d0ebf72019-05-14 15:53:42 -06001824 with open(self.TestFile('bss_data'), 'rb') as fd:
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001825 TestFunctional._MakeInputFile('-boot', fd.read())
Simon Glass741f2d62018-10-01 12:22:30 -06001826 data = self._DoReadFile('097_elf_strip.dts')
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001827
Simon Glass163ed6c2018-09-14 04:57:36 -06001828 def testPackOverlapMap(self):
1829 """Test that overlapping regions are detected"""
1830 with test_util.capture_sys_output() as (stdout, stderr):
1831 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001832 self._DoTestFile('014_pack_overlap.dts', map=True)
Simon Glass163ed6c2018-09-14 04:57:36 -06001833 map_fname = tools.GetOutputFilename('image.map')
1834 self.assertEqual("Wrote map file '%s' to show errors\n" % map_fname,
1835 stdout.getvalue())
1836
1837 # We should not get an inmage, but there should be a map file
1838 self.assertFalse(os.path.exists(tools.GetOutputFilename('image.bin')))
1839 self.assertTrue(os.path.exists(map_fname))
Simon Glasseb546ac2019-05-17 22:00:51 -06001840 map_data = tools.ReadFile(map_fname, binary=False)
Simon Glass163ed6c2018-09-14 04:57:36 -06001841 self.assertEqual('''ImagePos Offset Size Name
1842<none> 00000000 00000007 main-section
1843<none> 00000000 00000004 u-boot
1844<none> 00000003 00000004 u-boot-align
1845''', map_data)
1846
Simon Glass093d1682019-07-08 13:18:25 -06001847 def testPackRefCode(self):
Simon Glass3ae192c2018-10-01 12:22:31 -06001848 """Test that an image with an Intel Reference code binary works"""
1849 data = self._DoReadFile('100_intel_refcode.dts')
1850 self.assertEqual(REFCODE_DATA, data[:len(REFCODE_DATA)])
1851
Simon Glass9481c802019-04-25 21:58:39 -06001852 def testSectionOffset(self):
1853 """Tests use of a section with an offset"""
1854 data, _, map_data, _ = self._DoReadFileDtb('101_sections_offset.dts',
1855 map=True)
1856 self.assertEqual('''ImagePos Offset Size Name
185700000000 00000000 00000038 main-section
185800000004 00000004 00000010 section@0
185900000004 00000000 00000004 u-boot
186000000018 00000018 00000010 section@1
186100000018 00000000 00000004 u-boot
18620000002c 0000002c 00000004 section@2
18630000002c 00000000 00000004 u-boot
1864''', map_data)
1865 self.assertEqual(data,
Simon Glasse6d85ff2019-05-14 15:53:47 -06001866 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1867 tools.GetBytes(0x21, 12) +
1868 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1869 tools.GetBytes(0x61, 12) +
1870 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1871 tools.GetBytes(0x26, 8))
Simon Glass9481c802019-04-25 21:58:39 -06001872
Simon Glassac62fba2019-07-08 13:18:53 -06001873 def testCbfsRaw(self):
1874 """Test base handling of a Coreboot Filesystem (CBFS)
1875
1876 The exact contents of the CBFS is verified by similar tests in
1877 cbfs_util_test.py. The tests here merely check that the files added to
1878 the CBFS can be found in the final image.
1879 """
1880 data = self._DoReadFile('102_cbfs_raw.dts')
1881 size = 0xb0
1882
1883 cbfs = cbfs_util.CbfsReader(data)
1884 self.assertEqual(size, cbfs.rom_size)
1885
1886 self.assertIn('u-boot-dtb', cbfs.files)
1887 cfile = cbfs.files['u-boot-dtb']
1888 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
1889
1890 def testCbfsArch(self):
1891 """Test on non-x86 architecture"""
1892 data = self._DoReadFile('103_cbfs_raw_ppc.dts')
1893 size = 0x100
1894
1895 cbfs = cbfs_util.CbfsReader(data)
1896 self.assertEqual(size, cbfs.rom_size)
1897
1898 self.assertIn('u-boot-dtb', cbfs.files)
1899 cfile = cbfs.files['u-boot-dtb']
1900 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
1901
1902 def testCbfsStage(self):
1903 """Tests handling of a Coreboot Filesystem (CBFS)"""
1904 if not elf.ELF_TOOLS:
1905 self.skipTest('Python elftools not available')
1906 elf_fname = os.path.join(self._indir, 'cbfs-stage.elf')
1907 elf.MakeElf(elf_fname, U_BOOT_DATA, U_BOOT_DTB_DATA)
1908 size = 0xb0
1909
1910 data = self._DoReadFile('104_cbfs_stage.dts')
1911 cbfs = cbfs_util.CbfsReader(data)
1912 self.assertEqual(size, cbfs.rom_size)
1913
1914 self.assertIn('u-boot', cbfs.files)
1915 cfile = cbfs.files['u-boot']
1916 self.assertEqual(U_BOOT_DATA + U_BOOT_DTB_DATA, cfile.data)
1917
1918 def testCbfsRawCompress(self):
1919 """Test handling of compressing raw files"""
1920 self._CheckLz4()
1921 data = self._DoReadFile('105_cbfs_raw_compress.dts')
1922 size = 0x140
1923
1924 cbfs = cbfs_util.CbfsReader(data)
1925 self.assertIn('u-boot', cbfs.files)
1926 cfile = cbfs.files['u-boot']
1927 self.assertEqual(COMPRESS_DATA, cfile.data)
1928
1929 def testCbfsBadArch(self):
1930 """Test handling of a bad architecture"""
1931 with self.assertRaises(ValueError) as e:
1932 self._DoReadFile('106_cbfs_bad_arch.dts')
1933 self.assertIn("Invalid architecture 'bad-arch'", str(e.exception))
1934
1935 def testCbfsNoSize(self):
1936 """Test handling of a missing size property"""
1937 with self.assertRaises(ValueError) as e:
1938 self._DoReadFile('107_cbfs_no_size.dts')
1939 self.assertIn('entry must have a size property', str(e.exception))
1940
1941 def testCbfsNoCOntents(self):
1942 """Test handling of a CBFS entry which does not provide contentsy"""
1943 with self.assertRaises(ValueError) as e:
1944 self._DoReadFile('108_cbfs_no_contents.dts')
1945 self.assertIn('Could not complete processing of contents',
1946 str(e.exception))
1947
1948 def testCbfsBadCompress(self):
1949 """Test handling of a bad architecture"""
1950 with self.assertRaises(ValueError) as e:
1951 self._DoReadFile('109_cbfs_bad_compress.dts')
1952 self.assertIn("Invalid compression in 'u-boot': 'invalid-algo'",
1953 str(e.exception))
1954
1955 def testCbfsNamedEntries(self):
1956 """Test handling of named entries"""
1957 data = self._DoReadFile('110_cbfs_name.dts')
1958
1959 cbfs = cbfs_util.CbfsReader(data)
1960 self.assertIn('FRED', cbfs.files)
1961 cfile1 = cbfs.files['FRED']
1962 self.assertEqual(U_BOOT_DATA, cfile1.data)
1963
1964 self.assertIn('hello', cbfs.files)
1965 cfile2 = cbfs.files['hello']
1966 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
1967
Simon Glassc5ac1382019-07-08 13:18:54 -06001968 def _SetupIfwi(self, fname):
1969 """Set up to run an IFWI test
1970
1971 Args:
1972 fname: Filename of input file to provide (fitimage.bin or ifwi.bin)
1973 """
1974 self._SetupSplElf()
1975
1976 # Intel Integrated Firmware Image (IFWI) file
1977 with gzip.open(self.TestFile('%s.gz' % fname), 'rb') as fd:
1978 data = fd.read()
1979 TestFunctional._MakeInputFile(fname,data)
1980
1981 def _CheckIfwi(self, data):
1982 """Check that an image with an IFWI contains the correct output
1983
1984 Args:
1985 data: Conents of output file
1986 """
1987 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
1988 if data[:0x1000] != expected_desc:
1989 self.fail('Expected descriptor binary at start of image')
1990
1991 # We expect to find the TPL wil in subpart IBBP entry IBBL
1992 image_fname = tools.GetOutputFilename('image.bin')
1993 tpl_fname = tools.GetOutputFilename('tpl.out')
1994 tools.RunIfwiTool(image_fname, tools.CMD_EXTRACT, fname=tpl_fname,
1995 subpart='IBBP', entry_name='IBBL')
1996
1997 tpl_data = tools.ReadFile(tpl_fname)
1998 self.assertEqual(tpl_data[:len(U_BOOT_TPL_DATA)], U_BOOT_TPL_DATA)
1999
2000 def testPackX86RomIfwi(self):
2001 """Test that an x86 ROM with Integrated Firmware Image can be created"""
2002 self._SetupIfwi('fitimage.bin')
2003 data = self._DoReadFile('111_x86-rom-ifwi.dts')
2004 self._CheckIfwi(data)
2005
2006 def testPackX86RomIfwiNoDesc(self):
2007 """Test that an x86 ROM with IFWI can be created from an ifwi.bin file"""
2008 self._SetupIfwi('ifwi.bin')
2009 data = self._DoReadFile('112_x86-rom-ifwi-nodesc.dts')
2010 self._CheckIfwi(data)
2011
2012 def testPackX86RomIfwiNoData(self):
2013 """Test that an x86 ROM with IFWI handles missing data"""
2014 self._SetupIfwi('ifwi.bin')
2015 with self.assertRaises(ValueError) as e:
2016 data = self._DoReadFile('113_x86-rom-ifwi-nodata.dts')
2017 self.assertIn('Could not complete processing of contents',
2018 str(e.exception))
Simon Glass53af22a2018-07-17 13:25:32 -06002019
Simon Glasse073d4e2019-07-08 13:18:56 -06002020 def testCbfsOffset(self):
2021 """Test a CBFS with files at particular offsets
2022
2023 Like all CFBS tests, this is just checking the logic that calls
2024 cbfs_util. See cbfs_util_test for fully tests (e.g. test_cbfs_offset()).
2025 """
2026 data = self._DoReadFile('114_cbfs_offset.dts')
2027 size = 0x200
2028
2029 cbfs = cbfs_util.CbfsReader(data)
2030 self.assertEqual(size, cbfs.rom_size)
2031
2032 self.assertIn('u-boot', cbfs.files)
2033 cfile = cbfs.files['u-boot']
2034 self.assertEqual(U_BOOT_DATA, cfile.data)
2035 self.assertEqual(0x40, cfile.cbfs_offset)
2036
2037 self.assertIn('u-boot-dtb', cbfs.files)
2038 cfile2 = cbfs.files['u-boot-dtb']
2039 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
2040 self.assertEqual(0x140, cfile2.cbfs_offset)
2041
Simon Glass086cec92019-07-08 14:25:27 -06002042 def testFdtmap(self):
2043 """Test an FDT map can be inserted in the image"""
2044 data = self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
2045 fdtmap_data = data[len(U_BOOT_DATA):]
2046 magic = fdtmap_data[:8]
2047 self.assertEqual('_FDTMAP_', magic)
2048 self.assertEqual(tools.GetBytes(0, 8), fdtmap_data[8:16])
2049
2050 fdt_data = fdtmap_data[16:]
2051 dtb = fdt.Fdt.FromData(fdt_data)
2052 dtb.Scan()
2053 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'],
2054 prefix='/')
2055 self.assertEqual({
2056 'image-pos': 0,
2057 'offset': 0,
2058 'u-boot:offset': 0,
2059 'u-boot:size': len(U_BOOT_DATA),
2060 'u-boot:image-pos': 0,
2061 'fdtmap:image-pos': 4,
2062 'fdtmap:offset': 4,
2063 'fdtmap:size': len(fdtmap_data),
2064 'size': len(data),
2065 }, props)
2066
2067 def testFdtmapNoMatch(self):
2068 """Check handling of an FDT map when the section cannot be found"""
2069 self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
2070
2071 # Mangle the section name, which should cause a mismatch between the
2072 # correct FDT path and the one expected by the section
2073 image = control.images['image']
Simon Glasscf228942019-07-08 14:25:28 -06002074 image._node.path += '-suffix'
Simon Glass086cec92019-07-08 14:25:27 -06002075 entries = image.GetEntries()
2076 fdtmap = entries['fdtmap']
2077 with self.assertRaises(ValueError) as e:
2078 fdtmap._GetFdtmap()
2079 self.assertIn("Cannot locate node for path '/binman-suffix'",
2080 str(e.exception))
2081
Simon Glasscf228942019-07-08 14:25:28 -06002082 def testFdtmapHeader(self):
2083 """Test an FDT map and image header can be inserted in the image"""
2084 data = self.data = self._DoReadFileRealDtb('116_fdtmap_hdr.dts')
2085 fdtmap_pos = len(U_BOOT_DATA)
2086 fdtmap_data = data[fdtmap_pos:]
2087 fdt_data = fdtmap_data[16:]
2088 dtb = fdt.Fdt.FromData(fdt_data)
2089 fdt_size = dtb.GetFdtObj().totalsize()
2090 hdr_data = data[-8:]
2091 self.assertEqual('BinM', hdr_data[:4])
2092 offset = struct.unpack('<I', hdr_data[4:])[0] & 0xffffffff
2093 self.assertEqual(fdtmap_pos - 0x400, offset - (1 << 32))
2094
2095 def testFdtmapHeaderStart(self):
2096 """Test an image header can be inserted at the image start"""
2097 data = self.data = self._DoReadFileRealDtb('117_fdtmap_hdr_start.dts')
2098 fdtmap_pos = 0x100 + len(U_BOOT_DATA)
2099 hdr_data = data[:8]
2100 self.assertEqual('BinM', hdr_data[:4])
2101 offset = struct.unpack('<I', hdr_data[4:])[0]
2102 self.assertEqual(fdtmap_pos, offset)
2103
2104 def testFdtmapHeaderPos(self):
2105 """Test an image header can be inserted at a chosen position"""
2106 data = self.data = self._DoReadFileRealDtb('118_fdtmap_hdr_pos.dts')
2107 fdtmap_pos = 0x100 + len(U_BOOT_DATA)
2108 hdr_data = data[0x80:0x88]
2109 self.assertEqual('BinM', hdr_data[:4])
2110 offset = struct.unpack('<I', hdr_data[4:])[0]
2111 self.assertEqual(fdtmap_pos, offset)
2112
2113 def testHeaderMissingFdtmap(self):
2114 """Test an image header requires an fdtmap"""
2115 with self.assertRaises(ValueError) as e:
2116 self.data = self._DoReadFileRealDtb('119_fdtmap_hdr_missing.dts')
2117 self.assertIn("'image_header' section must have an 'fdtmap' sibling",
2118 str(e.exception))
2119
2120 def testHeaderNoLocation(self):
2121 """Test an image header with a no specified location is detected"""
2122 with self.assertRaises(ValueError) as e:
2123 self.data = self._DoReadFileRealDtb('120_hdr_no_location.dts')
2124 self.assertIn("Invalid location 'None', expected 'start' or 'end'",
2125 str(e.exception))
2126
Simon Glassc52c9e72019-07-08 14:25:37 -06002127 def testEntryExpand(self):
2128 """Test expanding an entry after it is packed"""
2129 data = self._DoReadFile('121_entry_expand.dts')
2130 self.assertEqual(b'aa', data[:2])
2131 self.assertEqual(U_BOOT_DATA, data[2:2 + len(U_BOOT_DATA)])
2132 self.assertEqual(b'aa', data[-2:])
2133
2134 def testEntryExpandBad(self):
2135 """Test expanding an entry after it is packed, twice"""
2136 with self.assertRaises(ValueError) as e:
2137 self._DoReadFile('122_entry_expand_twice.dts')
2138 self.assertIn("Image '/binman': Entries expanded after packing",
2139 str(e.exception))
2140
2141 def testEntryExpandSection(self):
2142 """Test expanding an entry within a section after it is packed"""
2143 data = self._DoReadFile('123_entry_expand_section.dts')
2144 self.assertEqual(b'aa', data[:2])
2145 self.assertEqual(U_BOOT_DATA, data[2:2 + len(U_BOOT_DATA)])
2146 self.assertEqual(b'aa', data[-2:])
2147
Simon Glass6c223fd2019-07-08 14:25:38 -06002148 def testCompressDtb(self):
2149 """Test that compress of device-tree files is supported"""
2150 self._CheckLz4()
2151 data = self.data = self._DoReadFileRealDtb('124_compress_dtb.dts')
2152 self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
2153 comp_data = data[len(U_BOOT_DATA):]
2154 orig = self._decompress(comp_data)
2155 dtb = fdt.Fdt.FromData(orig)
2156 dtb.Scan()
2157 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
2158 expected = {
2159 'u-boot:size': len(U_BOOT_DATA),
2160 'u-boot-dtb:uncomp-size': len(orig),
2161 'u-boot-dtb:size': len(comp_data),
2162 'size': len(data),
2163 }
2164 self.assertEqual(expected, props)
2165
Simon Glass69f7cb32019-07-08 14:25:41 -06002166 def testCbfsUpdateFdt(self):
2167 """Test that we can update the device tree with CBFS offset/size info"""
2168 self._CheckLz4()
2169 data, _, _, out_dtb_fname = self._DoReadFileDtb('125_cbfs_update.dts',
2170 update_dtb=True)
2171 dtb = fdt.Fdt(out_dtb_fname)
2172 dtb.Scan()
2173 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos',
2174 'uncomp-size'])
2175 del props['cbfs/u-boot:size']
2176 self.assertEqual({
2177 'offset': 0,
2178 'size': len(data),
2179 'image-pos': 0,
2180 'cbfs:offset': 0,
2181 'cbfs:size': len(data),
2182 'cbfs:image-pos': 0,
2183 'cbfs/u-boot:offset': 0x38,
2184 'cbfs/u-boot:uncomp-size': len(U_BOOT_DATA),
2185 'cbfs/u-boot:image-pos': 0x38,
2186 'cbfs/u-boot-dtb:offset': 0xb8,
2187 'cbfs/u-boot-dtb:size': len(U_BOOT_DATA),
2188 'cbfs/u-boot-dtb:image-pos': 0xb8,
2189 }, props)
2190
Simon Glass8a1ad062019-07-08 14:25:42 -06002191 def testCbfsBadType(self):
2192 """Test an image header with a no specified location is detected"""
2193 with self.assertRaises(ValueError) as e:
2194 self._DoReadFile('126_cbfs_bad_type.dts')
2195 self.assertIn("Unknown cbfs-type 'badtype'", str(e.exception))
2196
Simon Glass41b8ba02019-07-08 14:25:43 -06002197 def testList(self):
2198 """Test listing the files in an image"""
2199 self._CheckLz4()
2200 data = self._DoReadFile('127_list.dts')
2201 image = control.images['image']
2202 entries = image.BuildEntryList()
2203 self.assertEqual(7, len(entries))
2204
2205 ent = entries[0]
2206 self.assertEqual(0, ent.indent)
2207 self.assertEqual('main-section', ent.name)
2208 self.assertEqual('section', ent.etype)
2209 self.assertEqual(len(data), ent.size)
2210 self.assertEqual(0, ent.image_pos)
2211 self.assertEqual(None, ent.uncomp_size)
2212 self.assertEqual(None, ent.offset)
2213
2214 ent = entries[1]
2215 self.assertEqual(1, ent.indent)
2216 self.assertEqual('u-boot', ent.name)
2217 self.assertEqual('u-boot', ent.etype)
2218 self.assertEqual(len(U_BOOT_DATA), ent.size)
2219 self.assertEqual(0, ent.image_pos)
2220 self.assertEqual(None, ent.uncomp_size)
2221 self.assertEqual(0, ent.offset)
2222
2223 ent = entries[2]
2224 self.assertEqual(1, ent.indent)
2225 self.assertEqual('section', ent.name)
2226 self.assertEqual('section', ent.etype)
2227 section_size = ent.size
2228 self.assertEqual(0x100, ent.image_pos)
2229 self.assertEqual(None, ent.uncomp_size)
2230 self.assertEqual(len(U_BOOT_DATA), ent.offset)
2231
2232 ent = entries[3]
2233 self.assertEqual(2, ent.indent)
2234 self.assertEqual('cbfs', ent.name)
2235 self.assertEqual('cbfs', ent.etype)
2236 self.assertEqual(0x400, ent.size)
2237 self.assertEqual(0x100, ent.image_pos)
2238 self.assertEqual(None, ent.uncomp_size)
2239 self.assertEqual(0, ent.offset)
2240
2241 ent = entries[4]
2242 self.assertEqual(3, ent.indent)
2243 self.assertEqual('u-boot', ent.name)
2244 self.assertEqual('u-boot', ent.etype)
2245 self.assertEqual(len(U_BOOT_DATA), ent.size)
2246 self.assertEqual(0x138, ent.image_pos)
2247 self.assertEqual(None, ent.uncomp_size)
2248 self.assertEqual(0x38, ent.offset)
2249
2250 ent = entries[5]
2251 self.assertEqual(3, ent.indent)
2252 self.assertEqual('u-boot-dtb', ent.name)
2253 self.assertEqual('text', ent.etype)
2254 self.assertGreater(len(COMPRESS_DATA), ent.size)
2255 self.assertEqual(0x178, ent.image_pos)
2256 self.assertEqual(len(COMPRESS_DATA), ent.uncomp_size)
2257 self.assertEqual(0x78, ent.offset)
2258
2259 ent = entries[6]
2260 self.assertEqual(2, ent.indent)
2261 self.assertEqual('u-boot-dtb', ent.name)
2262 self.assertEqual('u-boot-dtb', ent.etype)
2263 self.assertEqual(0x500, ent.image_pos)
2264 self.assertEqual(len(U_BOOT_DTB_DATA), ent.uncomp_size)
2265 dtb_size = ent.size
2266 # Compressing this data expands it since headers are added
2267 self.assertGreater(dtb_size, len(U_BOOT_DTB_DATA))
2268 self.assertEqual(0x400, ent.offset)
2269
2270 self.assertEqual(len(data), 0x100 + section_size)
2271 self.assertEqual(section_size, 0x400 + dtb_size)
2272
Simon Glasse1925fa2019-07-08 14:25:44 -06002273 def testFindFdtmap(self):
2274 """Test locating an FDT map in an image"""
2275 self._CheckLz4()
2276 data = self.data = self._DoReadFileRealDtb('128_decode_image.dts')
2277 image = control.images['image']
2278 entries = image.GetEntries()
2279 entry = entries['fdtmap']
2280 self.assertEqual(entry.image_pos, fdtmap.LocateFdtmap(data))
2281
2282 def testFindFdtmapMissing(self):
2283 """Test failing to locate an FDP map"""
2284 data = self._DoReadFile('005_simple.dts')
2285 self.assertEqual(None, fdtmap.LocateFdtmap(data))
2286
Simon Glass2d260032019-07-08 14:25:45 -06002287 def testFindImageHeader(self):
2288 """Test locating a image header"""
2289 self._CheckLz4()
Simon Glassffded752019-07-08 14:25:46 -06002290 data = self.data = self._DoReadFileRealDtb('128_decode_image.dts')
Simon Glass2d260032019-07-08 14:25:45 -06002291 image = control.images['image']
2292 entries = image.GetEntries()
2293 entry = entries['fdtmap']
2294 # The header should point to the FDT map
2295 self.assertEqual(entry.image_pos, image_header.LocateHeaderOffset(data))
2296
2297 def testFindImageHeaderStart(self):
2298 """Test locating a image header located at the start of an image"""
Simon Glassffded752019-07-08 14:25:46 -06002299 data = self.data = self._DoReadFileRealDtb('117_fdtmap_hdr_start.dts')
Simon Glass2d260032019-07-08 14:25:45 -06002300 image = control.images['image']
2301 entries = image.GetEntries()
2302 entry = entries['fdtmap']
2303 # The header should point to the FDT map
2304 self.assertEqual(entry.image_pos, image_header.LocateHeaderOffset(data))
2305
2306 def testFindImageHeaderMissing(self):
2307 """Test failing to locate an image header"""
2308 data = self._DoReadFile('005_simple.dts')
2309 self.assertEqual(None, image_header.LocateHeaderOffset(data))
2310
Simon Glassffded752019-07-08 14:25:46 -06002311 def testReadImage(self):
2312 """Test reading an image and accessing its FDT map"""
2313 self._CheckLz4()
2314 data = self.data = self._DoReadFileRealDtb('128_decode_image.dts')
2315 image_fname = tools.GetOutputFilename('image.bin')
2316 orig_image = control.images['image']
2317 image = Image.FromFile(image_fname)
2318 self.assertEqual(orig_image.GetEntries().keys(),
2319 image.GetEntries().keys())
2320
2321 orig_entry = orig_image.GetEntries()['fdtmap']
2322 entry = image.GetEntries()['fdtmap']
2323 self.assertEquals(orig_entry.offset, entry.offset)
2324 self.assertEquals(orig_entry.size, entry.size)
2325 self.assertEquals(orig_entry.image_pos, entry.image_pos)
2326
2327 def testReadImageNoHeader(self):
2328 """Test accessing an image's FDT map without an image header"""
2329 self._CheckLz4()
2330 data = self._DoReadFileRealDtb('129_decode_image_nohdr.dts')
2331 image_fname = tools.GetOutputFilename('image.bin')
2332 image = Image.FromFile(image_fname)
2333 self.assertTrue(isinstance(image, Image))
2334 self.assertEqual('image', image._name)
2335
2336 def testReadImageFail(self):
2337 """Test failing to read an image image's FDT map"""
2338 self._DoReadFile('005_simple.dts')
2339 image_fname = tools.GetOutputFilename('image.bin')
2340 with self.assertRaises(ValueError) as e:
2341 image = Image.FromFile(image_fname)
2342 self.assertIn("Cannot find FDT map in image", str(e.exception))
Simon Glasse073d4e2019-07-08 13:18:56 -06002343
Simon Glass9fc60b42017-11-12 21:52:22 -07002344if __name__ == "__main__":
2345 unittest.main()