blob: c4065551e798135d51f9313501788a459397b99d [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
9from optparse import OptionParser
10import os
11import shutil
12import struct
13import sys
14import tempfile
15import unittest
16
17import binman
18import cmdline
19import command
20import control
Simon Glass19790632017-11-13 18:55:01 -070021import elf
Simon Glass99ed4a22017-05-27 07:38:30 -060022import fdt
Simon Glass4f443042016-11-25 20:15:52 -070023import fdt_util
Simon Glass11e36cc2018-07-17 13:25:38 -060024import fmap_util
Simon Glassfd8d1f72018-07-17 13:25:36 -060025import test_util
Simon Glass4f443042016-11-25 20:15:52 -070026import tools
27import tout
28
29# Contents of test files, corresponding to different entry types
Simon Glass6b187df2017-11-12 21:52:27 -070030U_BOOT_DATA = '1234'
31U_BOOT_IMG_DATA = 'img'
Simon Glassf6898902017-11-13 18:54:59 -070032U_BOOT_SPL_DATA = '56780123456789abcde'
Simon Glassb8ef5b62018-07-17 13:25:48 -060033U_BOOT_TPL_DATA = 'tpl'
Simon Glass6b187df2017-11-12 21:52:27 -070034BLOB_DATA = '89'
35ME_DATA = '0abcd'
36VGA_DATA = 'vga'
37U_BOOT_DTB_DATA = 'udtb'
Simon Glass47419ea2017-11-13 18:54:55 -070038U_BOOT_SPL_DTB_DATA = 'spldtb'
Simon Glassb8ef5b62018-07-17 13:25:48 -060039U_BOOT_TPL_DTB_DATA = 'tpldtb'
Simon Glass6b187df2017-11-12 21:52:27 -070040X86_START16_DATA = 'start16'
41X86_START16_SPL_DATA = 'start16spl'
Simon Glass35b384c2018-09-14 04:57:10 -060042X86_START16_TPL_DATA = 'start16tpl'
Simon Glass6b187df2017-11-12 21:52:27 -070043U_BOOT_NODTB_DATA = 'nodtb with microcode pointer somewhere in here'
44U_BOOT_SPL_NODTB_DATA = 'splnodtb with microcode pointer somewhere in here'
45FSP_DATA = 'fsp'
46CMC_DATA = 'cmc'
47VBT_DATA = 'vbt'
Simon Glassca4f4ff2017-11-12 21:52:28 -070048MRC_DATA = 'mrc'
Simon Glassbb748372018-07-17 13:25:33 -060049TEXT_DATA = 'text'
50TEXT_DATA2 = 'text2'
51TEXT_DATA3 = 'text3'
Simon Glassec127af2018-07-17 13:25:39 -060052CROS_EC_RW_DATA = 'ecrw'
Simon Glass0ef87aa2018-07-17 13:25:44 -060053GBB_DATA = 'gbbd'
54BMPBLK_DATA = 'bmp'
Simon Glass24d0d3c2018-07-17 13:25:47 -060055VBLOCK_DATA = 'vblk'
Simon Glassec127af2018-07-17 13:25:39 -060056
Simon Glass4f443042016-11-25 20:15:52 -070057
58class TestFunctional(unittest.TestCase):
59 """Functional tests for binman
60
61 Most of these use a sample .dts file to build an image and then check
62 that it looks correct. The sample files are in the test/ subdirectory
63 and are numbered.
64
65 For each entry type a very small test file is created using fixed
66 string contents. This makes it easy to test that things look right, and
67 debug problems.
68
69 In some cases a 'real' file must be used - these are also supplied in
70 the test/ diurectory.
71 """
72 @classmethod
73 def setUpClass(self):
Simon Glass4d5994f2017-11-12 21:52:20 -070074 global entry
75 import entry
76
Simon Glass4f443042016-11-25 20:15:52 -070077 # Handle the case where argv[0] is 'python'
78 self._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
79 self._binman_pathname = os.path.join(self._binman_dir, 'binman')
80
81 # Create a temporary directory for input files
82 self._indir = tempfile.mkdtemp(prefix='binmant.')
83
84 # Create some test files
85 TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
86 TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
87 TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
Simon Glassb8ef5b62018-07-17 13:25:48 -060088 TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
Simon Glass4f443042016-11-25 20:15:52 -070089 TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
Simon Glasse0ff8552016-11-25 20:15:53 -070090 TestFunctional._MakeInputFile('me.bin', ME_DATA)
91 TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
Simon Glassb8ef5b62018-07-17 13:25:48 -060092 self._ResetDtbs()
Simon Glasse0ff8552016-11-25 20:15:53 -070093 TestFunctional._MakeInputFile('u-boot-x86-16bit.bin', X86_START16_DATA)
Simon Glass87722132017-11-12 21:52:26 -070094 TestFunctional._MakeInputFile('spl/u-boot-x86-16bit-spl.bin',
95 X86_START16_SPL_DATA)
Simon Glass35b384c2018-09-14 04:57:10 -060096 TestFunctional._MakeInputFile('tpl/u-boot-x86-16bit-tpl.bin',
97 X86_START16_TPL_DATA)
Simon Glass4f443042016-11-25 20:15:52 -070098 TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
Simon Glass6b187df2017-11-12 21:52:27 -070099 TestFunctional._MakeInputFile('spl/u-boot-spl-nodtb.bin',
100 U_BOOT_SPL_NODTB_DATA)
Simon Glassda229092016-11-25 20:15:56 -0700101 TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
102 TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
Bin Meng59ea8c22017-08-15 22:41:54 -0700103 TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
Simon Glassca4f4ff2017-11-12 21:52:28 -0700104 TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
Simon Glassec127af2018-07-17 13:25:39 -0600105 TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
Simon Glass0ef87aa2018-07-17 13:25:44 -0600106 TestFunctional._MakeInputDir('devkeys')
107 TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
Simon Glass4f443042016-11-25 20:15:52 -0700108 self._output_setup = False
109
Simon Glasse0ff8552016-11-25 20:15:53 -0700110 # ELF file with a '_dt_ucode_base_size' symbol
111 with open(self.TestFile('u_boot_ucode_ptr')) as fd:
112 TestFunctional._MakeInputFile('u-boot', fd.read())
113
114 # Intel flash descriptor file
115 with open(self.TestFile('descriptor.bin')) as fd:
116 TestFunctional._MakeInputFile('descriptor.bin', fd.read())
117
Simon Glass4f443042016-11-25 20:15:52 -0700118 @classmethod
119 def tearDownClass(self):
120 """Remove the temporary input directory and its contents"""
121 if self._indir:
122 shutil.rmtree(self._indir)
123 self._indir = None
124
125 def setUp(self):
126 # Enable this to turn on debugging output
127 # tout.Init(tout.DEBUG)
128 command.test_result = None
129
130 def tearDown(self):
131 """Remove the temporary output directory"""
132 tools._FinaliseForTest()
133
Simon Glassb8ef5b62018-07-17 13:25:48 -0600134 @classmethod
135 def _ResetDtbs(self):
136 TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
137 TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
138 TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
139
Simon Glass4f443042016-11-25 20:15:52 -0700140 def _RunBinman(self, *args, **kwargs):
141 """Run binman using the command line
142
143 Args:
144 Arguments to pass, as a list of strings
145 kwargs: Arguments to pass to Command.RunPipe()
146 """
147 result = command.RunPipe([[self._binman_pathname] + list(args)],
148 capture=True, capture_stderr=True, raise_on_error=False)
149 if result.return_code and kwargs.get('raise_on_error', True):
150 raise Exception("Error running '%s': %s" % (' '.join(args),
151 result.stdout + result.stderr))
152 return result
153
154 def _DoBinman(self, *args):
155 """Run binman using directly (in the same process)
156
157 Args:
158 Arguments to pass, as a list of strings
159 Returns:
160 Return value (0 for success)
161 """
Simon Glass7fe91732017-11-13 18:55:00 -0700162 args = list(args)
163 if '-D' in sys.argv:
164 args = args + ['-D']
165 (options, args) = cmdline.ParseArgs(args)
Simon Glass4f443042016-11-25 20:15:52 -0700166 options.pager = 'binman-invalid-pager'
167 options.build_dir = self._indir
168
169 # For testing, you can force an increase in verbosity here
170 # options.verbosity = tout.DEBUG
171 return control.Binman(options, args)
172
Simon Glass53af22a2018-07-17 13:25:32 -0600173 def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
174 entry_args=None):
Simon Glass4f443042016-11-25 20:15:52 -0700175 """Run binman with a given test file
176
177 Args:
Simon Glass7ae5f312018-06-01 09:38:19 -0600178 fname: Device-tree source filename to use (e.g. 05_simple.dts)
179 debug: True to enable debugging output
Simon Glass3b0c3822018-06-01 09:38:20 -0600180 map: True to output map files for the images
Simon Glass3ab95982018-08-01 15:22:37 -0600181 update_dtb: Update the offset and size of each entry in the device
Simon Glass16b8d6b2018-07-06 10:27:42 -0600182 tree before packing it into the image
Simon Glass4f443042016-11-25 20:15:52 -0700183 """
Simon Glass7fe91732017-11-13 18:55:00 -0700184 args = ['-p', '-I', self._indir, '-d', self.TestFile(fname)]
185 if debug:
186 args.append('-D')
Simon Glass3b0c3822018-06-01 09:38:20 -0600187 if map:
188 args.append('-m')
Simon Glass16b8d6b2018-07-06 10:27:42 -0600189 if update_dtb:
190 args.append('-up')
Simon Glass53af22a2018-07-17 13:25:32 -0600191 if entry_args:
192 for arg, value in entry_args.iteritems():
193 args.append('-a%s=%s' % (arg, value))
Simon Glass7fe91732017-11-13 18:55:00 -0700194 return self._DoBinman(*args)
Simon Glass4f443042016-11-25 20:15:52 -0700195
196 def _SetupDtb(self, fname, outfile='u-boot.dtb'):
Simon Glasse0ff8552016-11-25 20:15:53 -0700197 """Set up a new test device-tree file
198
199 The given file is compiled and set up as the device tree to be used
200 for ths test.
201
202 Args:
203 fname: Filename of .dts file to read
Simon Glass7ae5f312018-06-01 09:38:19 -0600204 outfile: Output filename for compiled device-tree binary
Simon Glasse0ff8552016-11-25 20:15:53 -0700205
206 Returns:
Simon Glass7ae5f312018-06-01 09:38:19 -0600207 Contents of device-tree binary
Simon Glasse0ff8552016-11-25 20:15:53 -0700208 """
Simon Glass4f443042016-11-25 20:15:52 -0700209 if not self._output_setup:
210 tools.PrepareOutputDir(self._indir, True)
211 self._output_setup = True
212 dtb = fdt_util.EnsureCompiled(self.TestFile(fname))
213 with open(dtb) as fd:
214 data = fd.read()
215 TestFunctional._MakeInputFile(outfile, data)
Simon Glasse0ff8552016-11-25 20:15:53 -0700216 return data
Simon Glass4f443042016-11-25 20:15:52 -0700217
Simon Glass16b8d6b2018-07-06 10:27:42 -0600218 def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
Simon Glass53af22a2018-07-17 13:25:32 -0600219 update_dtb=False, entry_args=None):
Simon Glass4f443042016-11-25 20:15:52 -0700220 """Run binman and return the resulting image
221
222 This runs binman with a given test file and then reads the resulting
223 output file. It is a shortcut function since most tests need to do
224 these steps.
225
226 Raises an assertion failure if binman returns a non-zero exit code.
227
228 Args:
Simon Glass7ae5f312018-06-01 09:38:19 -0600229 fname: Device-tree source filename to use (e.g. 05_simple.dts)
Simon Glass4f443042016-11-25 20:15:52 -0700230 use_real_dtb: True to use the test file as the contents of
231 the u-boot-dtb entry. Normally this is not needed and the
232 test contents (the U_BOOT_DTB_DATA string) can be used.
233 But in some test we need the real contents.
Simon Glass3b0c3822018-06-01 09:38:20 -0600234 map: True to output map files for the images
Simon Glass3ab95982018-08-01 15:22:37 -0600235 update_dtb: Update the offset and size of each entry in the device
Simon Glass16b8d6b2018-07-06 10:27:42 -0600236 tree before packing it into the image
Simon Glasse0ff8552016-11-25 20:15:53 -0700237
238 Returns:
239 Tuple:
240 Resulting image contents
241 Device tree contents
Simon Glass3b0c3822018-06-01 09:38:20 -0600242 Map data showing contents of image (or None if none)
Simon Glassea6922e2018-07-17 13:25:27 -0600243 Output device tree binary filename ('u-boot.dtb' path)
Simon Glass4f443042016-11-25 20:15:52 -0700244 """
Simon Glasse0ff8552016-11-25 20:15:53 -0700245 dtb_data = None
Simon Glass4f443042016-11-25 20:15:52 -0700246 # Use the compiled test file as the u-boot-dtb input
247 if use_real_dtb:
Simon Glasse0ff8552016-11-25 20:15:53 -0700248 dtb_data = self._SetupDtb(fname)
Simon Glass4f443042016-11-25 20:15:52 -0700249
250 try:
Simon Glass53af22a2018-07-17 13:25:32 -0600251 retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
252 entry_args=entry_args)
Simon Glass4f443042016-11-25 20:15:52 -0700253 self.assertEqual(0, retcode)
Simon Glass16b8d6b2018-07-06 10:27:42 -0600254 out_dtb_fname = control.GetFdtPath('u-boot.dtb')
Simon Glass4f443042016-11-25 20:15:52 -0700255
256 # Find the (only) image, read it and return its contents
257 image = control.images['image']
Simon Glass16b8d6b2018-07-06 10:27:42 -0600258 image_fname = tools.GetOutputFilename('image.bin')
259 self.assertTrue(os.path.exists(image_fname))
Simon Glass3b0c3822018-06-01 09:38:20 -0600260 if map:
261 map_fname = tools.GetOutputFilename('image.map')
262 with open(map_fname) as fd:
263 map_data = fd.read()
264 else:
265 map_data = None
Simon Glass16b8d6b2018-07-06 10:27:42 -0600266 with open(image_fname) as fd:
267 return fd.read(), dtb_data, map_data, out_dtb_fname
Simon Glass4f443042016-11-25 20:15:52 -0700268 finally:
269 # Put the test file back
270 if use_real_dtb:
Simon Glassb8ef5b62018-07-17 13:25:48 -0600271 self._ResetDtbs()
Simon Glass4f443042016-11-25 20:15:52 -0700272
Simon Glasse0ff8552016-11-25 20:15:53 -0700273 def _DoReadFile(self, fname, use_real_dtb=False):
Simon Glass7ae5f312018-06-01 09:38:19 -0600274 """Helper function which discards the device-tree binary
275
276 Args:
277 fname: Device-tree source filename to use (e.g. 05_simple.dts)
278 use_real_dtb: True to use the test file as the contents of
279 the u-boot-dtb entry. Normally this is not needed and the
280 test contents (the U_BOOT_DTB_DATA string) can be used.
281 But in some test we need the real contents.
Simon Glassea6922e2018-07-17 13:25:27 -0600282
283 Returns:
284 Resulting image contents
Simon Glass7ae5f312018-06-01 09:38:19 -0600285 """
Simon Glasse0ff8552016-11-25 20:15:53 -0700286 return self._DoReadFileDtb(fname, use_real_dtb)[0]
287
Simon Glass4f443042016-11-25 20:15:52 -0700288 @classmethod
289 def _MakeInputFile(self, fname, contents):
290 """Create a new test input file, creating directories as needed
291
292 Args:
Simon Glass3ab95982018-08-01 15:22:37 -0600293 fname: Filename to create
Simon Glass4f443042016-11-25 20:15:52 -0700294 contents: File contents to write in to the file
295 Returns:
296 Full pathname of file created
297 """
298 pathname = os.path.join(self._indir, fname)
299 dirname = os.path.dirname(pathname)
300 if dirname and not os.path.exists(dirname):
301 os.makedirs(dirname)
302 with open(pathname, 'wb') as fd:
303 fd.write(contents)
304 return pathname
305
306 @classmethod
Simon Glass0ef87aa2018-07-17 13:25:44 -0600307 def _MakeInputDir(self, dirname):
308 """Create a new test input directory, creating directories as needed
309
310 Args:
311 dirname: Directory name to create
312
313 Returns:
314 Full pathname of directory created
315 """
316 pathname = os.path.join(self._indir, dirname)
317 if not os.path.exists(pathname):
318 os.makedirs(pathname)
319 return pathname
320
321 @classmethod
Simon Glass4f443042016-11-25 20:15:52 -0700322 def TestFile(self, fname):
323 return os.path.join(self._binman_dir, 'test', fname)
324
325 def AssertInList(self, grep_list, target):
326 """Assert that at least one of a list of things is in a target
327
328 Args:
329 grep_list: List of strings to check
330 target: Target string
331 """
332 for grep in grep_list:
333 if grep in target:
334 return
335 self.fail("Error: '%' not found in '%s'" % (grep_list, target))
336
337 def CheckNoGaps(self, entries):
338 """Check that all entries fit together without gaps
339
340 Args:
341 entries: List of entries to check
342 """
Simon Glass3ab95982018-08-01 15:22:37 -0600343 offset = 0
Simon Glass4f443042016-11-25 20:15:52 -0700344 for entry in entries.values():
Simon Glass3ab95982018-08-01 15:22:37 -0600345 self.assertEqual(offset, entry.offset)
346 offset += entry.size
Simon Glass4f443042016-11-25 20:15:52 -0700347
Simon Glasse0ff8552016-11-25 20:15:53 -0700348 def GetFdtLen(self, dtb):
Simon Glass7ae5f312018-06-01 09:38:19 -0600349 """Get the totalsize field from a device-tree binary
Simon Glasse0ff8552016-11-25 20:15:53 -0700350
351 Args:
Simon Glass7ae5f312018-06-01 09:38:19 -0600352 dtb: Device-tree binary contents
Simon Glasse0ff8552016-11-25 20:15:53 -0700353
354 Returns:
Simon Glass7ae5f312018-06-01 09:38:19 -0600355 Total size of device-tree binary, from the header
Simon Glasse0ff8552016-11-25 20:15:53 -0700356 """
357 return struct.unpack('>L', dtb[4:8])[0]
358
Simon Glasscee02e62018-07-17 13:25:52 -0600359 def _GetPropTree(self, dtb, prop_names):
Simon Glass16b8d6b2018-07-06 10:27:42 -0600360 def AddNode(node, path):
361 if node.name != '/':
362 path += '/' + node.name
Simon Glass16b8d6b2018-07-06 10:27:42 -0600363 for subnode in node.subnodes:
364 for prop in subnode.props.values():
Simon Glasscee02e62018-07-17 13:25:52 -0600365 if prop.name in prop_names:
Simon Glass16b8d6b2018-07-06 10:27:42 -0600366 prop_path = path + '/' + subnode.name + ':' + prop.name
367 tree[prop_path[len('/binman/'):]] = fdt_util.fdt32_to_cpu(
368 prop.value)
Simon Glass16b8d6b2018-07-06 10:27:42 -0600369 AddNode(subnode, path)
370
371 tree = {}
Simon Glass16b8d6b2018-07-06 10:27:42 -0600372 AddNode(dtb.GetRoot(), '')
373 return tree
374
Simon Glass4f443042016-11-25 20:15:52 -0700375 def testRun(self):
376 """Test a basic run with valid args"""
377 result = self._RunBinman('-h')
378
379 def testFullHelp(self):
380 """Test that the full help is displayed with -H"""
381 result = self._RunBinman('-H')
382 help_file = os.path.join(self._binman_dir, 'README')
Tom Rini3759df02018-01-16 15:29:50 -0500383 # Remove possible extraneous strings
384 extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
385 gothelp = result.stdout.replace(extra, '')
386 self.assertEqual(len(gothelp), os.path.getsize(help_file))
Simon Glass4f443042016-11-25 20:15:52 -0700387 self.assertEqual(0, len(result.stderr))
388 self.assertEqual(0, result.return_code)
389
390 def testFullHelpInternal(self):
391 """Test that the full help is displayed with -H"""
392 try:
393 command.test_result = command.CommandResult()
394 result = self._DoBinman('-H')
395 help_file = os.path.join(self._binman_dir, 'README')
396 finally:
397 command.test_result = None
398
399 def testHelp(self):
400 """Test that the basic help is displayed with -h"""
401 result = self._RunBinman('-h')
402 self.assertTrue(len(result.stdout) > 200)
403 self.assertEqual(0, len(result.stderr))
404 self.assertEqual(0, result.return_code)
405
Simon Glass4f443042016-11-25 20:15:52 -0700406 def testBoard(self):
407 """Test that we can run it with a specific board"""
408 self._SetupDtb('05_simple.dts', 'sandbox/u-boot.dtb')
409 TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
410 result = self._DoBinman('-b', 'sandbox')
411 self.assertEqual(0, result)
412
413 def testNeedBoard(self):
414 """Test that we get an error when no board ius supplied"""
415 with self.assertRaises(ValueError) as e:
416 result = self._DoBinman()
417 self.assertIn("Must provide a board to process (use -b <board>)",
418 str(e.exception))
419
420 def testMissingDt(self):
Simon Glass7ae5f312018-06-01 09:38:19 -0600421 """Test that an invalid device-tree file generates an error"""
Simon Glass4f443042016-11-25 20:15:52 -0700422 with self.assertRaises(Exception) as e:
423 self._RunBinman('-d', 'missing_file')
424 # We get one error from libfdt, and a different one from fdtget.
425 self.AssertInList(["Couldn't open blob from 'missing_file'",
426 'No such file or directory'], str(e.exception))
427
428 def testBrokenDt(self):
Simon Glass7ae5f312018-06-01 09:38:19 -0600429 """Test that an invalid device-tree source file generates an error
Simon Glass4f443042016-11-25 20:15:52 -0700430
431 Since this is a source file it should be compiled and the error
432 will come from the device-tree compiler (dtc).
433 """
434 with self.assertRaises(Exception) as e:
435 self._RunBinman('-d', self.TestFile('01_invalid.dts'))
436 self.assertIn("FATAL ERROR: Unable to parse input tree",
437 str(e.exception))
438
439 def testMissingNode(self):
440 """Test that a device tree without a 'binman' node generates an error"""
441 with self.assertRaises(Exception) as e:
442 self._DoBinman('-d', self.TestFile('02_missing_node.dts'))
443 self.assertIn("does not have a 'binman' node", str(e.exception))
444
445 def testEmpty(self):
446 """Test that an empty binman node works OK (i.e. does nothing)"""
447 result = self._RunBinman('-d', self.TestFile('03_empty.dts'))
448 self.assertEqual(0, len(result.stderr))
449 self.assertEqual(0, result.return_code)
450
451 def testInvalidEntry(self):
452 """Test that an invalid entry is flagged"""
453 with self.assertRaises(Exception) as e:
454 result = self._RunBinman('-d',
455 self.TestFile('04_invalid_entry.dts'))
Simon Glass4f443042016-11-25 20:15:52 -0700456 self.assertIn("Unknown entry type 'not-a-valid-type' in node "
457 "'/binman/not-a-valid-type'", str(e.exception))
458
459 def testSimple(self):
460 """Test a simple binman with a single file"""
461 data = self._DoReadFile('05_simple.dts')
462 self.assertEqual(U_BOOT_DATA, data)
463
Simon Glass7fe91732017-11-13 18:55:00 -0700464 def testSimpleDebug(self):
465 """Test a simple binman run with debugging enabled"""
466 data = self._DoTestFile('05_simple.dts', debug=True)
467
Simon Glass4f443042016-11-25 20:15:52 -0700468 def testDual(self):
469 """Test that we can handle creating two images
470
471 This also tests image padding.
472 """
473 retcode = self._DoTestFile('06_dual_image.dts')
474 self.assertEqual(0, retcode)
475
476 image = control.images['image1']
477 self.assertEqual(len(U_BOOT_DATA), image._size)
478 fname = tools.GetOutputFilename('image1.bin')
479 self.assertTrue(os.path.exists(fname))
480 with open(fname) as fd:
481 data = fd.read()
482 self.assertEqual(U_BOOT_DATA, data)
483
484 image = control.images['image2']
485 self.assertEqual(3 + len(U_BOOT_DATA) + 5, image._size)
486 fname = tools.GetOutputFilename('image2.bin')
487 self.assertTrue(os.path.exists(fname))
488 with open(fname) as fd:
489 data = fd.read()
490 self.assertEqual(U_BOOT_DATA, data[3:7])
491 self.assertEqual(chr(0) * 3, data[:3])
492 self.assertEqual(chr(0) * 5, data[7:])
493
494 def testBadAlign(self):
495 """Test that an invalid alignment value is detected"""
496 with self.assertRaises(ValueError) as e:
497 self._DoTestFile('07_bad_align.dts')
498 self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
499 "of two", str(e.exception))
500
501 def testPackSimple(self):
502 """Test that packing works as expected"""
503 retcode = self._DoTestFile('08_pack.dts')
504 self.assertEqual(0, retcode)
505 self.assertIn('image', control.images)
506 image = control.images['image']
Simon Glass8f1da502018-06-01 09:38:12 -0600507 entries = image.GetEntries()
Simon Glass4f443042016-11-25 20:15:52 -0700508 self.assertEqual(5, len(entries))
509
510 # First u-boot
511 self.assertIn('u-boot', entries)
512 entry = entries['u-boot']
Simon Glass3ab95982018-08-01 15:22:37 -0600513 self.assertEqual(0, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700514 self.assertEqual(len(U_BOOT_DATA), entry.size)
515
516 # Second u-boot, aligned to 16-byte boundary
517 self.assertIn('u-boot-align', entries)
518 entry = entries['u-boot-align']
Simon Glass3ab95982018-08-01 15:22:37 -0600519 self.assertEqual(16, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700520 self.assertEqual(len(U_BOOT_DATA), entry.size)
521
522 # Third u-boot, size 23 bytes
523 self.assertIn('u-boot-size', entries)
524 entry = entries['u-boot-size']
Simon Glass3ab95982018-08-01 15:22:37 -0600525 self.assertEqual(20, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700526 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
527 self.assertEqual(23, entry.size)
528
529 # Fourth u-boot, placed immediate after the above
530 self.assertIn('u-boot-next', entries)
531 entry = entries['u-boot-next']
Simon Glass3ab95982018-08-01 15:22:37 -0600532 self.assertEqual(43, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700533 self.assertEqual(len(U_BOOT_DATA), entry.size)
534
Simon Glass3ab95982018-08-01 15:22:37 -0600535 # Fifth u-boot, placed at a fixed offset
Simon Glass4f443042016-11-25 20:15:52 -0700536 self.assertIn('u-boot-fixed', entries)
537 entry = entries['u-boot-fixed']
Simon Glass3ab95982018-08-01 15:22:37 -0600538 self.assertEqual(61, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700539 self.assertEqual(len(U_BOOT_DATA), entry.size)
540
541 self.assertEqual(65, image._size)
542
543 def testPackExtra(self):
544 """Test that extra packing feature works as expected"""
545 retcode = self._DoTestFile('09_pack_extra.dts')
546
547 self.assertEqual(0, retcode)
548 self.assertIn('image', control.images)
549 image = control.images['image']
Simon Glass8f1da502018-06-01 09:38:12 -0600550 entries = image.GetEntries()
Simon Glass4f443042016-11-25 20:15:52 -0700551 self.assertEqual(5, len(entries))
552
553 # First u-boot with padding before and after
554 self.assertIn('u-boot', entries)
555 entry = entries['u-boot']
Simon Glass3ab95982018-08-01 15:22:37 -0600556 self.assertEqual(0, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700557 self.assertEqual(3, entry.pad_before)
558 self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
559
560 # Second u-boot has an aligned size, but it has no effect
561 self.assertIn('u-boot-align-size-nop', entries)
562 entry = entries['u-boot-align-size-nop']
Simon Glass3ab95982018-08-01 15:22:37 -0600563 self.assertEqual(12, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700564 self.assertEqual(4, entry.size)
565
566 # Third u-boot has an aligned size too
567 self.assertIn('u-boot-align-size', entries)
568 entry = entries['u-boot-align-size']
Simon Glass3ab95982018-08-01 15:22:37 -0600569 self.assertEqual(16, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700570 self.assertEqual(32, entry.size)
571
572 # Fourth u-boot has an aligned end
573 self.assertIn('u-boot-align-end', entries)
574 entry = entries['u-boot-align-end']
Simon Glass3ab95982018-08-01 15:22:37 -0600575 self.assertEqual(48, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700576 self.assertEqual(16, entry.size)
577
578 # Fifth u-boot immediately afterwards
579 self.assertIn('u-boot-align-both', entries)
580 entry = entries['u-boot-align-both']
Simon Glass3ab95982018-08-01 15:22:37 -0600581 self.assertEqual(64, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700582 self.assertEqual(64, entry.size)
583
584 self.CheckNoGaps(entries)
585 self.assertEqual(128, image._size)
586
587 def testPackAlignPowerOf2(self):
588 """Test that invalid entry alignment is detected"""
589 with self.assertRaises(ValueError) as e:
590 self._DoTestFile('10_pack_align_power2.dts')
591 self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
592 "of two", str(e.exception))
593
594 def testPackAlignSizePowerOf2(self):
595 """Test that invalid entry size alignment is detected"""
596 with self.assertRaises(ValueError) as e:
597 self._DoTestFile('11_pack_align_size_power2.dts')
598 self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
599 "power of two", str(e.exception))
600
601 def testPackInvalidAlign(self):
Simon Glass3ab95982018-08-01 15:22:37 -0600602 """Test detection of an offset that does not match its alignment"""
Simon Glass4f443042016-11-25 20:15:52 -0700603 with self.assertRaises(ValueError) as e:
604 self._DoTestFile('12_pack_inv_align.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600605 self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
Simon Glass4f443042016-11-25 20:15:52 -0700606 "align 0x4 (4)", str(e.exception))
607
608 def testPackInvalidSizeAlign(self):
609 """Test that invalid entry size alignment is detected"""
610 with self.assertRaises(ValueError) as e:
611 self._DoTestFile('13_pack_inv_size_align.dts')
612 self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
613 "align-size 0x4 (4)", str(e.exception))
614
615 def testPackOverlap(self):
616 """Test that overlapping regions are detected"""
617 with self.assertRaises(ValueError) as e:
618 self._DoTestFile('14_pack_overlap.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600619 self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
Simon Glass4f443042016-11-25 20:15:52 -0700620 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
621 str(e.exception))
622
623 def testPackEntryOverflow(self):
624 """Test that entries that overflow their size are detected"""
625 with self.assertRaises(ValueError) as e:
626 self._DoTestFile('15_pack_overflow.dts')
627 self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
628 "but entry size is 0x3 (3)", str(e.exception))
629
630 def testPackImageOverflow(self):
631 """Test that entries which overflow the image size are detected"""
632 with self.assertRaises(ValueError) as e:
633 self._DoTestFile('16_pack_image_overflow.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600634 self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section "
Simon Glass4f443042016-11-25 20:15:52 -0700635 "size 0x3 (3)", str(e.exception))
636
637 def testPackImageSize(self):
638 """Test that the image size can be set"""
639 retcode = self._DoTestFile('17_pack_image_size.dts')
640 self.assertEqual(0, retcode)
641 self.assertIn('image', control.images)
642 image = control.images['image']
643 self.assertEqual(7, image._size)
644
645 def testPackImageSizeAlign(self):
646 """Test that image size alignemnt works as expected"""
647 retcode = self._DoTestFile('18_pack_image_align.dts')
648 self.assertEqual(0, retcode)
649 self.assertIn('image', control.images)
650 image = control.images['image']
651 self.assertEqual(16, image._size)
652
653 def testPackInvalidImageAlign(self):
654 """Test that invalid image alignment is detected"""
655 with self.assertRaises(ValueError) as e:
656 self._DoTestFile('19_pack_inv_image_align.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600657 self.assertIn("Section '/binman': Size 0x7 (7) does not match "
Simon Glass4f443042016-11-25 20:15:52 -0700658 "align-size 0x8 (8)", str(e.exception))
659
660 def testPackAlignPowerOf2(self):
661 """Test that invalid image alignment is detected"""
662 with self.assertRaises(ValueError) as e:
663 self._DoTestFile('20_pack_inv_image_align_power2.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600664 self.assertIn("Section '/binman': Alignment size 131 must be a power of "
Simon Glass4f443042016-11-25 20:15:52 -0700665 "two", str(e.exception))
666
667 def testImagePadByte(self):
668 """Test that the image pad byte can be specified"""
Simon Glass19790632017-11-13 18:55:01 -0700669 with open(self.TestFile('bss_data')) as fd:
670 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
Simon Glass4f443042016-11-25 20:15:52 -0700671 data = self._DoReadFile('21_image_pad.dts')
Simon Glassf6898902017-11-13 18:54:59 -0700672 self.assertEqual(U_BOOT_SPL_DATA + (chr(0xff) * 1) + U_BOOT_DATA, data)
Simon Glass4f443042016-11-25 20:15:52 -0700673
674 def testImageName(self):
675 """Test that image files can be named"""
676 retcode = self._DoTestFile('22_image_name.dts')
677 self.assertEqual(0, retcode)
678 image = control.images['image1']
679 fname = tools.GetOutputFilename('test-name')
680 self.assertTrue(os.path.exists(fname))
681
682 image = control.images['image2']
683 fname = tools.GetOutputFilename('test-name.xx')
684 self.assertTrue(os.path.exists(fname))
685
686 def testBlobFilename(self):
687 """Test that generic blobs can be provided by filename"""
688 data = self._DoReadFile('23_blob.dts')
689 self.assertEqual(BLOB_DATA, data)
690
691 def testPackSorted(self):
692 """Test that entries can be sorted"""
693 data = self._DoReadFile('24_sorted.dts')
Simon Glassf6898902017-11-13 18:54:59 -0700694 self.assertEqual(chr(0) * 1 + U_BOOT_SPL_DATA + chr(0) * 2 +
Simon Glass4f443042016-11-25 20:15:52 -0700695 U_BOOT_DATA, data)
696
Simon Glass3ab95982018-08-01 15:22:37 -0600697 def testPackZeroOffset(self):
698 """Test that an entry at offset 0 is not given a new offset"""
Simon Glass4f443042016-11-25 20:15:52 -0700699 with self.assertRaises(ValueError) as e:
700 self._DoTestFile('25_pack_zero_size.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600701 self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
Simon Glass4f443042016-11-25 20:15:52 -0700702 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
703 str(e.exception))
704
705 def testPackUbootDtb(self):
706 """Test that a device tree can be added to U-Boot"""
707 data = self._DoReadFile('26_pack_u_boot_dtb.dts')
708 self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
Simon Glasse0ff8552016-11-25 20:15:53 -0700709
710 def testPackX86RomNoSize(self):
711 """Test that the end-at-4gb property requires a size property"""
712 with self.assertRaises(ValueError) as e:
713 self._DoTestFile('27_pack_4gb_no_size.dts')
Simon Glass8f1da502018-06-01 09:38:12 -0600714 self.assertIn("Section '/binman': Section size must be provided when "
Simon Glasse0ff8552016-11-25 20:15:53 -0700715 "using end-at-4gb", str(e.exception))
716
717 def testPackX86RomOutside(self):
Simon Glass3ab95982018-08-01 15:22:37 -0600718 """Test that the end-at-4gb property checks for offset boundaries"""
Simon Glasse0ff8552016-11-25 20:15:53 -0700719 with self.assertRaises(ValueError) as e:
720 self._DoTestFile('28_pack_4gb_outside.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600721 self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
Simon Glass8f1da502018-06-01 09:38:12 -0600722 "the section starting at 0xffffffe0 (4294967264)",
Simon Glasse0ff8552016-11-25 20:15:53 -0700723 str(e.exception))
724
725 def testPackX86Rom(self):
726 """Test that a basic x86 ROM can be created"""
727 data = self._DoReadFile('29_x86-rom.dts')
Simon Glassf6898902017-11-13 18:54:59 -0700728 self.assertEqual(U_BOOT_DATA + chr(0) * 7 + U_BOOT_SPL_DATA +
729 chr(0) * 2, data)
Simon Glasse0ff8552016-11-25 20:15:53 -0700730
731 def testPackX86RomMeNoDesc(self):
732 """Test that an invalid Intel descriptor entry is detected"""
733 TestFunctional._MakeInputFile('descriptor.bin', '')
734 with self.assertRaises(ValueError) as e:
735 self._DoTestFile('31_x86-rom-me.dts')
736 self.assertIn("Node '/binman/intel-descriptor': Cannot find FD "
737 "signature", str(e.exception))
738
739 def testPackX86RomBadDesc(self):
740 """Test that the Intel requires a descriptor entry"""
741 with self.assertRaises(ValueError) as e:
742 self._DoTestFile('30_x86-rom-me-no-desc.dts')
Simon Glass3ab95982018-08-01 15:22:37 -0600743 self.assertIn("Node '/binman/intel-me': No offset set with "
744 "offset-unset: should another entry provide this correct "
745 "offset?", str(e.exception))
Simon Glasse0ff8552016-11-25 20:15:53 -0700746
747 def testPackX86RomMe(self):
748 """Test that an x86 ROM with an ME region can be created"""
749 data = self._DoReadFile('31_x86-rom-me.dts')
750 self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
751
752 def testPackVga(self):
753 """Test that an image with a VGA binary can be created"""
754 data = self._DoReadFile('32_intel-vga.dts')
755 self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
756
757 def testPackStart16(self):
758 """Test that an image with an x86 start16 region can be created"""
759 data = self._DoReadFile('33_x86-start16.dts')
760 self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
761
Simon Glass736bb0a2018-07-06 10:27:17 -0600762 def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False):
Simon Glassadc57012018-07-06 10:27:16 -0600763 """Handle running a test for insertion of microcode
764
765 Args:
766 dts_fname: Name of test .dts file
767 nodtb_data: Data that we expect in the first section
Simon Glass736bb0a2018-07-06 10:27:17 -0600768 ucode_second: True if the microsecond entry is second instead of
769 third
Simon Glassadc57012018-07-06 10:27:16 -0600770
771 Returns:
772 Tuple:
773 Contents of first region (U-Boot or SPL)
Simon Glass3ab95982018-08-01 15:22:37 -0600774 Offset and size components of microcode pointer, as inserted
Simon Glassadc57012018-07-06 10:27:16 -0600775 in the above (two 4-byte words)
776 """
Simon Glass6b187df2017-11-12 21:52:27 -0700777 data = self._DoReadFile(dts_fname, True)
Simon Glasse0ff8552016-11-25 20:15:53 -0700778
779 # Now check the device tree has no microcode
Simon Glass736bb0a2018-07-06 10:27:17 -0600780 if ucode_second:
781 ucode_content = data[len(nodtb_data):]
782 ucode_pos = len(nodtb_data)
783 dtb_with_ucode = ucode_content[16:]
784 fdt_len = self.GetFdtLen(dtb_with_ucode)
785 else:
786 dtb_with_ucode = data[len(nodtb_data):]
787 fdt_len = self.GetFdtLen(dtb_with_ucode)
788 ucode_content = dtb_with_ucode[fdt_len:]
789 ucode_pos = len(nodtb_data) + fdt_len
Simon Glasse0ff8552016-11-25 20:15:53 -0700790 fname = tools.GetOutputFilename('test.dtb')
791 with open(fname, 'wb') as fd:
Simon Glassadc57012018-07-06 10:27:16 -0600792 fd.write(dtb_with_ucode)
Simon Glassec3f3782017-05-27 07:38:29 -0600793 dtb = fdt.FdtScan(fname)
794 ucode = dtb.GetNode('/microcode')
Simon Glasse0ff8552016-11-25 20:15:53 -0700795 self.assertTrue(ucode)
796 for node in ucode.subnodes:
797 self.assertFalse(node.props.get('data'))
798
Simon Glasse0ff8552016-11-25 20:15:53 -0700799 # Check that the microcode appears immediately after the Fdt
800 # This matches the concatenation of the data properties in
Simon Glass87722132017-11-12 21:52:26 -0700801 # the /microcode/update@xxx nodes in 34_x86_ucode.dts.
Simon Glasse0ff8552016-11-25 20:15:53 -0700802 ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
803 0x78235609)
Simon Glassadc57012018-07-06 10:27:16 -0600804 self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
Simon Glasse0ff8552016-11-25 20:15:53 -0700805
806 # Check that the microcode pointer was inserted. It should match the
Simon Glass3ab95982018-08-01 15:22:37 -0600807 # expected offset and size
Simon Glasse0ff8552016-11-25 20:15:53 -0700808 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
809 len(ucode_data))
Simon Glass736bb0a2018-07-06 10:27:17 -0600810 u_boot = data[:len(nodtb_data)]
811 return u_boot, pos_and_size
Simon Glass6b187df2017-11-12 21:52:27 -0700812
813 def testPackUbootMicrocode(self):
814 """Test that x86 microcode can be handled correctly
815
816 We expect to see the following in the image, in order:
817 u-boot-nodtb.bin with a microcode pointer inserted at the correct
818 place
819 u-boot.dtb with the microcode removed
820 the microcode
821 """
822 first, pos_and_size = self._RunMicrocodeTest('34_x86_ucode.dts',
823 U_BOOT_NODTB_DATA)
Simon Glasse0ff8552016-11-25 20:15:53 -0700824 self.assertEqual('nodtb with microcode' + pos_and_size +
825 ' somewhere in here', first)
826
Simon Glass160a7662017-05-27 07:38:26 -0600827 def _RunPackUbootSingleMicrocode(self):
Simon Glasse0ff8552016-11-25 20:15:53 -0700828 """Test that x86 microcode can be handled correctly
829
830 We expect to see the following in the image, in order:
831 u-boot-nodtb.bin with a microcode pointer inserted at the correct
832 place
833 u-boot.dtb with the microcode
834 an empty microcode region
835 """
836 # We need the libfdt library to run this test since only that allows
837 # finding the offset of a property. This is required by
838 # Entry_u_boot_dtb_with_ucode.ObtainContents().
Simon Glasse0ff8552016-11-25 20:15:53 -0700839 data = self._DoReadFile('35_x86_single_ucode.dts', True)
840
841 second = data[len(U_BOOT_NODTB_DATA):]
842
843 fdt_len = self.GetFdtLen(second)
844 third = second[fdt_len:]
845 second = second[:fdt_len]
846
Simon Glass160a7662017-05-27 07:38:26 -0600847 ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
848 self.assertIn(ucode_data, second)
849 ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
Simon Glasse0ff8552016-11-25 20:15:53 -0700850
Simon Glass160a7662017-05-27 07:38:26 -0600851 # Check that the microcode pointer was inserted. It should match the
Simon Glass3ab95982018-08-01 15:22:37 -0600852 # expected offset and size
Simon Glass160a7662017-05-27 07:38:26 -0600853 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
854 len(ucode_data))
855 first = data[:len(U_BOOT_NODTB_DATA)]
856 self.assertEqual('nodtb with microcode' + pos_and_size +
857 ' somewhere in here', first)
Simon Glassc49deb82016-11-25 20:15:54 -0700858
Simon Glass75db0862016-11-25 20:15:55 -0700859 def testPackUbootSingleMicrocode(self):
860 """Test that x86 microcode can be handled correctly with fdt_normal.
861 """
Simon Glass160a7662017-05-27 07:38:26 -0600862 self._RunPackUbootSingleMicrocode()
Simon Glass75db0862016-11-25 20:15:55 -0700863
Simon Glassc49deb82016-11-25 20:15:54 -0700864 def testUBootImg(self):
865 """Test that u-boot.img can be put in a file"""
866 data = self._DoReadFile('36_u_boot_img.dts')
867 self.assertEqual(U_BOOT_IMG_DATA, data)
Simon Glass75db0862016-11-25 20:15:55 -0700868
869 def testNoMicrocode(self):
870 """Test that a missing microcode region is detected"""
871 with self.assertRaises(ValueError) as e:
872 self._DoReadFile('37_x86_no_ucode.dts', True)
873 self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
874 "node found in ", str(e.exception))
875
876 def testMicrocodeWithoutNode(self):
877 """Test that a missing u-boot-dtb-with-ucode node is detected"""
878 with self.assertRaises(ValueError) as e:
879 self._DoReadFile('38_x86_ucode_missing_node.dts', True)
880 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
881 "microcode region u-boot-dtb-with-ucode", str(e.exception))
882
883 def testMicrocodeWithoutNode2(self):
884 """Test that a missing u-boot-ucode node is detected"""
885 with self.assertRaises(ValueError) as e:
886 self._DoReadFile('39_x86_ucode_missing_node2.dts', True)
887 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
888 "microcode region u-boot-ucode", str(e.exception))
889
890 def testMicrocodeWithoutPtrInElf(self):
891 """Test that a U-Boot binary without the microcode symbol is detected"""
892 # ELF file without a '_dt_ucode_base_size' symbol
Simon Glass75db0862016-11-25 20:15:55 -0700893 try:
894 with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
895 TestFunctional._MakeInputFile('u-boot', fd.read())
896
897 with self.assertRaises(ValueError) as e:
Simon Glass160a7662017-05-27 07:38:26 -0600898 self._RunPackUbootSingleMicrocode()
Simon Glass75db0862016-11-25 20:15:55 -0700899 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
900 "_dt_ucode_base_size symbol in u-boot", str(e.exception))
901
902 finally:
903 # Put the original file back
904 with open(self.TestFile('u_boot_ucode_ptr')) as fd:
905 TestFunctional._MakeInputFile('u-boot', fd.read())
906
907 def testMicrocodeNotInImage(self):
908 """Test that microcode must be placed within the image"""
909 with self.assertRaises(ValueError) as e:
910 self._DoReadFile('40_x86_ucode_not_in_image.dts', True)
911 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
912 "pointer _dt_ucode_base_size at fffffe14 is outside the "
Simon Glass25ac0e62018-06-01 09:38:14 -0600913 "section ranging from 00000000 to 0000002e", str(e.exception))
Simon Glass75db0862016-11-25 20:15:55 -0700914
915 def testWithoutMicrocode(self):
916 """Test that we can cope with an image without microcode (e.g. qemu)"""
917 with open(self.TestFile('u_boot_no_ucode_ptr')) as fd:
918 TestFunctional._MakeInputFile('u-boot', fd.read())
Simon Glass16b8d6b2018-07-06 10:27:42 -0600919 data, dtb, _, _ = self._DoReadFileDtb('44_x86_optional_ucode.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -0700920
921 # Now check the device tree has no microcode
922 self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
923 second = data[len(U_BOOT_NODTB_DATA):]
924
925 fdt_len = self.GetFdtLen(second)
926 self.assertEqual(dtb, second[:fdt_len])
927
928 used_len = len(U_BOOT_NODTB_DATA) + fdt_len
929 third = data[used_len:]
930 self.assertEqual(chr(0) * (0x200 - used_len), third)
931
932 def testUnknownPosSize(self):
933 """Test that microcode must be placed within the image"""
934 with self.assertRaises(ValueError) as e:
935 self._DoReadFile('41_unknown_pos_size.dts', True)
Simon Glass3ab95982018-08-01 15:22:37 -0600936 self.assertIn("Section '/binman': Unable to set offset/size for unknown "
Simon Glass75db0862016-11-25 20:15:55 -0700937 "entry 'invalid-entry'", str(e.exception))
Simon Glassda229092016-11-25 20:15:56 -0700938
939 def testPackFsp(self):
940 """Test that an image with a FSP binary can be created"""
941 data = self._DoReadFile('42_intel-fsp.dts')
942 self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
943
944 def testPackCmc(self):
Bin Meng59ea8c22017-08-15 22:41:54 -0700945 """Test that an image with a CMC binary can be created"""
Simon Glassda229092016-11-25 20:15:56 -0700946 data = self._DoReadFile('43_intel-cmc.dts')
947 self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
Bin Meng59ea8c22017-08-15 22:41:54 -0700948
949 def testPackVbt(self):
950 """Test that an image with a VBT binary can be created"""
951 data = self._DoReadFile('46_intel-vbt.dts')
952 self.assertEqual(VBT_DATA, data[:len(VBT_DATA)])
Simon Glass9fc60b42017-11-12 21:52:22 -0700953
Simon Glass56509842017-11-12 21:52:25 -0700954 def testSplBssPad(self):
955 """Test that we can pad SPL's BSS with zeros"""
Simon Glass6b187df2017-11-12 21:52:27 -0700956 # ELF file with a '__bss_size' symbol
957 with open(self.TestFile('bss_data')) as fd:
958 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
Simon Glass56509842017-11-12 21:52:25 -0700959 data = self._DoReadFile('47_spl_bss_pad.dts')
960 self.assertEqual(U_BOOT_SPL_DATA + (chr(0) * 10) + U_BOOT_DATA, data)
961
Simon Glassb50e5612017-11-13 18:54:54 -0700962 with open(self.TestFile('u_boot_ucode_ptr')) as fd:
963 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
964 with self.assertRaises(ValueError) as e:
965 data = self._DoReadFile('47_spl_bss_pad.dts')
966 self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
967 str(e.exception))
968
Simon Glass87722132017-11-12 21:52:26 -0700969 def testPackStart16Spl(self):
Simon Glass35b384c2018-09-14 04:57:10 -0600970 """Test that an image with an x86 start16 SPL region can be created"""
Simon Glass87722132017-11-12 21:52:26 -0700971 data = self._DoReadFile('48_x86-start16-spl.dts')
972 self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)])
973
Simon Glass736bb0a2018-07-06 10:27:17 -0600974 def _PackUbootSplMicrocode(self, dts, ucode_second=False):
975 """Helper function for microcode tests
Simon Glass6b187df2017-11-12 21:52:27 -0700976
977 We expect to see the following in the image, in order:
978 u-boot-spl-nodtb.bin with a microcode pointer inserted at the
979 correct place
980 u-boot.dtb with the microcode removed
981 the microcode
Simon Glass736bb0a2018-07-06 10:27:17 -0600982
983 Args:
984 dts: Device tree file to use for test
985 ucode_second: True if the microsecond entry is second instead of
986 third
Simon Glass6b187df2017-11-12 21:52:27 -0700987 """
988 # ELF file with a '_dt_ucode_base_size' symbol
989 with open(self.TestFile('u_boot_ucode_ptr')) as fd:
990 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
Simon Glass736bb0a2018-07-06 10:27:17 -0600991 first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA,
992 ucode_second=ucode_second)
Simon Glass6b187df2017-11-12 21:52:27 -0700993 self.assertEqual('splnodtb with microc' + pos_and_size +
994 'ter somewhere in here', first)
995
Simon Glass736bb0a2018-07-06 10:27:17 -0600996 def testPackUbootSplMicrocode(self):
997 """Test that x86 microcode can be handled correctly in SPL"""
998 self._PackUbootSplMicrocode('49_x86_ucode_spl.dts')
999
1000 def testPackUbootSplMicrocodeReorder(self):
1001 """Test that order doesn't matter for microcode entries
1002
1003 This is the same as testPackUbootSplMicrocode but when we process the
1004 u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode
1005 entry, so we reply on binman to try later.
1006 """
1007 self._PackUbootSplMicrocode('58_x86_ucode_spl_needs_retry.dts',
1008 ucode_second=True)
1009
Simon Glassca4f4ff2017-11-12 21:52:28 -07001010 def testPackMrc(self):
1011 """Test that an image with an MRC binary can be created"""
1012 data = self._DoReadFile('50_intel_mrc.dts')
1013 self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
1014
Simon Glass47419ea2017-11-13 18:54:55 -07001015 def testSplDtb(self):
1016 """Test that an image with spl/u-boot-spl.dtb can be created"""
1017 data = self._DoReadFile('51_u_boot_spl_dtb.dts')
1018 self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
1019
Simon Glass4e6fdbe2017-11-13 18:54:56 -07001020 def testSplNoDtb(self):
1021 """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
1022 data = self._DoReadFile('52_u_boot_spl_nodtb.dts')
1023 self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
1024
Simon Glass19790632017-11-13 18:55:01 -07001025 def testSymbols(self):
1026 """Test binman can assign symbols embedded in U-Boot"""
1027 elf_fname = self.TestFile('u_boot_binman_syms')
1028 syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
1029 addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
Simon Glass3ab95982018-08-01 15:22:37 -06001030 self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
Simon Glass19790632017-11-13 18:55:01 -07001031
1032 with open(self.TestFile('u_boot_binman_syms')) as fd:
1033 TestFunctional._MakeInputFile('spl/u-boot-spl', fd.read())
1034 data = self._DoReadFile('53_symbols.dts')
1035 sym_values = struct.pack('<LQL', 0x24 + 0, 0x24 + 24, 0x24 + 20)
1036 expected = (sym_values + U_BOOT_SPL_DATA[16:] + chr(0xff) +
1037 U_BOOT_DATA +
1038 sym_values + U_BOOT_SPL_DATA[16:])
1039 self.assertEqual(expected, data)
1040
Simon Glassdd57c132018-06-01 09:38:11 -06001041 def testPackUnitAddress(self):
1042 """Test that we support multiple binaries with the same name"""
1043 data = self._DoReadFile('54_unit_address.dts')
1044 self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
1045
Simon Glass18546952018-06-01 09:38:16 -06001046 def testSections(self):
1047 """Basic test of sections"""
1048 data = self._DoReadFile('55_sections.dts')
Simon Glass8122f392018-07-17 13:25:28 -06001049 expected = (U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12 +
1050 U_BOOT_DATA + '&' * 4)
Simon Glass18546952018-06-01 09:38:16 -06001051 self.assertEqual(expected, data)
Simon Glass9fc60b42017-11-12 21:52:22 -07001052
Simon Glass3b0c3822018-06-01 09:38:20 -06001053 def testMap(self):
1054 """Tests outputting a map of the images"""
Simon Glass16b8d6b2018-07-06 10:27:42 -06001055 _, _, map_data, _ = self._DoReadFileDtb('55_sections.dts', map=True)
Simon Glass1be70d22018-07-17 13:25:49 -06001056 self.assertEqual('''ImagePos Offset Size Name
105700000000 00000000 00000028 main-section
105800000000 00000000 00000010 section@0
105900000000 00000000 00000004 u-boot
106000000010 00000010 00000010 section@1
106100000010 00000000 00000004 u-boot
106200000020 00000020 00000004 section@2
106300000020 00000000 00000004 u-boot
Simon Glass3b0c3822018-06-01 09:38:20 -06001064''', map_data)
1065
Simon Glassc8d48ef2018-06-01 09:38:21 -06001066 def testNamePrefix(self):
1067 """Tests that name prefixes are used"""
Simon Glass16b8d6b2018-07-06 10:27:42 -06001068 _, _, map_data, _ = self._DoReadFileDtb('56_name_prefix.dts', map=True)
Simon Glass1be70d22018-07-17 13:25:49 -06001069 self.assertEqual('''ImagePos Offset Size Name
107000000000 00000000 00000028 main-section
107100000000 00000000 00000010 section@0
107200000000 00000000 00000004 ro-u-boot
107300000010 00000010 00000010 section@1
107400000010 00000000 00000004 rw-u-boot
Simon Glassc8d48ef2018-06-01 09:38:21 -06001075''', map_data)
1076
Simon Glass736bb0a2018-07-06 10:27:17 -06001077 def testUnknownContents(self):
1078 """Test that obtaining the contents works as expected"""
1079 with self.assertRaises(ValueError) as e:
1080 self._DoReadFile('57_unknown_contents.dts', True)
1081 self.assertIn("Section '/binman': Internal error: Could not complete "
1082 "processing of contents: remaining [<_testing.Entry__testing ",
1083 str(e.exception))
1084
Simon Glass5c890232018-07-06 10:27:19 -06001085 def testBadChangeSize(self):
1086 """Test that trying to change the size of an entry fails"""
1087 with self.assertRaises(ValueError) as e:
1088 self._DoReadFile('59_change_size.dts', True)
1089 self.assertIn("Node '/binman/_testing': Cannot update entry size from "
1090 '2 to 1', str(e.exception))
1091
Simon Glass16b8d6b2018-07-06 10:27:42 -06001092 def testUpdateFdt(self):
Simon Glass3ab95982018-08-01 15:22:37 -06001093 """Test that we can update the device tree with offset/size info"""
Simon Glass16b8d6b2018-07-06 10:27:42 -06001094 _, _, _, out_dtb_fname = self._DoReadFileDtb('60_fdt_update.dts',
1095 update_dtb=True)
Simon Glasscee02e62018-07-17 13:25:52 -06001096 dtb = fdt.Fdt(out_dtb_fname)
1097 dtb.Scan()
1098 props = self._GetPropTree(dtb, ['offset', 'size', 'image-pos'])
Simon Glass16b8d6b2018-07-06 10:27:42 -06001099 self.assertEqual({
Simon Glassdbf6be92018-08-01 15:22:42 -06001100 'image-pos': 0,
Simon Glass8122f392018-07-17 13:25:28 -06001101 'offset': 0,
Simon Glass3ab95982018-08-01 15:22:37 -06001102 '_testing:offset': 32,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001103 '_testing:size': 1,
Simon Glassdbf6be92018-08-01 15:22:42 -06001104 '_testing:image-pos': 32,
Simon Glass3ab95982018-08-01 15:22:37 -06001105 'section@0/u-boot:offset': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001106 'section@0/u-boot:size': len(U_BOOT_DATA),
Simon Glassdbf6be92018-08-01 15:22:42 -06001107 'section@0/u-boot:image-pos': 0,
Simon Glass3ab95982018-08-01 15:22:37 -06001108 'section@0:offset': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001109 'section@0:size': 16,
Simon Glassdbf6be92018-08-01 15:22:42 -06001110 'section@0:image-pos': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001111
Simon Glass3ab95982018-08-01 15:22:37 -06001112 'section@1/u-boot:offset': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001113 'section@1/u-boot:size': len(U_BOOT_DATA),
Simon Glassdbf6be92018-08-01 15:22:42 -06001114 'section@1/u-boot:image-pos': 16,
Simon Glass3ab95982018-08-01 15:22:37 -06001115 'section@1:offset': 16,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001116 'section@1:size': 16,
Simon Glassdbf6be92018-08-01 15:22:42 -06001117 'section@1:image-pos': 16,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001118 'size': 40
1119 }, props)
1120
1121 def testUpdateFdtBad(self):
1122 """Test that we detect when ProcessFdt never completes"""
1123 with self.assertRaises(ValueError) as e:
1124 self._DoReadFileDtb('61_fdt_update_bad.dts', update_dtb=True)
1125 self.assertIn('Could not complete processing of Fdt: remaining '
1126 '[<_testing.Entry__testing', str(e.exception))
Simon Glass5c890232018-07-06 10:27:19 -06001127
Simon Glass53af22a2018-07-17 13:25:32 -06001128 def testEntryArgs(self):
1129 """Test passing arguments to entries from the command line"""
1130 entry_args = {
1131 'test-str-arg': 'test1',
1132 'test-int-arg': '456',
1133 }
1134 self._DoReadFileDtb('62_entry_args.dts', entry_args=entry_args)
1135 self.assertIn('image', control.images)
1136 entry = control.images['image'].GetEntries()['_testing']
1137 self.assertEqual('test0', entry.test_str_fdt)
1138 self.assertEqual('test1', entry.test_str_arg)
1139 self.assertEqual(123, entry.test_int_fdt)
1140 self.assertEqual(456, entry.test_int_arg)
1141
1142 def testEntryArgsMissing(self):
1143 """Test missing arguments and properties"""
1144 entry_args = {
1145 'test-int-arg': '456',
1146 }
1147 self._DoReadFileDtb('63_entry_args_missing.dts', entry_args=entry_args)
1148 entry = control.images['image'].GetEntries()['_testing']
1149 self.assertEqual('test0', entry.test_str_fdt)
1150 self.assertEqual(None, entry.test_str_arg)
1151 self.assertEqual(None, entry.test_int_fdt)
1152 self.assertEqual(456, entry.test_int_arg)
1153
1154 def testEntryArgsRequired(self):
1155 """Test missing arguments and properties"""
1156 entry_args = {
1157 'test-int-arg': '456',
1158 }
1159 with self.assertRaises(ValueError) as e:
1160 self._DoReadFileDtb('64_entry_args_required.dts')
1161 self.assertIn("Node '/binman/_testing': Missing required "
1162 'properties/entry args: test-str-arg, test-int-fdt, test-int-arg',
1163 str(e.exception))
1164
1165 def testEntryArgsInvalidFormat(self):
1166 """Test that an invalid entry-argument format is detected"""
1167 args = ['-d', self.TestFile('64_entry_args_required.dts'), '-ano-value']
1168 with self.assertRaises(ValueError) as e:
1169 self._DoBinman(*args)
1170 self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
1171
1172 def testEntryArgsInvalidInteger(self):
1173 """Test that an invalid entry-argument integer is detected"""
1174 entry_args = {
1175 'test-int-arg': 'abc',
1176 }
1177 with self.assertRaises(ValueError) as e:
1178 self._DoReadFileDtb('62_entry_args.dts', entry_args=entry_args)
1179 self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
1180 "'test-int-arg' (value 'abc') to integer",
1181 str(e.exception))
1182
1183 def testEntryArgsInvalidDatatype(self):
1184 """Test that an invalid entry-argument datatype is detected
1185
1186 This test could be written in entry_test.py except that it needs
1187 access to control.entry_args, which seems more than that module should
1188 be able to see.
1189 """
1190 entry_args = {
1191 'test-bad-datatype-arg': '12',
1192 }
1193 with self.assertRaises(ValueError) as e:
1194 self._DoReadFileDtb('65_entry_args_unknown_datatype.dts',
1195 entry_args=entry_args)
1196 self.assertIn('GetArg() internal error: Unknown data type ',
1197 str(e.exception))
1198
Simon Glassbb748372018-07-17 13:25:33 -06001199 def testText(self):
1200 """Test for a text entry type"""
1201 entry_args = {
1202 'test-id': TEXT_DATA,
1203 'test-id2': TEXT_DATA2,
1204 'test-id3': TEXT_DATA3,
1205 }
1206 data, _, _, _ = self._DoReadFileDtb('66_text.dts',
1207 entry_args=entry_args)
1208 expected = (TEXT_DATA + chr(0) * (8 - len(TEXT_DATA)) + TEXT_DATA2 +
1209 TEXT_DATA3 + 'some text')
1210 self.assertEqual(expected, data)
1211
Simon Glassfd8d1f72018-07-17 13:25:36 -06001212 def testEntryDocs(self):
1213 """Test for creation of entry documentation"""
1214 with test_util.capture_sys_output() as (stdout, stderr):
1215 control.WriteEntryDocs(binman.GetEntryModules())
1216 self.assertTrue(len(stdout.getvalue()) > 0)
1217
1218 def testEntryDocsMissing(self):
1219 """Test handling of missing entry documentation"""
1220 with self.assertRaises(ValueError) as e:
1221 with test_util.capture_sys_output() as (stdout, stderr):
1222 control.WriteEntryDocs(binman.GetEntryModules(), 'u_boot')
1223 self.assertIn('Documentation is missing for modules: u_boot',
1224 str(e.exception))
1225
Simon Glass11e36cc2018-07-17 13:25:38 -06001226 def testFmap(self):
1227 """Basic test of generation of a flashrom fmap"""
1228 data = self._DoReadFile('67_fmap.dts')
1229 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1230 expected = U_BOOT_DATA + '!' * 12 + U_BOOT_DATA + 'a' * 12
1231 self.assertEqual(expected, data[:32])
1232 self.assertEqual('__FMAP__', fhdr.signature)
1233 self.assertEqual(1, fhdr.ver_major)
1234 self.assertEqual(0, fhdr.ver_minor)
1235 self.assertEqual(0, fhdr.base)
1236 self.assertEqual(16 + 16 +
1237 fmap_util.FMAP_HEADER_LEN +
1238 fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
1239 self.assertEqual('FMAP', fhdr.name)
1240 self.assertEqual(3, fhdr.nareas)
1241 for fentry in fentries:
1242 self.assertEqual(0, fentry.flags)
1243
1244 self.assertEqual(0, fentries[0].offset)
1245 self.assertEqual(4, fentries[0].size)
1246 self.assertEqual('RO_U_BOOT', fentries[0].name)
1247
1248 self.assertEqual(16, fentries[1].offset)
1249 self.assertEqual(4, fentries[1].size)
1250 self.assertEqual('RW_U_BOOT', fentries[1].name)
1251
1252 self.assertEqual(32, fentries[2].offset)
1253 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1254 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
1255 self.assertEqual('FMAP', fentries[2].name)
1256
Simon Glassec127af2018-07-17 13:25:39 -06001257 def testBlobNamedByArg(self):
1258 """Test we can add a blob with the filename coming from an entry arg"""
1259 entry_args = {
1260 'cros-ec-rw-path': 'ecrw.bin',
1261 }
1262 data, _, _, _ = self._DoReadFileDtb('68_blob_named_by_arg.dts',
1263 entry_args=entry_args)
1264
Simon Glass3af8e492018-07-17 13:25:40 -06001265 def testFill(self):
1266 """Test for an fill entry type"""
1267 data = self._DoReadFile('69_fill.dts')
1268 expected = 8 * chr(0xff) + 8 * chr(0)
1269 self.assertEqual(expected, data)
1270
1271 def testFillNoSize(self):
1272 """Test for an fill entry type with no size"""
1273 with self.assertRaises(ValueError) as e:
1274 self._DoReadFile('70_fill_no_size.dts')
1275 self.assertIn("'fill' entry must have a size property",
1276 str(e.exception))
1277
Simon Glass0ef87aa2018-07-17 13:25:44 -06001278 def _HandleGbbCommand(self, pipe_list):
1279 """Fake calls to the futility utility"""
1280 if pipe_list[0][0] == 'futility':
1281 fname = pipe_list[0][-1]
1282 # Append our GBB data to the file, which will happen every time the
1283 # futility command is called.
1284 with open(fname, 'a') as fd:
1285 fd.write(GBB_DATA)
1286 return command.CommandResult()
1287
1288 def testGbb(self):
1289 """Test for the Chromium OS Google Binary Block"""
1290 command.test_result = self._HandleGbbCommand
1291 entry_args = {
1292 'keydir': 'devkeys',
1293 'bmpblk': 'bmpblk.bin',
1294 }
1295 data, _, _, _ = self._DoReadFileDtb('71_gbb.dts', entry_args=entry_args)
1296
1297 # Since futility
1298 expected = GBB_DATA + GBB_DATA + 8 * chr(0) + (0x2180 - 16) * chr(0)
1299 self.assertEqual(expected, data)
1300
1301 def testGbbTooSmall(self):
1302 """Test for the Chromium OS Google Binary Block being large enough"""
1303 with self.assertRaises(ValueError) as e:
1304 self._DoReadFileDtb('72_gbb_too_small.dts')
1305 self.assertIn("Node '/binman/gbb': GBB is too small",
1306 str(e.exception))
1307
1308 def testGbbNoSize(self):
1309 """Test for the Chromium OS Google Binary Block having a size"""
1310 with self.assertRaises(ValueError) as e:
1311 self._DoReadFileDtb('73_gbb_no_size.dts')
1312 self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
1313 str(e.exception))
1314
Simon Glass24d0d3c2018-07-17 13:25:47 -06001315 def _HandleVblockCommand(self, pipe_list):
1316 """Fake calls to the futility utility"""
1317 if pipe_list[0][0] == 'futility':
1318 fname = pipe_list[0][3]
Simon Glassa326b492018-09-14 04:57:11 -06001319 with open(fname, 'wb') as fd:
Simon Glass24d0d3c2018-07-17 13:25:47 -06001320 fd.write(VBLOCK_DATA)
1321 return command.CommandResult()
1322
1323 def testVblock(self):
1324 """Test for the Chromium OS Verified Boot Block"""
1325 command.test_result = self._HandleVblockCommand
1326 entry_args = {
1327 'keydir': 'devkeys',
1328 }
1329 data, _, _, _ = self._DoReadFileDtb('74_vblock.dts',
1330 entry_args=entry_args)
1331 expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
1332 self.assertEqual(expected, data)
1333
1334 def testVblockNoContent(self):
1335 """Test we detect a vblock which has no content to sign"""
1336 with self.assertRaises(ValueError) as e:
1337 self._DoReadFile('75_vblock_no_content.dts')
1338 self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
1339 'property', str(e.exception))
1340
1341 def testVblockBadPhandle(self):
1342 """Test that we detect a vblock with an invalid phandle in contents"""
1343 with self.assertRaises(ValueError) as e:
1344 self._DoReadFile('76_vblock_bad_phandle.dts')
1345 self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
1346 '1000', str(e.exception))
1347
1348 def testVblockBadEntry(self):
1349 """Test that we detect an entry that points to a non-entry"""
1350 with self.assertRaises(ValueError) as e:
1351 self._DoReadFile('77_vblock_bad_entry.dts')
1352 self.assertIn("Node '/binman/vblock': Cannot find entry for node "
1353 "'other'", str(e.exception))
1354
Simon Glassb8ef5b62018-07-17 13:25:48 -06001355 def testTpl(self):
1356 """Test that an image with TPL and ots device tree can be created"""
1357 # ELF file with a '__bss_size' symbol
1358 with open(self.TestFile('bss_data')) as fd:
1359 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
1360 data = self._DoReadFile('78_u_boot_tpl.dts')
1361 self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
1362
Simon Glass15a587c2018-07-17 13:25:51 -06001363 def testUsesPos(self):
1364 """Test that the 'pos' property cannot be used anymore"""
1365 with self.assertRaises(ValueError) as e:
1366 data = self._DoReadFile('79_uses_pos.dts')
1367 self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
1368 "'pos'", str(e.exception))
1369
Simon Glassd178eab2018-09-14 04:57:08 -06001370 def testFillZero(self):
1371 """Test for an fill entry type with a size of 0"""
1372 data = self._DoReadFile('80_fill_empty.dts')
1373 self.assertEqual(chr(0) * 16, data)
1374
Simon Glass0b489362018-09-14 04:57:09 -06001375 def testTextMissing(self):
1376 """Test for a text entry type where there is no text"""
1377 with self.assertRaises(ValueError) as e:
1378 self._DoReadFileDtb('66_text.dts',)
1379 self.assertIn("Node '/binman/text': No value provided for text label "
1380 "'test-id'", str(e.exception))
1381
Simon Glass35b384c2018-09-14 04:57:10 -06001382 def testPackStart16Tpl(self):
1383 """Test that an image with an x86 start16 TPL region can be created"""
1384 data = self._DoReadFile('81_x86-start16-tpl.dts')
1385 self.assertEqual(X86_START16_TPL_DATA, data[:len(X86_START16_TPL_DATA)])
1386
Simon Glass53af22a2018-07-17 13:25:32 -06001387
Simon Glass9fc60b42017-11-12 21:52:22 -07001388if __name__ == "__main__":
1389 unittest.main()