blob: 9ef259a699b0bc66333e3dae7690af848576cc45 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001# SPDX-License-Identifier: GPL-2.0+
Simon Glass4f443042016-11-25 20:15:52 -07002# Copyright (c) 2016 Google, Inc
3# Written by Simon Glass <sjg@chromium.org>
4#
Simon Glass4f443042016-11-25 20:15:52 -07005# To run a single test, change to this directory, and:
6#
7# python -m unittest func_test.TestFunctional.testHelp
8
Simon Glasse0e5df92018-09-14 04:57:31 -06009import hashlib
Simon Glass4f443042016-11-25 20:15:52 -070010from optparse import OptionParser
11import os
12import shutil
13import struct
14import sys
15import tempfile
16import unittest
17
18import binman
19import cmdline
20import command
21import control
Simon Glass19790632017-11-13 18:55:01 -070022import elf
Simon Glass99ed4a22017-05-27 07:38:30 -060023import fdt
Simon Glass4f443042016-11-25 20:15:52 -070024import fdt_util
Simon Glass11e36cc2018-07-17 13:25:38 -060025import fmap_util
Simon Glassfd8d1f72018-07-17 13:25:36 -060026import test_util
Simon Glassc55a50f2018-09-14 04:57:19 -060027import state
Simon Glass4f443042016-11-25 20:15:52 -070028import tools
29import tout
30
31# Contents of test files, corresponding to different entry types
Simon Glass6b187df2017-11-12 21:52:27 -070032U_BOOT_DATA = '1234'
33U_BOOT_IMG_DATA = 'img'
Simon Glassf6898902017-11-13 18:54:59 -070034U_BOOT_SPL_DATA = '56780123456789abcde'
Simon Glassb8ef5b62018-07-17 13:25:48 -060035U_BOOT_TPL_DATA = 'tpl'
Simon Glass6b187df2017-11-12 21:52:27 -070036BLOB_DATA = '89'
37ME_DATA = '0abcd'
38VGA_DATA = 'vga'
39U_BOOT_DTB_DATA = 'udtb'
Simon Glass47419ea2017-11-13 18:54:55 -070040U_BOOT_SPL_DTB_DATA = 'spldtb'
Simon Glassb8ef5b62018-07-17 13:25:48 -060041U_BOOT_TPL_DTB_DATA = 'tpldtb'
Simon Glass6b187df2017-11-12 21:52:27 -070042X86_START16_DATA = 'start16'
43X86_START16_SPL_DATA = 'start16spl'
Simon Glass35b384c2018-09-14 04:57:10 -060044X86_START16_TPL_DATA = 'start16tpl'
Jagdish Gediya9d368f32018-09-03 21:35:08 +053045PPC_MPC85XX_BR_DATA = 'ppcmpc85xxbr'
Simon Glass6b187df2017-11-12 21:52:27 -070046U_BOOT_NODTB_DATA = 'nodtb with microcode pointer somewhere in here'
47U_BOOT_SPL_NODTB_DATA = 'splnodtb with microcode pointer somewhere in here'
Simon Glassf0253632018-09-14 04:57:32 -060048U_BOOT_TPL_NODTB_DATA = 'tplnodtb with microcode pointer somewhere in here'
Simon Glass6b187df2017-11-12 21:52:27 -070049FSP_DATA = 'fsp'
50CMC_DATA = 'cmc'
51VBT_DATA = 'vbt'
Simon Glassca4f4ff2017-11-12 21:52:28 -070052MRC_DATA = 'mrc'
Simon Glassbb748372018-07-17 13:25:33 -060053TEXT_DATA = 'text'
54TEXT_DATA2 = 'text2'
55TEXT_DATA3 = 'text3'
Simon Glassec127af2018-07-17 13:25:39 -060056CROS_EC_RW_DATA = 'ecrw'
Simon Glass0ef87aa2018-07-17 13:25:44 -060057GBB_DATA = 'gbbd'
58BMPBLK_DATA = 'bmp'
Simon Glass24d0d3c2018-07-17 13:25:47 -060059VBLOCK_DATA = 'vblk'
Simon Glass0a98b282018-09-14 04:57:28 -060060FILES_DATA = ("sorry I'm late\nOh, don't bother apologising, I'm " +
61 "sorry you're alive\n")
Simon Glass83d73c22018-09-14 04:57:26 -060062COMPRESS_DATA = 'data to compress'
Simon Glassec127af2018-07-17 13:25:39 -060063
Simon Glass4f443042016-11-25 20:15:52 -070064
65class TestFunctional(unittest.TestCase):
66 """Functional tests for binman
67
68 Most of these use a sample .dts file to build an image and then check
69 that it looks correct. The sample files are in the test/ subdirectory
70 and are numbered.
71
72 For each entry type a very small test file is created using fixed
73 string contents. This makes it easy to test that things look right, and
74 debug problems.
75
76 In some cases a 'real' file must be used - these are also supplied in
77 the test/ diurectory.
78 """
79 @classmethod
80 def setUpClass(self):
Simon Glass4d5994f2017-11-12 21:52:20 -070081 global entry
82 import entry
83
Simon Glass4f443042016-11-25 20:15:52 -070084 # Handle the case where argv[0] is 'python'
85 self._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
86 self._binman_pathname = os.path.join(self._binman_dir, 'binman')
87
88 # Create a temporary directory for input files
89 self._indir = tempfile.mkdtemp(prefix='binmant.')
90
91 # Create some test files
92 TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
93 TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
94 TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
Simon Glassb8ef5b62018-07-17 13:25:48 -060095 TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
Simon Glass4f443042016-11-25 20:15:52 -070096 TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
Simon Glasse0ff8552016-11-25 20:15:53 -070097 TestFunctional._MakeInputFile('me.bin', ME_DATA)
98 TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
Simon Glassb8ef5b62018-07-17 13:25:48 -060099 self._ResetDtbs()
Simon Glasse0ff8552016-11-25 20:15:53 -0700100 TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
Jagdish Gediya9d368f32018-09-03 21:35:08 +0530101 TestFunctional._MakeInputFile('u-boot-br.bin', PPC_MPC85XX_BR_DATA)
Simon Glass87722132017-11-12 21:52:26 -0700102 TestFunctional._MakeInputFile('spl/u-boot-x86-16bit-spl.bin',
103 X86_START16_SPL_DATA)
Simon Glass35b384c2018-09-14 04:57:10 -0600104 TestFunctional._MakeInputFile('tpl/u-boot-x86-16bit-tpl.bin',
105 X86_START16_TPL_DATA)
Simon Glass4f443042016-11-25 20:15:52 -0700106 TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
Simon Glass6b187df2017-11-12 21:52:27 -0700107 TestFunctional._MakeInputFile('spl/u-boot-spl-nodtb.bin',
108 U_BOOT_SPL_NODTB_DATA)
Simon Glassf0253632018-09-14 04:57:32 -0600109 TestFunctional._MakeInputFile('tpl/u-boot-tpl-nodtb.bin',
110 U_BOOT_TPL_NODTB_DATA)
Simon Glassda229092016-11-25 20:15:56 -0700111 TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
112 TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
Bin Meng59ea8c22017-08-15 22:41:54 -0700113 TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
Simon Glassca4f4ff2017-11-12 21:52:28 -0700114 TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
Simon Glassec127af2018-07-17 13:25:39 -0600115 TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
Simon Glass0ef87aa2018-07-17 13:25:44 -0600116 TestFunctional._MakeInputDir('devkeys')
117 TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
Simon Glass4f443042016-11-25 20:15:52 -0700118
Simon Glasse0ff8552016-11-25 20:15:53 -0700119 # ELF file with a '_dt_ucode_base_size' symbol
120 with open(self.TestFile('u_boot_ucode_ptr')) as fd:
121 TestFunctional._MakeInputFile('u-boot', fd.read())
122
123 # Intel flash descriptor file
124 with open(self.TestFile('descriptor.bin')) as fd:
125 TestFunctional._MakeInputFile('descriptor.bin', fd.read())
126
Simon Glass0a98b282018-09-14 04:57:28 -0600127 shutil.copytree(self.TestFile('files'),
128 os.path.join(self._indir, 'files'))
129
Simon Glass83d73c22018-09-14 04:57:26 -0600130 TestFunctional._MakeInputFile('compress', COMPRESS_DATA)
131
Simon Glass4f443042016-11-25 20:15:52 -0700132 @classmethod
133 def tearDownClass(self):
134 """Remove the temporary input directory and its contents"""
135 if self._indir:
136 shutil.rmtree(self._indir)
137 self._indir = None
138
139 def setUp(self):
140 # Enable this to turn on debugging output
141 # tout.Init(tout.DEBUG)
142 command.test_result = None
143
144 def tearDown(self):
145 """Remove the temporary output directory"""
146 tools._FinaliseForTest()
147
Simon Glassb8ef5b62018-07-17 13:25:48 -0600148 @classmethod
149 def _ResetDtbs(self):
150 TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
151 TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
152 TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
153
Simon Glass4f443042016-11-25 20:15:52 -0700154 def _RunBinman(self, *args, **kwargs):
155 """Run binman using the command line
156
157 Args:
158 Arguments to pass, as a list of strings
159 kwargs: Arguments to pass to Command.RunPipe()
160 """
161 result = command.RunPipe([[self._binman_pathname] + list(args)],
162 capture=True, capture_stderr=True, raise_on_error=False)
163 if result.return_code and kwargs.get('raise_on_error', True):
164 raise Exception("Error running '%s': %s" % (' '.join(args),
165 result.stdout + result.stderr))
166 return result
167
168 def _DoBinman(self, *args):
169 """Run binman using directly (in the same process)
170
171 Args:
172 Arguments to pass, as a list of strings
173 Returns:
174 Return value (0 for success)
175 """
Simon Glass7fe91732017-11-13 18:55:00 -0700176 args = list(args)
177 if '-D' in sys.argv:
178 args = args + ['-D']
179 (options, args) = cmdline.ParseArgs(args)
Simon Glass4f443042016-11-25 20:15:52 -0700180 options.pager = 'binman-invalid-pager'
181 options.build_dir = self._indir
182
183 # For testing, you can force an increase in verbosity here
184 # options.verbosity = tout.DEBUG
185 return control.Binman(options, args)
186
Simon Glass53af22a2018-07-17 13:25:32 -0600187 def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
Simon Glass93d17412018-09-14 04:57:23 -0600188 entry_args=None, images=None, use_real_dtb=False):
Simon Glass4f443042016-11-25 20:15:52 -0700189 """Run binman with a given test file
190
191 Args:
Simon Glass7ae5f312018-06-01 09:38:19 -0600192 fname: Device-tree source filename to use (e.g. 05_simple.dts)
193 debug: True to enable debugging output
Simon Glass3b0c3822018-06-01 09:38:20 -0600194 map: True to output map files for the images
Simon Glass3ab95982018-08-01 15:22:37 -0600195 update_dtb: Update the offset and size of each entry in the device
Simon Glass16b8d6b2018-07-06 10:27:42 -0600196 tree before packing it into the image
Simon Glass0bfa7b02018-09-14 04:57:12 -0600197 entry_args: Dict of entry args to supply to binman
198 key: arg name
199 value: value of that arg
200 images: List of image names to build
Simon Glass4f443042016-11-25 20:15:52 -0700201 """
Simon Glass7fe91732017-11-13 18:55:00 -0700202 args = ['-p', '-I', self._indir, '-d', self.TestFile(fname)]
203 if debug:
204 args.append('-D')
Simon Glass3b0c3822018-06-01 09:38:20 -0600205 if map:
206 args.append('-m')
Simon Glass16b8d6b2018-07-06 10:27:42 -0600207 if update_dtb:
208 args.append('-up')
Simon Glass93d17412018-09-14 04:57:23 -0600209 if not use_real_dtb:
210 args.append('--fake-dtb')
Simon Glass53af22a2018-07-17 13:25:32 -0600211 if entry_args:
212 for arg, value in entry_args.iteritems():
213 args.append('-a%s=%s' % (arg, value))
Simon Glass0bfa7b02018-09-14 04:57:12 -0600214 if images:
215 for image in images:
216 args += ['-i', image]
Simon Glass7fe91732017-11-13 18:55:00 -0700217 return self._DoBinman(*args)
Simon Glass4f443042016-11-25 20:15:52 -0700218
219 def _SetupDtb(self, fname, outfile='u-boot.dtb'):
Simon Glasse0ff8552016-11-25 20:15:53 -0700220 """Set up a new test device-tree file
221
222 The given file is compiled and set up as the device tree to be used
223 for ths test.
224
225 Args:
226 fname: Filename of .dts file to read
Simon Glass7ae5f312018-06-01 09:38:19 -0600227 outfile: Output filename for compiled device-tree binary
Simon Glasse0ff8552016-11-25 20:15:53 -0700228
229 Returns:
Simon Glass7ae5f312018-06-01 09:38:19 -0600230 Contents of device-tree binary
Simon Glasse0ff8552016-11-25 20:15:53 -0700231 """
Simon Glasse0e62752018-10-01 21:12:41 -0600232 tools.PrepareOutputDir(None)
Simon Glass4f443042016-11-25 20:15:52 -0700233 dtb = fdt_util.EnsureCompiled(self.TestFile(fname))
234 with open(dtb) as fd:
235 data = fd.read()
236 TestFunctional._MakeInputFile(outfile, data)
Simon Glasse0e62752018-10-01 21:12:41 -0600237 tools.FinaliseOutputDir()
238 return data
Simon Glass4f443042016-11-25 20:15:52 -0700239
Simon Glass6ed45ba2018-09-14 04:57:24 -0600240 def _GetDtbContentsForSplTpl(self, dtb_data, name):
241 """Create a version of the main DTB for SPL or SPL
242
243 For testing we don't actually have different versions of the DTB. With
244 U-Boot we normally run fdtgrep to remove unwanted nodes, but for tests
245 we don't normally have any unwanted nodes.
246
247 We still want the DTBs for SPL and TPL to be different though, since
248 otherwise it is confusing to know which one we are looking at. So add
249 an 'spl' or 'tpl' property to the top-level node.
250 """
251 dtb = fdt.Fdt.FromData(dtb_data)
252 dtb.Scan()
253 dtb.GetNode('/binman').AddZeroProp(name)
254 dtb.Sync(auto_resize=True)
255 dtb.Pack()
256 return dtb.GetContents()
257
Simon Glass16b8d6b2018-07-06 10:27:42 -0600258 def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
Simon Glass6ed45ba2018-09-14 04:57:24 -0600259 update_dtb=False, entry_args=None, reset_dtbs=True):
Simon Glass4f443042016-11-25 20:15:52 -0700260 """Run binman and return the resulting image
261
262 This runs binman with a given test file and then reads the resulting
263 output file. It is a shortcut function since most tests need to do
264 these steps.
265
266 Raises an assertion failure if binman returns a non-zero exit code.
267
268 Args:
Simon Glass7ae5f312018-06-01 09:38:19 -0600269 fname: Device-tree source filename to use (e.g. 05_simple.dts)
Simon Glass4f443042016-11-25 20:15:52 -0700270 use_real_dtb: True to use the test file as the contents of
271 the u-boot-dtb entry. Normally this is not needed and the
272 test contents (the U_BOOT_DTB_DATA string) can be used.
273 But in some test we need the real contents.
Simon Glass3b0c3822018-06-01 09:38:20 -0600274 map: True to output map files for the images
Simon Glass3ab95982018-08-01 15:22:37 -0600275 update_dtb: Update the offset and size of each entry in the device
Simon Glass16b8d6b2018-07-06 10:27:42 -0600276 tree before packing it into the image
Simon Glasse0ff8552016-11-25 20:15:53 -0700277
278 Returns:
279 Tuple:
280 Resulting image contents
281 Device tree contents
Simon Glass3b0c3822018-06-01 09:38:20 -0600282 Map data showing contents of image (or None if none)
Simon Glassea6922e2018-07-17 13:25:27 -0600283 Output device tree binary filename ('u-boot.dtb' path)
Simon Glass4f443042016-11-25 20:15:52 -0700284 """
Simon Glasse0ff8552016-11-25 20:15:53 -0700285 dtb_data = None
Simon Glass4f443042016-11-25 20:15:52 -0700286 # Use the compiled test file as the u-boot-dtb input
287 if use_real_dtb:
Simon Glasse0ff8552016-11-25 20:15:53 -0700288 dtb_data = self._SetupDtb(fname)
Simon Glass6ed45ba2018-09-14 04:57:24 -0600289 infile = os.path.join(self._indir, 'u-boot.dtb')
290
291 # For testing purposes, make a copy of the DT for SPL and TPL. Add
292 # a node indicating which it is, so aid verification.
293 for name in ['spl', 'tpl']:
294 dtb_fname = '%s/u-boot-%s.dtb' % (name, name)
295 outfile = os.path.join(self._indir, dtb_fname)
296 TestFunctional._MakeInputFile(dtb_fname,
297 self._GetDtbContentsForSplTpl(dtb_data, name))
Simon Glass4f443042016-11-25 20:15:52 -0700298
299 try:
Simon Glass53af22a2018-07-17 13:25:32 -0600300 retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
Simon Glass6ed45ba2018-09-14 04:57:24 -0600301 entry_args=entry_args, use_real_dtb=use_real_dtb)
Simon Glass4f443042016-11-25 20:15:52 -0700302 self.assertEqual(0, retcode)
Simon Glass6ed45ba2018-09-14 04:57:24 -0600303 out_dtb_fname = tools.GetOutputFilename('u-boot.dtb.out')
Simon Glass4f443042016-11-25 20:15:52 -0700304
305 # Find the (only) image, read it and return its contents
306 image = control.images['image']
Simon Glass16b8d6b2018-07-06 10:27:42 -0600307 image_fname = tools.GetOutputFilename('image.bin')
308 self.assertTrue(os.path.exists(image_fname))
Simon Glass3b0c3822018-06-01 09:38:20 -0600309 if map:
310 map_fname = tools.GetOutputFilename('image.map')
311 with open(map_fname) as fd:
312 map_data = fd.read()
313 else:
314 map_data = None
Simon Glass16b8d6b2018-07-06 10:27:42 -0600315 with open(image_fname) as fd:
316 return fd.read(), dtb_data, map_data, out_dtb_fname
Simon Glass4f443042016-11-25 20:15:52 -0700317 finally:
318 # Put the test file back
Simon Glass6ed45ba2018-09-14 04:57:24 -0600319 if reset_dtbs and use_real_dtb:
Simon Glassb8ef5b62018-07-17 13:25:48 -0600320 self._ResetDtbs()
Simon Glass4f443042016-11-25 20:15:52 -0700321
Simon Glasse0ff8552016-11-25 20:15:53 -0700322 def _DoReadFile(self, fname, use_real_dtb=False):
Simon Glass7ae5f312018-06-01 09:38:19 -0600323 """Helper function which discards the device-tree binary
324
325 Args:
326 fname: Device-tree source filename to use (e.g. 05_simple.dts)
327 use_real_dtb: True to use the test file as the contents of
328 the u-boot-dtb entry. Normally this is not needed and the
329 test contents (the U_BOOT_DTB_DATA string) can be used.
330 But in some test we need the real contents.
Simon Glassea6922e2018-07-17 13:25:27 -0600331
332 Returns:
333 Resulting image contents
Simon Glass7ae5f312018-06-01 09:38:19 -0600334 """
Simon Glasse0ff8552016-11-25 20:15:53 -0700335 return self._DoReadFileDtb(fname, use_real_dtb)[0]
336
Simon Glass4f443042016-11-25 20:15:52 -0700337 @classmethod
338 def _MakeInputFile(self, fname, contents):
339 """Create a new test input file, creating directories as needed
340
341 Args:
Simon Glass3ab95982018-08-01 15:22:37 -0600342 fname: Filename to create
Simon Glass4f443042016-11-25 20:15:52 -0700343 contents: File contents to write in to the file
344 Returns:
345 Full pathname of file created
346 """
347 pathname = os.path.join(self._indir, fname)
348 dirname = os.path.dirname(pathname)
349 if dirname and not os.path.exists(dirname):
350 os.makedirs(dirname)
351 with open(pathname, 'wb') as fd:
352 fd.write(contents)
353 return pathname
354
355 @classmethod
Simon Glass0ef87aa2018-07-17 13:25:44 -0600356 def _MakeInputDir(self, dirname):
357 """Create a new test input directory, creating directories as needed
358
359 Args:
360 dirname: Directory name to create
361
362 Returns:
363 Full pathname of directory created
364 """
365 pathname = os.path.join(self._indir, dirname)
366 if not os.path.exists(pathname):
367 os.makedirs(pathname)
368 return pathname
369
370 @classmethod
Simon Glass4f443042016-11-25 20:15:52 -0700371 def TestFile(self, fname):
372 return os.path.join(self._binman_dir, 'test', fname)
373
374 def AssertInList(self, grep_list, target):
375 """Assert that at least one of a list of things is in a target
376
377 Args:
378 grep_list: List of strings to check
379 target: Target string
380 """
381 for grep in grep_list:
382 if grep in target:
383 return
384 self.fail("Error: '%' not found in '%s'" % (grep_list, target))
385
386 def CheckNoGaps(self, entries):
387 """Check that all entries fit together without gaps
388
389 Args:
390 entries: List of entries to check
391 """
Simon Glass3ab95982018-08-01 15:22:37 -0600392 offset = 0
Simon Glass4f443042016-11-25 20:15:52 -0700393 for entry in entries.values():
Simon Glass3ab95982018-08-01 15:22:37 -0600394 self.assertEqual(offset, entry.offset)
395 offset += entry.size
Simon Glass4f443042016-11-25 20:15:52 -0700396
Simon Glasse0ff8552016-11-25 20:15:53 -0700397 def GetFdtLen(self, dtb):
Simon Glass7ae5f312018-06-01 09:38:19 -0600398 """Get the totalsize field from a device-tree binary
Simon Glasse0ff8552016-11-25 20:15:53 -0700399
400 Args:
Simon Glass7ae5f312018-06-01 09:38:19 -0600401 dtb: Device-tree binary contents
Simon Glasse0ff8552016-11-25 20:15:53 -0700402
403 Returns:
Simon Glass7ae5f312018-06-01 09:38:19 -0600404 Total size of device-tree binary, from the header
Simon Glasse0ff8552016-11-25 20:15:53 -0700405 """
406 return struct.unpack('>L', dtb[4:8])[0]
407
Simon Glasscee02e62018-07-17 13:25:52 -0600408 def _GetPropTree(self, dtb, prop_names):
Simon Glass16b8d6b2018-07-06 10:27:42 -0600409 def AddNode(node, path):
410 if node.name != '/':
411 path += '/' + node.name
Simon Glass16b8d6b2018-07-06 10:27:42 -0600412 for subnode in node.subnodes:
413 for prop in subnode.props.values():
Simon Glasscee02e62018-07-17 13:25:52 -0600414 if prop.name in prop_names:
Simon Glass16b8d6b2018-07-06 10:27:42 -0600415 prop_path = path + '/' + subnode.name + ':' + prop.name
416 tree[prop_path[len('/binman/'):]] = fdt_util.fdt32_to_cpu(
417 prop.value)
Simon Glass16b8d6b2018-07-06 10:27:42 -0600418 AddNode(subnode, path)
419
420 tree = {}
Simon Glass16b8d6b2018-07-06 10:27:42 -0600421 AddNode(dtb.GetRoot(), '')
422 return tree
423
Simon Glass4f443042016-11-25 20:15:52 -0700424 def testRun(self):
425 """Test a basic run with valid args"""
426 result = self._RunBinman('-h')
427
428 def testFullHelp(self):
429 """Test that the full help is displayed with -H"""
430 result = self._RunBinman('-H')
431 help_file = os.path.join(self._binman_dir, 'README')
Tom Rini3759df02018-01-16 15:29:50 -0500432 # Remove possible extraneous strings
433 extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
434 gothelp = result.stdout.replace(extra, '')
435 self.assertEqual(len(gothelp), os.path.getsize(help_file))
Simon Glass4f443042016-11-25 20:15:52 -0700436 self.assertEqual(0, len(result.stderr))
437 self.assertEqual(0, result.return_code)
438
439 def testFullHelpInternal(self):
440 """Test that the full help is displayed with -H"""
441 try:
442 command.test_result = command.CommandResult()
443 result = self._DoBinman('-H')
444 help_file = os.path.join(self._binman_dir, 'README')
445 finally:
446 command.test_result = None
447
448 def testHelp(self):
449 """Test that the basic help is displayed with -h"""
450 result = self._RunBinman('-h')
451 self.assertTrue(len(result.stdout) > 200)
452 self.assertEqual(0, len(result.stderr))
453 self.assertEqual(0, result.return_code)
454
Simon Glass4f443042016-11-25 20:15:52 -0700455 def testBoard(self):
456 """Test that we can run it with a specific board"""
457 self._SetupDtb('05_simple.dts', 'sandbox/u-boot.dtb')
458 TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
459 result = self._DoBinman('-b', 'sandbox')
460 self.assertEqual(0, result)
461
462 def testNeedBoard(self):
463 """Test that we get an error when no board ius supplied"""
464 with self.assertRaises(ValueError) as e:
465 result = self._DoBinman()
466 self.assertIn("Must provide a board to process (use -b <board>)",
467 str(e.exception))
468
469 def testMissingDt(self):
Simon Glass7ae5f312018-06-01 09:38:19 -0600470 """Test that an invalid device-tree file generates an error"""
Simon Glass4f443042016-11-25 20:15:52 -0700471 with self.assertRaises(Exception) as e:
472 self._RunBinman('-d', 'missing_file')
473 # We get one error from libfdt, and a different one from fdtget.
474 self.AssertInList(["Couldn't open blob from 'missing_file'",
475 'No such file or directory'], str(e.exception))
476
477 def testBrokenDt(self):
Simon Glass7ae5f312018-06-01 09:38:19 -0600478 """Test that an invalid device-tree source file generates an error
Simon Glass4f443042016-11-25 20:15:52 -0700479
480 Since this is a source file it should be compiled and the error
481 will come from the device-tree compiler (dtc).
482 """
483 with self.assertRaises(Exception) as e:
484 self._RunBinman('-d', self.TestFile('01_invalid.dts'))
485 self.assertIn("FATAL ERROR: Unable to parse input tree",
486 str(e.exception))
487
488 def testMissingNode(self):
489 """Test that a device tree without a 'binman' node generates an error"""
490 with self.assertRaises(Exception) as e:
491 self._DoBinman('-d', self.TestFile('02_missing_node.dts'))
492 self.assertIn("does not have a 'binman' node", str(e.exception))
493
494 def testEmpty(self):
495 """Test that an empty binman node works OK (i.e. does nothing)"""
496 result = self._RunBinman('-d', self.TestFile('03_empty.dts'))
497 self.assertEqual(0, len(result.stderr))
498 self.assertEqual(0, result.return_code)
499
500 def testInvalidEntry(self):
501 """Test that an invalid entry is flagged"""
502 with self.assertRaises(Exception) as e:
503 result = self._RunBinman('-d',
504 self.TestFile('04_invalid_entry.dts'))
Simon Glass4f443042016-11-25 20:15:52 -0700505 self.assertIn("Unknown entry type 'not-a-valid-type' in node "
506 "'/binman/not-a-valid-type'", str(e.exception))
507
508 def testSimple(self):
509 """Test a simple binman with a single file"""
510 data = self._DoReadFile('05_simple.dts')
511 self.assertEqual(U_BOOT_DATA, data)
512
Simon Glass7fe91732017-11-13 18:55:00 -0700513 def testSimpleDebug(self):
514 """Test a simple binman run with debugging enabled"""
515 data = self._DoTestFile('05_simple.dts', debug=True)
516
Simon Glass4f443042016-11-25 20:15:52 -0700517 def testDual(self):
518 """Test that we can handle creating two images
519
520 This also tests image padding.
521 """
522 retcode = self._DoTestFile('06_dual_image.dts')
523 self.assertEqual(0, retcode)
524
525 image = control.images['image1']
526 self.assertEqual(len(U_BOOT_DATA), image._size)
527 fname = tools.GetOutputFilename('image1.bin')
528 self.assertTrue(os.path.exists(fname))
529 with open(fname) as fd:
530 data = fd.read()
531 self.assertEqual(U_BOOT_DATA, data)
532
533 image = control.images['image2']
534 self.assertEqual(3 + len(U_BOOT_DATA) + 5, image._size)
535 fname = tools.GetOutputFilename('image2.bin')
536 self.assertTrue(os.path.exists(fname))
537 with open(fname) as fd:
538 data = fd.read()
539 self.assertEqual(U_BOOT_DATA, data[3:7])
540 self.assertEqual(chr(0) * 3, data[:3])
541 self.assertEqual(chr(0) * 5, data[7:])
542
543 def testBadAlign(self):
544 """Test that an invalid alignment value is detected"""
545 with self.assertRaises(ValueError) as e:
546 self._DoTestFile('07_bad_align.dts')
547 self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
548 "of two", str(e.exception))
549
550 def testPackSimple(self):
551 """Test that packing works as expected"""
552 retcode = self._DoTestFile('08_pack.dts')
553 self.assertEqual(0, retcode)
554 self.assertIn('image', control.images)
555 image = control.images['image']
Simon Glass8f1da502018-06-01 09:38:12 -0600556 entries = image.GetEntries()
Simon Glass4f443042016-11-25 20:15:52 -0700557 self.assertEqual(5, len(entries))
558
559 # First u-boot
560 self.assertIn('u-boot', entries)
561 entry = entries['u-boot']
Simon Glass3ab95982018-08-01 15:22:37 -0600562 self.assertEqual(0, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700563 self.assertEqual(len(U_BOOT_DATA), entry.size)
564
565 # Second u-boot, aligned to 16-byte boundary
566 self.assertIn('u-boot-align', entries)
567 entry = entries['u-boot-align']
Simon Glass3ab95982018-08-01 15:22:37 -0600568 self.assertEqual(16, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700569 self.assertEqual(len(U_BOOT_DATA), entry.size)
570
571 # Third u-boot, size 23 bytes
572 self.assertIn('u-boot-size', entries)
573 entry = entries['u-boot-size']
Simon Glass3ab95982018-08-01 15:22:37 -0600574 self.assertEqual(20, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700575 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
576 self.assertEqual(23, entry.size)
577
578 # Fourth u-boot, placed immediate after the above
579 self.assertIn('u-boot-next', entries)
580 entry = entries['u-boot-next']
Simon Glass3ab95982018-08-01 15:22:37 -0600581 self.assertEqual(43, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700582 self.assertEqual(len(U_BOOT_DATA), entry.size)
583
Simon Glass3ab95982018-08-01 15:22:37 -0600584 # Fifth u-boot, placed at a fixed offset
Simon Glass4f443042016-11-25 20:15:52 -0700585 self.assertIn('u-boot-fixed', entries)
586 entry = entries['u-boot-fixed']
Simon Glass3ab95982018-08-01 15:22:37 -0600587 self.assertEqual(61, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700588 self.assertEqual(len(U_BOOT_DATA), entry.size)
589
590 self.assertEqual(65, image._size)
591
592 def testPackExtra(self):
593 """Test that extra packing feature works as expected"""
594 retcode = self._DoTestFile('09_pack_extra.dts')
595
596 self.assertEqual(0, retcode)
597 self.assertIn('image', control.images)
598 image = control.images['image']
Simon Glass8f1da502018-06-01 09:38:12 -0600599 entries = image.GetEntries()
Simon Glass4f443042016-11-25 20:15:52 -0700600 self.assertEqual(5, len(entries))
601
602 # First u-boot with padding before and after
603 self.assertIn('u-boot', entries)
604 entry = entries['u-boot']
Simon Glass3ab95982018-08-01 15:22:37 -0600605 self.assertEqual(0, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700606 self.assertEqual(3, entry.pad_before)
607 self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
608
609 # Second u-boot has an aligned size, but it has no effect
610 self.assertIn('u-boot-align-size-nop', entries)
611 entry = entries['u-boot-align-size-nop']
Simon Glass3ab95982018-08-01 15:22:37 -0600612 self.assertEqual(12, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700613 self.assertEqual(4, entry.size)
614
615 # Third u-boot has an aligned size too
616 self.assertIn('u-boot-align-size', entries)
617 entry = entries['u-boot-align-size']
Simon Glass3ab95982018-08-01 15:22:37 -0600618 self.assertEqual(16, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700619 self.assertEqual(32, entry.size)
620
621 # Fourth u-boot has an aligned end
622 self.assertIn('u-boot-align-end', entries)
623 entry = entries['u-boot-align-end']
Simon Glass3ab95982018-08-01 15:22:37 -0600624 self.assertEqual(48, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700625 self.assertEqual(16, entry.size)
626
627 # Fifth u-boot immediately afterwards
628 self.assertIn('u-boot-align-both', entries)
629 entry = entries['u-boot-align-both']
Simon Glass3ab95982018-08-01 15:22:37 -0600630 self.assertEqual(64, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700631 self.assertEqual(64, entry.size)
632
633 self.CheckNoGaps(entries)
634 self.assertEqual(128, image._size)
635
636 def testPackAlignPowerOf2(self):
637 """Test that invalid entry alignment is detected"""
638 with self.assertRaises(ValueError) as e:
639 self._DoTestFile('10_pack_align_power2.dts')
640 self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
641 "of two", str(e.exception))
642
643 def testPackAlignSizePowerOf2(self):
644 """Test that invalid entry size alignment is detected"""
645 with self.assertRaises(ValueError) as e:
646 self._DoTestFile('11_pack_align_size_power2.dts')
647 self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
648 "power of two", str(e.exception))
649
650 def testPackInvalidAlign(self):
Simon Glass3ab95982018-08-01 15:22:37 -0600651 """Test detection of an offset that does not match its alignment"""
Simon Glass4f443042016-11-25 20:15:52 -0700652 with self.assertRaises(ValueError) as e:
653 self._DoTestFile('12_pack_inv_align.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600654 self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
Simon Glass4f443042016-11-25 20:15:52 -0700655 "align 0x4 (4)", str(e.exception))
656
657 def testPackInvalidSizeAlign(self):
658 """Test that invalid entry size alignment is detected"""
659 with self.assertRaises(ValueError) as e:
660 self._DoTestFile('13_pack_inv_size_align.dts')
661 self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
662 "align-size 0x4 (4)", str(e.exception))
663
664 def testPackOverlap(self):
665 """Test that overlapping regions are detected"""
666 with self.assertRaises(ValueError) as e:
667 self._DoTestFile('14_pack_overlap.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600668 self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
Simon Glass4f443042016-11-25 20:15:52 -0700669 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
670 str(e.exception))
671
672 def testPackEntryOverflow(self):
673 """Test that entries that overflow their size are detected"""
674 with self.assertRaises(ValueError) as e:
675 self._DoTestFile('15_pack_overflow.dts')
676 self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
677 "but entry size is 0x3 (3)", str(e.exception))
678
679 def testPackImageOverflow(self):
680 """Test that entries which overflow the image size are detected"""
681 with self.assertRaises(ValueError) as e:
682 self._DoTestFile('16_pack_image_overflow.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600683 self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section "
Simon Glass4f443042016-11-25 20:15:52 -0700684 "size 0x3 (3)", str(e.exception))
685
686 def testPackImageSize(self):
687 """Test that the image size can be set"""
688 retcode = self._DoTestFile('17_pack_image_size.dts')
689 self.assertEqual(0, retcode)
690 self.assertIn('image', control.images)
691 image = control.images['image']
692 self.assertEqual(7, image._size)
693
694 def testPackImageSizeAlign(self):
695 """Test that image size alignemnt works as expected"""
696 retcode = self._DoTestFile('18_pack_image_align.dts')
697 self.assertEqual(0, retcode)
698 self.assertIn('image', control.images)
699 image = control.images['image']
700 self.assertEqual(16, image._size)
701
702 def testPackInvalidImageAlign(self):
703 """Test that invalid image alignment is detected"""
704 with self.assertRaises(ValueError) as e:
705 self._DoTestFile('19_pack_inv_image_align.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600706 self.assertIn("Section '/binman': Size 0x7 (7) does not match "
Simon Glass4f443042016-11-25 20:15:52 -0700707 "align-size 0x8 (8)", str(e.exception))
708
709 def testPackAlignPowerOf2(self):
710 """Test that invalid image alignment is detected"""
711 with self.assertRaises(ValueError) as e:
712 self._DoTestFile('20_pack_inv_image_align_power2.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600713 self.assertIn("Section '/binman': Alignment size 131 must be a power of "
Simon Glass4f443042016-11-25 20:15:52 -0700714 "two", str(e.exception))
715
716 def testImagePadByte(self):
717 """Test that the image pad byte can be specified"""
Simon Glass19790632017-11-13 18:55:01 -0700718 with open(self.TestFile('bss_data')) as fd:
719 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
Simon Glass4f443042016-11-25 20:15:52 -0700720 data = self._DoReadFile('21_image_pad.dts')
Simon Glassf6898902017-11-13 18:54:59 -0700721 self.assertEqual(U_BOOT_SPL_DATA + (chr(0xff) * 1) + U_BOOT_DATA, data)
Simon Glass4f443042016-11-25 20:15:52 -0700722
723 def testImageName(self):
724 """Test that image files can be named"""
725 retcode = self._DoTestFile('22_image_name.dts')
726 self.assertEqual(0, retcode)
727 image = control.images['image1']
728 fname = tools.GetOutputFilename('test-name')
729 self.assertTrue(os.path.exists(fname))
730
731 image = control.images['image2']
732 fname = tools.GetOutputFilename('test-name.xx')
733 self.assertTrue(os.path.exists(fname))
734
735 def testBlobFilename(self):
736 """Test that generic blobs can be provided by filename"""
737 data = self._DoReadFile('23_blob.dts')
738 self.assertEqual(BLOB_DATA, data)
739
740 def testPackSorted(self):
741 """Test that entries can be sorted"""
742 data = self._DoReadFile('24_sorted.dts')
Simon Glassf6898902017-11-13 18:54:59 -0700743 self.assertEqual(chr(0) * 1 + U_BOOT_SPL_DATA + chr(0) * 2 +
Simon Glass4f443042016-11-25 20:15:52 -0700744 U_BOOT_DATA, data)
745
Simon Glass3ab95982018-08-01 15:22:37 -0600746 def testPackZeroOffset(self):
747 """Test that an entry at offset 0 is not given a new offset"""
Simon Glass4f443042016-11-25 20:15:52 -0700748 with self.assertRaises(ValueError) as e:
749 self._DoTestFile('25_pack_zero_size.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600750 self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
Simon Glass4f443042016-11-25 20:15:52 -0700751 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
752 str(e.exception))
753
754 def testPackUbootDtb(self):
755 """Test that a device tree can be added to U-Boot"""
756 data = self._DoReadFile('26_pack_u_boot_dtb.dts')
757 self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
Simon Glasse0ff8552016-11-25 20:15:53 -0700758
759 def testPackX86RomNoSize(self):
760 """Test that the end-at-4gb property requires a size property"""
761 with self.assertRaises(ValueError) as e:
762 self._DoTestFile('27_pack_4gb_no_size.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600763 self.assertIn("Section '/binman': Section size must be provided when "
Simon Glasse0ff8552016-11-25 20:15:53 -0700764 "using end-at-4gb", str(e.exception))
765
Jagdish Gediya94b57db2018-09-03 21:35:07 +0530766 def test4gbAndSkipAtStartTogether(self):
767 """Test that the end-at-4gb and skip-at-size property can't be used
768 together"""
769 with self.assertRaises(ValueError) as e:
770 self._DoTestFile('80_4gb_and_skip_at_start_together.dts')
771 self.assertIn("Section '/binman': Provide either 'end-at-4gb' or "
772 "'skip-at-start'", str(e.exception))
773
Simon Glasse0ff8552016-11-25 20:15:53 -0700774 def testPackX86RomOutside(self):
Simon Glass3ab95982018-08-01 15:22:37 -0600775 """Test that the end-at-4gb property checks for offset boundaries"""
Simon Glasse0ff8552016-11-25 20:15:53 -0700776 with self.assertRaises(ValueError) as e:
777 self._DoTestFile('28_pack_4gb_outside.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600778 self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
Simon Glass8f1da502018-06-01 09:38:12 -0600779 "the section starting at 0xffffffe0 (4294967264)",
Simon Glasse0ff8552016-11-25 20:15:53 -0700780 str(e.exception))
781
782 def testPackX86Rom(self):
783 """Test that a basic x86 ROM can be created"""
784 data = self._DoReadFile('29_x86-rom.dts')
Simon Glassf6898902017-11-13 18:54:59 -0700785 self.assertEqual(U_BOOT_DATA + chr(0) * 7 + U_BOOT_SPL_DATA +
786 chr(0) * 2, data)
Simon Glasse0ff8552016-11-25 20:15:53 -0700787
788 def testPackX86RomMeNoDesc(self):
789 """Test that an invalid Intel descriptor entry is detected"""
790 TestFunctional._MakeInputFile('descriptor.bin', '')
791 with self.assertRaises(ValueError) as e:
792 self._DoTestFile('31_x86-rom-me.dts')
793 self.assertIn("Node '/binman/intel-descriptor': Cannot find FD "
794 "signature", str(e.exception))
795
796 def testPackX86RomBadDesc(self):
797 """Test that the Intel requires a descriptor entry"""
798 with self.assertRaises(ValueError) as e:
799 self._DoTestFile('30_x86-rom-me-no-desc.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600800 self.assertIn("Node '/binman/intel-me': No offset set with "
801 "offset-unset: should another entry provide this correct "
802 "offset?", str(e.exception))
Simon Glasse0ff8552016-11-25 20:15:53 -0700803
804 def testPackX86RomMe(self):
805 """Test that an x86 ROM with an ME region can be created"""
806 data = self._DoReadFile('31_x86-rom-me.dts')
807 self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
808
809 def testPackVga(self):
810 """Test that an image with a VGA binary can be created"""
811 data = self._DoReadFile('32_intel-vga.dts')
812 self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
813
814 def testPackStart16(self):
815 """Test that an image with an x86 start16 region can be created"""
816 data = self._DoReadFile('33_x86-start16.dts')
817 self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
818
Jagdish Gediya9d368f32018-09-03 21:35:08 +0530819 def testPackPowerpcMpc85xxBootpgResetvec(self):
820 """Test that an image with powerpc-mpc85xx-bootpg-resetvec can be
821 created"""
822 data = self._DoReadFile('81_powerpc_mpc85xx_bootpg_resetvec.dts')
823 self.assertEqual(PPC_MPC85XX_BR_DATA, data[:len(PPC_MPC85XX_BR_DATA)])
824
Simon Glass736bb0a2018-07-06 10:27:17 -0600825 def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False):
Simon Glassadc57012018-07-06 10:27:16 -0600826 """Handle running a test for insertion of microcode
827
828 Args:
829 dts_fname: Name of test .dts file
830 nodtb_data: Data that we expect in the first section
Simon Glass736bb0a2018-07-06 10:27:17 -0600831 ucode_second: True if the microsecond entry is second instead of
832 third
Simon Glassadc57012018-07-06 10:27:16 -0600833
834 Returns:
835 Tuple:
836 Contents of first region (U-Boot or SPL)
Simon Glass3ab95982018-08-01 15:22:37 -0600837 Offset and size components of microcode pointer, as inserted
Simon Glassadc57012018-07-06 10:27:16 -0600838 in the above (two 4-byte words)
839 """
Simon Glass6b187df2017-11-12 21:52:27 -0700840 data = self._DoReadFile(dts_fname, True)
Simon Glasse0ff8552016-11-25 20:15:53 -0700841
842 # Now check the device tree has no microcode
Simon Glass736bb0a2018-07-06 10:27:17 -0600843 if ucode_second:
844 ucode_content = data[len(nodtb_data):]
845 ucode_pos = len(nodtb_data)
846 dtb_with_ucode = ucode_content[16:]
847 fdt_len = self.GetFdtLen(dtb_with_ucode)
848 else:
849 dtb_with_ucode = data[len(nodtb_data):]
850 fdt_len = self.GetFdtLen(dtb_with_ucode)
851 ucode_content = dtb_with_ucode[fdt_len:]
852 ucode_pos = len(nodtb_data) + fdt_len
Simon Glasse0ff8552016-11-25 20:15:53 -0700853 fname = tools.GetOutputFilename('test.dtb')
854 with open(fname, 'wb') as fd:
Simon Glassadc57012018-07-06 10:27:16 -0600855 fd.write(dtb_with_ucode)
Simon Glassec3f3782017-05-27 07:38:29 -0600856 dtb = fdt.FdtScan(fname)
857 ucode = dtb.GetNode('/microcode')
Simon Glasse0ff8552016-11-25 20:15:53 -0700858 self.assertTrue(ucode)
859 for node in ucode.subnodes:
860 self.assertFalse(node.props.get('data'))
861
Simon Glasse0ff8552016-11-25 20:15:53 -0700862 # Check that the microcode appears immediately after the Fdt
863 # This matches the concatenation of the data properties in
Simon Glass87722132017-11-12 21:52:26 -0700864 # the /microcode/update@xxx nodes in 34_x86_ucode.dts.
Simon Glasse0ff8552016-11-25 20:15:53 -0700865 ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
866 0x78235609)
Simon Glassadc57012018-07-06 10:27:16 -0600867 self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
Simon Glasse0ff8552016-11-25 20:15:53 -0700868
869 # Check that the microcode pointer was inserted. It should match the
Simon Glass3ab95982018-08-01 15:22:37 -0600870 # expected offset and size
Simon Glasse0ff8552016-11-25 20:15:53 -0700871 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
872 len(ucode_data))
Simon Glass736bb0a2018-07-06 10:27:17 -0600873 u_boot = data[:len(nodtb_data)]
874 return u_boot, pos_and_size
Simon Glass6b187df2017-11-12 21:52:27 -0700875
876 def testPackUbootMicrocode(self):
877 """Test that x86 microcode can be handled correctly
878
879 We expect to see the following in the image, in order:
880 u-boot-nodtb.bin with a microcode pointer inserted at the correct
881 place
882 u-boot.dtb with the microcode removed
883 the microcode
884 """
885 first, pos_and_size = self._RunMicrocodeTest('34_x86_ucode.dts',
886 U_BOOT_NODTB_DATA)
Simon Glasse0ff8552016-11-25 20:15:53 -0700887 self.assertEqual('nodtb with microcode' + pos_and_size +
888 ' somewhere in here', first)
889
Simon Glass160a7662017-05-27 07:38:26 -0600890 def _RunPackUbootSingleMicrocode(self):
Simon Glasse0ff8552016-11-25 20:15:53 -0700891 """Test that x86 microcode can be handled correctly
892
893 We expect to see the following in the image, in order:
894 u-boot-nodtb.bin with a microcode pointer inserted at the correct
895 place
896 u-boot.dtb with the microcode
897 an empty microcode region
898 """
899 # We need the libfdt library to run this test since only that allows
900 # finding the offset of a property. This is required by
901 # Entry_u_boot_dtb_with_ucode.ObtainContents().
Simon Glasse0ff8552016-11-25 20:15:53 -0700902 data = self._DoReadFile('35_x86_single_ucode.dts', True)
903
904 second = data[len(U_BOOT_NODTB_DATA):]
905
906 fdt_len = self.GetFdtLen(second)
907 third = second[fdt_len:]
908 second = second[:fdt_len]
909
Simon Glass160a7662017-05-27 07:38:26 -0600910 ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
911 self.assertIn(ucode_data, second)
912 ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
Simon Glasse0ff8552016-11-25 20:15:53 -0700913
Simon Glass160a7662017-05-27 07:38:26 -0600914 # Check that the microcode pointer was inserted. It should match the
Simon Glass3ab95982018-08-01 15:22:37 -0600915 # expected offset and size
Simon Glass160a7662017-05-27 07:38:26 -0600916 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
917 len(ucode_data))
918 first = data[:len(U_BOOT_NODTB_DATA)]
919 self.assertEqual('nodtb with microcode' + pos_and_size +
920 ' somewhere in here', first)
Simon Glassc49deb82016-11-25 20:15:54 -0700921
Simon Glass75db0862016-11-25 20:15:55 -0700922 def testPackUbootSingleMicrocode(self):
923 """Test that x86 microcode can be handled correctly with fdt_normal.
924 """
Simon Glass160a7662017-05-27 07:38:26 -0600925 self._RunPackUbootSingleMicrocode()
Simon Glass75db0862016-11-25 20:15:55 -0700926
Simon Glassc49deb82016-11-25 20:15:54 -0700927 def testUBootImg(self):
928 """Test that u-boot.img can be put in a file"""
929 data = self._DoReadFile('36_u_boot_img.dts')
930 self.assertEqual(U_BOOT_IMG_DATA, data)
Simon Glass75db0862016-11-25 20:15:55 -0700931
932 def testNoMicrocode(self):
933 """Test that a missing microcode region is detected"""
934 with self.assertRaises(ValueError) as e:
935 self._DoReadFile('37_x86_no_ucode.dts', True)
936 self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
937 "node found in ", str(e.exception))
938
939 def testMicrocodeWithoutNode(self):
940 """Test that a missing u-boot-dtb-with-ucode node is detected"""
941 with self.assertRaises(ValueError) as e:
942 self._DoReadFile('38_x86_ucode_missing_node.dts', True)
943 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
944 "microcode region u-boot-dtb-with-ucode", str(e.exception))
945
946 def testMicrocodeWithoutNode2(self):
947 """Test that a missing u-boot-ucode node is detected"""
948 with self.assertRaises(ValueError) as e:
949 self._DoReadFile('39_x86_ucode_missing_node2.dts', True)
950 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
951 "microcode region u-boot-ucode", str(e.exception))
952
953 def testMicrocodeWithoutPtrInElf(self):
954 """Test that a U-Boot binary without the microcode symbol is detected"""
955 # ELF file without a '_dt_ucode_base_size' symbol
Simon Glass75db0862016-11-25 20:15:55 -0700956 try:
957 with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
958 TestFunctional._MakeInputFile('u-boot', fd.read())
959
960 with self.assertRaises(ValueError) as e:
Simon Glass160a7662017-05-27 07:38:26 -0600961 self._RunPackUbootSingleMicrocode()
Simon Glass75db0862016-11-25 20:15:55 -0700962 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
963 "_dt_ucode_base_size symbol in u-boot", str(e.exception))
964
965 finally:
966 # Put the original file back
967 with open(self.TestFile('u_boot_ucode_ptr')) as fd:
968 TestFunctional._MakeInputFile('u-boot', fd.read())
969
970 def testMicrocodeNotInImage(self):
971 """Test that microcode must be placed within the image"""
972 with self.assertRaises(ValueError) as e:
973 self._DoReadFile('40_x86_ucode_not_in_image.dts', True)
974 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
975 "pointer _dt_ucode_base_size at fffffe14 is outside the "
Simon Glass25ac0e62018-06-01 09:38:14 -0600976 "section ranging from 00000000 to 0000002e", str(e.exception))
Simon Glass75db0862016-11-25 20:15:55 -0700977
978 def testWithoutMicrocode(self):
979 """Test that we can cope with an image without microcode (e.g. qemu)"""
980 with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
981 TestFunctional._MakeInputFile('u-boot', fd.read())
Simon Glass16b8d6b2018-07-06 10:27:42 -0600982 data, dtb, _, _ = self._DoReadFileDtb('44_x86_optional_ucode.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -0700983
984 # Now check the device tree has no microcode
985 self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
986 second = data[len(U_BOOT_NODTB_DATA):]
987
988 fdt_len = self.GetFdtLen(second)
989 self.assertEqual(dtb, second[:fdt_len])
990
991 used_len = len(U_BOOT_NODTB_DATA) + fdt_len
992 third = data[used_len:]
993 self.assertEqual(chr(0) * (0x200 - used_len), third)
994
995 def testUnknownPosSize(self):
996 """Test that microcode must be placed within the image"""
997 with self.assertRaises(ValueError) as e:
998 self._DoReadFile('41_unknown_pos_size.dts', True)
Simon Glass3ab95982018-08-01 15:22:37 -0600999 self.assertIn("Section '/binman': Unable to set offset/size for unknown "
Simon Glass75db0862016-11-25 20:15:55 -07001000 "entry 'invalid-entry'", str(e.exception))
Simon Glassda229092016-11-25 20:15:56 -07001001
1002 def testPackFsp(self):
1003 """Test that an image with a FSP binary can be created"""
1004 data = self._DoReadFile('42_intel-fsp.dts')
1005 self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
1006
1007 def testPackCmc(self):
Bin Meng59ea8c22017-08-15 22:41:54 -07001008 """Test that an image with a CMC binary can be created"""
Simon Glassda229092016-11-25 20:15:56 -07001009 data = self._DoReadFile('43_intel-cmc.dts')
1010 self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
Bin Meng59ea8c22017-08-15 22:41:54 -07001011
1012 def testPackVbt(self):
1013 """Test that an image with a VBT binary can be created"""
1014 data = self._DoReadFile('46_intel-vbt.dts')
1015 self.assertEqual(VBT_DATA, data[:len(VBT_DATA)])
Simon Glass9fc60b42017-11-12 21:52:22 -07001016
Simon Glass56509842017-11-12 21:52:25 -07001017 def testSplBssPad(self):
1018 """Test that we can pad SPL's BSS with zeros"""
Simon Glass6b187df2017-11-12 21:52:27 -07001019 # ELF file with a '__bss_size' symbol
1020 with open(self.TestFile('bss_data')) as fd:
1021 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
Simon Glass56509842017-11-12 21:52:25 -07001022 data = self._DoReadFile('47_spl_bss_pad.dts')
1023 self.assertEqual(U_BOOT_SPL_DATA + (chr(0) * 10) + U_BOOT_DATA, data)
1024
Simon Glassb50e5612017-11-13 18:54:54 -07001025 with open(self.TestFile('u_boot_ucode_ptr')) as fd:
1026 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
1027 with self.assertRaises(ValueError) as e:
1028 data = self._DoReadFile('47_spl_bss_pad.dts')
1029 self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
1030 str(e.exception))
1031
Simon Glass87722132017-11-12 21:52:26 -07001032 def testPackStart16Spl(self):
Simon Glass35b384c2018-09-14 04:57:10 -06001033 """Test that an image with an x86 start16 SPL region can be created"""
Simon Glass87722132017-11-12 21:52:26 -07001034 data = self._DoReadFile('48_x86-start16-spl.dts')
1035 self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)])
1036
Simon Glass736bb0a2018-07-06 10:27:17 -06001037 def _PackUbootSplMicrocode(self, dts, ucode_second=False):
1038 """Helper function for microcode tests
Simon Glass6b187df2017-11-12 21:52:27 -07001039
1040 We expect to see the following in the image, in order:
1041 u-boot-spl-nodtb.bin with a microcode pointer inserted at the
1042 correct place
1043 u-boot.dtb with the microcode removed
1044 the microcode
Simon Glass736bb0a2018-07-06 10:27:17 -06001045
1046 Args:
1047 dts: Device tree file to use for test
1048 ucode_second: True if the microsecond entry is second instead of
1049 third
Simon Glass6b187df2017-11-12 21:52:27 -07001050 """
1051 # ELF file with a '_dt_ucode_base_size' symbol
1052 with open(self.TestFile('u_boot_ucode_ptr')) as fd:
1053 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
Simon Glass736bb0a2018-07-06 10:27:17 -06001054 first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA,
1055 ucode_second=ucode_second)
Simon Glass6b187df2017-11-12 21:52:27 -07001056 self.assertEqual('splnodtb with microc' + pos_and_size +
1057 'ter somewhere in here', first)
1058
Simon Glass736bb0a2018-07-06 10:27:17 -06001059 def testPackUbootSplMicrocode(self):
1060 """Test that x86 microcode can be handled correctly in SPL"""
1061 self._PackUbootSplMicrocode('49_x86_ucode_spl.dts')
1062
1063 def testPackUbootSplMicrocodeReorder(self):
1064 """Test that order doesn't matter for microcode entries
1065
1066 This is the same as testPackUbootSplMicrocode but when we process the
1067 u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode
1068 entry, so we reply on binman to try later.
1069 """
1070 self._PackUbootSplMicrocode('58_x86_ucode_spl_needs_retry.dts',
1071 ucode_second=True)
1072
Simon Glassca4f4ff2017-11-12 21:52:28 -07001073 def testPackMrc(self):
1074 """Test that an image with an MRC binary can be created"""
1075 data = self._DoReadFile('50_intel_mrc.dts')
1076 self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
1077
Simon Glass47419ea2017-11-13 18:54:55 -07001078 def testSplDtb(self):
1079 """Test that an image with spl/u-boot-spl.dtb can be created"""
1080 data = self._DoReadFile('51_u_boot_spl_dtb.dts')
1081 self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
1082
Simon Glass4e6fdbe2017-11-13 18:54:56 -07001083 def testSplNoDtb(self):
1084 """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
1085 data = self._DoReadFile('52_u_boot_spl_nodtb.dts')
1086 self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
1087
Simon Glass19790632017-11-13 18:55:01 -07001088 def testSymbols(self):
1089 """Test binman can assign symbols embedded in U-Boot"""
1090 elf_fname = self.TestFile('u_boot_binman_syms')
1091 syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
1092 addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
Simon Glass3ab95982018-08-01 15:22:37 -06001093 self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
Simon Glass19790632017-11-13 18:55:01 -07001094
1095 with open(self.TestFile('u_boot_binman_syms')) as fd:
1096 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
1097 data = self._DoReadFile('53_symbols.dts')
1098 sym_values = struct.pack('<LQL', 0x24 + 0, 0x24 + 24, 0x24 + 20)
1099 expected = (sym_values + U_BOOT_SPL_DATA[16:] + chr(0xff) +
1100 U_BOOT_DATA +
1101 sym_values + U_BOOT_SPL_DATA[16:])
1102 self.assertEqual(expected, data)
1103
Simon Glassdd57c132018-06-01 09:38:11 -06001104 def testPackUnitAddress(self):
1105 """Test that we support multiple binaries with the same name"""
1106 data = self._DoReadFile('54_unit_address.dts')
1107 self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
1108
Simon Glass18546952018-06-01 09:38:16 -06001109 def testSections(self):
1110 """Basic test of sections"""
1111 data = self._DoReadFile('55_sections.dts')
Simon Glass8122f392018-07-17 13:25:28 -06001112 expected = (U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12 +
1113 U_BOOT_DATA + '&' * 4)
Simon Glass18546952018-06-01 09:38:16 -06001114 self.assertEqual(expected, data)
Simon Glass9fc60b42017-11-12 21:52:22 -07001115
Simon Glass3b0c3822018-06-01 09:38:20 -06001116 def testMap(self):
1117 """Tests outputting a map of the images"""
Simon Glass16b8d6b2018-07-06 10:27:42 -06001118 _, _, map_data, _ = self._DoReadFileDtb('55_sections.dts', map=True)
Simon Glass1be70d22018-07-17 13:25:49 -06001119 self.assertEqual('''ImagePos Offset Size Name
112000000000 00000000 00000028 main-section
112100000000 00000000 00000010 section@0
112200000000 00000000 00000004 u-boot
112300000010 00000010 00000010 section@1
112400000010 00000000 00000004 u-boot
112500000020 00000020 00000004 section@2
112600000020 00000000 00000004 u-boot
Simon Glass3b0c3822018-06-01 09:38:20 -06001127''', map_data)
1128
Simon Glassc8d48ef2018-06-01 09:38:21 -06001129 def testNamePrefix(self):
1130 """Tests that name prefixes are used"""
Simon Glass16b8d6b2018-07-06 10:27:42 -06001131 _, _, map_data, _ = self._DoReadFileDtb('56_name_prefix.dts', map=True)
Simon Glass1be70d22018-07-17 13:25:49 -06001132 self.assertEqual('''ImagePos Offset Size Name
113300000000 00000000 00000028 main-section
113400000000 00000000 00000010 section@0
113500000000 00000000 00000004 ro-u-boot
113600000010 00000010 00000010 section@1
113700000010 00000000 00000004 rw-u-boot
Simon Glassc8d48ef2018-06-01 09:38:21 -06001138''', map_data)
1139
Simon Glass736bb0a2018-07-06 10:27:17 -06001140 def testUnknownContents(self):
1141 """Test that obtaining the contents works as expected"""
1142 with self.assertRaises(ValueError) as e:
1143 self._DoReadFile('57_unknown_contents.dts', True)
1144 self.assertIn("Section '/binman': Internal error: Could not complete "
1145 "processing of contents: remaining [<_testing.Entry__testing ",
1146 str(e.exception))
1147
Simon Glass5c890232018-07-06 10:27:19 -06001148 def testBadChangeSize(self):
1149 """Test that trying to change the size of an entry fails"""
1150 with self.assertRaises(ValueError) as e:
1151 self._DoReadFile('59_change_size.dts', True)
1152 self.assertIn("Node '/binman/_testing': Cannot update entry size from "
1153 '2 to 1', str(e.exception))
1154
Simon Glass16b8d6b2018-07-06 10:27:42 -06001155 def testUpdateFdt(self):
Simon Glass3ab95982018-08-01 15:22:37 -06001156 """Test that we can update the device tree with offset/size info"""
Simon Glass16b8d6b2018-07-06 10:27:42 -06001157 _, _, _, out_dtb_fname = self._DoReadFileDtb('60_fdt_update.dts',
1158 update_dtb=True)
Simon Glasscee02e62018-07-17 13:25:52 -06001159 dtb = fdt.Fdt(out_dtb_fname)
1160 dtb.Scan()
1161 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'])
Simon Glass16b8d6b2018-07-06 10:27:42 -06001162 self.assertEqual({
Simon Glassdbf6be92018-08-01 15:22:42 -06001163 'image-pos': 0,
Simon Glass8122f392018-07-17 13:25:28 -06001164 'offset': 0,
Simon Glass3ab95982018-08-01 15:22:37 -06001165 '_testing:offset': 32,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001166 '_testing:size': 1,
Simon Glassdbf6be92018-08-01 15:22:42 -06001167 '_testing:image-pos': 32,
Simon Glass3ab95982018-08-01 15:22:37 -06001168 'section@0/u-boot:offset': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001169 'section@0/u-boot:size': len(U_BOOT_DATA),
Simon Glassdbf6be92018-08-01 15:22:42 -06001170 'section@0/u-boot:image-pos': 0,
Simon Glass3ab95982018-08-01 15:22:37 -06001171 'section@0:offset': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001172 'section@0:size': 16,
Simon Glassdbf6be92018-08-01 15:22:42 -06001173 'section@0:image-pos': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001174
Simon Glass3ab95982018-08-01 15:22:37 -06001175 'section@1/u-boot:offset': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001176 'section@1/u-boot:size': len(U_BOOT_DATA),
Simon Glassdbf6be92018-08-01 15:22:42 -06001177 'section@1/u-boot:image-pos': 16,
Simon Glass3ab95982018-08-01 15:22:37 -06001178 'section@1:offset': 16,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001179 'section@1:size': 16,
Simon Glassdbf6be92018-08-01 15:22:42 -06001180 'section@1:image-pos': 16,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001181 'size': 40
1182 }, props)
1183
1184 def testUpdateFdtBad(self):
1185 """Test that we detect when ProcessFdt never completes"""
1186 with self.assertRaises(ValueError) as e:
1187 self._DoReadFileDtb('61_fdt_update_bad.dts', update_dtb=True)
1188 self.assertIn('Could not complete processing of Fdt: remaining '
1189 '[<_testing.Entry__testing', str(e.exception))
Simon Glass5c890232018-07-06 10:27:19 -06001190
Simon Glass53af22a2018-07-17 13:25:32 -06001191 def testEntryArgs(self):
1192 """Test passing arguments to entries from the command line"""
1193 entry_args = {
1194 'test-str-arg': 'test1',
1195 'test-int-arg': '456',
1196 }
1197 self._DoReadFileDtb('62_entry_args.dts', entry_args=entry_args)
1198 self.assertIn('image', control.images)
1199 entry = control.images['image'].GetEntries()['_testing']
1200 self.assertEqual('test0', entry.test_str_fdt)
1201 self.assertEqual('test1', entry.test_str_arg)
1202 self.assertEqual(123, entry.test_int_fdt)
1203 self.assertEqual(456, entry.test_int_arg)
1204
1205 def testEntryArgsMissing(self):
1206 """Test missing arguments and properties"""
1207 entry_args = {
1208 'test-int-arg': '456',
1209 }
1210 self._DoReadFileDtb('63_entry_args_missing.dts', entry_args=entry_args)
1211 entry = control.images['image'].GetEntries()['_testing']
1212 self.assertEqual('test0', entry.test_str_fdt)
1213 self.assertEqual(None, entry.test_str_arg)
1214 self.assertEqual(None, entry.test_int_fdt)
1215 self.assertEqual(456, entry.test_int_arg)
1216
1217 def testEntryArgsRequired(self):
1218 """Test missing arguments and properties"""
1219 entry_args = {
1220 'test-int-arg': '456',
1221 }
1222 with self.assertRaises(ValueError) as e:
1223 self._DoReadFileDtb('64_entry_args_required.dts')
1224 self.assertIn("Node '/binman/_testing': Missing required "
1225 'properties/entry args: test-str-arg, test-int-fdt, test-int-arg',
1226 str(e.exception))
1227
1228 def testEntryArgsInvalidFormat(self):
1229 """Test that an invalid entry-argument format is detected"""
1230 args = ['-d', self.TestFile('64_entry_args_required.dts'), '-ano-value']
1231 with self.assertRaises(ValueError) as e:
1232 self._DoBinman(*args)
1233 self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
1234
1235 def testEntryArgsInvalidInteger(self):
1236 """Test that an invalid entry-argument integer is detected"""
1237 entry_args = {
1238 'test-int-arg': 'abc',
1239 }
1240 with self.assertRaises(ValueError) as e:
1241 self._DoReadFileDtb('62_entry_args.dts', entry_args=entry_args)
1242 self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
1243 "'test-int-arg' (value 'abc') to integer",
1244 str(e.exception))
1245
1246 def testEntryArgsInvalidDatatype(self):
1247 """Test that an invalid entry-argument datatype is detected
1248
1249 This test could be written in entry_test.py except that it needs
1250 access to control.entry_args, which seems more than that module should
1251 be able to see.
1252 """
1253 entry_args = {
1254 'test-bad-datatype-arg': '12',
1255 }
1256 with self.assertRaises(ValueError) as e:
1257 self._DoReadFileDtb('65_entry_args_unknown_datatype.dts',
1258 entry_args=entry_args)
1259 self.assertIn('GetArg() internal error: Unknown data type ',
1260 str(e.exception))
1261
Simon Glassbb748372018-07-17 13:25:33 -06001262 def testText(self):
1263 """Test for a text entry type"""
1264 entry_args = {
1265 'test-id': TEXT_DATA,
1266 'test-id2': TEXT_DATA2,
1267 'test-id3': TEXT_DATA3,
1268 }
1269 data, _, _, _ = self._DoReadFileDtb('66_text.dts',
1270 entry_args=entry_args)
1271 expected = (TEXT_DATA + chr(0) * (8 - len(TEXT_DATA)) + TEXT_DATA2 +
1272 TEXT_DATA3 + 'some text')
1273 self.assertEqual(expected, data)
1274
Simon Glassfd8d1f72018-07-17 13:25:36 -06001275 def testEntryDocs(self):
1276 """Test for creation of entry documentation"""
1277 with test_util.capture_sys_output() as (stdout, stderr):
1278 control.WriteEntryDocs(binman.GetEntryModules())
1279 self.assertTrue(len(stdout.getvalue()) > 0)
1280
1281 def testEntryDocsMissing(self):
1282 """Test handling of missing entry documentation"""
1283 with self.assertRaises(ValueError) as e:
1284 with test_util.capture_sys_output() as (stdout, stderr):
1285 control.WriteEntryDocs(binman.GetEntryModules(), 'u_boot')
1286 self.assertIn('Documentation is missing for modules: u_boot',
1287 str(e.exception))
1288
Simon Glass11e36cc2018-07-17 13:25:38 -06001289 def testFmap(self):
1290 """Basic test of generation of a flashrom fmap"""
1291 data = self._DoReadFile('67_fmap.dts')
1292 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1293 expected = U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12
1294 self.assertEqual(expected, data[:32])
1295 self.assertEqual('__FMAP__', fhdr.signature)
1296 self.assertEqual(1, fhdr.ver_major)
1297 self.assertEqual(0, fhdr.ver_minor)
1298 self.assertEqual(0, fhdr.base)
1299 self.assertEqual(16 + 16 +
1300 fmap_util.FMAP_HEADER_LEN +
1301 fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
1302 self.assertEqual('FMAP', fhdr.name)
1303 self.assertEqual(3, fhdr.nareas)
1304 for fentry in fentries:
1305 self.assertEqual(0, fentry.flags)
1306
1307 self.assertEqual(0, fentries[0].offset)
1308 self.assertEqual(4, fentries[0].size)
1309 self.assertEqual('RO_U_BOOT', fentries[0].name)
1310
1311 self.assertEqual(16, fentries[1].offset)
1312 self.assertEqual(4, fentries[1].size)
1313 self.assertEqual('RW_U_BOOT', fentries[1].name)
1314
1315 self.assertEqual(32, fentries[2].offset)
1316 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1317 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1318 self.assertEqual('FMAP', fentries[2].name)
1319
Simon Glassec127af2018-07-17 13:25:39 -06001320 def testBlobNamedByArg(self):
1321 """Test we can add a blob with the filename coming from an entry arg"""
1322 entry_args = {
1323 'cros-ec-rw-path': 'ecrw.bin',
1324 }
1325 data, _, _, _ = self._DoReadFileDtb('68_blob_named_by_arg.dts',
1326 entry_args=entry_args)
1327
Simon Glass3af8e492018-07-17 13:25:40 -06001328 def testFill(self):
1329 """Test for an fill entry type"""
1330 data = self._DoReadFile('69_fill.dts')
1331 expected = 8 * chr(0xff) + 8 * chr(0)
1332 self.assertEqual(expected, data)
1333
1334 def testFillNoSize(self):
1335 """Test for an fill entry type with no size"""
1336 with self.assertRaises(ValueError) as e:
1337 self._DoReadFile('70_fill_no_size.dts')
1338 self.assertIn("'fill' entry must have a size property",
1339 str(e.exception))
1340
Simon Glass0ef87aa2018-07-17 13:25:44 -06001341 def _HandleGbbCommand(self, pipe_list):
1342 """Fake calls to the futility utility"""
1343 if pipe_list[0][0] == 'futility':
1344 fname = pipe_list[0][-1]
1345 # Append our GBB data to the file, which will happen every time the
1346 # futility command is called.
1347 with open(fname, 'a') as fd:
1348 fd.write(GBB_DATA)
1349 return command.CommandResult()
1350
1351 def testGbb(self):
1352 """Test for the Chromium OS Google Binary Block"""
1353 command.test_result = self._HandleGbbCommand
1354 entry_args = {
1355 'keydir': 'devkeys',
1356 'bmpblk': 'bmpblk.bin',
1357 }
1358 data, _, _, _ = self._DoReadFileDtb('71_gbb.dts', entry_args=entry_args)
1359
1360 # Since futility
1361 expected = GBB_DATA + GBB_DATA + 8 * chr(0) + (0x2180 - 16) * chr(0)
1362 self.assertEqual(expected, data)
1363
1364 def testGbbTooSmall(self):
1365 """Test for the Chromium OS Google Binary Block being large enough"""
1366 with self.assertRaises(ValueError) as e:
1367 self._DoReadFileDtb('72_gbb_too_small.dts')
1368 self.assertIn("Node '/binman/gbb': GBB is too small",
1369 str(e.exception))
1370
1371 def testGbbNoSize(self):
1372 """Test for the Chromium OS Google Binary Block having a size"""
1373 with self.assertRaises(ValueError) as e:
1374 self._DoReadFileDtb('73_gbb_no_size.dts')
1375 self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
1376 str(e.exception))
1377
Simon Glass24d0d3c2018-07-17 13:25:47 -06001378 def _HandleVblockCommand(self, pipe_list):
1379 """Fake calls to the futility utility"""
1380 if pipe_list[0][0] == 'futility':
1381 fname = pipe_list[0][3]
Simon Glassa326b492018-09-14 04:57:11 -06001382 with open(fname, 'wb') as fd:
Simon Glass24d0d3c2018-07-17 13:25:47 -06001383 fd.write(VBLOCK_DATA)
1384 return command.CommandResult()
1385
1386 def testVblock(self):
1387 """Test for the Chromium OS Verified Boot Block"""
1388 command.test_result = self._HandleVblockCommand
1389 entry_args = {
1390 'keydir': 'devkeys',
1391 }
1392 data, _, _, _ = self._DoReadFileDtb('74_vblock.dts',
1393 entry_args=entry_args)
1394 expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
1395 self.assertEqual(expected, data)
1396
1397 def testVblockNoContent(self):
1398 """Test we detect a vblock which has no content to sign"""
1399 with self.assertRaises(ValueError) as e:
1400 self._DoReadFile('75_vblock_no_content.dts')
1401 self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
1402 'property', str(e.exception))
1403
1404 def testVblockBadPhandle(self):
1405 """Test that we detect a vblock with an invalid phandle in contents"""
1406 with self.assertRaises(ValueError) as e:
1407 self._DoReadFile('76_vblock_bad_phandle.dts')
1408 self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
1409 '1000', str(e.exception))
1410
1411 def testVblockBadEntry(self):
1412 """Test that we detect an entry that points to a non-entry"""
1413 with self.assertRaises(ValueError) as e:
1414 self._DoReadFile('77_vblock_bad_entry.dts')
1415 self.assertIn("Node '/binman/vblock': Cannot find entry for node "
1416 "'other'", str(e.exception))
1417
Simon Glassb8ef5b62018-07-17 13:25:48 -06001418 def testTpl(self):
1419 """Test that an image with TPL and ots device tree can be created"""
1420 # ELF file with a '__bss_size' symbol
1421 with open(self.TestFile('bss_data')) as fd:
1422 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1423 data = self._DoReadFile('78_u_boot_tpl.dts')
1424 self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
1425
Simon Glass15a587c2018-07-17 13:25:51 -06001426 def testUsesPos(self):
1427 """Test that the 'pos' property cannot be used anymore"""
1428 with self.assertRaises(ValueError) as e:
1429 data = self._DoReadFile('79_uses_pos.dts')
1430 self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
1431 "'pos'", str(e.exception))
1432
Simon Glassd178eab2018-09-14 04:57:08 -06001433 def testFillZero(self):
1434 """Test for an fill entry type with a size of 0"""
1435 data = self._DoReadFile('80_fill_empty.dts')
1436 self.assertEqual(chr(0) * 16, data)
1437
Simon Glass0b489362018-09-14 04:57:09 -06001438 def testTextMissing(self):
1439 """Test for a text entry type where there is no text"""
1440 with self.assertRaises(ValueError) as e:
1441 self._DoReadFileDtb('66_text.dts',)
1442 self.assertIn("Node '/binman/text': No value provided for text label "
1443 "'test-id'", str(e.exception))
1444
Simon Glass35b384c2018-09-14 04:57:10 -06001445 def testPackStart16Tpl(self):
1446 """Test that an image with an x86 start16 TPL region can be created"""
1447 data = self._DoReadFile('81_x86-start16-tpl.dts')
1448 self.assertEqual(X86_START16_TPL_DATA, data[:len(X86_START16_TPL_DATA)])
1449
Simon Glass0bfa7b02018-09-14 04:57:12 -06001450 def testSelectImage(self):
1451 """Test that we can select which images to build"""
1452 with test_util.capture_sys_output() as (stdout, stderr):
1453 retcode = self._DoTestFile('06_dual_image.dts', images=['image2'])
1454 self.assertEqual(0, retcode)
1455 self.assertIn('Skipping images: image1', stdout.getvalue())
1456
1457 self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
1458 self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
1459
Simon Glass6ed45ba2018-09-14 04:57:24 -06001460 def testUpdateFdtAll(self):
1461 """Test that all device trees are updated with offset/size info"""
1462 data, _, _, _ = self._DoReadFileDtb('82_fdt_update_all.dts',
1463 use_real_dtb=True, update_dtb=True)
1464
1465 base_expected = {
1466 'section:image-pos': 0,
1467 'u-boot-tpl-dtb:size': 513,
1468 'u-boot-spl-dtb:size': 513,
1469 'u-boot-spl-dtb:offset': 493,
1470 'image-pos': 0,
1471 'section/u-boot-dtb:image-pos': 0,
1472 'u-boot-spl-dtb:image-pos': 493,
1473 'section/u-boot-dtb:size': 493,
1474 'u-boot-tpl-dtb:image-pos': 1006,
1475 'section/u-boot-dtb:offset': 0,
1476 'section:size': 493,
1477 'offset': 0,
1478 'section:offset': 0,
1479 'u-boot-tpl-dtb:offset': 1006,
1480 'size': 1519
1481 }
1482
1483 # We expect three device-tree files in the output, one after the other.
1484 # Read them in sequence. We look for an 'spl' property in the SPL tree,
1485 # and 'tpl' in the TPL tree, to make sure they are distinct from the
1486 # main U-Boot tree. All three should have the same postions and offset.
1487 start = 0
1488 for item in ['', 'spl', 'tpl']:
1489 dtb = fdt.Fdt.FromData(data[start:])
1490 dtb.Scan()
1491 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos',
1492 'spl', 'tpl'])
1493 expected = dict(base_expected)
1494 if item:
1495 expected[item] = 0
1496 self.assertEqual(expected, props)
1497 start += dtb._fdt_obj.totalsize()
1498
1499 def testUpdateFdtOutput(self):
1500 """Test that output DTB files are updated"""
1501 try:
1502 data, dtb_data, _, _ = self._DoReadFileDtb('82_fdt_update_all.dts',
1503 use_real_dtb=True, update_dtb=True, reset_dtbs=False)
1504
1505 # Unfortunately, compiling a source file always results in a file
1506 # called source.dtb (see fdt_util.EnsureCompiled()). The test
1507 # source file (e.g. test/75_fdt_update_all.dts) thus does not enter
1508 # binman as a file called u-boot.dtb. To fix this, copy the file
1509 # over to the expected place.
1510 #tools.WriteFile(os.path.join(self._indir, 'u-boot.dtb'),
1511 #tools.ReadFile(tools.GetOutputFilename('source.dtb')))
1512 start = 0
1513 for fname in ['u-boot.dtb.out', 'spl/u-boot-spl.dtb.out',
1514 'tpl/u-boot-tpl.dtb.out']:
1515 dtb = fdt.Fdt.FromData(data[start:])
1516 size = dtb._fdt_obj.totalsize()
1517 pathname = tools.GetOutputFilename(os.path.split(fname)[1])
1518 outdata = tools.ReadFile(pathname)
1519 name = os.path.split(fname)[0]
1520
1521 if name:
1522 orig_indata = self._GetDtbContentsForSplTpl(dtb_data, name)
1523 else:
1524 orig_indata = dtb_data
1525 self.assertNotEqual(outdata, orig_indata,
1526 "Expected output file '%s' be updated" % pathname)
1527 self.assertEqual(outdata, data[start:start + size],
1528 "Expected output file '%s' to match output image" %
1529 pathname)
1530 start += size
1531 finally:
1532 self._ResetDtbs()
1533
Simon Glass83d73c22018-09-14 04:57:26 -06001534 def _decompress(self, data):
1535 out = os.path.join(self._indir, 'lz4.tmp')
1536 with open(out, 'wb') as fd:
1537 fd.write(data)
1538 return tools.Run('lz4', '-dc', out)
1539 '''
1540 try:
1541 orig = lz4.frame.decompress(data)
1542 except AttributeError:
1543 orig = lz4.decompress(data)
1544 '''
1545
1546 def testCompress(self):
1547 """Test compression of blobs"""
1548 data, _, _, out_dtb_fname = self._DoReadFileDtb('83_compress.dts',
1549 use_real_dtb=True, update_dtb=True)
1550 dtb = fdt.Fdt(out_dtb_fname)
1551 dtb.Scan()
1552 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
1553 orig = self._decompress(data)
1554 self.assertEquals(COMPRESS_DATA, orig)
1555 expected = {
1556 'blob:uncomp-size': len(COMPRESS_DATA),
1557 'blob:size': len(data),
1558 'size': len(data),
1559 }
1560 self.assertEqual(expected, props)
1561
Simon Glass0a98b282018-09-14 04:57:28 -06001562 def testFiles(self):
1563 """Test bringing in multiple files"""
1564 data = self._DoReadFile('84_files.dts')
1565 self.assertEqual(FILES_DATA, data)
1566
1567 def testFilesCompress(self):
1568 """Test bringing in multiple files and compressing them"""
1569 data = self._DoReadFile('85_files_compress.dts')
1570
1571 image = control.images['image']
1572 entries = image.GetEntries()
1573 files = entries['files']
1574 entries = files._section._entries
1575
1576 orig = ''
1577 for i in range(1, 3):
1578 key = '%d.dat' % i
1579 start = entries[key].image_pos
1580 len = entries[key].size
1581 chunk = data[start:start + len]
1582 orig += self._decompress(chunk)
1583
1584 self.assertEqual(FILES_DATA, orig)
1585
1586 def testFilesMissing(self):
1587 """Test missing files"""
1588 with self.assertRaises(ValueError) as e:
1589 data = self._DoReadFile('86_files_none.dts')
1590 self.assertIn("Node '/binman/files': Pattern \'files/*.none\' matched "
1591 'no files', str(e.exception))
1592
1593 def testFilesNoPattern(self):
1594 """Test missing files"""
1595 with self.assertRaises(ValueError) as e:
1596 data = self._DoReadFile('87_files_no_pattern.dts')
1597 self.assertIn("Node '/binman/files': Missing 'pattern' property",
1598 str(e.exception))
1599
Simon Glassba64a0b2018-09-14 04:57:29 -06001600 def testExpandSize(self):
1601 """Test an expanding entry"""
1602 data, _, map_data, _ = self._DoReadFileDtb('88_expand_size.dts',
1603 map=True)
1604 expect = ('a' * 8 + U_BOOT_DATA +
1605 MRC_DATA + 'b' * 1 + U_BOOT_DATA +
1606 'c' * 8 + U_BOOT_DATA +
1607 'd' * 8)
1608 self.assertEqual(expect, data)
1609 self.assertEqual('''ImagePos Offset Size Name
161000000000 00000000 00000028 main-section
161100000000 00000000 00000008 fill
161200000008 00000008 00000004 u-boot
16130000000c 0000000c 00000004 section
16140000000c 00000000 00000003 intel-mrc
161500000010 00000010 00000004 u-boot2
161600000014 00000014 0000000c section2
161700000014 00000000 00000008 fill
16180000001c 00000008 00000004 u-boot
161900000020 00000020 00000008 fill2
1620''', map_data)
1621
1622 def testExpandSizeBad(self):
1623 """Test an expanding entry which fails to provide contents"""
Simon Glass163ed6c2018-09-14 04:57:36 -06001624 with test_util.capture_sys_output() as (stdout, stderr):
1625 with self.assertRaises(ValueError) as e:
1626 self._DoReadFileDtb('89_expand_size_bad.dts', map=True)
Simon Glassba64a0b2018-09-14 04:57:29 -06001627 self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
1628 'expanding entry', str(e.exception))
1629
Simon Glasse0e5df92018-09-14 04:57:31 -06001630 def testHash(self):
1631 """Test hashing of the contents of an entry"""
1632 _, _, _, out_dtb_fname = self._DoReadFileDtb('90_hash.dts',
1633 use_real_dtb=True, update_dtb=True)
1634 dtb = fdt.Fdt(out_dtb_fname)
1635 dtb.Scan()
1636 hash_node = dtb.GetNode('/binman/u-boot/hash').props['value']
1637 m = hashlib.sha256()
1638 m.update(U_BOOT_DATA)
1639 self.assertEqual(m.digest(), ''.join(hash_node.value))
1640
1641 def testHashNoAlgo(self):
1642 with self.assertRaises(ValueError) as e:
1643 self._DoReadFileDtb('91_hash_no_algo.dts', update_dtb=True)
1644 self.assertIn("Node \'/binman/u-boot\': Missing \'algo\' property for "
1645 'hash node', str(e.exception))
1646
1647 def testHashBadAlgo(self):
1648 with self.assertRaises(ValueError) as e:
1649 self._DoReadFileDtb('92_hash_bad_algo.dts', update_dtb=True)
1650 self.assertIn("Node '/binman/u-boot': Unknown hash algorithm",
1651 str(e.exception))
1652
1653 def testHashSection(self):
1654 """Test hashing of the contents of an entry"""
1655 _, _, _, out_dtb_fname = self._DoReadFileDtb('99_hash_section.dts',
1656 use_real_dtb=True, update_dtb=True)
1657 dtb = fdt.Fdt(out_dtb_fname)
1658 dtb.Scan()
1659 hash_node = dtb.GetNode('/binman/section/hash').props['value']
1660 m = hashlib.sha256()
1661 m.update(U_BOOT_DATA)
1662 m.update(16 * 'a')
1663 self.assertEqual(m.digest(), ''.join(hash_node.value))
1664
Simon Glassf0253632018-09-14 04:57:32 -06001665 def testPackUBootTplMicrocode(self):
1666 """Test that x86 microcode can be handled correctly in TPL
1667
1668 We expect to see the following in the image, in order:
1669 u-boot-tpl-nodtb.bin with a microcode pointer inserted at the correct
1670 place
1671 u-boot-tpl.dtb with the microcode removed
1672 the microcode
1673 """
1674 with open(self.TestFile('u_boot_ucode_ptr')) as fd:
1675 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1676 first, pos_and_size = self._RunMicrocodeTest('93_x86_tpl_ucode.dts',
1677 U_BOOT_TPL_NODTB_DATA)
1678 self.assertEqual('tplnodtb with microc' + pos_and_size +
1679 'ter somewhere in here', first)
1680
Simon Glassf8f8df62018-09-14 04:57:34 -06001681 def testFmapX86(self):
1682 """Basic test of generation of a flashrom fmap"""
1683 data = self._DoReadFile('94_fmap_x86.dts')
1684 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1685 expected = U_BOOT_DATA + MRC_DATA + 'a' * (32 - 7)
1686 self.assertEqual(expected, data[:32])
1687 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1688
1689 self.assertEqual(0x100, fhdr.image_size)
1690
1691 self.assertEqual(0, fentries[0].offset)
1692 self.assertEqual(4, fentries[0].size)
1693 self.assertEqual('U_BOOT', fentries[0].name)
1694
1695 self.assertEqual(4, fentries[1].offset)
1696 self.assertEqual(3, fentries[1].size)
1697 self.assertEqual('INTEL_MRC', fentries[1].name)
1698
1699 self.assertEqual(32, fentries[2].offset)
1700 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1701 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1702 self.assertEqual('FMAP', fentries[2].name)
1703
1704 def testFmapX86Section(self):
1705 """Basic test of generation of a flashrom fmap"""
1706 data = self._DoReadFile('95_fmap_x86_section.dts')
1707 expected = U_BOOT_DATA + MRC_DATA + 'b' * (32 - 7)
1708 self.assertEqual(expected, data[:32])
1709 fhdr, fentries = fmap_util.DecodeFmap(data[36:])
1710
1711 self.assertEqual(0x100, fhdr.image_size)
1712
1713 self.assertEqual(0, fentries[0].offset)
1714 self.assertEqual(4, fentries[0].size)
1715 self.assertEqual('U_BOOT', fentries[0].name)
1716
1717 self.assertEqual(4, fentries[1].offset)
1718 self.assertEqual(3, fentries[1].size)
1719 self.assertEqual('INTEL_MRC', fentries[1].name)
1720
1721 self.assertEqual(36, fentries[2].offset)
1722 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1723 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1724 self.assertEqual('FMAP', fentries[2].name)
1725
Simon Glassfe1ae3e2018-09-14 04:57:35 -06001726 def testElf(self):
1727 """Basic test of ELF entries"""
1728 with open(self.TestFile('bss_data')) as fd:
1729 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
1730 with open(self.TestFile('bss_data')) as fd:
1731 TestFunctional._MakeInputFile('-boot', fd.read())
1732 data = self._DoReadFile('96_elf.dts')
1733
1734 def testElfStripg(self):
1735 """Basic test of ELF entries"""
1736 with open(self.TestFile('bss_data')) as fd:
1737 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
1738 with open(self.TestFile('bss_data')) as fd:
1739 TestFunctional._MakeInputFile('-boot', fd.read())
1740 data = self._DoReadFile('97_elf_strip.dts')
1741
Simon Glass163ed6c2018-09-14 04:57:36 -06001742 def testPackOverlapMap(self):
1743 """Test that overlapping regions are detected"""
1744 with test_util.capture_sys_output() as (stdout, stderr):
1745 with self.assertRaises(ValueError) as e:
1746 self._DoTestFile('14_pack_overlap.dts', map=True)
1747 map_fname = tools.GetOutputFilename('image.map')
1748 self.assertEqual("Wrote map file '%s' to show errors\n" % map_fname,
1749 stdout.getvalue())
1750
1751 # We should not get an inmage, but there should be a map file
1752 self.assertFalse(os.path.exists(tools.GetOutputFilename('image.bin')))
1753 self.assertTrue(os.path.exists(map_fname))
1754 map_data = tools.ReadFile(map_fname)
1755 self.assertEqual('''ImagePos Offset Size Name
1756<none> 00000000 00000007 main-section
1757<none> 00000000 00000004 u-boot
1758<none> 00000003 00000004 u-boot-align
1759''', map_data)
1760
Simon Glass53af22a2018-07-17 13:25:32 -06001761
Simon Glass9fc60b42017-11-12 21:52:22 -07001762if __name__ == "__main__":
1763 unittest.main()