blob: ed787745606408e969ef559861e2fe9f70bfefb5 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001# SPDX-License-Identifier: GPL-2.0+
Simon Glass57454f42016-11-25 20:15:52 -07002# Copyright (c) 2016 Google, Inc
3# Written by Simon Glass <sjg@chromium.org>
4#
Simon Glass57454f42016-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 Glassae7cf032018-09-14 04:57:31 -06009import hashlib
Simon Glass57454f42016-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 Glass4ca8e042017-11-13 18:55:01 -070022import elf
Simon Glassa9440932017-05-27 07:38:30 -060023import fdt
Simon Glass57454f42016-11-25 20:15:52 -070024import fdt_util
Simon Glass704784b2018-07-17 13:25:38 -060025import fmap_util
Simon Glass969616c2018-07-17 13:25:36 -060026import test_util
Simon Glass29aa7362018-09-14 04:57:19 -060027import state
Simon Glass57454f42016-11-25 20:15:52 -070028import tools
29import tout
30
31# Contents of test files, corresponding to different entry types
Simon Glass3d274232017-11-12 21:52:27 -070032U_BOOT_DATA = '1234'
33U_BOOT_IMG_DATA = 'img'
Simon Glassd6051522017-11-13 18:54:59 -070034U_BOOT_SPL_DATA = '56780123456789abcde'
Simon Glass8425a1f2018-07-17 13:25:48 -060035U_BOOT_TPL_DATA = 'tpl'
Simon Glass3d274232017-11-12 21:52:27 -070036BLOB_DATA = '89'
37ME_DATA = '0abcd'
38VGA_DATA = 'vga'
39U_BOOT_DTB_DATA = 'udtb'
Simon Glass9aa6a6f2017-11-13 18:54:55 -070040U_BOOT_SPL_DTB_DATA = 'spldtb'
Simon Glass8425a1f2018-07-17 13:25:48 -060041U_BOOT_TPL_DTB_DATA = 'tpldtb'
Simon Glass3d274232017-11-12 21:52:27 -070042X86_START16_DATA = 'start16'
43X86_START16_SPL_DATA = 'start16spl'
Simon Glassed40e962018-09-14 04:57:10 -060044X86_START16_TPL_DATA = 'start16tpl'
Jagdish Gediya311d4842018-09-03 21:35:08 +053045PPC_MPC85XX_BR_DATA = 'ppcmpc85xxbr'
Simon Glass3d274232017-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 Glass3fb4f422018-09-14 04:57:32 -060048U_BOOT_TPL_NODTB_DATA = 'tplnodtb with microcode pointer somewhere in here'
Simon Glass3d274232017-11-12 21:52:27 -070049FSP_DATA = 'fsp'
50CMC_DATA = 'cmc'
51VBT_DATA = 'vbt'
Simon Glassa409c932017-11-12 21:52:28 -070052MRC_DATA = 'mrc'
Simon Glass2ca52032018-07-17 13:25:33 -060053TEXT_DATA = 'text'
54TEXT_DATA2 = 'text2'
55TEXT_DATA3 = 'text3'
Simon Glassdb168d42018-07-17 13:25:39 -060056CROS_EC_RW_DATA = 'ecrw'
Simon Glassc1ae83c2018-07-17 13:25:44 -060057GBB_DATA = 'gbbd'
58BMPBLK_DATA = 'bmp'
Simon Glass5c350162018-07-17 13:25:47 -060059VBLOCK_DATA = 'vblk'
Simon Glassac6328c2018-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 Glass7ba33592018-09-14 04:57:26 -060062COMPRESS_DATA = 'data to compress'
Simon Glassdb168d42018-07-17 13:25:39 -060063
Simon Glass57454f42016-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 Glassb3393262017-11-12 21:52:20 -070081 global entry
82 import entry
83
Simon Glass57454f42016-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 Glass8425a1f2018-07-17 13:25:48 -060095 TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
Simon Glass57454f42016-11-25 20:15:52 -070096 TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
Simon Glass72232452016-11-25 20:15:53 -070097 TestFunctional._MakeInputFile('me.bin', ME_DATA)
98 TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
Simon Glass8425a1f2018-07-17 13:25:48 -060099 self._ResetDtbs()
Simon Glass72232452016-11-25 20:15:53 -0700100 TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
Jagdish Gediya311d4842018-09-03 21:35:08 +0530101 TestFunctional._MakeInputFile('u-boot-br.bin', PPC_MPC85XX_BR_DATA)
Simon Glasse83679d2017-11-12 21:52:26 -0700102 TestFunctional._MakeInputFile('spl/u-boot-x86-16bit-spl.bin',
103 X86_START16_SPL_DATA)
Simon Glassed40e962018-09-14 04:57:10 -0600104 TestFunctional._MakeInputFile('tpl/u-boot-x86-16bit-tpl.bin',
105 X86_START16_TPL_DATA)
Simon Glass57454f42016-11-25 20:15:52 -0700106 TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
Simon Glass3d274232017-11-12 21:52:27 -0700107 TestFunctional._MakeInputFile('spl/u-boot-spl-nodtb.bin',
108 U_BOOT_SPL_NODTB_DATA)
Simon Glass3fb4f422018-09-14 04:57:32 -0600109 TestFunctional._MakeInputFile('tpl/u-boot-tpl-nodtb.bin',
110 U_BOOT_TPL_NODTB_DATA)
Simon Glassb4176d42016-11-25 20:15:56 -0700111 TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
112 TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
Bin Mengd7bcdf52017-08-15 22:41:54 -0700113 TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
Simon Glassa409c932017-11-12 21:52:28 -0700114 TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
Simon Glassdb168d42018-07-17 13:25:39 -0600115 TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
Simon Glassc1ae83c2018-07-17 13:25:44 -0600116 TestFunctional._MakeInputDir('devkeys')
117 TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
Simon Glass57454f42016-11-25 20:15:52 -0700118
Simon Glass72232452016-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 Glassac6328c2018-09-14 04:57:28 -0600127 shutil.copytree(self.TestFile('files'),
128 os.path.join(self._indir, 'files'))
129
Simon Glass7ba33592018-09-14 04:57:26 -0600130 TestFunctional._MakeInputFile('compress', COMPRESS_DATA)
131
Simon Glass57454f42016-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 Glass8425a1f2018-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 Glass57454f42016-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 Glass075a45c2017-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 Glass57454f42016-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 Glass91710b32018-07-17 13:25:32 -0600187 def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
Simon Glass31402012018-09-14 04:57:23 -0600188 entry_args=None, images=None, use_real_dtb=False):
Simon Glass57454f42016-11-25 20:15:52 -0700189 """Run binman with a given test file
190
191 Args:
Simon Glass1e324002018-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 Glass30732662018-06-01 09:38:20 -0600194 map: True to output map files for the images
Simon Glasse8561af2018-08-01 15:22:37 -0600195 update_dtb: Update the offset and size of each entry in the device
Simon Glassa87014e2018-07-06 10:27:42 -0600196 tree before packing it into the image
Simon Glass3b376c32018-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 Glass57454f42016-11-25 20:15:52 -0700201 """
Simon Glass075a45c2017-11-13 18:55:00 -0700202 args = ['-p', '-I', self._indir, '-d', self.TestFile(fname)]
203 if debug:
204 args.append('-D')
Simon Glass30732662018-06-01 09:38:20 -0600205 if map:
206 args.append('-m')
Simon Glassa87014e2018-07-06 10:27:42 -0600207 if update_dtb:
208 args.append('-up')
Simon Glass31402012018-09-14 04:57:23 -0600209 if not use_real_dtb:
210 args.append('--fake-dtb')
Simon Glass91710b32018-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 Glass3b376c32018-09-14 04:57:12 -0600214 if images:
215 for image in images:
216 args += ['-i', image]
Simon Glass075a45c2017-11-13 18:55:00 -0700217 return self._DoBinman(*args)
Simon Glass57454f42016-11-25 20:15:52 -0700218
219 def _SetupDtb(self, fname, outfile='u-boot.dtb'):
Simon Glass72232452016-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 Glass1e324002018-06-01 09:38:19 -0600227 outfile: Output filename for compiled device-tree binary
Simon Glass72232452016-11-25 20:15:53 -0700228
229 Returns:
Simon Glass1e324002018-06-01 09:38:19 -0600230 Contents of device-tree binary
Simon Glass72232452016-11-25 20:15:53 -0700231 """
Simon Glass752e7552018-10-01 21:12:41 -0600232 tools.PrepareOutputDir(None)
Simon Glass57454f42016-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 Glass752e7552018-10-01 21:12:41 -0600237 tools.FinaliseOutputDir()
238 return data
Simon Glass57454f42016-11-25 20:15:52 -0700239
Simon Glasse219aa42018-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 Glassa87014e2018-07-06 10:27:42 -0600258 def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
Simon Glasse219aa42018-09-14 04:57:24 -0600259 update_dtb=False, entry_args=None, reset_dtbs=True):
Simon Glass57454f42016-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 Glass1e324002018-06-01 09:38:19 -0600269 fname: Device-tree source filename to use (e.g. 05_simple.dts)
Simon Glass57454f42016-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 Glass30732662018-06-01 09:38:20 -0600274 map: True to output map files for the images
Simon Glasse8561af2018-08-01 15:22:37 -0600275 update_dtb: Update the offset and size of each entry in the device
Simon Glassa87014e2018-07-06 10:27:42 -0600276 tree before packing it into the image
Simon Glass72232452016-11-25 20:15:53 -0700277
278 Returns:
279 Tuple:
280 Resulting image contents
281 Device tree contents
Simon Glass30732662018-06-01 09:38:20 -0600282 Map data showing contents of image (or None if none)
Simon Glassdef77b52018-07-17 13:25:27 -0600283 Output device tree binary filename ('u-boot.dtb' path)
Simon Glass57454f42016-11-25 20:15:52 -0700284 """
Simon Glass72232452016-11-25 20:15:53 -0700285 dtb_data = None
Simon Glass57454f42016-11-25 20:15:52 -0700286 # Use the compiled test file as the u-boot-dtb input
287 if use_real_dtb:
Simon Glass72232452016-11-25 20:15:53 -0700288 dtb_data = self._SetupDtb(fname)
Simon Glasse219aa42018-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 Glass57454f42016-11-25 20:15:52 -0700298
299 try:
Simon Glass91710b32018-07-17 13:25:32 -0600300 retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
Simon Glasse219aa42018-09-14 04:57:24 -0600301 entry_args=entry_args, use_real_dtb=use_real_dtb)
Simon Glass57454f42016-11-25 20:15:52 -0700302 self.assertEqual(0, retcode)
Simon Glasse219aa42018-09-14 04:57:24 -0600303 out_dtb_fname = tools.GetOutputFilename('u-boot.dtb.out')
Simon Glass57454f42016-11-25 20:15:52 -0700304
305 # Find the (only) image, read it and return its contents
306 image = control.images['image']
Simon Glassa87014e2018-07-06 10:27:42 -0600307 image_fname = tools.GetOutputFilename('image.bin')
308 self.assertTrue(os.path.exists(image_fname))
Simon Glass30732662018-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 Glassa87014e2018-07-06 10:27:42 -0600315 with open(image_fname) as fd:
316 return fd.read(), dtb_data, map_data, out_dtb_fname
Simon Glass57454f42016-11-25 20:15:52 -0700317 finally:
318 # Put the test file back
Simon Glasse219aa42018-09-14 04:57:24 -0600319 if reset_dtbs and use_real_dtb:
Simon Glass8425a1f2018-07-17 13:25:48 -0600320 self._ResetDtbs()
Simon Glass57454f42016-11-25 20:15:52 -0700321
Simon Glass72232452016-11-25 20:15:53 -0700322 def _DoReadFile(self, fname, use_real_dtb=False):
Simon Glass1e324002018-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 Glassdef77b52018-07-17 13:25:27 -0600331
332 Returns:
333 Resulting image contents
Simon Glass1e324002018-06-01 09:38:19 -0600334 """
Simon Glass72232452016-11-25 20:15:53 -0700335 return self._DoReadFileDtb(fname, use_real_dtb)[0]
336
Simon Glass57454f42016-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 Glasse8561af2018-08-01 15:22:37 -0600342 fname: Filename to create
Simon Glass57454f42016-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 Glassc1ae83c2018-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 Glass57454f42016-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 Glasse8561af2018-08-01 15:22:37 -0600392 offset = 0
Simon Glass57454f42016-11-25 20:15:52 -0700393 for entry in entries.values():
Simon Glasse8561af2018-08-01 15:22:37 -0600394 self.assertEqual(offset, entry.offset)
395 offset += entry.size
Simon Glass57454f42016-11-25 20:15:52 -0700396
Simon Glass72232452016-11-25 20:15:53 -0700397 def GetFdtLen(self, dtb):
Simon Glass1e324002018-06-01 09:38:19 -0600398 """Get the totalsize field from a device-tree binary
Simon Glass72232452016-11-25 20:15:53 -0700399
400 Args:
Simon Glass1e324002018-06-01 09:38:19 -0600401 dtb: Device-tree binary contents
Simon Glass72232452016-11-25 20:15:53 -0700402
403 Returns:
Simon Glass1e324002018-06-01 09:38:19 -0600404 Total size of device-tree binary, from the header
Simon Glass72232452016-11-25 20:15:53 -0700405 """
406 return struct.unpack('>L', dtb[4:8])[0]
407
Simon Glass5463a6a2018-07-17 13:25:52 -0600408 def _GetPropTree(self, dtb, prop_names):
Simon Glassa87014e2018-07-06 10:27:42 -0600409 def AddNode(node, path):
410 if node.name != '/':
411 path += '/' + node.name
Simon Glassa87014e2018-07-06 10:27:42 -0600412 for subnode in node.subnodes:
413 for prop in subnode.props.values():
Simon Glass5463a6a2018-07-17 13:25:52 -0600414 if prop.name in prop_names:
Simon Glassa87014e2018-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 Glassa87014e2018-07-06 10:27:42 -0600418 AddNode(subnode, path)
419
420 tree = {}
Simon Glassa87014e2018-07-06 10:27:42 -0600421 AddNode(dtb.GetRoot(), '')
422 return tree
423
Simon Glass57454f42016-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 Rinic3c0b6d2018-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 Glass57454f42016-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 Glass57454f42016-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 Glass1e324002018-06-01 09:38:19 -0600470 """Test that an invalid device-tree file generates an error"""
Simon Glass57454f42016-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 Glass1e324002018-06-01 09:38:19 -0600478 """Test that an invalid device-tree source file generates an error
Simon Glass57454f42016-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 Glass57454f42016-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 Glass075a45c2017-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 Glass57454f42016-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 Glasseca32212018-06-01 09:38:12 -0600556 entries = image.GetEntries()
Simon Glass57454f42016-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 Glasse8561af2018-08-01 15:22:37 -0600562 self.assertEqual(0, entry.offset)
Simon Glass57454f42016-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 Glasse8561af2018-08-01 15:22:37 -0600568 self.assertEqual(16, entry.offset)
Simon Glass57454f42016-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 Glasse8561af2018-08-01 15:22:37 -0600574 self.assertEqual(20, entry.offset)
Simon Glass57454f42016-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 Glasse8561af2018-08-01 15:22:37 -0600581 self.assertEqual(43, entry.offset)
Simon Glass57454f42016-11-25 20:15:52 -0700582 self.assertEqual(len(U_BOOT_DATA), entry.size)
583
Simon Glasse8561af2018-08-01 15:22:37 -0600584 # Fifth u-boot, placed at a fixed offset
Simon Glass57454f42016-11-25 20:15:52 -0700585 self.assertIn('u-boot-fixed', entries)
586 entry = entries['u-boot-fixed']
Simon Glasse8561af2018-08-01 15:22:37 -0600587 self.assertEqual(61, entry.offset)
Simon Glass57454f42016-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 Glasseca32212018-06-01 09:38:12 -0600599 entries = image.GetEntries()
Simon Glass57454f42016-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 Glasse8561af2018-08-01 15:22:37 -0600605 self.assertEqual(0, entry.offset)
Simon Glass57454f42016-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 Glasse8561af2018-08-01 15:22:37 -0600612 self.assertEqual(12, entry.offset)
Simon Glass57454f42016-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 Glasse8561af2018-08-01 15:22:37 -0600618 self.assertEqual(16, entry.offset)
Simon Glass57454f42016-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 Glasse8561af2018-08-01 15:22:37 -0600624 self.assertEqual(48, entry.offset)
Simon Glass57454f42016-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 Glasse8561af2018-08-01 15:22:37 -0600630 self.assertEqual(64, entry.offset)
Simon Glass57454f42016-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 Glasse8561af2018-08-01 15:22:37 -0600651 """Test detection of an offset that does not match its alignment"""
Simon Glass57454f42016-11-25 20:15:52 -0700652 with self.assertRaises(ValueError) as e:
653 self._DoTestFile('12_pack_inv_align.dts')
Simon Glasse8561af2018-08-01 15:22:37 -0600654 self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
Simon Glass57454f42016-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 Glasse8561af2018-08-01 15:22:37 -0600668 self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
Simon Glass57454f42016-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 Glasseca32212018-06-01 09:38:12 -0600683 self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section "
Simon Glass57454f42016-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 Glasseca32212018-06-01 09:38:12 -0600706 self.assertIn("Section '/binman': Size 0x7 (7) does not match "
Simon Glass57454f42016-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 Glasseca32212018-06-01 09:38:12 -0600713 self.assertIn("Section '/binman': Alignment size 131 must be a power of "
Simon Glass57454f42016-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 Glass4ca8e042017-11-13 18:55:01 -0700718 with open(self.TestFile('bss_data')) as fd:
719 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
Simon Glass57454f42016-11-25 20:15:52 -0700720 data = self._DoReadFile('21_image_pad.dts')
Simon Glassd6051522017-11-13 18:54:59 -0700721 self.assertEqual(U_BOOT_SPL_DATA + (chr(0xff) * 1) + U_BOOT_DATA, data)
Simon Glass57454f42016-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 Glassd6051522017-11-13 18:54:59 -0700743 self.assertEqual(chr(0) * 1 + U_BOOT_SPL_DATA + chr(0) * 2 +
Simon Glass57454f42016-11-25 20:15:52 -0700744 U_BOOT_DATA, data)
745
Simon Glasse8561af2018-08-01 15:22:37 -0600746 def testPackZeroOffset(self):
747 """Test that an entry at offset 0 is not given a new offset"""
Simon Glass57454f42016-11-25 20:15:52 -0700748 with self.assertRaises(ValueError) as e:
749 self._DoTestFile('25_pack_zero_size.dts')
Simon Glasse8561af2018-08-01 15:22:37 -0600750 self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
Simon Glass57454f42016-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 Glass72232452016-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 Glasseca32212018-06-01 09:38:12 -0600763 self.assertIn("Section '/binman': Section size must be provided when "
Simon Glass72232452016-11-25 20:15:53 -0700764 "using end-at-4gb", str(e.exception))
765
Jagdish Gediya0fb978c2018-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 Glass72232452016-11-25 20:15:53 -0700774 def testPackX86RomOutside(self):
Simon Glasse8561af2018-08-01 15:22:37 -0600775 """Test that the end-at-4gb property checks for offset boundaries"""
Simon Glass72232452016-11-25 20:15:53 -0700776 with self.assertRaises(ValueError) as e:
777 self._DoTestFile('28_pack_4gb_outside.dts')
Simon Glasse8561af2018-08-01 15:22:37 -0600778 self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
Simon Glasseca32212018-06-01 09:38:12 -0600779 "the section starting at 0xffffffe0 (4294967264)",
Simon Glass72232452016-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 Glassd6051522017-11-13 18:54:59 -0700785 self.assertEqual(U_BOOT_DATA + chr(0) * 7 + U_BOOT_SPL_DATA +
786 chr(0) * 2, data)
Simon Glass72232452016-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 Glasse8561af2018-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 Glass72232452016-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 Gediya311d4842018-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 Glass6ba679c2018-07-06 10:27:17 -0600825 def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False):
Simon Glass820af1d2018-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 Glass6ba679c2018-07-06 10:27:17 -0600831 ucode_second: True if the microsecond entry is second instead of
832 third
Simon Glass820af1d2018-07-06 10:27:16 -0600833
834 Returns:
835 Tuple:
836 Contents of first region (U-Boot or SPL)
Simon Glasse8561af2018-08-01 15:22:37 -0600837 Offset and size components of microcode pointer, as inserted
Simon Glass820af1d2018-07-06 10:27:16 -0600838 in the above (two 4-byte words)
839 """
Simon Glass3d274232017-11-12 21:52:27 -0700840 data = self._DoReadFile(dts_fname, True)
Simon Glass72232452016-11-25 20:15:53 -0700841
842 # Now check the device tree has no microcode
Simon Glass6ba679c2018-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 Glass72232452016-11-25 20:15:53 -0700853 fname = tools.GetOutputFilename('test.dtb')
854 with open(fname, 'wb') as fd:
Simon Glass820af1d2018-07-06 10:27:16 -0600855 fd.write(dtb_with_ucode)
Simon Glass22c92ca2017-05-27 07:38:29 -0600856 dtb = fdt.FdtScan(fname)
857 ucode = dtb.GetNode('/microcode')
Simon Glass72232452016-11-25 20:15:53 -0700858 self.assertTrue(ucode)
859 for node in ucode.subnodes:
860 self.assertFalse(node.props.get('data'))
861
Simon Glass72232452016-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 Glasse83679d2017-11-12 21:52:26 -0700864 # the /microcode/update@xxx nodes in 34_x86_ucode.dts.
Simon Glass72232452016-11-25 20:15:53 -0700865 ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
866 0x78235609)
Simon Glass820af1d2018-07-06 10:27:16 -0600867 self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
Simon Glass72232452016-11-25 20:15:53 -0700868
869 # Check that the microcode pointer was inserted. It should match the
Simon Glasse8561af2018-08-01 15:22:37 -0600870 # expected offset and size
Simon Glass72232452016-11-25 20:15:53 -0700871 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
872 len(ucode_data))
Simon Glass6ba679c2018-07-06 10:27:17 -0600873 u_boot = data[:len(nodtb_data)]
874 return u_boot, pos_and_size
Simon Glass3d274232017-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 Glass72232452016-11-25 20:15:53 -0700887 self.assertEqual('nodtb with microcode' + pos_and_size +
888 ' somewhere in here', first)
889
Simon Glassbac25c82017-05-27 07:38:26 -0600890 def _RunPackUbootSingleMicrocode(self):
Simon Glass72232452016-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 Glass72232452016-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 Glassbac25c82017-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 Glass72232452016-11-25 20:15:53 -0700913
Simon Glassbac25c82017-05-27 07:38:26 -0600914 # Check that the microcode pointer was inserted. It should match the
Simon Glasse8561af2018-08-01 15:22:37 -0600915 # expected offset and size
Simon Glassbac25c82017-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 Glass996021e2016-11-25 20:15:54 -0700921
Simon Glassd2dfb5f2016-11-25 20:15:55 -0700922 def testPackUbootSingleMicrocode(self):
923 """Test that x86 microcode can be handled correctly with fdt_normal.
924 """
Simon Glassbac25c82017-05-27 07:38:26 -0600925 self._RunPackUbootSingleMicrocode()
Simon Glassd2dfb5f2016-11-25 20:15:55 -0700926
Simon Glass996021e2016-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 Glassd2dfb5f2016-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 Glassd2dfb5f2016-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 Glassbac25c82017-05-27 07:38:26 -0600961 self._RunPackUbootSingleMicrocode()
Simon Glassd2dfb5f2016-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 Glassad5a7712018-06-01 09:38:14 -0600976 "section ranging from 00000000 to 0000002e", str(e.exception))
Simon Glassd2dfb5f2016-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 Glassa87014e2018-07-06 10:27:42 -0600982 data, dtb, _, _ = self._DoReadFileDtb('44_x86_optional_ucode.dts', True)
Simon Glassd2dfb5f2016-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 Glasse8561af2018-08-01 15:22:37 -0600999 self.assertIn("Section '/binman': Unable to set offset/size for unknown "
Simon Glassd2dfb5f2016-11-25 20:15:55 -07001000 "entry 'invalid-entry'", str(e.exception))
Simon Glassb4176d42016-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 Mengd7bcdf52017-08-15 22:41:54 -07001008 """Test that an image with a CMC binary can be created"""
Simon Glassb4176d42016-11-25 20:15:56 -07001009 data = self._DoReadFile('43_intel-cmc.dts')
1010 self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
Bin Mengd7bcdf52017-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 Glassac599912017-11-12 21:52:22 -07001016
Simon Glass7f94e832017-11-12 21:52:25 -07001017 def testSplBssPad(self):
1018 """Test that we can pad SPL's BSS with zeros"""
Simon Glass3d274232017-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 Glass7f94e832017-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 Glass04cda032018-10-01 21:12:42 -06001025 def testSplBssPadMissing(self):
1026 """Test that a missing symbol is detected"""
Simon Glass24ad3652017-11-13 18:54:54 -07001027 with open(self.TestFile('u_boot_ucode_ptr')) as fd:
1028 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
1029 with self.assertRaises(ValueError) as e:
Simon Glass04cda032018-10-01 21:12:42 -06001030 self._DoReadFile('47_spl_bss_pad.dts')
Simon Glass24ad3652017-11-13 18:54:54 -07001031 self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
1032 str(e.exception))
1033
Simon Glasse83679d2017-11-12 21:52:26 -07001034 def testPackStart16Spl(self):
Simon Glassed40e962018-09-14 04:57:10 -06001035 """Test that an image with an x86 start16 SPL region can be created"""
Simon Glasse83679d2017-11-12 21:52:26 -07001036 data = self._DoReadFile('48_x86-start16-spl.dts')
1037 self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)])
1038
Simon Glass6ba679c2018-07-06 10:27:17 -06001039 def _PackUbootSplMicrocode(self, dts, ucode_second=False):
1040 """Helper function for microcode tests
Simon Glass3d274232017-11-12 21:52:27 -07001041
1042 We expect to see the following in the image, in order:
1043 u-boot-spl-nodtb.bin with a microcode pointer inserted at the
1044 correct place
1045 u-boot.dtb with the microcode removed
1046 the microcode
Simon Glass6ba679c2018-07-06 10:27:17 -06001047
1048 Args:
1049 dts: Device tree file to use for test
1050 ucode_second: True if the microsecond entry is second instead of
1051 third
Simon Glass3d274232017-11-12 21:52:27 -07001052 """
1053 # ELF file with a '_dt_ucode_base_size' symbol
1054 with open(self.TestFile('u_boot_ucode_ptr')) as fd:
1055 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
Simon Glass6ba679c2018-07-06 10:27:17 -06001056 first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA,
1057 ucode_second=ucode_second)
Simon Glass3d274232017-11-12 21:52:27 -07001058 self.assertEqual('splnodtb with microc' + pos_and_size +
1059 'ter somewhere in here', first)
1060
Simon Glass6ba679c2018-07-06 10:27:17 -06001061 def testPackUbootSplMicrocode(self):
1062 """Test that x86 microcode can be handled correctly in SPL"""
1063 self._PackUbootSplMicrocode('49_x86_ucode_spl.dts')
1064
1065 def testPackUbootSplMicrocodeReorder(self):
1066 """Test that order doesn't matter for microcode entries
1067
1068 This is the same as testPackUbootSplMicrocode but when we process the
1069 u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode
1070 entry, so we reply on binman to try later.
1071 """
1072 self._PackUbootSplMicrocode('58_x86_ucode_spl_needs_retry.dts',
1073 ucode_second=True)
1074
Simon Glassa409c932017-11-12 21:52:28 -07001075 def testPackMrc(self):
1076 """Test that an image with an MRC binary can be created"""
1077 data = self._DoReadFile('50_intel_mrc.dts')
1078 self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
1079
Simon Glass9aa6a6f2017-11-13 18:54:55 -07001080 def testSplDtb(self):
1081 """Test that an image with spl/u-boot-spl.dtb can be created"""
1082 data = self._DoReadFile('51_u_boot_spl_dtb.dts')
1083 self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
1084
Simon Glass0a6da312017-11-13 18:54:56 -07001085 def testSplNoDtb(self):
1086 """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
1087 data = self._DoReadFile('52_u_boot_spl_nodtb.dts')
1088 self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
1089
Simon Glass4ca8e042017-11-13 18:55:01 -07001090 def testSymbols(self):
1091 """Test binman can assign symbols embedded in U-Boot"""
1092 elf_fname = self.TestFile('u_boot_binman_syms')
1093 syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
1094 addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
Simon Glasse8561af2018-08-01 15:22:37 -06001095 self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
Simon Glass4ca8e042017-11-13 18:55:01 -07001096
1097 with open(self.TestFile('u_boot_binman_syms')) as fd:
1098 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
1099 data = self._DoReadFile('53_symbols.dts')
1100 sym_values = struct.pack('<LQL', 0x24 + 0, 0x24 + 24, 0x24 + 20)
1101 expected = (sym_values + U_BOOT_SPL_DATA[16:] + chr(0xff) +
1102 U_BOOT_DATA +
1103 sym_values + U_BOOT_SPL_DATA[16:])
1104 self.assertEqual(expected, data)
1105
Simon Glasse76a3e62018-06-01 09:38:11 -06001106 def testPackUnitAddress(self):
1107 """Test that we support multiple binaries with the same name"""
1108 data = self._DoReadFile('54_unit_address.dts')
1109 self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
1110
Simon Glassa91e1152018-06-01 09:38:16 -06001111 def testSections(self):
1112 """Basic test of sections"""
1113 data = self._DoReadFile('55_sections.dts')
Simon Glass3a9a2b82018-07-17 13:25:28 -06001114 expected = (U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12 +
1115 U_BOOT_DATA + '&' * 4)
Simon Glassa91e1152018-06-01 09:38:16 -06001116 self.assertEqual(expected, data)
Simon Glassac599912017-11-12 21:52:22 -07001117
Simon Glass30732662018-06-01 09:38:20 -06001118 def testMap(self):
1119 """Tests outputting a map of the images"""
Simon Glassa87014e2018-07-06 10:27:42 -06001120 _, _, map_data, _ = self._DoReadFileDtb('55_sections.dts', map=True)
Simon Glass7eca7922018-07-17 13:25:49 -06001121 self.assertEqual('''ImagePos Offset Size Name
112200000000 00000000 00000028 main-section
112300000000 00000000 00000010 section@0
112400000000 00000000 00000004 u-boot
112500000010 00000010 00000010 section@1
112600000010 00000000 00000004 u-boot
112700000020 00000020 00000004 section@2
112800000020 00000000 00000004 u-boot
Simon Glass30732662018-06-01 09:38:20 -06001129''', map_data)
1130
Simon Glass3b78d532018-06-01 09:38:21 -06001131 def testNamePrefix(self):
1132 """Tests that name prefixes are used"""
Simon Glassa87014e2018-07-06 10:27:42 -06001133 _, _, map_data, _ = self._DoReadFileDtb('56_name_prefix.dts', map=True)
Simon Glass7eca7922018-07-17 13:25:49 -06001134 self.assertEqual('''ImagePos Offset Size Name
113500000000 00000000 00000028 main-section
113600000000 00000000 00000010 section@0
113700000000 00000000 00000004 ro-u-boot
113800000010 00000010 00000010 section@1
113900000010 00000000 00000004 rw-u-boot
Simon Glass3b78d532018-06-01 09:38:21 -06001140''', map_data)
1141
Simon Glass6ba679c2018-07-06 10:27:17 -06001142 def testUnknownContents(self):
1143 """Test that obtaining the contents works as expected"""
1144 with self.assertRaises(ValueError) as e:
1145 self._DoReadFile('57_unknown_contents.dts', True)
1146 self.assertIn("Section '/binman': Internal error: Could not complete "
1147 "processing of contents: remaining [<_testing.Entry__testing ",
1148 str(e.exception))
1149
Simon Glass2e1169f2018-07-06 10:27:19 -06001150 def testBadChangeSize(self):
1151 """Test that trying to change the size of an entry fails"""
1152 with self.assertRaises(ValueError) as e:
1153 self._DoReadFile('59_change_size.dts', True)
1154 self.assertIn("Node '/binman/_testing': Cannot update entry size from "
1155 '2 to 1', str(e.exception))
1156
Simon Glassa87014e2018-07-06 10:27:42 -06001157 def testUpdateFdt(self):
Simon Glasse8561af2018-08-01 15:22:37 -06001158 """Test that we can update the device tree with offset/size info"""
Simon Glassa87014e2018-07-06 10:27:42 -06001159 _, _, _, out_dtb_fname = self._DoReadFileDtb('60_fdt_update.dts',
1160 update_dtb=True)
Simon Glass5463a6a2018-07-17 13:25:52 -06001161 dtb = fdt.Fdt(out_dtb_fname)
1162 dtb.Scan()
1163 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'])
Simon Glassa87014e2018-07-06 10:27:42 -06001164 self.assertEqual({
Simon Glass9dcc8612018-08-01 15:22:42 -06001165 'image-pos': 0,
Simon Glass3a9a2b82018-07-17 13:25:28 -06001166 'offset': 0,
Simon Glasse8561af2018-08-01 15:22:37 -06001167 '_testing:offset': 32,
Simon Glassa87014e2018-07-06 10:27:42 -06001168 '_testing:size': 1,
Simon Glass9dcc8612018-08-01 15:22:42 -06001169 '_testing:image-pos': 32,
Simon Glasse8561af2018-08-01 15:22:37 -06001170 'section@0/u-boot:offset': 0,
Simon Glassa87014e2018-07-06 10:27:42 -06001171 'section@0/u-boot:size': len(U_BOOT_DATA),
Simon Glass9dcc8612018-08-01 15:22:42 -06001172 'section@0/u-boot:image-pos': 0,
Simon Glasse8561af2018-08-01 15:22:37 -06001173 'section@0:offset': 0,
Simon Glassa87014e2018-07-06 10:27:42 -06001174 'section@0:size': 16,
Simon Glass9dcc8612018-08-01 15:22:42 -06001175 'section@0:image-pos': 0,
Simon Glassa87014e2018-07-06 10:27:42 -06001176
Simon Glasse8561af2018-08-01 15:22:37 -06001177 'section@1/u-boot:offset': 0,
Simon Glassa87014e2018-07-06 10:27:42 -06001178 'section@1/u-boot:size': len(U_BOOT_DATA),
Simon Glass9dcc8612018-08-01 15:22:42 -06001179 'section@1/u-boot:image-pos': 16,
Simon Glasse8561af2018-08-01 15:22:37 -06001180 'section@1:offset': 16,
Simon Glassa87014e2018-07-06 10:27:42 -06001181 'section@1:size': 16,
Simon Glass9dcc8612018-08-01 15:22:42 -06001182 'section@1:image-pos': 16,
Simon Glassa87014e2018-07-06 10:27:42 -06001183 'size': 40
1184 }, props)
1185
1186 def testUpdateFdtBad(self):
1187 """Test that we detect when ProcessFdt never completes"""
1188 with self.assertRaises(ValueError) as e:
1189 self._DoReadFileDtb('61_fdt_update_bad.dts', update_dtb=True)
1190 self.assertIn('Could not complete processing of Fdt: remaining '
1191 '[<_testing.Entry__testing', str(e.exception))
Simon Glass2e1169f2018-07-06 10:27:19 -06001192
Simon Glass91710b32018-07-17 13:25:32 -06001193 def testEntryArgs(self):
1194 """Test passing arguments to entries from the command line"""
1195 entry_args = {
1196 'test-str-arg': 'test1',
1197 'test-int-arg': '456',
1198 }
1199 self._DoReadFileDtb('62_entry_args.dts', entry_args=entry_args)
1200 self.assertIn('image', control.images)
1201 entry = control.images['image'].GetEntries()['_testing']
1202 self.assertEqual('test0', entry.test_str_fdt)
1203 self.assertEqual('test1', entry.test_str_arg)
1204 self.assertEqual(123, entry.test_int_fdt)
1205 self.assertEqual(456, entry.test_int_arg)
1206
1207 def testEntryArgsMissing(self):
1208 """Test missing arguments and properties"""
1209 entry_args = {
1210 'test-int-arg': '456',
1211 }
1212 self._DoReadFileDtb('63_entry_args_missing.dts', entry_args=entry_args)
1213 entry = control.images['image'].GetEntries()['_testing']
1214 self.assertEqual('test0', entry.test_str_fdt)
1215 self.assertEqual(None, entry.test_str_arg)
1216 self.assertEqual(None, entry.test_int_fdt)
1217 self.assertEqual(456, entry.test_int_arg)
1218
1219 def testEntryArgsRequired(self):
1220 """Test missing arguments and properties"""
1221 entry_args = {
1222 'test-int-arg': '456',
1223 }
1224 with self.assertRaises(ValueError) as e:
1225 self._DoReadFileDtb('64_entry_args_required.dts')
1226 self.assertIn("Node '/binman/_testing': Missing required "
1227 'properties/entry args: test-str-arg, test-int-fdt, test-int-arg',
1228 str(e.exception))
1229
1230 def testEntryArgsInvalidFormat(self):
1231 """Test that an invalid entry-argument format is detected"""
1232 args = ['-d', self.TestFile('64_entry_args_required.dts'), '-ano-value']
1233 with self.assertRaises(ValueError) as e:
1234 self._DoBinman(*args)
1235 self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
1236
1237 def testEntryArgsInvalidInteger(self):
1238 """Test that an invalid entry-argument integer is detected"""
1239 entry_args = {
1240 'test-int-arg': 'abc',
1241 }
1242 with self.assertRaises(ValueError) as e:
1243 self._DoReadFileDtb('62_entry_args.dts', entry_args=entry_args)
1244 self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
1245 "'test-int-arg' (value 'abc') to integer",
1246 str(e.exception))
1247
1248 def testEntryArgsInvalidDatatype(self):
1249 """Test that an invalid entry-argument datatype is detected
1250
1251 This test could be written in entry_test.py except that it needs
1252 access to control.entry_args, which seems more than that module should
1253 be able to see.
1254 """
1255 entry_args = {
1256 'test-bad-datatype-arg': '12',
1257 }
1258 with self.assertRaises(ValueError) as e:
1259 self._DoReadFileDtb('65_entry_args_unknown_datatype.dts',
1260 entry_args=entry_args)
1261 self.assertIn('GetArg() internal error: Unknown data type ',
1262 str(e.exception))
1263
Simon Glass2ca52032018-07-17 13:25:33 -06001264 def testText(self):
1265 """Test for a text entry type"""
1266 entry_args = {
1267 'test-id': TEXT_DATA,
1268 'test-id2': TEXT_DATA2,
1269 'test-id3': TEXT_DATA3,
1270 }
1271 data, _, _, _ = self._DoReadFileDtb('66_text.dts',
1272 entry_args=entry_args)
1273 expected = (TEXT_DATA + chr(0) * (8 - len(TEXT_DATA)) + TEXT_DATA2 +
1274 TEXT_DATA3 + 'some text')
1275 self.assertEqual(expected, data)
1276
Simon Glass969616c2018-07-17 13:25:36 -06001277 def testEntryDocs(self):
1278 """Test for creation of entry documentation"""
1279 with test_util.capture_sys_output() as (stdout, stderr):
1280 control.WriteEntryDocs(binman.GetEntryModules())
1281 self.assertTrue(len(stdout.getvalue()) > 0)
1282
1283 def testEntryDocsMissing(self):
1284 """Test handling of missing entry documentation"""
1285 with self.assertRaises(ValueError) as e:
1286 with test_util.capture_sys_output() as (stdout, stderr):
1287 control.WriteEntryDocs(binman.GetEntryModules(), 'u_boot')
1288 self.assertIn('Documentation is missing for modules: u_boot',
1289 str(e.exception))
1290
Simon Glass704784b2018-07-17 13:25:38 -06001291 def testFmap(self):
1292 """Basic test of generation of a flashrom fmap"""
1293 data = self._DoReadFile('67_fmap.dts')
1294 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1295 expected = U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12
1296 self.assertEqual(expected, data[:32])
1297 self.assertEqual('__FMAP__', fhdr.signature)
1298 self.assertEqual(1, fhdr.ver_major)
1299 self.assertEqual(0, fhdr.ver_minor)
1300 self.assertEqual(0, fhdr.base)
1301 self.assertEqual(16 + 16 +
1302 fmap_util.FMAP_HEADER_LEN +
1303 fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
1304 self.assertEqual('FMAP', fhdr.name)
1305 self.assertEqual(3, fhdr.nareas)
1306 for fentry in fentries:
1307 self.assertEqual(0, fentry.flags)
1308
1309 self.assertEqual(0, fentries[0].offset)
1310 self.assertEqual(4, fentries[0].size)
1311 self.assertEqual('RO_U_BOOT', fentries[0].name)
1312
1313 self.assertEqual(16, fentries[1].offset)
1314 self.assertEqual(4, fentries[1].size)
1315 self.assertEqual('RW_U_BOOT', fentries[1].name)
1316
1317 self.assertEqual(32, fentries[2].offset)
1318 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1319 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1320 self.assertEqual('FMAP', fentries[2].name)
1321
Simon Glassdb168d42018-07-17 13:25:39 -06001322 def testBlobNamedByArg(self):
1323 """Test we can add a blob with the filename coming from an entry arg"""
1324 entry_args = {
1325 'cros-ec-rw-path': 'ecrw.bin',
1326 }
1327 data, _, _, _ = self._DoReadFileDtb('68_blob_named_by_arg.dts',
1328 entry_args=entry_args)
1329
Simon Glass53f53992018-07-17 13:25:40 -06001330 def testFill(self):
1331 """Test for an fill entry type"""
1332 data = self._DoReadFile('69_fill.dts')
1333 expected = 8 * chr(0xff) + 8 * chr(0)
1334 self.assertEqual(expected, data)
1335
1336 def testFillNoSize(self):
1337 """Test for an fill entry type with no size"""
1338 with self.assertRaises(ValueError) as e:
1339 self._DoReadFile('70_fill_no_size.dts')
1340 self.assertIn("'fill' entry must have a size property",
1341 str(e.exception))
1342
Simon Glassc1ae83c2018-07-17 13:25:44 -06001343 def _HandleGbbCommand(self, pipe_list):
1344 """Fake calls to the futility utility"""
1345 if pipe_list[0][0] == 'futility':
1346 fname = pipe_list[0][-1]
1347 # Append our GBB data to the file, which will happen every time the
1348 # futility command is called.
1349 with open(fname, 'a') as fd:
1350 fd.write(GBB_DATA)
1351 return command.CommandResult()
1352
1353 def testGbb(self):
1354 """Test for the Chromium OS Google Binary Block"""
1355 command.test_result = self._HandleGbbCommand
1356 entry_args = {
1357 'keydir': 'devkeys',
1358 'bmpblk': 'bmpblk.bin',
1359 }
1360 data, _, _, _ = self._DoReadFileDtb('71_gbb.dts', entry_args=entry_args)
1361
1362 # Since futility
1363 expected = GBB_DATA + GBB_DATA + 8 * chr(0) + (0x2180 - 16) * chr(0)
1364 self.assertEqual(expected, data)
1365
1366 def testGbbTooSmall(self):
1367 """Test for the Chromium OS Google Binary Block being large enough"""
1368 with self.assertRaises(ValueError) as e:
1369 self._DoReadFileDtb('72_gbb_too_small.dts')
1370 self.assertIn("Node '/binman/gbb': GBB is too small",
1371 str(e.exception))
1372
1373 def testGbbNoSize(self):
1374 """Test for the Chromium OS Google Binary Block having a size"""
1375 with self.assertRaises(ValueError) as e:
1376 self._DoReadFileDtb('73_gbb_no_size.dts')
1377 self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
1378 str(e.exception))
1379
Simon Glass5c350162018-07-17 13:25:47 -06001380 def _HandleVblockCommand(self, pipe_list):
1381 """Fake calls to the futility utility"""
1382 if pipe_list[0][0] == 'futility':
1383 fname = pipe_list[0][3]
Simon Glass639505b2018-09-14 04:57:11 -06001384 with open(fname, 'wb') as fd:
Simon Glass5c350162018-07-17 13:25:47 -06001385 fd.write(VBLOCK_DATA)
1386 return command.CommandResult()
1387
1388 def testVblock(self):
1389 """Test for the Chromium OS Verified Boot Block"""
1390 command.test_result = self._HandleVblockCommand
1391 entry_args = {
1392 'keydir': 'devkeys',
1393 }
1394 data, _, _, _ = self._DoReadFileDtb('74_vblock.dts',
1395 entry_args=entry_args)
1396 expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
1397 self.assertEqual(expected, data)
1398
1399 def testVblockNoContent(self):
1400 """Test we detect a vblock which has no content to sign"""
1401 with self.assertRaises(ValueError) as e:
1402 self._DoReadFile('75_vblock_no_content.dts')
1403 self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
1404 'property', str(e.exception))
1405
1406 def testVblockBadPhandle(self):
1407 """Test that we detect a vblock with an invalid phandle in contents"""
1408 with self.assertRaises(ValueError) as e:
1409 self._DoReadFile('76_vblock_bad_phandle.dts')
1410 self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
1411 '1000', str(e.exception))
1412
1413 def testVblockBadEntry(self):
1414 """Test that we detect an entry that points to a non-entry"""
1415 with self.assertRaises(ValueError) as e:
1416 self._DoReadFile('77_vblock_bad_entry.dts')
1417 self.assertIn("Node '/binman/vblock': Cannot find entry for node "
1418 "'other'", str(e.exception))
1419
Simon Glass8425a1f2018-07-17 13:25:48 -06001420 def testTpl(self):
1421 """Test that an image with TPL and ots device tree can be created"""
1422 # ELF file with a '__bss_size' symbol
1423 with open(self.TestFile('bss_data')) as fd:
1424 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1425 data = self._DoReadFile('78_u_boot_tpl.dts')
1426 self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
1427
Simon Glass24b97442018-07-17 13:25:51 -06001428 def testUsesPos(self):
1429 """Test that the 'pos' property cannot be used anymore"""
1430 with self.assertRaises(ValueError) as e:
1431 data = self._DoReadFile('79_uses_pos.dts')
1432 self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
1433 "'pos'", str(e.exception))
1434
Simon Glass274bf092018-09-14 04:57:08 -06001435 def testFillZero(self):
1436 """Test for an fill entry type with a size of 0"""
1437 data = self._DoReadFile('80_fill_empty.dts')
1438 self.assertEqual(chr(0) * 16, data)
1439
Simon Glass267de432018-09-14 04:57:09 -06001440 def testTextMissing(self):
1441 """Test for a text entry type where there is no text"""
1442 with self.assertRaises(ValueError) as e:
1443 self._DoReadFileDtb('66_text.dts',)
1444 self.assertIn("Node '/binman/text': No value provided for text label "
1445 "'test-id'", str(e.exception))
1446
Simon Glassed40e962018-09-14 04:57:10 -06001447 def testPackStart16Tpl(self):
1448 """Test that an image with an x86 start16 TPL region can be created"""
1449 data = self._DoReadFile('81_x86-start16-tpl.dts')
1450 self.assertEqual(X86_START16_TPL_DATA, data[:len(X86_START16_TPL_DATA)])
1451
Simon Glass3b376c32018-09-14 04:57:12 -06001452 def testSelectImage(self):
1453 """Test that we can select which images to build"""
1454 with test_util.capture_sys_output() as (stdout, stderr):
1455 retcode = self._DoTestFile('06_dual_image.dts', images=['image2'])
1456 self.assertEqual(0, retcode)
1457 self.assertIn('Skipping images: image1', stdout.getvalue())
1458
1459 self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
1460 self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
1461
Simon Glasse219aa42018-09-14 04:57:24 -06001462 def testUpdateFdtAll(self):
1463 """Test that all device trees are updated with offset/size info"""
1464 data, _, _, _ = self._DoReadFileDtb('82_fdt_update_all.dts',
1465 use_real_dtb=True, update_dtb=True)
1466
1467 base_expected = {
1468 'section:image-pos': 0,
1469 'u-boot-tpl-dtb:size': 513,
1470 'u-boot-spl-dtb:size': 513,
1471 'u-boot-spl-dtb:offset': 493,
1472 'image-pos': 0,
1473 'section/u-boot-dtb:image-pos': 0,
1474 'u-boot-spl-dtb:image-pos': 493,
1475 'section/u-boot-dtb:size': 493,
1476 'u-boot-tpl-dtb:image-pos': 1006,
1477 'section/u-boot-dtb:offset': 0,
1478 'section:size': 493,
1479 'offset': 0,
1480 'section:offset': 0,
1481 'u-boot-tpl-dtb:offset': 1006,
1482 'size': 1519
1483 }
1484
1485 # We expect three device-tree files in the output, one after the other.
1486 # Read them in sequence. We look for an 'spl' property in the SPL tree,
1487 # and 'tpl' in the TPL tree, to make sure they are distinct from the
1488 # main U-Boot tree. All three should have the same postions and offset.
1489 start = 0
1490 for item in ['', 'spl', 'tpl']:
1491 dtb = fdt.Fdt.FromData(data[start:])
1492 dtb.Scan()
1493 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos',
1494 'spl', 'tpl'])
1495 expected = dict(base_expected)
1496 if item:
1497 expected[item] = 0
1498 self.assertEqual(expected, props)
1499 start += dtb._fdt_obj.totalsize()
1500
1501 def testUpdateFdtOutput(self):
1502 """Test that output DTB files are updated"""
1503 try:
1504 data, dtb_data, _, _ = self._DoReadFileDtb('82_fdt_update_all.dts',
1505 use_real_dtb=True, update_dtb=True, reset_dtbs=False)
1506
1507 # Unfortunately, compiling a source file always results in a file
1508 # called source.dtb (see fdt_util.EnsureCompiled()). The test
1509 # source file (e.g. test/75_fdt_update_all.dts) thus does not enter
1510 # binman as a file called u-boot.dtb. To fix this, copy the file
1511 # over to the expected place.
1512 #tools.WriteFile(os.path.join(self._indir, 'u-boot.dtb'),
1513 #tools.ReadFile(tools.GetOutputFilename('source.dtb')))
1514 start = 0
1515 for fname in ['u-boot.dtb.out', 'spl/u-boot-spl.dtb.out',
1516 'tpl/u-boot-tpl.dtb.out']:
1517 dtb = fdt.Fdt.FromData(data[start:])
1518 size = dtb._fdt_obj.totalsize()
1519 pathname = tools.GetOutputFilename(os.path.split(fname)[1])
1520 outdata = tools.ReadFile(pathname)
1521 name = os.path.split(fname)[0]
1522
1523 if name:
1524 orig_indata = self._GetDtbContentsForSplTpl(dtb_data, name)
1525 else:
1526 orig_indata = dtb_data
1527 self.assertNotEqual(outdata, orig_indata,
1528 "Expected output file '%s' be updated" % pathname)
1529 self.assertEqual(outdata, data[start:start + size],
1530 "Expected output file '%s' to match output image" %
1531 pathname)
1532 start += size
1533 finally:
1534 self._ResetDtbs()
1535
Simon Glass7ba33592018-09-14 04:57:26 -06001536 def _decompress(self, data):
1537 out = os.path.join(self._indir, 'lz4.tmp')
1538 with open(out, 'wb') as fd:
1539 fd.write(data)
1540 return tools.Run('lz4', '-dc', out)
1541 '''
1542 try:
1543 orig = lz4.frame.decompress(data)
1544 except AttributeError:
1545 orig = lz4.decompress(data)
1546 '''
1547
1548 def testCompress(self):
1549 """Test compression of blobs"""
1550 data, _, _, out_dtb_fname = self._DoReadFileDtb('83_compress.dts',
1551 use_real_dtb=True, update_dtb=True)
1552 dtb = fdt.Fdt(out_dtb_fname)
1553 dtb.Scan()
1554 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
1555 orig = self._decompress(data)
1556 self.assertEquals(COMPRESS_DATA, orig)
1557 expected = {
1558 'blob:uncomp-size': len(COMPRESS_DATA),
1559 'blob:size': len(data),
1560 'size': len(data),
1561 }
1562 self.assertEqual(expected, props)
1563
Simon Glassac6328c2018-09-14 04:57:28 -06001564 def testFiles(self):
1565 """Test bringing in multiple files"""
1566 data = self._DoReadFile('84_files.dts')
1567 self.assertEqual(FILES_DATA, data)
1568
1569 def testFilesCompress(self):
1570 """Test bringing in multiple files and compressing them"""
1571 data = self._DoReadFile('85_files_compress.dts')
1572
1573 image = control.images['image']
1574 entries = image.GetEntries()
1575 files = entries['files']
1576 entries = files._section._entries
1577
1578 orig = ''
1579 for i in range(1, 3):
1580 key = '%d.dat' % i
1581 start = entries[key].image_pos
1582 len = entries[key].size
1583 chunk = data[start:start + len]
1584 orig += self._decompress(chunk)
1585
1586 self.assertEqual(FILES_DATA, orig)
1587
1588 def testFilesMissing(self):
1589 """Test missing files"""
1590 with self.assertRaises(ValueError) as e:
1591 data = self._DoReadFile('86_files_none.dts')
1592 self.assertIn("Node '/binman/files': Pattern \'files/*.none\' matched "
1593 'no files', str(e.exception))
1594
1595 def testFilesNoPattern(self):
1596 """Test missing files"""
1597 with self.assertRaises(ValueError) as e:
1598 data = self._DoReadFile('87_files_no_pattern.dts')
1599 self.assertIn("Node '/binman/files': Missing 'pattern' property",
1600 str(e.exception))
1601
Simon Glassfa79a812018-09-14 04:57:29 -06001602 def testExpandSize(self):
1603 """Test an expanding entry"""
1604 data, _, map_data, _ = self._DoReadFileDtb('88_expand_size.dts',
1605 map=True)
1606 expect = ('a' * 8 + U_BOOT_DATA +
1607 MRC_DATA + 'b' * 1 + U_BOOT_DATA +
1608 'c' * 8 + U_BOOT_DATA +
1609 'd' * 8)
1610 self.assertEqual(expect, data)
1611 self.assertEqual('''ImagePos Offset Size Name
161200000000 00000000 00000028 main-section
161300000000 00000000 00000008 fill
161400000008 00000008 00000004 u-boot
16150000000c 0000000c 00000004 section
16160000000c 00000000 00000003 intel-mrc
161700000010 00000010 00000004 u-boot2
161800000014 00000014 0000000c section2
161900000014 00000000 00000008 fill
16200000001c 00000008 00000004 u-boot
162100000020 00000020 00000008 fill2
1622''', map_data)
1623
1624 def testExpandSizeBad(self):
1625 """Test an expanding entry which fails to provide contents"""
Simon Glasscd817d52018-09-14 04:57:36 -06001626 with test_util.capture_sys_output() as (stdout, stderr):
1627 with self.assertRaises(ValueError) as e:
1628 self._DoReadFileDtb('89_expand_size_bad.dts', map=True)
Simon Glassfa79a812018-09-14 04:57:29 -06001629 self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
1630 'expanding entry', str(e.exception))
1631
Simon Glassae7cf032018-09-14 04:57:31 -06001632 def testHash(self):
1633 """Test hashing of the contents of an entry"""
1634 _, _, _, out_dtb_fname = self._DoReadFileDtb('90_hash.dts',
1635 use_real_dtb=True, update_dtb=True)
1636 dtb = fdt.Fdt(out_dtb_fname)
1637 dtb.Scan()
1638 hash_node = dtb.GetNode('/binman/u-boot/hash').props['value']
1639 m = hashlib.sha256()
1640 m.update(U_BOOT_DATA)
1641 self.assertEqual(m.digest(), ''.join(hash_node.value))
1642
1643 def testHashNoAlgo(self):
1644 with self.assertRaises(ValueError) as e:
1645 self._DoReadFileDtb('91_hash_no_algo.dts', update_dtb=True)
1646 self.assertIn("Node \'/binman/u-boot\': Missing \'algo\' property for "
1647 'hash node', str(e.exception))
1648
1649 def testHashBadAlgo(self):
1650 with self.assertRaises(ValueError) as e:
1651 self._DoReadFileDtb('92_hash_bad_algo.dts', update_dtb=True)
1652 self.assertIn("Node '/binman/u-boot': Unknown hash algorithm",
1653 str(e.exception))
1654
1655 def testHashSection(self):
1656 """Test hashing of the contents of an entry"""
1657 _, _, _, out_dtb_fname = self._DoReadFileDtb('99_hash_section.dts',
1658 use_real_dtb=True, update_dtb=True)
1659 dtb = fdt.Fdt(out_dtb_fname)
1660 dtb.Scan()
1661 hash_node = dtb.GetNode('/binman/section/hash').props['value']
1662 m = hashlib.sha256()
1663 m.update(U_BOOT_DATA)
1664 m.update(16 * 'a')
1665 self.assertEqual(m.digest(), ''.join(hash_node.value))
1666
Simon Glass3fb4f422018-09-14 04:57:32 -06001667 def testPackUBootTplMicrocode(self):
1668 """Test that x86 microcode can be handled correctly in TPL
1669
1670 We expect to see the following in the image, in order:
1671 u-boot-tpl-nodtb.bin with a microcode pointer inserted at the correct
1672 place
1673 u-boot-tpl.dtb with the microcode removed
1674 the microcode
1675 """
1676 with open(self.TestFile('u_boot_ucode_ptr')) as fd:
1677 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1678 first, pos_and_size = self._RunMicrocodeTest('93_x86_tpl_ucode.dts',
1679 U_BOOT_TPL_NODTB_DATA)
1680 self.assertEqual('tplnodtb with microc' + pos_and_size +
1681 'ter somewhere in here', first)
1682
Simon Glassc64aea52018-09-14 04:57:34 -06001683 def testFmapX86(self):
1684 """Basic test of generation of a flashrom fmap"""
1685 data = self._DoReadFile('94_fmap_x86.dts')
1686 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1687 expected = U_BOOT_DATA + MRC_DATA + 'a' * (32 - 7)
1688 self.assertEqual(expected, data[:32])
1689 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1690
1691 self.assertEqual(0x100, fhdr.image_size)
1692
1693 self.assertEqual(0, fentries[0].offset)
1694 self.assertEqual(4, fentries[0].size)
1695 self.assertEqual('U_BOOT', fentries[0].name)
1696
1697 self.assertEqual(4, fentries[1].offset)
1698 self.assertEqual(3, fentries[1].size)
1699 self.assertEqual('INTEL_MRC', fentries[1].name)
1700
1701 self.assertEqual(32, fentries[2].offset)
1702 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1703 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1704 self.assertEqual('FMAP', fentries[2].name)
1705
1706 def testFmapX86Section(self):
1707 """Basic test of generation of a flashrom fmap"""
1708 data = self._DoReadFile('95_fmap_x86_section.dts')
1709 expected = U_BOOT_DATA + MRC_DATA + 'b' * (32 - 7)
1710 self.assertEqual(expected, data[:32])
1711 fhdr, fentries = fmap_util.DecodeFmap(data[36:])
1712
1713 self.assertEqual(0x100, fhdr.image_size)
1714
1715 self.assertEqual(0, fentries[0].offset)
1716 self.assertEqual(4, fentries[0].size)
1717 self.assertEqual('U_BOOT', fentries[0].name)
1718
1719 self.assertEqual(4, fentries[1].offset)
1720 self.assertEqual(3, fentries[1].size)
1721 self.assertEqual('INTEL_MRC', fentries[1].name)
1722
1723 self.assertEqual(36, fentries[2].offset)
1724 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1725 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1726 self.assertEqual('FMAP', fentries[2].name)
1727
Simon Glassb1714232018-09-14 04:57:35 -06001728 def testElf(self):
1729 """Basic test of ELF entries"""
1730 with open(self.TestFile('bss_data')) as fd:
1731 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
1732 with open(self.TestFile('bss_data')) as fd:
1733 TestFunctional._MakeInputFile('-boot', fd.read())
1734 data = self._DoReadFile('96_elf.dts')
1735
1736 def testElfStripg(self):
1737 """Basic test of ELF entries"""
1738 with open(self.TestFile('bss_data')) as fd:
1739 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
1740 with open(self.TestFile('bss_data')) as fd:
1741 TestFunctional._MakeInputFile('-boot', fd.read())
1742 data = self._DoReadFile('97_elf_strip.dts')
1743
Simon Glasscd817d52018-09-14 04:57:36 -06001744 def testPackOverlapMap(self):
1745 """Test that overlapping regions are detected"""
1746 with test_util.capture_sys_output() as (stdout, stderr):
1747 with self.assertRaises(ValueError) as e:
1748 self._DoTestFile('14_pack_overlap.dts', map=True)
1749 map_fname = tools.GetOutputFilename('image.map')
1750 self.assertEqual("Wrote map file '%s' to show errors\n" % map_fname,
1751 stdout.getvalue())
1752
1753 # We should not get an inmage, but there should be a map file
1754 self.assertFalse(os.path.exists(tools.GetOutputFilename('image.bin')))
1755 self.assertTrue(os.path.exists(map_fname))
1756 map_data = tools.ReadFile(map_fname)
1757 self.assertEqual('''ImagePos Offset Size Name
1758<none> 00000000 00000007 main-section
1759<none> 00000000 00000004 u-boot
1760<none> 00000003 00000004 u-boot-align
1761''', map_data)
1762
Simon Glass91710b32018-07-17 13:25:32 -06001763
Simon Glassac599912017-11-12 21:52:22 -07001764if __name__ == "__main__":
1765 unittest.main()