blob: 51eab6fbfada9ea2edf3d9880034cf71c11ef4a7 [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 Glass1c420c92019-07-08 13:18:49 -06009from __future__ import print_function
10
Simon Glassae7cf032018-09-14 04:57:31 -060011import hashlib
Simon Glass57454f42016-11-25 20:15:52 -070012from optparse import OptionParser
13import os
14import shutil
15import struct
16import sys
17import tempfile
18import unittest
19
20import binman
Simon Glass1de34482019-07-08 13:18:53 -060021import cbfs_util
Simon Glass57454f42016-11-25 20:15:52 -070022import cmdline
23import command
24import control
Simon Glass4ca8e042017-11-13 18:55:01 -070025import elf
Simon Glassf6290892019-08-24 07:22:53 -060026import elf_test
Simon Glassa9440932017-05-27 07:38:30 -060027import fdt
Simon Glass8d8bf4e2019-07-08 14:25:44 -060028from etype import fdtmap
Simon Glassed39a3c2019-07-08 14:25:45 -060029from etype import image_header
Simon Glass57454f42016-11-25 20:15:52 -070030import fdt_util
Simon Glass704784b2018-07-17 13:25:38 -060031import fmap_util
Simon Glass969616c2018-07-17 13:25:36 -060032import test_util
Simon Glass759af872019-07-08 13:18:54 -060033import gzip
Simon Glassb8424fa2019-07-08 14:25:46 -060034from image import Image
Simon Glass29aa7362018-09-14 04:57:19 -060035import state
Simon Glass57454f42016-11-25 20:15:52 -070036import tools
37import tout
38
39# Contents of test files, corresponding to different entry types
Simon Glass303f62f2019-05-17 22:00:46 -060040U_BOOT_DATA = b'1234'
41U_BOOT_IMG_DATA = b'img'
42U_BOOT_SPL_DATA = b'56780123456789abcde'
43U_BOOT_TPL_DATA = b'tpl'
44BLOB_DATA = b'89'
45ME_DATA = b'0abcd'
46VGA_DATA = b'vga'
47U_BOOT_DTB_DATA = b'udtb'
48U_BOOT_SPL_DTB_DATA = b'spldtb'
49U_BOOT_TPL_DTB_DATA = b'tpldtb'
50X86_START16_DATA = b'start16'
51X86_START16_SPL_DATA = b'start16spl'
52X86_START16_TPL_DATA = b'start16tpl'
Simon Glass0b074d62019-08-24 07:22:48 -060053X86_RESET16_DATA = b'reset16'
54X86_RESET16_SPL_DATA = b'reset16spl'
55X86_RESET16_TPL_DATA = b'reset16tpl'
Simon Glass303f62f2019-05-17 22:00:46 -060056PPC_MPC85XX_BR_DATA = b'ppcmpc85xxbr'
57U_BOOT_NODTB_DATA = b'nodtb with microcode pointer somewhere in here'
58U_BOOT_SPL_NODTB_DATA = b'splnodtb with microcode pointer somewhere in here'
59U_BOOT_TPL_NODTB_DATA = b'tplnodtb with microcode pointer somewhere in here'
60FSP_DATA = b'fsp'
61CMC_DATA = b'cmc'
62VBT_DATA = b'vbt'
63MRC_DATA = b'mrc'
Simon Glass2ca52032018-07-17 13:25:33 -060064TEXT_DATA = 'text'
65TEXT_DATA2 = 'text2'
66TEXT_DATA3 = 'text3'
Simon Glass303f62f2019-05-17 22:00:46 -060067CROS_EC_RW_DATA = b'ecrw'
68GBB_DATA = b'gbbd'
69BMPBLK_DATA = b'bmp'
70VBLOCK_DATA = b'vblk'
71FILES_DATA = (b"sorry I'm late\nOh, don't bother apologising, I'm " +
72 b"sorry you're alive\n")
Simon Glassccec0262019-07-08 13:18:42 -060073COMPRESS_DATA = b'compress xxxxxxxxxxxxxxxxxxxxxx data'
Simon Glass303f62f2019-05-17 22:00:46 -060074REFCODE_DATA = b'refcode'
Simon Glassdb168d42018-07-17 13:25:39 -060075
Simon Glass2c6adba2019-07-20 12:23:47 -060076# The expected size for the device tree in some tests
Simon Glass4c613bf2019-07-08 14:25:50 -060077EXTRACT_DTB_SIZE = 0x3c9
78
Simon Glass2c6adba2019-07-20 12:23:47 -060079# Properties expected to be in the device tree when update_dtb is used
80BASE_DTB_PROPS = ['offset', 'size', 'image-pos']
81
Simon Glassfb30e292019-07-20 12:23:51 -060082# Extra properties expected to be in the device tree when allow-repack is used
83REPACK_DTB_PROPS = ['orig-offset', 'orig-size']
84
Simon Glass57454f42016-11-25 20:15:52 -070085
86class TestFunctional(unittest.TestCase):
87 """Functional tests for binman
88
89 Most of these use a sample .dts file to build an image and then check
90 that it looks correct. The sample files are in the test/ subdirectory
91 and are numbered.
92
93 For each entry type a very small test file is created using fixed
94 string contents. This makes it easy to test that things look right, and
95 debug problems.
96
97 In some cases a 'real' file must be used - these are also supplied in
98 the test/ diurectory.
99 """
100 @classmethod
Simon Glass862f8e22019-08-24 07:22:43 -0600101 def setUpClass(cls):
Simon Glassb3393262017-11-12 21:52:20 -0700102 global entry
103 import entry
104
Simon Glass57454f42016-11-25 20:15:52 -0700105 # Handle the case where argv[0] is 'python'
Simon Glass862f8e22019-08-24 07:22:43 -0600106 cls._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
107 cls._binman_pathname = os.path.join(cls._binman_dir, 'binman')
Simon Glass57454f42016-11-25 20:15:52 -0700108
109 # Create a temporary directory for input files
Simon Glass862f8e22019-08-24 07:22:43 -0600110 cls._indir = tempfile.mkdtemp(prefix='binmant.')
Simon Glass57454f42016-11-25 20:15:52 -0700111
112 # Create some test files
113 TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
114 TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
115 TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
Simon Glass8425a1f2018-07-17 13:25:48 -0600116 TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
Simon Glass57454f42016-11-25 20:15:52 -0700117 TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
Simon Glass72232452016-11-25 20:15:53 -0700118 TestFunctional._MakeInputFile('me.bin', ME_DATA)
119 TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
Simon Glass862f8e22019-08-24 07:22:43 -0600120 cls._ResetDtbs()
Simon Glass0b074d62019-08-24 07:22:48 -0600121
Jagdish Gediya311d4842018-09-03 21:35:08 +0530122 TestFunctional._MakeInputFile('u-boot-br.bin', PPC_MPC85XX_BR_DATA)
Simon Glass0b074d62019-08-24 07:22:48 -0600123
Simon Glassabab18c2019-08-24 07:22:49 -0600124 TestFunctional._MakeInputFile('u-boot-x86-start16.bin', X86_START16_DATA)
125 TestFunctional._MakeInputFile('spl/u-boot-x86-start16-spl.bin',
Simon Glasse83679d2017-11-12 21:52:26 -0700126 X86_START16_SPL_DATA)
Simon Glassabab18c2019-08-24 07:22:49 -0600127 TestFunctional._MakeInputFile('tpl/u-boot-x86-start16-tpl.bin',
Simon Glassed40e962018-09-14 04:57:10 -0600128 X86_START16_TPL_DATA)
Simon Glass0b074d62019-08-24 07:22:48 -0600129
130 TestFunctional._MakeInputFile('u-boot-x86-reset16.bin',
131 X86_RESET16_DATA)
132 TestFunctional._MakeInputFile('spl/u-boot-x86-reset16-spl.bin',
133 X86_RESET16_SPL_DATA)
134 TestFunctional._MakeInputFile('tpl/u-boot-x86-reset16-tpl.bin',
135 X86_RESET16_TPL_DATA)
136
Simon Glass57454f42016-11-25 20:15:52 -0700137 TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
Simon Glass3d274232017-11-12 21:52:27 -0700138 TestFunctional._MakeInputFile('spl/u-boot-spl-nodtb.bin',
139 U_BOOT_SPL_NODTB_DATA)
Simon Glass3fb4f422018-09-14 04:57:32 -0600140 TestFunctional._MakeInputFile('tpl/u-boot-tpl-nodtb.bin',
141 U_BOOT_TPL_NODTB_DATA)
Simon Glassb4176d42016-11-25 20:15:56 -0700142 TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
143 TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
Bin Mengd7bcdf52017-08-15 22:41:54 -0700144 TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
Simon Glassa409c932017-11-12 21:52:28 -0700145 TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
Simon Glassdb168d42018-07-17 13:25:39 -0600146 TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
Simon Glassc1ae83c2018-07-17 13:25:44 -0600147 TestFunctional._MakeInputDir('devkeys')
148 TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
Simon Glass41902e42018-10-01 12:22:31 -0600149 TestFunctional._MakeInputFile('refcode.bin', REFCODE_DATA)
Simon Glass57454f42016-11-25 20:15:52 -0700150
Simon Glassf6290892019-08-24 07:22:53 -0600151 cls._elf_testdir = os.path.join(cls._indir, 'elftest')
152 elf_test.BuildElfTestFiles(cls._elf_testdir)
153
Simon Glass72232452016-11-25 20:15:53 -0700154 # ELF file with a '_dt_ucode_base_size' symbol
Simon Glass4affd4b2019-08-24 07:22:54 -0600155 TestFunctional._MakeInputFile('u-boot',
156 tools.ReadFile(cls.ElfTestFile('u_boot_ucode_ptr')))
Simon Glass72232452016-11-25 20:15:53 -0700157
158 # Intel flash descriptor file
Simon Glass862f8e22019-08-24 07:22:43 -0600159 with open(cls.TestFile('descriptor.bin'), 'rb') as fd:
Simon Glass72232452016-11-25 20:15:53 -0700160 TestFunctional._MakeInputFile('descriptor.bin', fd.read())
161
Simon Glass862f8e22019-08-24 07:22:43 -0600162 shutil.copytree(cls.TestFile('files'),
163 os.path.join(cls._indir, 'files'))
Simon Glassac6328c2018-09-14 04:57:28 -0600164
Simon Glass7ba33592018-09-14 04:57:26 -0600165 TestFunctional._MakeInputFile('compress', COMPRESS_DATA)
166
Simon Glass1de34482019-07-08 13:18:53 -0600167 # Travis-CI may have an old lz4
Simon Glass862f8e22019-08-24 07:22:43 -0600168 cls.have_lz4 = True
Simon Glass1de34482019-07-08 13:18:53 -0600169 try:
170 tools.Run('lz4', '--no-frame-crc', '-c',
Simon Glass862f8e22019-08-24 07:22:43 -0600171 os.path.join(cls._indir, 'u-boot.bin'))
Simon Glass1de34482019-07-08 13:18:53 -0600172 except:
Simon Glass862f8e22019-08-24 07:22:43 -0600173 cls.have_lz4 = False
Simon Glass1de34482019-07-08 13:18:53 -0600174
Simon Glass57454f42016-11-25 20:15:52 -0700175 @classmethod
Simon Glass862f8e22019-08-24 07:22:43 -0600176 def tearDownClass(cls):
Simon Glass57454f42016-11-25 20:15:52 -0700177 """Remove the temporary input directory and its contents"""
Simon Glass862f8e22019-08-24 07:22:43 -0600178 if cls.preserve_indir:
179 print('Preserving input dir: %s' % cls._indir)
Simon Glass1c420c92019-07-08 13:18:49 -0600180 else:
Simon Glass862f8e22019-08-24 07:22:43 -0600181 if cls._indir:
182 shutil.rmtree(cls._indir)
183 cls._indir = None
Simon Glass57454f42016-11-25 20:15:52 -0700184
Simon Glass1c420c92019-07-08 13:18:49 -0600185 @classmethod
Simon Glasscebfab22019-07-08 13:18:50 -0600186 def setup_test_args(cls, preserve_indir=False, preserve_outdirs=False,
Simon Glassf46732a2019-07-08 14:25:29 -0600187 toolpath=None, verbosity=None):
Simon Glass1c420c92019-07-08 13:18:49 -0600188 """Accept arguments controlling test execution
189
190 Args:
191 preserve_indir: Preserve the shared input directory used by all
192 tests in this class.
193 preserve_outdir: Preserve the output directories used by tests. Each
194 test has its own, so this is normally only useful when running a
195 single test.
Simon Glasscebfab22019-07-08 13:18:50 -0600196 toolpath: ist of paths to use for tools
Simon Glass1c420c92019-07-08 13:18:49 -0600197 """
198 cls.preserve_indir = preserve_indir
199 cls.preserve_outdirs = preserve_outdirs
Simon Glasscebfab22019-07-08 13:18:50 -0600200 cls.toolpath = toolpath
Simon Glassf46732a2019-07-08 14:25:29 -0600201 cls.verbosity = verbosity
Simon Glass1c420c92019-07-08 13:18:49 -0600202
Simon Glass1de34482019-07-08 13:18:53 -0600203 def _CheckLz4(self):
204 if not self.have_lz4:
205 self.skipTest('lz4 --no-frame-crc not available')
206
Simon Glassee9d10d2019-07-20 12:24:09 -0600207 def _CleanupOutputDir(self):
208 """Remove the temporary output directory"""
209 if self.preserve_outdirs:
210 print('Preserving output dir: %s' % tools.outdir)
211 else:
212 tools._FinaliseForTest()
213
Simon Glass57454f42016-11-25 20:15:52 -0700214 def setUp(self):
215 # Enable this to turn on debugging output
216 # tout.Init(tout.DEBUG)
217 command.test_result = None
218
219 def tearDown(self):
220 """Remove the temporary output directory"""
Simon Glassee9d10d2019-07-20 12:24:09 -0600221 self._CleanupOutputDir()
Simon Glass57454f42016-11-25 20:15:52 -0700222
Simon Glassb3d6fc72019-07-20 12:24:10 -0600223 def _SetupImageInTmpdir(self):
224 """Set up the output image in a new temporary directory
225
226 This is used when an image has been generated in the output directory,
227 but we want to run binman again. This will create a new output
228 directory and fail to delete the original one.
229
230 This creates a new temporary directory, copies the image to it (with a
231 new name) and removes the old output directory.
232
233 Returns:
234 Tuple:
235 Temporary directory to use
236 New image filename
237 """
238 image_fname = tools.GetOutputFilename('image.bin')
239 tmpdir = tempfile.mkdtemp(prefix='binman.')
240 updated_fname = os.path.join(tmpdir, 'image-updated.bin')
241 tools.WriteFile(updated_fname, tools.ReadFile(image_fname))
242 self._CleanupOutputDir()
243 return tmpdir, updated_fname
244
Simon Glass8425a1f2018-07-17 13:25:48 -0600245 @classmethod
Simon Glass862f8e22019-08-24 07:22:43 -0600246 def _ResetDtbs(cls):
Simon Glass8425a1f2018-07-17 13:25:48 -0600247 TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
248 TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
249 TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
250
Simon Glass57454f42016-11-25 20:15:52 -0700251 def _RunBinman(self, *args, **kwargs):
252 """Run binman using the command line
253
254 Args:
255 Arguments to pass, as a list of strings
256 kwargs: Arguments to pass to Command.RunPipe()
257 """
258 result = command.RunPipe([[self._binman_pathname] + list(args)],
259 capture=True, capture_stderr=True, raise_on_error=False)
260 if result.return_code and kwargs.get('raise_on_error', True):
261 raise Exception("Error running '%s': %s" % (' '.join(args),
262 result.stdout + result.stderr))
263 return result
264
Simon Glassf46732a2019-07-08 14:25:29 -0600265 def _DoBinman(self, *argv):
Simon Glass57454f42016-11-25 20:15:52 -0700266 """Run binman using directly (in the same process)
267
268 Args:
269 Arguments to pass, as a list of strings
270 Returns:
271 Return value (0 for success)
272 """
Simon Glassf46732a2019-07-08 14:25:29 -0600273 argv = list(argv)
274 args = cmdline.ParseArgs(argv)
275 args.pager = 'binman-invalid-pager'
276 args.build_dir = self._indir
Simon Glass57454f42016-11-25 20:15:52 -0700277
278 # For testing, you can force an increase in verbosity here
Simon Glassf46732a2019-07-08 14:25:29 -0600279 # args.verbosity = tout.DEBUG
280 return control.Binman(args)
Simon Glass57454f42016-11-25 20:15:52 -0700281
Simon Glass91710b32018-07-17 13:25:32 -0600282 def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
Simon Glassb4595d82019-04-25 21:58:34 -0600283 entry_args=None, images=None, use_real_dtb=False,
284 verbosity=None):
Simon Glass57454f42016-11-25 20:15:52 -0700285 """Run binman with a given test file
286
287 Args:
Simon Glass511f6582018-10-01 12:22:30 -0600288 fname: Device-tree source filename to use (e.g. 005_simple.dts)
Simon Glass1e324002018-06-01 09:38:19 -0600289 debug: True to enable debugging output
Simon Glass30732662018-06-01 09:38:20 -0600290 map: True to output map files for the images
Simon Glasse8561af2018-08-01 15:22:37 -0600291 update_dtb: Update the offset and size of each entry in the device
Simon Glassa87014e2018-07-06 10:27:42 -0600292 tree before packing it into the image
Simon Glass3b376c32018-09-14 04:57:12 -0600293 entry_args: Dict of entry args to supply to binman
294 key: arg name
295 value: value of that arg
296 images: List of image names to build
Simon Glass57454f42016-11-25 20:15:52 -0700297 """
Simon Glassf46732a2019-07-08 14:25:29 -0600298 args = []
Simon Glass075a45c2017-11-13 18:55:00 -0700299 if debug:
300 args.append('-D')
Simon Glassf46732a2019-07-08 14:25:29 -0600301 if verbosity is not None:
302 args.append('-v%d' % verbosity)
303 elif self.verbosity:
304 args.append('-v%d' % self.verbosity)
305 if self.toolpath:
306 for path in self.toolpath:
307 args += ['--toolpath', path]
308 args += ['build', '-p', '-I', self._indir, '-d', self.TestFile(fname)]
Simon Glass30732662018-06-01 09:38:20 -0600309 if map:
310 args.append('-m')
Simon Glassa87014e2018-07-06 10:27:42 -0600311 if update_dtb:
Simon Glass38a411c2019-07-08 13:18:47 -0600312 args.append('-u')
Simon Glass31402012018-09-14 04:57:23 -0600313 if not use_real_dtb:
314 args.append('--fake-dtb')
Simon Glass91710b32018-07-17 13:25:32 -0600315 if entry_args:
Simon Glass5f3645b2019-05-14 15:53:41 -0600316 for arg, value in entry_args.items():
Simon Glass91710b32018-07-17 13:25:32 -0600317 args.append('-a%s=%s' % (arg, value))
Simon Glass3b376c32018-09-14 04:57:12 -0600318 if images:
319 for image in images:
320 args += ['-i', image]
Simon Glass075a45c2017-11-13 18:55:00 -0700321 return self._DoBinman(*args)
Simon Glass57454f42016-11-25 20:15:52 -0700322
323 def _SetupDtb(self, fname, outfile='u-boot.dtb'):
Simon Glass72232452016-11-25 20:15:53 -0700324 """Set up a new test device-tree file
325
326 The given file is compiled and set up as the device tree to be used
327 for ths test.
328
329 Args:
330 fname: Filename of .dts file to read
Simon Glass1e324002018-06-01 09:38:19 -0600331 outfile: Output filename for compiled device-tree binary
Simon Glass72232452016-11-25 20:15:53 -0700332
333 Returns:
Simon Glass1e324002018-06-01 09:38:19 -0600334 Contents of device-tree binary
Simon Glass72232452016-11-25 20:15:53 -0700335 """
Simon Glassb8d2daa2019-07-20 12:23:49 -0600336 tmpdir = tempfile.mkdtemp(prefix='binmant.')
337 dtb = fdt_util.EnsureCompiled(self.TestFile(fname), tmpdir)
Simon Glass33486662019-05-14 15:53:42 -0600338 with open(dtb, 'rb') as fd:
Simon Glass57454f42016-11-25 20:15:52 -0700339 data = fd.read()
340 TestFunctional._MakeInputFile(outfile, data)
Simon Glassb8d2daa2019-07-20 12:23:49 -0600341 shutil.rmtree(tmpdir)
Simon Glass752e7552018-10-01 21:12:41 -0600342 return data
Simon Glass57454f42016-11-25 20:15:52 -0700343
Simon Glasse219aa42018-09-14 04:57:24 -0600344 def _GetDtbContentsForSplTpl(self, dtb_data, name):
345 """Create a version of the main DTB for SPL or SPL
346
347 For testing we don't actually have different versions of the DTB. With
348 U-Boot we normally run fdtgrep to remove unwanted nodes, but for tests
349 we don't normally have any unwanted nodes.
350
351 We still want the DTBs for SPL and TPL to be different though, since
352 otherwise it is confusing to know which one we are looking at. So add
353 an 'spl' or 'tpl' property to the top-level node.
354 """
355 dtb = fdt.Fdt.FromData(dtb_data)
356 dtb.Scan()
357 dtb.GetNode('/binman').AddZeroProp(name)
358 dtb.Sync(auto_resize=True)
359 dtb.Pack()
360 return dtb.GetContents()
361
Simon Glassa87014e2018-07-06 10:27:42 -0600362 def _DoReadFileDtb(self, fname, use_real_dtb=False, map=False,
Simon Glasse219aa42018-09-14 04:57:24 -0600363 update_dtb=False, entry_args=None, reset_dtbs=True):
Simon Glass57454f42016-11-25 20:15:52 -0700364 """Run binman and return the resulting image
365
366 This runs binman with a given test file and then reads the resulting
367 output file. It is a shortcut function since most tests need to do
368 these steps.
369
370 Raises an assertion failure if binman returns a non-zero exit code.
371
372 Args:
Simon Glass511f6582018-10-01 12:22:30 -0600373 fname: Device-tree source filename to use (e.g. 005_simple.dts)
Simon Glass57454f42016-11-25 20:15:52 -0700374 use_real_dtb: True to use the test file as the contents of
375 the u-boot-dtb entry. Normally this is not needed and the
376 test contents (the U_BOOT_DTB_DATA string) can be used.
377 But in some test we need the real contents.
Simon Glass30732662018-06-01 09:38:20 -0600378 map: True to output map files for the images
Simon Glasse8561af2018-08-01 15:22:37 -0600379 update_dtb: Update the offset and size of each entry in the device
Simon Glassa87014e2018-07-06 10:27:42 -0600380 tree before packing it into the image
Simon Glass72232452016-11-25 20:15:53 -0700381
382 Returns:
383 Tuple:
384 Resulting image contents
385 Device tree contents
Simon Glass30732662018-06-01 09:38:20 -0600386 Map data showing contents of image (or None if none)
Simon Glassdef77b52018-07-17 13:25:27 -0600387 Output device tree binary filename ('u-boot.dtb' path)
Simon Glass57454f42016-11-25 20:15:52 -0700388 """
Simon Glass72232452016-11-25 20:15:53 -0700389 dtb_data = None
Simon Glass57454f42016-11-25 20:15:52 -0700390 # Use the compiled test file as the u-boot-dtb input
391 if use_real_dtb:
Simon Glass72232452016-11-25 20:15:53 -0700392 dtb_data = self._SetupDtb(fname)
Simon Glasse219aa42018-09-14 04:57:24 -0600393
394 # For testing purposes, make a copy of the DT for SPL and TPL. Add
395 # a node indicating which it is, so aid verification.
396 for name in ['spl', 'tpl']:
397 dtb_fname = '%s/u-boot-%s.dtb' % (name, name)
398 outfile = os.path.join(self._indir, dtb_fname)
399 TestFunctional._MakeInputFile(dtb_fname,
400 self._GetDtbContentsForSplTpl(dtb_data, name))
Simon Glass57454f42016-11-25 20:15:52 -0700401
402 try:
Simon Glass91710b32018-07-17 13:25:32 -0600403 retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
Simon Glasse219aa42018-09-14 04:57:24 -0600404 entry_args=entry_args, use_real_dtb=use_real_dtb)
Simon Glass57454f42016-11-25 20:15:52 -0700405 self.assertEqual(0, retcode)
Simon Glasse219aa42018-09-14 04:57:24 -0600406 out_dtb_fname = tools.GetOutputFilename('u-boot.dtb.out')
Simon Glass57454f42016-11-25 20:15:52 -0700407
408 # Find the (only) image, read it and return its contents
409 image = control.images['image']
Simon Glassa87014e2018-07-06 10:27:42 -0600410 image_fname = tools.GetOutputFilename('image.bin')
411 self.assertTrue(os.path.exists(image_fname))
Simon Glass30732662018-06-01 09:38:20 -0600412 if map:
413 map_fname = tools.GetOutputFilename('image.map')
414 with open(map_fname) as fd:
415 map_data = fd.read()
416 else:
417 map_data = None
Simon Glass33486662019-05-14 15:53:42 -0600418 with open(image_fname, 'rb') as fd:
Simon Glassa87014e2018-07-06 10:27:42 -0600419 return fd.read(), dtb_data, map_data, out_dtb_fname
Simon Glass57454f42016-11-25 20:15:52 -0700420 finally:
421 # Put the test file back
Simon Glasse219aa42018-09-14 04:57:24 -0600422 if reset_dtbs and use_real_dtb:
Simon Glass8425a1f2018-07-17 13:25:48 -0600423 self._ResetDtbs()
Simon Glass57454f42016-11-25 20:15:52 -0700424
Simon Glass5b4bce32019-07-08 14:25:26 -0600425 def _DoReadFileRealDtb(self, fname):
426 """Run binman with a real .dtb file and return the resulting data
427
428 Args:
429 fname: DT source filename to use (e.g. 082_fdt_update_all.dts)
430
431 Returns:
432 Resulting image contents
433 """
434 return self._DoReadFileDtb(fname, use_real_dtb=True, update_dtb=True)[0]
435
Simon Glass72232452016-11-25 20:15:53 -0700436 def _DoReadFile(self, fname, use_real_dtb=False):
Simon Glass1e324002018-06-01 09:38:19 -0600437 """Helper function which discards the device-tree binary
438
439 Args:
Simon Glass511f6582018-10-01 12:22:30 -0600440 fname: Device-tree source filename to use (e.g. 005_simple.dts)
Simon Glass1e324002018-06-01 09:38:19 -0600441 use_real_dtb: True to use the test file as the contents of
442 the u-boot-dtb entry. Normally this is not needed and the
443 test contents (the U_BOOT_DTB_DATA string) can be used.
444 But in some test we need the real contents.
Simon Glassdef77b52018-07-17 13:25:27 -0600445
446 Returns:
447 Resulting image contents
Simon Glass1e324002018-06-01 09:38:19 -0600448 """
Simon Glass72232452016-11-25 20:15:53 -0700449 return self._DoReadFileDtb(fname, use_real_dtb)[0]
450
Simon Glass57454f42016-11-25 20:15:52 -0700451 @classmethod
Simon Glass862f8e22019-08-24 07:22:43 -0600452 def _MakeInputFile(cls, fname, contents):
Simon Glass57454f42016-11-25 20:15:52 -0700453 """Create a new test input file, creating directories as needed
454
455 Args:
Simon Glasse8561af2018-08-01 15:22:37 -0600456 fname: Filename to create
Simon Glass57454f42016-11-25 20:15:52 -0700457 contents: File contents to write in to the file
458 Returns:
459 Full pathname of file created
460 """
Simon Glass862f8e22019-08-24 07:22:43 -0600461 pathname = os.path.join(cls._indir, fname)
Simon Glass57454f42016-11-25 20:15:52 -0700462 dirname = os.path.dirname(pathname)
463 if dirname and not os.path.exists(dirname):
464 os.makedirs(dirname)
465 with open(pathname, 'wb') as fd:
466 fd.write(contents)
467 return pathname
468
469 @classmethod
Simon Glass862f8e22019-08-24 07:22:43 -0600470 def _MakeInputDir(cls, dirname):
Simon Glassc1ae83c2018-07-17 13:25:44 -0600471 """Create a new test input directory, creating directories as needed
472
473 Args:
474 dirname: Directory name to create
475
476 Returns:
477 Full pathname of directory created
478 """
Simon Glass862f8e22019-08-24 07:22:43 -0600479 pathname = os.path.join(cls._indir, dirname)
Simon Glassc1ae83c2018-07-17 13:25:44 -0600480 if not os.path.exists(pathname):
481 os.makedirs(pathname)
482 return pathname
483
484 @classmethod
Simon Glass862f8e22019-08-24 07:22:43 -0600485 def _SetupSplElf(cls, src_fname='bss_data'):
Simon Glass7057d022018-10-01 21:12:47 -0600486 """Set up an ELF file with a '_dt_ucode_base_size' symbol
487
488 Args:
489 Filename of ELF file to use as SPL
490 """
Simon Glassf6290892019-08-24 07:22:53 -0600491 # TODO(sjg@chromium.org): Drop this when all Elf files use ElfTestFile()
Simon Glass5d0c0262019-08-24 07:22:56 -0600492 if src_fname in ['bss_data', 'u_boot_ucode_ptr', 'u_boot_no_ucode_ptr',
Simon Glassb8deb122019-08-24 07:22:57 -0600493 'u_boot_binman_syms', 'u_boot_binman_syms_size']:
Simon Glassf6290892019-08-24 07:22:53 -0600494 fname = cls.ElfTestFile(src_fname)
495 else:
496 fname = cls.TestFile(src_fname)
497 TestFunctional._MakeInputFile('spl/u-boot-spl', tools.ReadFile(fname))
Simon Glass7057d022018-10-01 21:12:47 -0600498
499 @classmethod
Simon Glass862f8e22019-08-24 07:22:43 -0600500 def TestFile(cls, fname):
501 return os.path.join(cls._binman_dir, 'test', fname)
Simon Glass57454f42016-11-25 20:15:52 -0700502
Simon Glassf6290892019-08-24 07:22:53 -0600503 @classmethod
504 def ElfTestFile(cls, fname):
505 return os.path.join(cls._elf_testdir, fname)
506
Simon Glass57454f42016-11-25 20:15:52 -0700507 def AssertInList(self, grep_list, target):
508 """Assert that at least one of a list of things is in a target
509
510 Args:
511 grep_list: List of strings to check
512 target: Target string
513 """
514 for grep in grep_list:
515 if grep in target:
516 return
Simon Glass848cdb52019-05-17 22:00:50 -0600517 self.fail("Error: '%s' not found in '%s'" % (grep_list, target))
Simon Glass57454f42016-11-25 20:15:52 -0700518
519 def CheckNoGaps(self, entries):
520 """Check that all entries fit together without gaps
521
522 Args:
523 entries: List of entries to check
524 """
Simon Glasse8561af2018-08-01 15:22:37 -0600525 offset = 0
Simon Glass57454f42016-11-25 20:15:52 -0700526 for entry in entries.values():
Simon Glasse8561af2018-08-01 15:22:37 -0600527 self.assertEqual(offset, entry.offset)
528 offset += entry.size
Simon Glass57454f42016-11-25 20:15:52 -0700529
Simon Glass72232452016-11-25 20:15:53 -0700530 def GetFdtLen(self, dtb):
Simon Glass1e324002018-06-01 09:38:19 -0600531 """Get the totalsize field from a device-tree binary
Simon Glass72232452016-11-25 20:15:53 -0700532
533 Args:
Simon Glass1e324002018-06-01 09:38:19 -0600534 dtb: Device-tree binary contents
Simon Glass72232452016-11-25 20:15:53 -0700535
536 Returns:
Simon Glass1e324002018-06-01 09:38:19 -0600537 Total size of device-tree binary, from the header
Simon Glass72232452016-11-25 20:15:53 -0700538 """
539 return struct.unpack('>L', dtb[4:8])[0]
540
Simon Glass0f621332019-07-08 14:25:27 -0600541 def _GetPropTree(self, dtb, prop_names, prefix='/binman/'):
Simon Glassa87014e2018-07-06 10:27:42 -0600542 def AddNode(node, path):
543 if node.name != '/':
544 path += '/' + node.name
Simon Glass0f621332019-07-08 14:25:27 -0600545 for prop in node.props.values():
546 if prop.name in prop_names:
547 prop_path = path + ':' + prop.name
548 tree[prop_path[len(prefix):]] = fdt_util.fdt32_to_cpu(
549 prop.value)
Simon Glassa87014e2018-07-06 10:27:42 -0600550 for subnode in node.subnodes:
Simon Glassa87014e2018-07-06 10:27:42 -0600551 AddNode(subnode, path)
552
553 tree = {}
Simon Glassa87014e2018-07-06 10:27:42 -0600554 AddNode(dtb.GetRoot(), '')
555 return tree
556
Simon Glass57454f42016-11-25 20:15:52 -0700557 def testRun(self):
558 """Test a basic run with valid args"""
559 result = self._RunBinman('-h')
560
561 def testFullHelp(self):
562 """Test that the full help is displayed with -H"""
563 result = self._RunBinman('-H')
564 help_file = os.path.join(self._binman_dir, 'README')
Tom Rinic3c0b6d2018-01-16 15:29:50 -0500565 # Remove possible extraneous strings
566 extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
567 gothelp = result.stdout.replace(extra, '')
568 self.assertEqual(len(gothelp), os.path.getsize(help_file))
Simon Glass57454f42016-11-25 20:15:52 -0700569 self.assertEqual(0, len(result.stderr))
570 self.assertEqual(0, result.return_code)
571
572 def testFullHelpInternal(self):
573 """Test that the full help is displayed with -H"""
574 try:
575 command.test_result = command.CommandResult()
576 result = self._DoBinman('-H')
577 help_file = os.path.join(self._binman_dir, 'README')
578 finally:
579 command.test_result = None
580
581 def testHelp(self):
582 """Test that the basic help is displayed with -h"""
583 result = self._RunBinman('-h')
584 self.assertTrue(len(result.stdout) > 200)
585 self.assertEqual(0, len(result.stderr))
586 self.assertEqual(0, result.return_code)
587
Simon Glass57454f42016-11-25 20:15:52 -0700588 def testBoard(self):
589 """Test that we can run it with a specific board"""
Simon Glass511f6582018-10-01 12:22:30 -0600590 self._SetupDtb('005_simple.dts', 'sandbox/u-boot.dtb')
Simon Glass57454f42016-11-25 20:15:52 -0700591 TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
Simon Glassf46732a2019-07-08 14:25:29 -0600592 result = self._DoBinman('build', '-b', 'sandbox')
Simon Glass57454f42016-11-25 20:15:52 -0700593 self.assertEqual(0, result)
594
595 def testNeedBoard(self):
596 """Test that we get an error when no board ius supplied"""
597 with self.assertRaises(ValueError) as e:
Simon Glassf46732a2019-07-08 14:25:29 -0600598 result = self._DoBinman('build')
Simon Glass57454f42016-11-25 20:15:52 -0700599 self.assertIn("Must provide a board to process (use -b <board>)",
600 str(e.exception))
601
602 def testMissingDt(self):
Simon Glass1e324002018-06-01 09:38:19 -0600603 """Test that an invalid device-tree file generates an error"""
Simon Glass57454f42016-11-25 20:15:52 -0700604 with self.assertRaises(Exception) as e:
Simon Glassf46732a2019-07-08 14:25:29 -0600605 self._RunBinman('build', '-d', 'missing_file')
Simon Glass57454f42016-11-25 20:15:52 -0700606 # We get one error from libfdt, and a different one from fdtget.
607 self.AssertInList(["Couldn't open blob from 'missing_file'",
608 'No such file or directory'], str(e.exception))
609
610 def testBrokenDt(self):
Simon Glass1e324002018-06-01 09:38:19 -0600611 """Test that an invalid device-tree source file generates an error
Simon Glass57454f42016-11-25 20:15:52 -0700612
613 Since this is a source file it should be compiled and the error
614 will come from the device-tree compiler (dtc).
615 """
616 with self.assertRaises(Exception) as e:
Simon Glassf46732a2019-07-08 14:25:29 -0600617 self._RunBinman('build', '-d', self.TestFile('001_invalid.dts'))
Simon Glass57454f42016-11-25 20:15:52 -0700618 self.assertIn("FATAL ERROR: Unable to parse input tree",
619 str(e.exception))
620
621 def testMissingNode(self):
622 """Test that a device tree without a 'binman' node generates an error"""
623 with self.assertRaises(Exception) as e:
Simon Glassf46732a2019-07-08 14:25:29 -0600624 self._DoBinman('build', '-d', self.TestFile('002_missing_node.dts'))
Simon Glass57454f42016-11-25 20:15:52 -0700625 self.assertIn("does not have a 'binman' node", str(e.exception))
626
627 def testEmpty(self):
628 """Test that an empty binman node works OK (i.e. does nothing)"""
Simon Glassf46732a2019-07-08 14:25:29 -0600629 result = self._RunBinman('build', '-d', self.TestFile('003_empty.dts'))
Simon Glass57454f42016-11-25 20:15:52 -0700630 self.assertEqual(0, len(result.stderr))
631 self.assertEqual(0, result.return_code)
632
633 def testInvalidEntry(self):
634 """Test that an invalid entry is flagged"""
635 with self.assertRaises(Exception) as e:
Simon Glassf46732a2019-07-08 14:25:29 -0600636 result = self._RunBinman('build', '-d',
Simon Glass511f6582018-10-01 12:22:30 -0600637 self.TestFile('004_invalid_entry.dts'))
Simon Glass57454f42016-11-25 20:15:52 -0700638 self.assertIn("Unknown entry type 'not-a-valid-type' in node "
639 "'/binman/not-a-valid-type'", str(e.exception))
640
641 def testSimple(self):
642 """Test a simple binman with a single file"""
Simon Glass511f6582018-10-01 12:22:30 -0600643 data = self._DoReadFile('005_simple.dts')
Simon Glass57454f42016-11-25 20:15:52 -0700644 self.assertEqual(U_BOOT_DATA, data)
645
Simon Glass075a45c2017-11-13 18:55:00 -0700646 def testSimpleDebug(self):
647 """Test a simple binman run with debugging enabled"""
Simon Glass52d06212019-07-08 14:25:53 -0600648 self._DoTestFile('005_simple.dts', debug=True)
Simon Glass075a45c2017-11-13 18:55:00 -0700649
Simon Glass57454f42016-11-25 20:15:52 -0700650 def testDual(self):
651 """Test that we can handle creating two images
652
653 This also tests image padding.
654 """
Simon Glass511f6582018-10-01 12:22:30 -0600655 retcode = self._DoTestFile('006_dual_image.dts')
Simon Glass57454f42016-11-25 20:15:52 -0700656 self.assertEqual(0, retcode)
657
658 image = control.images['image1']
Simon Glass39dd2152019-07-08 14:25:47 -0600659 self.assertEqual(len(U_BOOT_DATA), image.size)
Simon Glass57454f42016-11-25 20:15:52 -0700660 fname = tools.GetOutputFilename('image1.bin')
661 self.assertTrue(os.path.exists(fname))
Simon Glass33486662019-05-14 15:53:42 -0600662 with open(fname, 'rb') as fd:
Simon Glass57454f42016-11-25 20:15:52 -0700663 data = fd.read()
664 self.assertEqual(U_BOOT_DATA, data)
665
666 image = control.images['image2']
Simon Glass39dd2152019-07-08 14:25:47 -0600667 self.assertEqual(3 + len(U_BOOT_DATA) + 5, image.size)
Simon Glass57454f42016-11-25 20:15:52 -0700668 fname = tools.GetOutputFilename('image2.bin')
669 self.assertTrue(os.path.exists(fname))
Simon Glass33486662019-05-14 15:53:42 -0600670 with open(fname, 'rb') as fd:
Simon Glass57454f42016-11-25 20:15:52 -0700671 data = fd.read()
672 self.assertEqual(U_BOOT_DATA, data[3:7])
Simon Glassac0d4952019-05-14 15:53:47 -0600673 self.assertEqual(tools.GetBytes(0, 3), data[:3])
674 self.assertEqual(tools.GetBytes(0, 5), data[7:])
Simon Glass57454f42016-11-25 20:15:52 -0700675
676 def testBadAlign(self):
677 """Test that an invalid alignment value is detected"""
678 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -0600679 self._DoTestFile('007_bad_align.dts')
Simon Glass57454f42016-11-25 20:15:52 -0700680 self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
681 "of two", str(e.exception))
682
683 def testPackSimple(self):
684 """Test that packing works as expected"""
Simon Glass511f6582018-10-01 12:22:30 -0600685 retcode = self._DoTestFile('008_pack.dts')
Simon Glass57454f42016-11-25 20:15:52 -0700686 self.assertEqual(0, retcode)
687 self.assertIn('image', control.images)
688 image = control.images['image']
Simon Glasseca32212018-06-01 09:38:12 -0600689 entries = image.GetEntries()
Simon Glass57454f42016-11-25 20:15:52 -0700690 self.assertEqual(5, len(entries))
691
692 # First u-boot
693 self.assertIn('u-boot', entries)
694 entry = entries['u-boot']
Simon Glasse8561af2018-08-01 15:22:37 -0600695 self.assertEqual(0, entry.offset)
Simon Glass57454f42016-11-25 20:15:52 -0700696 self.assertEqual(len(U_BOOT_DATA), entry.size)
697
698 # Second u-boot, aligned to 16-byte boundary
699 self.assertIn('u-boot-align', entries)
700 entry = entries['u-boot-align']
Simon Glasse8561af2018-08-01 15:22:37 -0600701 self.assertEqual(16, entry.offset)
Simon Glass57454f42016-11-25 20:15:52 -0700702 self.assertEqual(len(U_BOOT_DATA), entry.size)
703
704 # Third u-boot, size 23 bytes
705 self.assertIn('u-boot-size', entries)
706 entry = entries['u-boot-size']
Simon Glasse8561af2018-08-01 15:22:37 -0600707 self.assertEqual(20, entry.offset)
Simon Glass57454f42016-11-25 20:15:52 -0700708 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
709 self.assertEqual(23, entry.size)
710
711 # Fourth u-boot, placed immediate after the above
712 self.assertIn('u-boot-next', entries)
713 entry = entries['u-boot-next']
Simon Glasse8561af2018-08-01 15:22:37 -0600714 self.assertEqual(43, entry.offset)
Simon Glass57454f42016-11-25 20:15:52 -0700715 self.assertEqual(len(U_BOOT_DATA), entry.size)
716
Simon Glasse8561af2018-08-01 15:22:37 -0600717 # Fifth u-boot, placed at a fixed offset
Simon Glass57454f42016-11-25 20:15:52 -0700718 self.assertIn('u-boot-fixed', entries)
719 entry = entries['u-boot-fixed']
Simon Glasse8561af2018-08-01 15:22:37 -0600720 self.assertEqual(61, entry.offset)
Simon Glass57454f42016-11-25 20:15:52 -0700721 self.assertEqual(len(U_BOOT_DATA), entry.size)
722
Simon Glass39dd2152019-07-08 14:25:47 -0600723 self.assertEqual(65, image.size)
Simon Glass57454f42016-11-25 20:15:52 -0700724
725 def testPackExtra(self):
726 """Test that extra packing feature works as expected"""
Simon Glass511f6582018-10-01 12:22:30 -0600727 retcode = self._DoTestFile('009_pack_extra.dts')
Simon Glass57454f42016-11-25 20:15:52 -0700728
729 self.assertEqual(0, retcode)
730 self.assertIn('image', control.images)
731 image = control.images['image']
Simon Glasseca32212018-06-01 09:38:12 -0600732 entries = image.GetEntries()
Simon Glass57454f42016-11-25 20:15:52 -0700733 self.assertEqual(5, len(entries))
734
735 # First u-boot with padding before and after
736 self.assertIn('u-boot', entries)
737 entry = entries['u-boot']
Simon Glasse8561af2018-08-01 15:22:37 -0600738 self.assertEqual(0, entry.offset)
Simon Glass57454f42016-11-25 20:15:52 -0700739 self.assertEqual(3, entry.pad_before)
740 self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
741
742 # Second u-boot has an aligned size, but it has no effect
743 self.assertIn('u-boot-align-size-nop', entries)
744 entry = entries['u-boot-align-size-nop']
Simon Glasse8561af2018-08-01 15:22:37 -0600745 self.assertEqual(12, entry.offset)
Simon Glass57454f42016-11-25 20:15:52 -0700746 self.assertEqual(4, entry.size)
747
748 # Third u-boot has an aligned size too
749 self.assertIn('u-boot-align-size', entries)
750 entry = entries['u-boot-align-size']
Simon Glasse8561af2018-08-01 15:22:37 -0600751 self.assertEqual(16, entry.offset)
Simon Glass57454f42016-11-25 20:15:52 -0700752 self.assertEqual(32, entry.size)
753
754 # Fourth u-boot has an aligned end
755 self.assertIn('u-boot-align-end', entries)
756 entry = entries['u-boot-align-end']
Simon Glasse8561af2018-08-01 15:22:37 -0600757 self.assertEqual(48, entry.offset)
Simon Glass57454f42016-11-25 20:15:52 -0700758 self.assertEqual(16, entry.size)
759
760 # Fifth u-boot immediately afterwards
761 self.assertIn('u-boot-align-both', entries)
762 entry = entries['u-boot-align-both']
Simon Glasse8561af2018-08-01 15:22:37 -0600763 self.assertEqual(64, entry.offset)
Simon Glass57454f42016-11-25 20:15:52 -0700764 self.assertEqual(64, entry.size)
765
766 self.CheckNoGaps(entries)
Simon Glass39dd2152019-07-08 14:25:47 -0600767 self.assertEqual(128, image.size)
Simon Glass57454f42016-11-25 20:15:52 -0700768
769 def testPackAlignPowerOf2(self):
770 """Test that invalid entry alignment is detected"""
771 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -0600772 self._DoTestFile('010_pack_align_power2.dts')
Simon Glass57454f42016-11-25 20:15:52 -0700773 self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
774 "of two", str(e.exception))
775
776 def testPackAlignSizePowerOf2(self):
777 """Test that invalid entry size alignment is detected"""
778 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -0600779 self._DoTestFile('011_pack_align_size_power2.dts')
Simon Glass57454f42016-11-25 20:15:52 -0700780 self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
781 "power of two", str(e.exception))
782
783 def testPackInvalidAlign(self):
Simon Glasse8561af2018-08-01 15:22:37 -0600784 """Test detection of an offset that does not match its alignment"""
Simon Glass57454f42016-11-25 20:15:52 -0700785 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -0600786 self._DoTestFile('012_pack_inv_align.dts')
Simon Glasse8561af2018-08-01 15:22:37 -0600787 self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
Simon Glass57454f42016-11-25 20:15:52 -0700788 "align 0x4 (4)", str(e.exception))
789
790 def testPackInvalidSizeAlign(self):
791 """Test that invalid entry size alignment is detected"""
792 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -0600793 self._DoTestFile('013_pack_inv_size_align.dts')
Simon Glass57454f42016-11-25 20:15:52 -0700794 self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
795 "align-size 0x4 (4)", str(e.exception))
796
797 def testPackOverlap(self):
798 """Test that overlapping regions are detected"""
799 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -0600800 self._DoTestFile('014_pack_overlap.dts')
Simon Glasse8561af2018-08-01 15:22:37 -0600801 self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
Simon Glass57454f42016-11-25 20:15:52 -0700802 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
803 str(e.exception))
804
805 def testPackEntryOverflow(self):
806 """Test that entries that overflow their size are detected"""
807 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -0600808 self._DoTestFile('015_pack_overflow.dts')
Simon Glass57454f42016-11-25 20:15:52 -0700809 self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
810 "but entry size is 0x3 (3)", str(e.exception))
811
812 def testPackImageOverflow(self):
813 """Test that entries which overflow the image size are detected"""
814 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -0600815 self._DoTestFile('016_pack_image_overflow.dts')
Simon Glasseca32212018-06-01 09:38:12 -0600816 self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section "
Simon Glass57454f42016-11-25 20:15:52 -0700817 "size 0x3 (3)", str(e.exception))
818
819 def testPackImageSize(self):
820 """Test that the image size can be set"""
Simon Glass511f6582018-10-01 12:22:30 -0600821 retcode = self._DoTestFile('017_pack_image_size.dts')
Simon Glass57454f42016-11-25 20:15:52 -0700822 self.assertEqual(0, retcode)
823 self.assertIn('image', control.images)
824 image = control.images['image']
Simon Glass39dd2152019-07-08 14:25:47 -0600825 self.assertEqual(7, image.size)
Simon Glass57454f42016-11-25 20:15:52 -0700826
827 def testPackImageSizeAlign(self):
828 """Test that image size alignemnt works as expected"""
Simon Glass511f6582018-10-01 12:22:30 -0600829 retcode = self._DoTestFile('018_pack_image_align.dts')
Simon Glass57454f42016-11-25 20:15:52 -0700830 self.assertEqual(0, retcode)
831 self.assertIn('image', control.images)
832 image = control.images['image']
Simon Glass39dd2152019-07-08 14:25:47 -0600833 self.assertEqual(16, image.size)
Simon Glass57454f42016-11-25 20:15:52 -0700834
835 def testPackInvalidImageAlign(self):
836 """Test that invalid image alignment is detected"""
837 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -0600838 self._DoTestFile('019_pack_inv_image_align.dts')
Simon Glasseca32212018-06-01 09:38:12 -0600839 self.assertIn("Section '/binman': Size 0x7 (7) does not match "
Simon Glass57454f42016-11-25 20:15:52 -0700840 "align-size 0x8 (8)", str(e.exception))
841
842 def testPackAlignPowerOf2(self):
843 """Test that invalid image alignment is detected"""
844 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -0600845 self._DoTestFile('020_pack_inv_image_align_power2.dts')
Simon Glass39dd2152019-07-08 14:25:47 -0600846 self.assertIn("Image '/binman': Alignment size 131 must be a power of "
Simon Glass57454f42016-11-25 20:15:52 -0700847 "two", str(e.exception))
848
849 def testImagePadByte(self):
850 """Test that the image pad byte can be specified"""
Simon Glass7057d022018-10-01 21:12:47 -0600851 self._SetupSplElf()
Simon Glass511f6582018-10-01 12:22:30 -0600852 data = self._DoReadFile('021_image_pad.dts')
Simon Glassac0d4952019-05-14 15:53:47 -0600853 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0xff, 1) +
854 U_BOOT_DATA, data)
Simon Glass57454f42016-11-25 20:15:52 -0700855
856 def testImageName(self):
857 """Test that image files can be named"""
Simon Glass511f6582018-10-01 12:22:30 -0600858 retcode = self._DoTestFile('022_image_name.dts')
Simon Glass57454f42016-11-25 20:15:52 -0700859 self.assertEqual(0, retcode)
860 image = control.images['image1']
861 fname = tools.GetOutputFilename('test-name')
862 self.assertTrue(os.path.exists(fname))
863
864 image = control.images['image2']
865 fname = tools.GetOutputFilename('test-name.xx')
866 self.assertTrue(os.path.exists(fname))
867
868 def testBlobFilename(self):
869 """Test that generic blobs can be provided by filename"""
Simon Glass511f6582018-10-01 12:22:30 -0600870 data = self._DoReadFile('023_blob.dts')
Simon Glass57454f42016-11-25 20:15:52 -0700871 self.assertEqual(BLOB_DATA, data)
872
873 def testPackSorted(self):
874 """Test that entries can be sorted"""
Simon Glass7057d022018-10-01 21:12:47 -0600875 self._SetupSplElf()
Simon Glass511f6582018-10-01 12:22:30 -0600876 data = self._DoReadFile('024_sorted.dts')
Simon Glassac0d4952019-05-14 15:53:47 -0600877 self.assertEqual(tools.GetBytes(0, 1) + U_BOOT_SPL_DATA +
878 tools.GetBytes(0, 2) + U_BOOT_DATA, data)
Simon Glass57454f42016-11-25 20:15:52 -0700879
Simon Glasse8561af2018-08-01 15:22:37 -0600880 def testPackZeroOffset(self):
881 """Test that an entry at offset 0 is not given a new offset"""
Simon Glass57454f42016-11-25 20:15:52 -0700882 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -0600883 self._DoTestFile('025_pack_zero_size.dts')
Simon Glasse8561af2018-08-01 15:22:37 -0600884 self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
Simon Glass57454f42016-11-25 20:15:52 -0700885 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
886 str(e.exception))
887
888 def testPackUbootDtb(self):
889 """Test that a device tree can be added to U-Boot"""
Simon Glass511f6582018-10-01 12:22:30 -0600890 data = self._DoReadFile('026_pack_u_boot_dtb.dts')
Simon Glass57454f42016-11-25 20:15:52 -0700891 self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
Simon Glass72232452016-11-25 20:15:53 -0700892
893 def testPackX86RomNoSize(self):
894 """Test that the end-at-4gb property requires a size property"""
895 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -0600896 self._DoTestFile('027_pack_4gb_no_size.dts')
Simon Glass39dd2152019-07-08 14:25:47 -0600897 self.assertIn("Image '/binman': Section size must be provided when "
Simon Glass72232452016-11-25 20:15:53 -0700898 "using end-at-4gb", str(e.exception))
899
Jagdish Gediya0fb978c2018-09-03 21:35:07 +0530900 def test4gbAndSkipAtStartTogether(self):
901 """Test that the end-at-4gb and skip-at-size property can't be used
902 together"""
903 with self.assertRaises(ValueError) as e:
904 self._DoTestFile('80_4gb_and_skip_at_start_together.dts')
Simon Glass39dd2152019-07-08 14:25:47 -0600905 self.assertIn("Image '/binman': Provide either 'end-at-4gb' or "
Jagdish Gediya0fb978c2018-09-03 21:35:07 +0530906 "'skip-at-start'", str(e.exception))
907
Simon Glass72232452016-11-25 20:15:53 -0700908 def testPackX86RomOutside(self):
Simon Glasse8561af2018-08-01 15:22:37 -0600909 """Test that the end-at-4gb property checks for offset boundaries"""
Simon Glass72232452016-11-25 20:15:53 -0700910 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -0600911 self._DoTestFile('028_pack_4gb_outside.dts')
Simon Glasse8561af2018-08-01 15:22:37 -0600912 self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) is outside "
Simon Glasseca32212018-06-01 09:38:12 -0600913 "the section starting at 0xffffffe0 (4294967264)",
Simon Glass72232452016-11-25 20:15:53 -0700914 str(e.exception))
915
916 def testPackX86Rom(self):
917 """Test that a basic x86 ROM can be created"""
Simon Glass7057d022018-10-01 21:12:47 -0600918 self._SetupSplElf()
Simon Glass511f6582018-10-01 12:22:30 -0600919 data = self._DoReadFile('029_x86-rom.dts')
Simon Glassac0d4952019-05-14 15:53:47 -0600920 self.assertEqual(U_BOOT_DATA + tools.GetBytes(0, 7) + U_BOOT_SPL_DATA +
921 tools.GetBytes(0, 2), data)
Simon Glass72232452016-11-25 20:15:53 -0700922
923 def testPackX86RomMeNoDesc(self):
924 """Test that an invalid Intel descriptor entry is detected"""
Simon Glass303f62f2019-05-17 22:00:46 -0600925 TestFunctional._MakeInputFile('descriptor.bin', b'')
Simon Glass72232452016-11-25 20:15:53 -0700926 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -0600927 self._DoTestFile('031_x86-rom-me.dts')
Simon Glassac4738b2019-07-08 13:18:32 -0600928 self.assertIn("Node '/binman/intel-descriptor': Cannot find Intel Flash Descriptor (FD) signature",
929 str(e.exception))
Simon Glass72232452016-11-25 20:15:53 -0700930
931 def testPackX86RomBadDesc(self):
932 """Test that the Intel requires a descriptor entry"""
933 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -0600934 self._DoTestFile('030_x86-rom-me-no-desc.dts')
Simon Glasse8561af2018-08-01 15:22:37 -0600935 self.assertIn("Node '/binman/intel-me': No offset set with "
936 "offset-unset: should another entry provide this correct "
937 "offset?", str(e.exception))
Simon Glass72232452016-11-25 20:15:53 -0700938
939 def testPackX86RomMe(self):
940 """Test that an x86 ROM with an ME region can be created"""
Simon Glass511f6582018-10-01 12:22:30 -0600941 data = self._DoReadFile('031_x86-rom-me.dts')
Simon Glass759af872019-07-08 13:18:54 -0600942 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
943 if data[:0x1000] != expected_desc:
944 self.fail('Expected descriptor binary at start of image')
Simon Glass72232452016-11-25 20:15:53 -0700945 self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
946
947 def testPackVga(self):
948 """Test that an image with a VGA binary can be created"""
Simon Glass511f6582018-10-01 12:22:30 -0600949 data = self._DoReadFile('032_intel-vga.dts')
Simon Glass72232452016-11-25 20:15:53 -0700950 self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
951
952 def testPackStart16(self):
953 """Test that an image with an x86 start16 region can be created"""
Simon Glass511f6582018-10-01 12:22:30 -0600954 data = self._DoReadFile('033_x86-start16.dts')
Simon Glass72232452016-11-25 20:15:53 -0700955 self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
956
Jagdish Gediya311d4842018-09-03 21:35:08 +0530957 def testPackPowerpcMpc85xxBootpgResetvec(self):
958 """Test that an image with powerpc-mpc85xx-bootpg-resetvec can be
959 created"""
960 data = self._DoReadFile('81_powerpc_mpc85xx_bootpg_resetvec.dts')
961 self.assertEqual(PPC_MPC85XX_BR_DATA, data[:len(PPC_MPC85XX_BR_DATA)])
962
Simon Glass6ba679c2018-07-06 10:27:17 -0600963 def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False):
Simon Glass820af1d2018-07-06 10:27:16 -0600964 """Handle running a test for insertion of microcode
965
966 Args:
967 dts_fname: Name of test .dts file
968 nodtb_data: Data that we expect in the first section
Simon Glass6ba679c2018-07-06 10:27:17 -0600969 ucode_second: True if the microsecond entry is second instead of
970 third
Simon Glass820af1d2018-07-06 10:27:16 -0600971
972 Returns:
973 Tuple:
974 Contents of first region (U-Boot or SPL)
Simon Glasse8561af2018-08-01 15:22:37 -0600975 Offset and size components of microcode pointer, as inserted
Simon Glass820af1d2018-07-06 10:27:16 -0600976 in the above (two 4-byte words)
977 """
Simon Glass3d274232017-11-12 21:52:27 -0700978 data = self._DoReadFile(dts_fname, True)
Simon Glass72232452016-11-25 20:15:53 -0700979
980 # Now check the device tree has no microcode
Simon Glass6ba679c2018-07-06 10:27:17 -0600981 if ucode_second:
982 ucode_content = data[len(nodtb_data):]
983 ucode_pos = len(nodtb_data)
984 dtb_with_ucode = ucode_content[16:]
985 fdt_len = self.GetFdtLen(dtb_with_ucode)
986 else:
987 dtb_with_ucode = data[len(nodtb_data):]
988 fdt_len = self.GetFdtLen(dtb_with_ucode)
989 ucode_content = dtb_with_ucode[fdt_len:]
990 ucode_pos = len(nodtb_data) + fdt_len
Simon Glass72232452016-11-25 20:15:53 -0700991 fname = tools.GetOutputFilename('test.dtb')
992 with open(fname, 'wb') as fd:
Simon Glass820af1d2018-07-06 10:27:16 -0600993 fd.write(dtb_with_ucode)
Simon Glass22c92ca2017-05-27 07:38:29 -0600994 dtb = fdt.FdtScan(fname)
995 ucode = dtb.GetNode('/microcode')
Simon Glass72232452016-11-25 20:15:53 -0700996 self.assertTrue(ucode)
997 for node in ucode.subnodes:
998 self.assertFalse(node.props.get('data'))
999
Simon Glass72232452016-11-25 20:15:53 -07001000 # Check that the microcode appears immediately after the Fdt
1001 # This matches the concatenation of the data properties in
Simon Glasse83679d2017-11-12 21:52:26 -07001002 # the /microcode/update@xxx nodes in 34_x86_ucode.dts.
Simon Glass72232452016-11-25 20:15:53 -07001003 ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
1004 0x78235609)
Simon Glass820af1d2018-07-06 10:27:16 -06001005 self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
Simon Glass72232452016-11-25 20:15:53 -07001006
1007 # Check that the microcode pointer was inserted. It should match the
Simon Glasse8561af2018-08-01 15:22:37 -06001008 # expected offset and size
Simon Glass72232452016-11-25 20:15:53 -07001009 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
1010 len(ucode_data))
Simon Glass6ba679c2018-07-06 10:27:17 -06001011 u_boot = data[:len(nodtb_data)]
1012 return u_boot, pos_and_size
Simon Glass3d274232017-11-12 21:52:27 -07001013
1014 def testPackUbootMicrocode(self):
1015 """Test that x86 microcode can be handled correctly
1016
1017 We expect to see the following in the image, in order:
1018 u-boot-nodtb.bin with a microcode pointer inserted at the correct
1019 place
1020 u-boot.dtb with the microcode removed
1021 the microcode
1022 """
Simon Glass511f6582018-10-01 12:22:30 -06001023 first, pos_and_size = self._RunMicrocodeTest('034_x86_ucode.dts',
Simon Glass3d274232017-11-12 21:52:27 -07001024 U_BOOT_NODTB_DATA)
Simon Glass303f62f2019-05-17 22:00:46 -06001025 self.assertEqual(b'nodtb with microcode' + pos_and_size +
1026 b' somewhere in here', first)
Simon Glass72232452016-11-25 20:15:53 -07001027
Simon Glassbac25c82017-05-27 07:38:26 -06001028 def _RunPackUbootSingleMicrocode(self):
Simon Glass72232452016-11-25 20:15:53 -07001029 """Test that x86 microcode can be handled correctly
1030
1031 We expect to see the following in the image, in order:
1032 u-boot-nodtb.bin with a microcode pointer inserted at the correct
1033 place
1034 u-boot.dtb with the microcode
1035 an empty microcode region
1036 """
1037 # We need the libfdt library to run this test since only that allows
1038 # finding the offset of a property. This is required by
1039 # Entry_u_boot_dtb_with_ucode.ObtainContents().
Simon Glass511f6582018-10-01 12:22:30 -06001040 data = self._DoReadFile('035_x86_single_ucode.dts', True)
Simon Glass72232452016-11-25 20:15:53 -07001041
1042 second = data[len(U_BOOT_NODTB_DATA):]
1043
1044 fdt_len = self.GetFdtLen(second)
1045 third = second[fdt_len:]
1046 second = second[:fdt_len]
1047
Simon Glassbac25c82017-05-27 07:38:26 -06001048 ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
1049 self.assertIn(ucode_data, second)
1050 ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
Simon Glass72232452016-11-25 20:15:53 -07001051
Simon Glassbac25c82017-05-27 07:38:26 -06001052 # Check that the microcode pointer was inserted. It should match the
Simon Glasse8561af2018-08-01 15:22:37 -06001053 # expected offset and size
Simon Glassbac25c82017-05-27 07:38:26 -06001054 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
1055 len(ucode_data))
1056 first = data[:len(U_BOOT_NODTB_DATA)]
Simon Glass303f62f2019-05-17 22:00:46 -06001057 self.assertEqual(b'nodtb with microcode' + pos_and_size +
1058 b' somewhere in here', first)
Simon Glass996021e2016-11-25 20:15:54 -07001059
Simon Glassd2dfb5f2016-11-25 20:15:55 -07001060 def testPackUbootSingleMicrocode(self):
1061 """Test that x86 microcode can be handled correctly with fdt_normal.
1062 """
Simon Glassbac25c82017-05-27 07:38:26 -06001063 self._RunPackUbootSingleMicrocode()
Simon Glassd2dfb5f2016-11-25 20:15:55 -07001064
Simon Glass996021e2016-11-25 20:15:54 -07001065 def testUBootImg(self):
1066 """Test that u-boot.img can be put in a file"""
Simon Glass511f6582018-10-01 12:22:30 -06001067 data = self._DoReadFile('036_u_boot_img.dts')
Simon Glass996021e2016-11-25 20:15:54 -07001068 self.assertEqual(U_BOOT_IMG_DATA, data)
Simon Glassd2dfb5f2016-11-25 20:15:55 -07001069
1070 def testNoMicrocode(self):
1071 """Test that a missing microcode region is detected"""
1072 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001073 self._DoReadFile('037_x86_no_ucode.dts', True)
Simon Glassd2dfb5f2016-11-25 20:15:55 -07001074 self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
1075 "node found in ", str(e.exception))
1076
1077 def testMicrocodeWithoutNode(self):
1078 """Test that a missing u-boot-dtb-with-ucode node is detected"""
1079 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001080 self._DoReadFile('038_x86_ucode_missing_node.dts', True)
Simon Glassd2dfb5f2016-11-25 20:15:55 -07001081 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1082 "microcode region u-boot-dtb-with-ucode", str(e.exception))
1083
1084 def testMicrocodeWithoutNode2(self):
1085 """Test that a missing u-boot-ucode node is detected"""
1086 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001087 self._DoReadFile('039_x86_ucode_missing_node2.dts', True)
Simon Glassd2dfb5f2016-11-25 20:15:55 -07001088 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1089 "microcode region u-boot-ucode", str(e.exception))
1090
1091 def testMicrocodeWithoutPtrInElf(self):
1092 """Test that a U-Boot binary without the microcode symbol is detected"""
1093 # ELF file without a '_dt_ucode_base_size' symbol
Simon Glassd2dfb5f2016-11-25 20:15:55 -07001094 try:
Simon Glassfaaaa162019-08-24 07:22:55 -06001095 TestFunctional._MakeInputFile('u-boot',
1096 tools.ReadFile(self.ElfTestFile('u_boot_no_ucode_ptr')))
Simon Glassd2dfb5f2016-11-25 20:15:55 -07001097
1098 with self.assertRaises(ValueError) as e:
Simon Glassbac25c82017-05-27 07:38:26 -06001099 self._RunPackUbootSingleMicrocode()
Simon Glassd2dfb5f2016-11-25 20:15:55 -07001100 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
1101 "_dt_ucode_base_size symbol in u-boot", str(e.exception))
1102
1103 finally:
1104 # Put the original file back
Simon Glass4affd4b2019-08-24 07:22:54 -06001105 TestFunctional._MakeInputFile('u-boot',
1106 tools.ReadFile(self.ElfTestFile('u_boot_ucode_ptr')))
Simon Glassd2dfb5f2016-11-25 20:15:55 -07001107
1108 def testMicrocodeNotInImage(self):
1109 """Test that microcode must be placed within the image"""
1110 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001111 self._DoReadFile('040_x86_ucode_not_in_image.dts', True)
Simon Glassd2dfb5f2016-11-25 20:15:55 -07001112 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
1113 "pointer _dt_ucode_base_size at fffffe14 is outside the "
Simon Glassad5a7712018-06-01 09:38:14 -06001114 "section ranging from 00000000 to 0000002e", str(e.exception))
Simon Glassd2dfb5f2016-11-25 20:15:55 -07001115
1116 def testWithoutMicrocode(self):
1117 """Test that we can cope with an image without microcode (e.g. qemu)"""
Simon Glassfaaaa162019-08-24 07:22:55 -06001118 TestFunctional._MakeInputFile('u-boot',
1119 tools.ReadFile(self.ElfTestFile('u_boot_no_ucode_ptr')))
Simon Glass511f6582018-10-01 12:22:30 -06001120 data, dtb, _, _ = self._DoReadFileDtb('044_x86_optional_ucode.dts', True)
Simon Glassd2dfb5f2016-11-25 20:15:55 -07001121
1122 # Now check the device tree has no microcode
1123 self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
1124 second = data[len(U_BOOT_NODTB_DATA):]
1125
1126 fdt_len = self.GetFdtLen(second)
1127 self.assertEqual(dtb, second[:fdt_len])
1128
1129 used_len = len(U_BOOT_NODTB_DATA) + fdt_len
1130 third = data[used_len:]
Simon Glassac0d4952019-05-14 15:53:47 -06001131 self.assertEqual(tools.GetBytes(0, 0x200 - used_len), third)
Simon Glassd2dfb5f2016-11-25 20:15:55 -07001132
1133 def testUnknownPosSize(self):
1134 """Test that microcode must be placed within the image"""
1135 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001136 self._DoReadFile('041_unknown_pos_size.dts', True)
Simon Glasse8561af2018-08-01 15:22:37 -06001137 self.assertIn("Section '/binman': Unable to set offset/size for unknown "
Simon Glassd2dfb5f2016-11-25 20:15:55 -07001138 "entry 'invalid-entry'", str(e.exception))
Simon Glassb4176d42016-11-25 20:15:56 -07001139
1140 def testPackFsp(self):
1141 """Test that an image with a FSP binary can be created"""
Simon Glass511f6582018-10-01 12:22:30 -06001142 data = self._DoReadFile('042_intel-fsp.dts')
Simon Glassb4176d42016-11-25 20:15:56 -07001143 self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
1144
1145 def testPackCmc(self):
Bin Mengd7bcdf52017-08-15 22:41:54 -07001146 """Test that an image with a CMC binary can be created"""
Simon Glass511f6582018-10-01 12:22:30 -06001147 data = self._DoReadFile('043_intel-cmc.dts')
Simon Glassb4176d42016-11-25 20:15:56 -07001148 self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
Bin Mengd7bcdf52017-08-15 22:41:54 -07001149
1150 def testPackVbt(self):
1151 """Test that an image with a VBT binary can be created"""
Simon Glass511f6582018-10-01 12:22:30 -06001152 data = self._DoReadFile('046_intel-vbt.dts')
Bin Mengd7bcdf52017-08-15 22:41:54 -07001153 self.assertEqual(VBT_DATA, data[:len(VBT_DATA)])
Simon Glassac599912017-11-12 21:52:22 -07001154
Simon Glass7f94e832017-11-12 21:52:25 -07001155 def testSplBssPad(self):
1156 """Test that we can pad SPL's BSS with zeros"""
Simon Glass3d274232017-11-12 21:52:27 -07001157 # ELF file with a '__bss_size' symbol
Simon Glass7057d022018-10-01 21:12:47 -06001158 self._SetupSplElf()
Simon Glass511f6582018-10-01 12:22:30 -06001159 data = self._DoReadFile('047_spl_bss_pad.dts')
Simon Glassac0d4952019-05-14 15:53:47 -06001160 self.assertEqual(U_BOOT_SPL_DATA + tools.GetBytes(0, 10) + U_BOOT_DATA,
1161 data)
Simon Glass7f94e832017-11-12 21:52:25 -07001162
Simon Glass04cda032018-10-01 21:12:42 -06001163 def testSplBssPadMissing(self):
1164 """Test that a missing symbol is detected"""
Simon Glass7057d022018-10-01 21:12:47 -06001165 self._SetupSplElf('u_boot_ucode_ptr')
Simon Glass24ad3652017-11-13 18:54:54 -07001166 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001167 self._DoReadFile('047_spl_bss_pad.dts')
Simon Glass24ad3652017-11-13 18:54:54 -07001168 self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
1169 str(e.exception))
1170
Simon Glasse83679d2017-11-12 21:52:26 -07001171 def testPackStart16Spl(self):
Simon Glassed40e962018-09-14 04:57:10 -06001172 """Test that an image with an x86 start16 SPL region can be created"""
Simon Glass511f6582018-10-01 12:22:30 -06001173 data = self._DoReadFile('048_x86-start16-spl.dts')
Simon Glasse83679d2017-11-12 21:52:26 -07001174 self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)])
1175
Simon Glass6ba679c2018-07-06 10:27:17 -06001176 def _PackUbootSplMicrocode(self, dts, ucode_second=False):
1177 """Helper function for microcode tests
Simon Glass3d274232017-11-12 21:52:27 -07001178
1179 We expect to see the following in the image, in order:
1180 u-boot-spl-nodtb.bin with a microcode pointer inserted at the
1181 correct place
1182 u-boot.dtb with the microcode removed
1183 the microcode
Simon Glass6ba679c2018-07-06 10:27:17 -06001184
1185 Args:
1186 dts: Device tree file to use for test
1187 ucode_second: True if the microsecond entry is second instead of
1188 third
Simon Glass3d274232017-11-12 21:52:27 -07001189 """
Simon Glass7057d022018-10-01 21:12:47 -06001190 self._SetupSplElf('u_boot_ucode_ptr')
Simon Glass6ba679c2018-07-06 10:27:17 -06001191 first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA,
1192 ucode_second=ucode_second)
Simon Glass303f62f2019-05-17 22:00:46 -06001193 self.assertEqual(b'splnodtb with microc' + pos_and_size +
1194 b'ter somewhere in here', first)
Simon Glass3d274232017-11-12 21:52:27 -07001195
Simon Glass6ba679c2018-07-06 10:27:17 -06001196 def testPackUbootSplMicrocode(self):
1197 """Test that x86 microcode can be handled correctly in SPL"""
Simon Glass511f6582018-10-01 12:22:30 -06001198 self._PackUbootSplMicrocode('049_x86_ucode_spl.dts')
Simon Glass6ba679c2018-07-06 10:27:17 -06001199
1200 def testPackUbootSplMicrocodeReorder(self):
1201 """Test that order doesn't matter for microcode entries
1202
1203 This is the same as testPackUbootSplMicrocode but when we process the
1204 u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode
1205 entry, so we reply on binman to try later.
1206 """
Simon Glass511f6582018-10-01 12:22:30 -06001207 self._PackUbootSplMicrocode('058_x86_ucode_spl_needs_retry.dts',
Simon Glass6ba679c2018-07-06 10:27:17 -06001208 ucode_second=True)
1209
Simon Glassa409c932017-11-12 21:52:28 -07001210 def testPackMrc(self):
1211 """Test that an image with an MRC binary can be created"""
Simon Glass511f6582018-10-01 12:22:30 -06001212 data = self._DoReadFile('050_intel_mrc.dts')
Simon Glassa409c932017-11-12 21:52:28 -07001213 self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
1214
Simon Glass9aa6a6f2017-11-13 18:54:55 -07001215 def testSplDtb(self):
1216 """Test that an image with spl/u-boot-spl.dtb can be created"""
Simon Glass511f6582018-10-01 12:22:30 -06001217 data = self._DoReadFile('051_u_boot_spl_dtb.dts')
Simon Glass9aa6a6f2017-11-13 18:54:55 -07001218 self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
1219
Simon Glass0a6da312017-11-13 18:54:56 -07001220 def testSplNoDtb(self):
1221 """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
Simon Glass511f6582018-10-01 12:22:30 -06001222 data = self._DoReadFile('052_u_boot_spl_nodtb.dts')
Simon Glass0a6da312017-11-13 18:54:56 -07001223 self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
1224
Simon Glass4ca8e042017-11-13 18:55:01 -07001225 def testSymbols(self):
1226 """Test binman can assign symbols embedded in U-Boot"""
Simon Glass5d0c0262019-08-24 07:22:56 -06001227 elf_fname = self.ElfTestFile('u_boot_binman_syms')
Simon Glass4ca8e042017-11-13 18:55:01 -07001228 syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
1229 addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
Simon Glasse8561af2018-08-01 15:22:37 -06001230 self.assertEqual(syms['_binman_u_boot_spl_prop_offset'].address, addr)
Simon Glass4ca8e042017-11-13 18:55:01 -07001231
Simon Glass7057d022018-10-01 21:12:47 -06001232 self._SetupSplElf('u_boot_binman_syms')
Simon Glass511f6582018-10-01 12:22:30 -06001233 data = self._DoReadFile('053_symbols.dts')
Simon Glass5d0c0262019-08-24 07:22:56 -06001234 sym_values = struct.pack('<LQL', 0, 24, 20)
Simon Glassac0d4952019-05-14 15:53:47 -06001235 expected = (sym_values + U_BOOT_SPL_DATA[16:] +
1236 tools.GetBytes(0xff, 1) + U_BOOT_DATA + sym_values +
1237 U_BOOT_SPL_DATA[16:])
Simon Glass4ca8e042017-11-13 18:55:01 -07001238 self.assertEqual(expected, data)
1239
Simon Glasse76a3e62018-06-01 09:38:11 -06001240 def testPackUnitAddress(self):
1241 """Test that we support multiple binaries with the same name"""
Simon Glass511f6582018-10-01 12:22:30 -06001242 data = self._DoReadFile('054_unit_address.dts')
Simon Glasse76a3e62018-06-01 09:38:11 -06001243 self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
1244
Simon Glassa91e1152018-06-01 09:38:16 -06001245 def testSections(self):
1246 """Basic test of sections"""
Simon Glass511f6582018-10-01 12:22:30 -06001247 data = self._DoReadFile('055_sections.dts')
Simon Glass303f62f2019-05-17 22:00:46 -06001248 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1249 U_BOOT_DATA + tools.GetBytes(ord('a'), 12) +
1250 U_BOOT_DATA + tools.GetBytes(ord('&'), 4))
Simon Glassa91e1152018-06-01 09:38:16 -06001251 self.assertEqual(expected, data)
Simon Glassac599912017-11-12 21:52:22 -07001252
Simon Glass30732662018-06-01 09:38:20 -06001253 def testMap(self):
1254 """Tests outputting a map of the images"""
Simon Glass511f6582018-10-01 12:22:30 -06001255 _, _, map_data, _ = self._DoReadFileDtb('055_sections.dts', map=True)
Simon Glass7eca7922018-07-17 13:25:49 -06001256 self.assertEqual('''ImagePos Offset Size Name
125700000000 00000000 00000028 main-section
125800000000 00000000 00000010 section@0
125900000000 00000000 00000004 u-boot
126000000010 00000010 00000010 section@1
126100000010 00000000 00000004 u-boot
126200000020 00000020 00000004 section@2
126300000020 00000000 00000004 u-boot
Simon Glass30732662018-06-01 09:38:20 -06001264''', map_data)
1265
Simon Glass3b78d532018-06-01 09:38:21 -06001266 def testNamePrefix(self):
1267 """Tests that name prefixes are used"""
Simon Glass511f6582018-10-01 12:22:30 -06001268 _, _, map_data, _ = self._DoReadFileDtb('056_name_prefix.dts', map=True)
Simon Glass7eca7922018-07-17 13:25:49 -06001269 self.assertEqual('''ImagePos Offset Size Name
127000000000 00000000 00000028 main-section
127100000000 00000000 00000010 section@0
127200000000 00000000 00000004 ro-u-boot
127300000010 00000010 00000010 section@1
127400000010 00000000 00000004 rw-u-boot
Simon Glass3b78d532018-06-01 09:38:21 -06001275''', map_data)
1276
Simon Glass6ba679c2018-07-06 10:27:17 -06001277 def testUnknownContents(self):
1278 """Test that obtaining the contents works as expected"""
1279 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001280 self._DoReadFile('057_unknown_contents.dts', True)
Simon Glass39dd2152019-07-08 14:25:47 -06001281 self.assertIn("Image '/binman': Internal error: Could not complete "
Simon Glass6ba679c2018-07-06 10:27:17 -06001282 "processing of contents: remaining [<_testing.Entry__testing ",
1283 str(e.exception))
1284
Simon Glass2e1169f2018-07-06 10:27:19 -06001285 def testBadChangeSize(self):
1286 """Test that trying to change the size of an entry fails"""
Simon Glasse61b6f62019-07-08 14:25:37 -06001287 try:
1288 state.SetAllowEntryExpansion(False)
1289 with self.assertRaises(ValueError) as e:
1290 self._DoReadFile('059_change_size.dts', True)
Simon Glass8c702fb2019-07-20 12:23:57 -06001291 self.assertIn("Node '/binman/_testing': Cannot update entry size from 2 to 3",
Simon Glasse61b6f62019-07-08 14:25:37 -06001292 str(e.exception))
1293 finally:
1294 state.SetAllowEntryExpansion(True)
Simon Glass2e1169f2018-07-06 10:27:19 -06001295
Simon Glassa87014e2018-07-06 10:27:42 -06001296 def testUpdateFdt(self):
Simon Glasse8561af2018-08-01 15:22:37 -06001297 """Test that we can update the device tree with offset/size info"""
Simon Glass511f6582018-10-01 12:22:30 -06001298 _, _, _, out_dtb_fname = self._DoReadFileDtb('060_fdt_update.dts',
Simon Glassa87014e2018-07-06 10:27:42 -06001299 update_dtb=True)
Simon Glass5463a6a2018-07-17 13:25:52 -06001300 dtb = fdt.Fdt(out_dtb_fname)
1301 dtb.Scan()
Simon Glassfb30e292019-07-20 12:23:51 -06001302 props = self._GetPropTree(dtb, BASE_DTB_PROPS + REPACK_DTB_PROPS)
Simon Glassa87014e2018-07-06 10:27:42 -06001303 self.assertEqual({
Simon Glass9dcc8612018-08-01 15:22:42 -06001304 'image-pos': 0,
Simon Glass3a9a2b82018-07-17 13:25:28 -06001305 'offset': 0,
Simon Glasse8561af2018-08-01 15:22:37 -06001306 '_testing:offset': 32,
Simon Glass8c702fb2019-07-20 12:23:57 -06001307 '_testing:size': 2,
Simon Glass9dcc8612018-08-01 15:22:42 -06001308 '_testing:image-pos': 32,
Simon Glasse8561af2018-08-01 15:22:37 -06001309 'section@0/u-boot:offset': 0,
Simon Glassa87014e2018-07-06 10:27:42 -06001310 'section@0/u-boot:size': len(U_BOOT_DATA),
Simon Glass9dcc8612018-08-01 15:22:42 -06001311 'section@0/u-boot:image-pos': 0,
Simon Glasse8561af2018-08-01 15:22:37 -06001312 'section@0:offset': 0,
Simon Glassa87014e2018-07-06 10:27:42 -06001313 'section@0:size': 16,
Simon Glass9dcc8612018-08-01 15:22:42 -06001314 'section@0:image-pos': 0,
Simon Glassa87014e2018-07-06 10:27:42 -06001315
Simon Glasse8561af2018-08-01 15:22:37 -06001316 'section@1/u-boot:offset': 0,
Simon Glassa87014e2018-07-06 10:27:42 -06001317 'section@1/u-boot:size': len(U_BOOT_DATA),
Simon Glass9dcc8612018-08-01 15:22:42 -06001318 'section@1/u-boot:image-pos': 16,
Simon Glasse8561af2018-08-01 15:22:37 -06001319 'section@1:offset': 16,
Simon Glassa87014e2018-07-06 10:27:42 -06001320 'section@1:size': 16,
Simon Glass9dcc8612018-08-01 15:22:42 -06001321 'section@1:image-pos': 16,
Simon Glassa87014e2018-07-06 10:27:42 -06001322 'size': 40
1323 }, props)
1324
1325 def testUpdateFdtBad(self):
1326 """Test that we detect when ProcessFdt never completes"""
1327 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001328 self._DoReadFileDtb('061_fdt_update_bad.dts', update_dtb=True)
Simon Glassa87014e2018-07-06 10:27:42 -06001329 self.assertIn('Could not complete processing of Fdt: remaining '
1330 '[<_testing.Entry__testing', str(e.exception))
Simon Glass2e1169f2018-07-06 10:27:19 -06001331
Simon Glass91710b32018-07-17 13:25:32 -06001332 def testEntryArgs(self):
1333 """Test passing arguments to entries from the command line"""
1334 entry_args = {
1335 'test-str-arg': 'test1',
1336 'test-int-arg': '456',
1337 }
Simon Glass511f6582018-10-01 12:22:30 -06001338 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
Simon Glass91710b32018-07-17 13:25:32 -06001339 self.assertIn('image', control.images)
1340 entry = control.images['image'].GetEntries()['_testing']
1341 self.assertEqual('test0', entry.test_str_fdt)
1342 self.assertEqual('test1', entry.test_str_arg)
1343 self.assertEqual(123, entry.test_int_fdt)
1344 self.assertEqual(456, entry.test_int_arg)
1345
1346 def testEntryArgsMissing(self):
1347 """Test missing arguments and properties"""
1348 entry_args = {
1349 'test-int-arg': '456',
1350 }
Simon Glass511f6582018-10-01 12:22:30 -06001351 self._DoReadFileDtb('063_entry_args_missing.dts', entry_args=entry_args)
Simon Glass91710b32018-07-17 13:25:32 -06001352 entry = control.images['image'].GetEntries()['_testing']
1353 self.assertEqual('test0', entry.test_str_fdt)
1354 self.assertEqual(None, entry.test_str_arg)
1355 self.assertEqual(None, entry.test_int_fdt)
1356 self.assertEqual(456, entry.test_int_arg)
1357
1358 def testEntryArgsRequired(self):
1359 """Test missing arguments and properties"""
1360 entry_args = {
1361 'test-int-arg': '456',
1362 }
1363 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001364 self._DoReadFileDtb('064_entry_args_required.dts')
Simon Glass91710b32018-07-17 13:25:32 -06001365 self.assertIn("Node '/binman/_testing': Missing required "
1366 'properties/entry args: test-str-arg, test-int-fdt, test-int-arg',
1367 str(e.exception))
1368
1369 def testEntryArgsInvalidFormat(self):
1370 """Test that an invalid entry-argument format is detected"""
Simon Glassf46732a2019-07-08 14:25:29 -06001371 args = ['build', '-d', self.TestFile('064_entry_args_required.dts'),
1372 '-ano-value']
Simon Glass91710b32018-07-17 13:25:32 -06001373 with self.assertRaises(ValueError) as e:
1374 self._DoBinman(*args)
1375 self.assertIn("Invalid entry arguemnt 'no-value'", str(e.exception))
1376
1377 def testEntryArgsInvalidInteger(self):
1378 """Test that an invalid entry-argument integer is detected"""
1379 entry_args = {
1380 'test-int-arg': 'abc',
1381 }
1382 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001383 self._DoReadFileDtb('062_entry_args.dts', entry_args=entry_args)
Simon Glass91710b32018-07-17 13:25:32 -06001384 self.assertIn("Node '/binman/_testing': Cannot convert entry arg "
1385 "'test-int-arg' (value 'abc') to integer",
1386 str(e.exception))
1387
1388 def testEntryArgsInvalidDatatype(self):
1389 """Test that an invalid entry-argument datatype is detected
1390
1391 This test could be written in entry_test.py except that it needs
1392 access to control.entry_args, which seems more than that module should
1393 be able to see.
1394 """
1395 entry_args = {
1396 'test-bad-datatype-arg': '12',
1397 }
1398 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001399 self._DoReadFileDtb('065_entry_args_unknown_datatype.dts',
Simon Glass91710b32018-07-17 13:25:32 -06001400 entry_args=entry_args)
1401 self.assertIn('GetArg() internal error: Unknown data type ',
1402 str(e.exception))
1403
Simon Glass2ca52032018-07-17 13:25:33 -06001404 def testText(self):
1405 """Test for a text entry type"""
1406 entry_args = {
1407 'test-id': TEXT_DATA,
1408 'test-id2': TEXT_DATA2,
1409 'test-id3': TEXT_DATA3,
1410 }
Simon Glass511f6582018-10-01 12:22:30 -06001411 data, _, _, _ = self._DoReadFileDtb('066_text.dts',
Simon Glass2ca52032018-07-17 13:25:33 -06001412 entry_args=entry_args)
Simon Glass303f62f2019-05-17 22:00:46 -06001413 expected = (tools.ToBytes(TEXT_DATA) +
1414 tools.GetBytes(0, 8 - len(TEXT_DATA)) +
1415 tools.ToBytes(TEXT_DATA2) + tools.ToBytes(TEXT_DATA3) +
Simon Glass47f6a622019-07-08 13:18:40 -06001416 b'some text' + b'more text')
Simon Glass2ca52032018-07-17 13:25:33 -06001417 self.assertEqual(expected, data)
1418
Simon Glass969616c2018-07-17 13:25:36 -06001419 def testEntryDocs(self):
1420 """Test for creation of entry documentation"""
1421 with test_util.capture_sys_output() as (stdout, stderr):
1422 control.WriteEntryDocs(binman.GetEntryModules())
1423 self.assertTrue(len(stdout.getvalue()) > 0)
1424
1425 def testEntryDocsMissing(self):
1426 """Test handling of missing entry documentation"""
1427 with self.assertRaises(ValueError) as e:
1428 with test_util.capture_sys_output() as (stdout, stderr):
1429 control.WriteEntryDocs(binman.GetEntryModules(), 'u_boot')
1430 self.assertIn('Documentation is missing for modules: u_boot',
1431 str(e.exception))
1432
Simon Glass704784b2018-07-17 13:25:38 -06001433 def testFmap(self):
1434 """Basic test of generation of a flashrom fmap"""
Simon Glass511f6582018-10-01 12:22:30 -06001435 data = self._DoReadFile('067_fmap.dts')
Simon Glass704784b2018-07-17 13:25:38 -06001436 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
Simon Glass303f62f2019-05-17 22:00:46 -06001437 expected = (U_BOOT_DATA + tools.GetBytes(ord('!'), 12) +
1438 U_BOOT_DATA + tools.GetBytes(ord('a'), 12))
Simon Glass704784b2018-07-17 13:25:38 -06001439 self.assertEqual(expected, data[:32])
Simon Glass303f62f2019-05-17 22:00:46 -06001440 self.assertEqual(b'__FMAP__', fhdr.signature)
Simon Glass704784b2018-07-17 13:25:38 -06001441 self.assertEqual(1, fhdr.ver_major)
1442 self.assertEqual(0, fhdr.ver_minor)
1443 self.assertEqual(0, fhdr.base)
1444 self.assertEqual(16 + 16 +
1445 fmap_util.FMAP_HEADER_LEN +
1446 fmap_util.FMAP_AREA_LEN * 3, fhdr.image_size)
Simon Glass303f62f2019-05-17 22:00:46 -06001447 self.assertEqual(b'FMAP', fhdr.name)
Simon Glass704784b2018-07-17 13:25:38 -06001448 self.assertEqual(3, fhdr.nareas)
1449 for fentry in fentries:
1450 self.assertEqual(0, fentry.flags)
1451
1452 self.assertEqual(0, fentries[0].offset)
1453 self.assertEqual(4, fentries[0].size)
Simon Glass303f62f2019-05-17 22:00:46 -06001454 self.assertEqual(b'RO_U_BOOT', fentries[0].name)
Simon Glass704784b2018-07-17 13:25:38 -06001455
1456 self.assertEqual(16, fentries[1].offset)
1457 self.assertEqual(4, fentries[1].size)
Simon Glass303f62f2019-05-17 22:00:46 -06001458 self.assertEqual(b'RW_U_BOOT', fentries[1].name)
Simon Glass704784b2018-07-17 13:25:38 -06001459
1460 self.assertEqual(32, fentries[2].offset)
1461 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1462 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
Simon Glass303f62f2019-05-17 22:00:46 -06001463 self.assertEqual(b'FMAP', fentries[2].name)
Simon Glass704784b2018-07-17 13:25:38 -06001464
Simon Glassdb168d42018-07-17 13:25:39 -06001465 def testBlobNamedByArg(self):
1466 """Test we can add a blob with the filename coming from an entry arg"""
1467 entry_args = {
1468 'cros-ec-rw-path': 'ecrw.bin',
1469 }
Simon Glass511f6582018-10-01 12:22:30 -06001470 data, _, _, _ = self._DoReadFileDtb('068_blob_named_by_arg.dts',
Simon Glassdb168d42018-07-17 13:25:39 -06001471 entry_args=entry_args)
1472
Simon Glass53f53992018-07-17 13:25:40 -06001473 def testFill(self):
1474 """Test for an fill entry type"""
Simon Glass511f6582018-10-01 12:22:30 -06001475 data = self._DoReadFile('069_fill.dts')
Simon Glassac0d4952019-05-14 15:53:47 -06001476 expected = tools.GetBytes(0xff, 8) + tools.GetBytes(0, 8)
Simon Glass53f53992018-07-17 13:25:40 -06001477 self.assertEqual(expected, data)
1478
1479 def testFillNoSize(self):
1480 """Test for an fill entry type with no size"""
1481 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001482 self._DoReadFile('070_fill_no_size.dts')
Simon Glass53f53992018-07-17 13:25:40 -06001483 self.assertIn("'fill' entry must have a size property",
1484 str(e.exception))
1485
Simon Glassc1ae83c2018-07-17 13:25:44 -06001486 def _HandleGbbCommand(self, pipe_list):
1487 """Fake calls to the futility utility"""
1488 if pipe_list[0][0] == 'futility':
1489 fname = pipe_list[0][-1]
1490 # Append our GBB data to the file, which will happen every time the
1491 # futility command is called.
Simon Glass33486662019-05-14 15:53:42 -06001492 with open(fname, 'ab') as fd:
Simon Glassc1ae83c2018-07-17 13:25:44 -06001493 fd.write(GBB_DATA)
1494 return command.CommandResult()
1495
1496 def testGbb(self):
1497 """Test for the Chromium OS Google Binary Block"""
1498 command.test_result = self._HandleGbbCommand
1499 entry_args = {
1500 'keydir': 'devkeys',
1501 'bmpblk': 'bmpblk.bin',
1502 }
Simon Glass511f6582018-10-01 12:22:30 -06001503 data, _, _, _ = self._DoReadFileDtb('071_gbb.dts', entry_args=entry_args)
Simon Glassc1ae83c2018-07-17 13:25:44 -06001504
1505 # Since futility
Simon Glassac0d4952019-05-14 15:53:47 -06001506 expected = (GBB_DATA + GBB_DATA + tools.GetBytes(0, 8) +
1507 tools.GetBytes(0, 0x2180 - 16))
Simon Glassc1ae83c2018-07-17 13:25:44 -06001508 self.assertEqual(expected, data)
1509
1510 def testGbbTooSmall(self):
1511 """Test for the Chromium OS Google Binary Block being large enough"""
1512 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001513 self._DoReadFileDtb('072_gbb_too_small.dts')
Simon Glassc1ae83c2018-07-17 13:25:44 -06001514 self.assertIn("Node '/binman/gbb': GBB is too small",
1515 str(e.exception))
1516
1517 def testGbbNoSize(self):
1518 """Test for the Chromium OS Google Binary Block having a size"""
1519 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001520 self._DoReadFileDtb('073_gbb_no_size.dts')
Simon Glassc1ae83c2018-07-17 13:25:44 -06001521 self.assertIn("Node '/binman/gbb': GBB must have a fixed size",
1522 str(e.exception))
1523
Simon Glass5c350162018-07-17 13:25:47 -06001524 def _HandleVblockCommand(self, pipe_list):
1525 """Fake calls to the futility utility"""
1526 if pipe_list[0][0] == 'futility':
1527 fname = pipe_list[0][3]
Simon Glass639505b2018-09-14 04:57:11 -06001528 with open(fname, 'wb') as fd:
Simon Glass5c350162018-07-17 13:25:47 -06001529 fd.write(VBLOCK_DATA)
1530 return command.CommandResult()
1531
1532 def testVblock(self):
1533 """Test for the Chromium OS Verified Boot Block"""
1534 command.test_result = self._HandleVblockCommand
1535 entry_args = {
1536 'keydir': 'devkeys',
1537 }
Simon Glass511f6582018-10-01 12:22:30 -06001538 data, _, _, _ = self._DoReadFileDtb('074_vblock.dts',
Simon Glass5c350162018-07-17 13:25:47 -06001539 entry_args=entry_args)
1540 expected = U_BOOT_DATA + VBLOCK_DATA + U_BOOT_DTB_DATA
1541 self.assertEqual(expected, data)
1542
1543 def testVblockNoContent(self):
1544 """Test we detect a vblock which has no content to sign"""
1545 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001546 self._DoReadFile('075_vblock_no_content.dts')
Simon Glass5c350162018-07-17 13:25:47 -06001547 self.assertIn("Node '/binman/vblock': Vblock must have a 'content' "
1548 'property', str(e.exception))
1549
1550 def testVblockBadPhandle(self):
1551 """Test that we detect a vblock with an invalid phandle in contents"""
1552 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001553 self._DoReadFile('076_vblock_bad_phandle.dts')
Simon Glass5c350162018-07-17 13:25:47 -06001554 self.assertIn("Node '/binman/vblock': Cannot find node for phandle "
1555 '1000', str(e.exception))
1556
1557 def testVblockBadEntry(self):
1558 """Test that we detect an entry that points to a non-entry"""
1559 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001560 self._DoReadFile('077_vblock_bad_entry.dts')
Simon Glass5c350162018-07-17 13:25:47 -06001561 self.assertIn("Node '/binman/vblock': Cannot find entry for node "
1562 "'other'", str(e.exception))
1563
Simon Glass8425a1f2018-07-17 13:25:48 -06001564 def testTpl(self):
1565 """Test that an image with TPL and ots device tree can be created"""
1566 # ELF file with a '__bss_size' symbol
Simon Glassf6290892019-08-24 07:22:53 -06001567 with open(self.ElfTestFile('bss_data'), 'rb') as fd:
Simon Glass8425a1f2018-07-17 13:25:48 -06001568 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
Simon Glass511f6582018-10-01 12:22:30 -06001569 data = self._DoReadFile('078_u_boot_tpl.dts')
Simon Glass8425a1f2018-07-17 13:25:48 -06001570 self.assertEqual(U_BOOT_TPL_DATA + U_BOOT_TPL_DTB_DATA, data)
1571
Simon Glass24b97442018-07-17 13:25:51 -06001572 def testUsesPos(self):
1573 """Test that the 'pos' property cannot be used anymore"""
1574 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001575 data = self._DoReadFile('079_uses_pos.dts')
Simon Glass24b97442018-07-17 13:25:51 -06001576 self.assertIn("Node '/binman/u-boot': Please use 'offset' instead of "
1577 "'pos'", str(e.exception))
1578
Simon Glass274bf092018-09-14 04:57:08 -06001579 def testFillZero(self):
1580 """Test for an fill entry type with a size of 0"""
Simon Glass511f6582018-10-01 12:22:30 -06001581 data = self._DoReadFile('080_fill_empty.dts')
Simon Glassac0d4952019-05-14 15:53:47 -06001582 self.assertEqual(tools.GetBytes(0, 16), data)
Simon Glass274bf092018-09-14 04:57:08 -06001583
Simon Glass267de432018-09-14 04:57:09 -06001584 def testTextMissing(self):
1585 """Test for a text entry type where there is no text"""
1586 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001587 self._DoReadFileDtb('066_text.dts',)
Simon Glass267de432018-09-14 04:57:09 -06001588 self.assertIn("Node '/binman/text': No value provided for text label "
1589 "'test-id'", str(e.exception))
1590
Simon Glassed40e962018-09-14 04:57:10 -06001591 def testPackStart16Tpl(self):
1592 """Test that an image with an x86 start16 TPL region can be created"""
Simon Glass511f6582018-10-01 12:22:30 -06001593 data = self._DoReadFile('081_x86-start16-tpl.dts')
Simon Glassed40e962018-09-14 04:57:10 -06001594 self.assertEqual(X86_START16_TPL_DATA, data[:len(X86_START16_TPL_DATA)])
1595
Simon Glass3b376c32018-09-14 04:57:12 -06001596 def testSelectImage(self):
1597 """Test that we can select which images to build"""
Simon Glassb4595d82019-04-25 21:58:34 -06001598 expected = 'Skipping images: image1'
1599
1600 # We should only get the expected message in verbose mode
Simon Glass8a50b4a2019-07-08 13:18:48 -06001601 for verbosity in (0, 2):
Simon Glassb4595d82019-04-25 21:58:34 -06001602 with test_util.capture_sys_output() as (stdout, stderr):
1603 retcode = self._DoTestFile('006_dual_image.dts',
1604 verbosity=verbosity,
1605 images=['image2'])
1606 self.assertEqual(0, retcode)
1607 if verbosity:
1608 self.assertIn(expected, stdout.getvalue())
1609 else:
1610 self.assertNotIn(expected, stdout.getvalue())
Simon Glass3b376c32018-09-14 04:57:12 -06001611
Simon Glassb4595d82019-04-25 21:58:34 -06001612 self.assertFalse(os.path.exists(tools.GetOutputFilename('image1.bin')))
1613 self.assertTrue(os.path.exists(tools.GetOutputFilename('image2.bin')))
Simon Glassb3d6fc72019-07-20 12:24:10 -06001614 self._CleanupOutputDir()
Simon Glass3b376c32018-09-14 04:57:12 -06001615
Simon Glasse219aa42018-09-14 04:57:24 -06001616 def testUpdateFdtAll(self):
1617 """Test that all device trees are updated with offset/size info"""
Simon Glass5b4bce32019-07-08 14:25:26 -06001618 data = self._DoReadFileRealDtb('082_fdt_update_all.dts')
Simon Glasse219aa42018-09-14 04:57:24 -06001619
1620 base_expected = {
1621 'section:image-pos': 0,
1622 'u-boot-tpl-dtb:size': 513,
1623 'u-boot-spl-dtb:size': 513,
1624 'u-boot-spl-dtb:offset': 493,
1625 'image-pos': 0,
1626 'section/u-boot-dtb:image-pos': 0,
1627 'u-boot-spl-dtb:image-pos': 493,
1628 'section/u-boot-dtb:size': 493,
1629 'u-boot-tpl-dtb:image-pos': 1006,
1630 'section/u-boot-dtb:offset': 0,
1631 'section:size': 493,
1632 'offset': 0,
1633 'section:offset': 0,
1634 'u-boot-tpl-dtb:offset': 1006,
1635 'size': 1519
1636 }
1637
1638 # We expect three device-tree files in the output, one after the other.
1639 # Read them in sequence. We look for an 'spl' property in the SPL tree,
1640 # and 'tpl' in the TPL tree, to make sure they are distinct from the
1641 # main U-Boot tree. All three should have the same postions and offset.
1642 start = 0
1643 for item in ['', 'spl', 'tpl']:
1644 dtb = fdt.Fdt.FromData(data[start:])
1645 dtb.Scan()
Simon Glassfb30e292019-07-20 12:23:51 -06001646 props = self._GetPropTree(dtb, BASE_DTB_PROPS + REPACK_DTB_PROPS +
1647 ['spl', 'tpl'])
Simon Glasse219aa42018-09-14 04:57:24 -06001648 expected = dict(base_expected)
1649 if item:
1650 expected[item] = 0
1651 self.assertEqual(expected, props)
1652 start += dtb._fdt_obj.totalsize()
1653
1654 def testUpdateFdtOutput(self):
1655 """Test that output DTB files are updated"""
1656 try:
Simon Glass511f6582018-10-01 12:22:30 -06001657 data, dtb_data, _, _ = self._DoReadFileDtb('082_fdt_update_all.dts',
Simon Glasse219aa42018-09-14 04:57:24 -06001658 use_real_dtb=True, update_dtb=True, reset_dtbs=False)
1659
1660 # Unfortunately, compiling a source file always results in a file
1661 # called source.dtb (see fdt_util.EnsureCompiled()). The test
Simon Glass511f6582018-10-01 12:22:30 -06001662 # source file (e.g. test/075_fdt_update_all.dts) thus does not enter
Simon Glasse219aa42018-09-14 04:57:24 -06001663 # binman as a file called u-boot.dtb. To fix this, copy the file
1664 # over to the expected place.
1665 #tools.WriteFile(os.path.join(self._indir, 'u-boot.dtb'),
1666 #tools.ReadFile(tools.GetOutputFilename('source.dtb')))
1667 start = 0
1668 for fname in ['u-boot.dtb.out', 'spl/u-boot-spl.dtb.out',
1669 'tpl/u-boot-tpl.dtb.out']:
1670 dtb = fdt.Fdt.FromData(data[start:])
1671 size = dtb._fdt_obj.totalsize()
1672 pathname = tools.GetOutputFilename(os.path.split(fname)[1])
1673 outdata = tools.ReadFile(pathname)
1674 name = os.path.split(fname)[0]
1675
1676 if name:
1677 orig_indata = self._GetDtbContentsForSplTpl(dtb_data, name)
1678 else:
1679 orig_indata = dtb_data
1680 self.assertNotEqual(outdata, orig_indata,
1681 "Expected output file '%s' be updated" % pathname)
1682 self.assertEqual(outdata, data[start:start + size],
1683 "Expected output file '%s' to match output image" %
1684 pathname)
1685 start += size
1686 finally:
1687 self._ResetDtbs()
1688
Simon Glass7ba33592018-09-14 04:57:26 -06001689 def _decompress(self, data):
Simon Glassccec0262019-07-08 13:18:42 -06001690 return tools.Decompress(data, 'lz4')
Simon Glass7ba33592018-09-14 04:57:26 -06001691
1692 def testCompress(self):
1693 """Test compression of blobs"""
Simon Glass1de34482019-07-08 13:18:53 -06001694 self._CheckLz4()
Simon Glass511f6582018-10-01 12:22:30 -06001695 data, _, _, out_dtb_fname = self._DoReadFileDtb('083_compress.dts',
Simon Glass7ba33592018-09-14 04:57:26 -06001696 use_real_dtb=True, update_dtb=True)
1697 dtb = fdt.Fdt(out_dtb_fname)
1698 dtb.Scan()
1699 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
1700 orig = self._decompress(data)
1701 self.assertEquals(COMPRESS_DATA, orig)
1702 expected = {
1703 'blob:uncomp-size': len(COMPRESS_DATA),
1704 'blob:size': len(data),
1705 'size': len(data),
1706 }
1707 self.assertEqual(expected, props)
1708
Simon Glassac6328c2018-09-14 04:57:28 -06001709 def testFiles(self):
1710 """Test bringing in multiple files"""
Simon Glass511f6582018-10-01 12:22:30 -06001711 data = self._DoReadFile('084_files.dts')
Simon Glassac6328c2018-09-14 04:57:28 -06001712 self.assertEqual(FILES_DATA, data)
1713
1714 def testFilesCompress(self):
1715 """Test bringing in multiple files and compressing them"""
Simon Glass1de34482019-07-08 13:18:53 -06001716 self._CheckLz4()
Simon Glass511f6582018-10-01 12:22:30 -06001717 data = self._DoReadFile('085_files_compress.dts')
Simon Glassac6328c2018-09-14 04:57:28 -06001718
1719 image = control.images['image']
1720 entries = image.GetEntries()
1721 files = entries['files']
Simon Glass39dd2152019-07-08 14:25:47 -06001722 entries = files._entries
Simon Glassac6328c2018-09-14 04:57:28 -06001723
Simon Glass303f62f2019-05-17 22:00:46 -06001724 orig = b''
Simon Glassac6328c2018-09-14 04:57:28 -06001725 for i in range(1, 3):
1726 key = '%d.dat' % i
1727 start = entries[key].image_pos
1728 len = entries[key].size
1729 chunk = data[start:start + len]
1730 orig += self._decompress(chunk)
1731
1732 self.assertEqual(FILES_DATA, orig)
1733
1734 def testFilesMissing(self):
1735 """Test missing files"""
1736 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001737 data = self._DoReadFile('086_files_none.dts')
Simon Glassac6328c2018-09-14 04:57:28 -06001738 self.assertIn("Node '/binman/files': Pattern \'files/*.none\' matched "
1739 'no files', str(e.exception))
1740
1741 def testFilesNoPattern(self):
1742 """Test missing files"""
1743 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001744 data = self._DoReadFile('087_files_no_pattern.dts')
Simon Glassac6328c2018-09-14 04:57:28 -06001745 self.assertIn("Node '/binman/files': Missing 'pattern' property",
1746 str(e.exception))
1747
Simon Glassfa79a812018-09-14 04:57:29 -06001748 def testExpandSize(self):
1749 """Test an expanding entry"""
Simon Glass511f6582018-10-01 12:22:30 -06001750 data, _, map_data, _ = self._DoReadFileDtb('088_expand_size.dts',
Simon Glassfa79a812018-09-14 04:57:29 -06001751 map=True)
Simon Glass303f62f2019-05-17 22:00:46 -06001752 expect = (tools.GetBytes(ord('a'), 8) + U_BOOT_DATA +
1753 MRC_DATA + tools.GetBytes(ord('b'), 1) + U_BOOT_DATA +
1754 tools.GetBytes(ord('c'), 8) + U_BOOT_DATA +
1755 tools.GetBytes(ord('d'), 8))
Simon Glassfa79a812018-09-14 04:57:29 -06001756 self.assertEqual(expect, data)
1757 self.assertEqual('''ImagePos Offset Size Name
175800000000 00000000 00000028 main-section
175900000000 00000000 00000008 fill
176000000008 00000008 00000004 u-boot
17610000000c 0000000c 00000004 section
17620000000c 00000000 00000003 intel-mrc
176300000010 00000010 00000004 u-boot2
176400000014 00000014 0000000c section2
176500000014 00000000 00000008 fill
17660000001c 00000008 00000004 u-boot
176700000020 00000020 00000008 fill2
1768''', map_data)
1769
1770 def testExpandSizeBad(self):
1771 """Test an expanding entry which fails to provide contents"""
Simon Glasscd817d52018-09-14 04:57:36 -06001772 with test_util.capture_sys_output() as (stdout, stderr):
1773 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001774 self._DoReadFileDtb('089_expand_size_bad.dts', map=True)
Simon Glassfa79a812018-09-14 04:57:29 -06001775 self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
1776 'expanding entry', str(e.exception))
1777
Simon Glassae7cf032018-09-14 04:57:31 -06001778 def testHash(self):
1779 """Test hashing of the contents of an entry"""
Simon Glass511f6582018-10-01 12:22:30 -06001780 _, _, _, out_dtb_fname = self._DoReadFileDtb('090_hash.dts',
Simon Glassae7cf032018-09-14 04:57:31 -06001781 use_real_dtb=True, update_dtb=True)
1782 dtb = fdt.Fdt(out_dtb_fname)
1783 dtb.Scan()
1784 hash_node = dtb.GetNode('/binman/u-boot/hash').props['value']
1785 m = hashlib.sha256()
1786 m.update(U_BOOT_DATA)
Simon Glass303f62f2019-05-17 22:00:46 -06001787 self.assertEqual(m.digest(), b''.join(hash_node.value))
Simon Glassae7cf032018-09-14 04:57:31 -06001788
1789 def testHashNoAlgo(self):
1790 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001791 self._DoReadFileDtb('091_hash_no_algo.dts', update_dtb=True)
Simon Glassae7cf032018-09-14 04:57:31 -06001792 self.assertIn("Node \'/binman/u-boot\': Missing \'algo\' property for "
1793 'hash node', str(e.exception))
1794
1795 def testHashBadAlgo(self):
1796 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001797 self._DoReadFileDtb('092_hash_bad_algo.dts', update_dtb=True)
Simon Glassae7cf032018-09-14 04:57:31 -06001798 self.assertIn("Node '/binman/u-boot': Unknown hash algorithm",
1799 str(e.exception))
1800
1801 def testHashSection(self):
1802 """Test hashing of the contents of an entry"""
Simon Glass511f6582018-10-01 12:22:30 -06001803 _, _, _, out_dtb_fname = self._DoReadFileDtb('099_hash_section.dts',
Simon Glassae7cf032018-09-14 04:57:31 -06001804 use_real_dtb=True, update_dtb=True)
1805 dtb = fdt.Fdt(out_dtb_fname)
1806 dtb.Scan()
1807 hash_node = dtb.GetNode('/binman/section/hash').props['value']
1808 m = hashlib.sha256()
1809 m.update(U_BOOT_DATA)
Simon Glass303f62f2019-05-17 22:00:46 -06001810 m.update(tools.GetBytes(ord('a'), 16))
1811 self.assertEqual(m.digest(), b''.join(hash_node.value))
Simon Glassae7cf032018-09-14 04:57:31 -06001812
Simon Glass3fb4f422018-09-14 04:57:32 -06001813 def testPackUBootTplMicrocode(self):
1814 """Test that x86 microcode can be handled correctly in TPL
1815
1816 We expect to see the following in the image, in order:
1817 u-boot-tpl-nodtb.bin with a microcode pointer inserted at the correct
1818 place
1819 u-boot-tpl.dtb with the microcode removed
1820 the microcode
1821 """
Simon Glass4affd4b2019-08-24 07:22:54 -06001822 TestFunctional._MakeInputFile('tpl/u-boot-tpl',
1823 tools.ReadFile(self.ElfTestFile('u_boot_ucode_ptr')))
Simon Glass511f6582018-10-01 12:22:30 -06001824 first, pos_and_size = self._RunMicrocodeTest('093_x86_tpl_ucode.dts',
Simon Glass3fb4f422018-09-14 04:57:32 -06001825 U_BOOT_TPL_NODTB_DATA)
Simon Glass303f62f2019-05-17 22:00:46 -06001826 self.assertEqual(b'tplnodtb with microc' + pos_and_size +
1827 b'ter somewhere in here', first)
Simon Glass3fb4f422018-09-14 04:57:32 -06001828
Simon Glassc64aea52018-09-14 04:57:34 -06001829 def testFmapX86(self):
1830 """Basic test of generation of a flashrom fmap"""
Simon Glass511f6582018-10-01 12:22:30 -06001831 data = self._DoReadFile('094_fmap_x86.dts')
Simon Glassc64aea52018-09-14 04:57:34 -06001832 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
Simon Glass303f62f2019-05-17 22:00:46 -06001833 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('a'), 32 - 7)
Simon Glassc64aea52018-09-14 04:57:34 -06001834 self.assertEqual(expected, data[:32])
1835 fhdr, fentries = fmap_util.DecodeFmap(data[32:])
1836
1837 self.assertEqual(0x100, fhdr.image_size)
1838
1839 self.assertEqual(0, fentries[0].offset)
1840 self.assertEqual(4, fentries[0].size)
Simon Glass303f62f2019-05-17 22:00:46 -06001841 self.assertEqual(b'U_BOOT', fentries[0].name)
Simon Glassc64aea52018-09-14 04:57:34 -06001842
1843 self.assertEqual(4, fentries[1].offset)
1844 self.assertEqual(3, fentries[1].size)
Simon Glass303f62f2019-05-17 22:00:46 -06001845 self.assertEqual(b'INTEL_MRC', fentries[1].name)
Simon Glassc64aea52018-09-14 04:57:34 -06001846
1847 self.assertEqual(32, fentries[2].offset)
1848 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1849 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
Simon Glass303f62f2019-05-17 22:00:46 -06001850 self.assertEqual(b'FMAP', fentries[2].name)
Simon Glassc64aea52018-09-14 04:57:34 -06001851
1852 def testFmapX86Section(self):
1853 """Basic test of generation of a flashrom fmap"""
Simon Glass511f6582018-10-01 12:22:30 -06001854 data = self._DoReadFile('095_fmap_x86_section.dts')
Simon Glass303f62f2019-05-17 22:00:46 -06001855 expected = U_BOOT_DATA + MRC_DATA + tools.GetBytes(ord('b'), 32 - 7)
Simon Glassc64aea52018-09-14 04:57:34 -06001856 self.assertEqual(expected, data[:32])
1857 fhdr, fentries = fmap_util.DecodeFmap(data[36:])
1858
1859 self.assertEqual(0x100, fhdr.image_size)
1860
1861 self.assertEqual(0, fentries[0].offset)
1862 self.assertEqual(4, fentries[0].size)
Simon Glass303f62f2019-05-17 22:00:46 -06001863 self.assertEqual(b'U_BOOT', fentries[0].name)
Simon Glassc64aea52018-09-14 04:57:34 -06001864
1865 self.assertEqual(4, fentries[1].offset)
1866 self.assertEqual(3, fentries[1].size)
Simon Glass303f62f2019-05-17 22:00:46 -06001867 self.assertEqual(b'INTEL_MRC', fentries[1].name)
Simon Glassc64aea52018-09-14 04:57:34 -06001868
1869 self.assertEqual(36, fentries[2].offset)
1870 self.assertEqual(fmap_util.FMAP_HEADER_LEN +
1871 fmap_util.FMAP_AREA_LEN * 3, fentries[2].size)
Simon Glass303f62f2019-05-17 22:00:46 -06001872 self.assertEqual(b'FMAP', fentries[2].name)
Simon Glassc64aea52018-09-14 04:57:34 -06001873
Simon Glassb1714232018-09-14 04:57:35 -06001874 def testElf(self):
1875 """Basic test of ELF entries"""
Simon Glass7057d022018-10-01 21:12:47 -06001876 self._SetupSplElf()
Simon Glassf6290892019-08-24 07:22:53 -06001877 with open(self.ElfTestFile('bss_data'), 'rb') as fd:
Simon Glassa899f712019-07-08 13:18:46 -06001878 TestFunctional._MakeInputFile('tpl/u-boot-tpl', fd.read())
Simon Glassf6290892019-08-24 07:22:53 -06001879 with open(self.ElfTestFile('bss_data'), 'rb') as fd:
Simon Glassb1714232018-09-14 04:57:35 -06001880 TestFunctional._MakeInputFile('-boot', fd.read())
Simon Glass511f6582018-10-01 12:22:30 -06001881 data = self._DoReadFile('096_elf.dts')
Simon Glassb1714232018-09-14 04:57:35 -06001882
Simon Glass0d673792019-07-08 13:18:25 -06001883 def testElfStrip(self):
Simon Glassb1714232018-09-14 04:57:35 -06001884 """Basic test of ELF entries"""
Simon Glass7057d022018-10-01 21:12:47 -06001885 self._SetupSplElf()
Simon Glassf6290892019-08-24 07:22:53 -06001886 with open(self.ElfTestFile('bss_data'), 'rb') as fd:
Simon Glassb1714232018-09-14 04:57:35 -06001887 TestFunctional._MakeInputFile('-boot', fd.read())
Simon Glass511f6582018-10-01 12:22:30 -06001888 data = self._DoReadFile('097_elf_strip.dts')
Simon Glassb1714232018-09-14 04:57:35 -06001889
Simon Glasscd817d52018-09-14 04:57:36 -06001890 def testPackOverlapMap(self):
1891 """Test that overlapping regions are detected"""
1892 with test_util.capture_sys_output() as (stdout, stderr):
1893 with self.assertRaises(ValueError) as e:
Simon Glass511f6582018-10-01 12:22:30 -06001894 self._DoTestFile('014_pack_overlap.dts', map=True)
Simon Glasscd817d52018-09-14 04:57:36 -06001895 map_fname = tools.GetOutputFilename('image.map')
1896 self.assertEqual("Wrote map file '%s' to show errors\n" % map_fname,
1897 stdout.getvalue())
1898
1899 # We should not get an inmage, but there should be a map file
1900 self.assertFalse(os.path.exists(tools.GetOutputFilename('image.bin')))
1901 self.assertTrue(os.path.exists(map_fname))
Simon Glassb3774752019-05-17 22:00:51 -06001902 map_data = tools.ReadFile(map_fname, binary=False)
Simon Glasscd817d52018-09-14 04:57:36 -06001903 self.assertEqual('''ImagePos Offset Size Name
1904<none> 00000000 00000007 main-section
1905<none> 00000000 00000004 u-boot
1906<none> 00000003 00000004 u-boot-align
1907''', map_data)
1908
Simon Glass0d673792019-07-08 13:18:25 -06001909 def testPackRefCode(self):
Simon Glass41902e42018-10-01 12:22:31 -06001910 """Test that an image with an Intel Reference code binary works"""
1911 data = self._DoReadFile('100_intel_refcode.dts')
1912 self.assertEqual(REFCODE_DATA, data[:len(REFCODE_DATA)])
1913
Simon Glasseb023b32019-04-25 21:58:39 -06001914 def testSectionOffset(self):
1915 """Tests use of a section with an offset"""
1916 data, _, map_data, _ = self._DoReadFileDtb('101_sections_offset.dts',
1917 map=True)
1918 self.assertEqual('''ImagePos Offset Size Name
191900000000 00000000 00000038 main-section
192000000004 00000004 00000010 section@0
192100000004 00000000 00000004 u-boot
192200000018 00000018 00000010 section@1
192300000018 00000000 00000004 u-boot
19240000002c 0000002c 00000004 section@2
19250000002c 00000000 00000004 u-boot
1926''', map_data)
1927 self.assertEqual(data,
Simon Glassac0d4952019-05-14 15:53:47 -06001928 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1929 tools.GetBytes(0x21, 12) +
1930 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1931 tools.GetBytes(0x61, 12) +
1932 tools.GetBytes(0x26, 4) + U_BOOT_DATA +
1933 tools.GetBytes(0x26, 8))
Simon Glasseb023b32019-04-25 21:58:39 -06001934
Simon Glass1de34482019-07-08 13:18:53 -06001935 def testCbfsRaw(self):
1936 """Test base handling of a Coreboot Filesystem (CBFS)
1937
1938 The exact contents of the CBFS is verified by similar tests in
1939 cbfs_util_test.py. The tests here merely check that the files added to
1940 the CBFS can be found in the final image.
1941 """
1942 data = self._DoReadFile('102_cbfs_raw.dts')
1943 size = 0xb0
1944
1945 cbfs = cbfs_util.CbfsReader(data)
1946 self.assertEqual(size, cbfs.rom_size)
1947
1948 self.assertIn('u-boot-dtb', cbfs.files)
1949 cfile = cbfs.files['u-boot-dtb']
1950 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
1951
1952 def testCbfsArch(self):
1953 """Test on non-x86 architecture"""
1954 data = self._DoReadFile('103_cbfs_raw_ppc.dts')
1955 size = 0x100
1956
1957 cbfs = cbfs_util.CbfsReader(data)
1958 self.assertEqual(size, cbfs.rom_size)
1959
1960 self.assertIn('u-boot-dtb', cbfs.files)
1961 cfile = cbfs.files['u-boot-dtb']
1962 self.assertEqual(U_BOOT_DTB_DATA, cfile.data)
1963
1964 def testCbfsStage(self):
1965 """Tests handling of a Coreboot Filesystem (CBFS)"""
1966 if not elf.ELF_TOOLS:
1967 self.skipTest('Python elftools not available')
1968 elf_fname = os.path.join(self._indir, 'cbfs-stage.elf')
1969 elf.MakeElf(elf_fname, U_BOOT_DATA, U_BOOT_DTB_DATA)
1970 size = 0xb0
1971
1972 data = self._DoReadFile('104_cbfs_stage.dts')
1973 cbfs = cbfs_util.CbfsReader(data)
1974 self.assertEqual(size, cbfs.rom_size)
1975
1976 self.assertIn('u-boot', cbfs.files)
1977 cfile = cbfs.files['u-boot']
1978 self.assertEqual(U_BOOT_DATA + U_BOOT_DTB_DATA, cfile.data)
1979
1980 def testCbfsRawCompress(self):
1981 """Test handling of compressing raw files"""
1982 self._CheckLz4()
1983 data = self._DoReadFile('105_cbfs_raw_compress.dts')
1984 size = 0x140
1985
1986 cbfs = cbfs_util.CbfsReader(data)
1987 self.assertIn('u-boot', cbfs.files)
1988 cfile = cbfs.files['u-boot']
1989 self.assertEqual(COMPRESS_DATA, cfile.data)
1990
1991 def testCbfsBadArch(self):
1992 """Test handling of a bad architecture"""
1993 with self.assertRaises(ValueError) as e:
1994 self._DoReadFile('106_cbfs_bad_arch.dts')
1995 self.assertIn("Invalid architecture 'bad-arch'", str(e.exception))
1996
1997 def testCbfsNoSize(self):
1998 """Test handling of a missing size property"""
1999 with self.assertRaises(ValueError) as e:
2000 self._DoReadFile('107_cbfs_no_size.dts')
2001 self.assertIn('entry must have a size property', str(e.exception))
2002
2003 def testCbfsNoCOntents(self):
2004 """Test handling of a CBFS entry which does not provide contentsy"""
2005 with self.assertRaises(ValueError) as e:
2006 self._DoReadFile('108_cbfs_no_contents.dts')
2007 self.assertIn('Could not complete processing of contents',
2008 str(e.exception))
2009
2010 def testCbfsBadCompress(self):
2011 """Test handling of a bad architecture"""
2012 with self.assertRaises(ValueError) as e:
2013 self._DoReadFile('109_cbfs_bad_compress.dts')
2014 self.assertIn("Invalid compression in 'u-boot': 'invalid-algo'",
2015 str(e.exception))
2016
2017 def testCbfsNamedEntries(self):
2018 """Test handling of named entries"""
2019 data = self._DoReadFile('110_cbfs_name.dts')
2020
2021 cbfs = cbfs_util.CbfsReader(data)
2022 self.assertIn('FRED', cbfs.files)
2023 cfile1 = cbfs.files['FRED']
2024 self.assertEqual(U_BOOT_DATA, cfile1.data)
2025
2026 self.assertIn('hello', cbfs.files)
2027 cfile2 = cbfs.files['hello']
2028 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
2029
Simon Glass759af872019-07-08 13:18:54 -06002030 def _SetupIfwi(self, fname):
2031 """Set up to run an IFWI test
2032
2033 Args:
2034 fname: Filename of input file to provide (fitimage.bin or ifwi.bin)
2035 """
2036 self._SetupSplElf()
2037
2038 # Intel Integrated Firmware Image (IFWI) file
2039 with gzip.open(self.TestFile('%s.gz' % fname), 'rb') as fd:
2040 data = fd.read()
2041 TestFunctional._MakeInputFile(fname,data)
2042
2043 def _CheckIfwi(self, data):
2044 """Check that an image with an IFWI contains the correct output
2045
2046 Args:
2047 data: Conents of output file
2048 """
2049 expected_desc = tools.ReadFile(self.TestFile('descriptor.bin'))
2050 if data[:0x1000] != expected_desc:
2051 self.fail('Expected descriptor binary at start of image')
2052
2053 # We expect to find the TPL wil in subpart IBBP entry IBBL
2054 image_fname = tools.GetOutputFilename('image.bin')
2055 tpl_fname = tools.GetOutputFilename('tpl.out')
2056 tools.RunIfwiTool(image_fname, tools.CMD_EXTRACT, fname=tpl_fname,
2057 subpart='IBBP', entry_name='IBBL')
2058
2059 tpl_data = tools.ReadFile(tpl_fname)
Simon Glassf55bd692019-08-24 07:22:51 -06002060 self.assertEqual(U_BOOT_TPL_DATA, tpl_data[:len(U_BOOT_TPL_DATA)])
Simon Glass759af872019-07-08 13:18:54 -06002061
2062 def testPackX86RomIfwi(self):
2063 """Test that an x86 ROM with Integrated Firmware Image can be created"""
2064 self._SetupIfwi('fitimage.bin')
2065 data = self._DoReadFile('111_x86-rom-ifwi.dts')
2066 self._CheckIfwi(data)
2067
2068 def testPackX86RomIfwiNoDesc(self):
2069 """Test that an x86 ROM with IFWI can be created from an ifwi.bin file"""
2070 self._SetupIfwi('ifwi.bin')
2071 data = self._DoReadFile('112_x86-rom-ifwi-nodesc.dts')
2072 self._CheckIfwi(data)
2073
2074 def testPackX86RomIfwiNoData(self):
2075 """Test that an x86 ROM with IFWI handles missing data"""
2076 self._SetupIfwi('ifwi.bin')
2077 with self.assertRaises(ValueError) as e:
2078 data = self._DoReadFile('113_x86-rom-ifwi-nodata.dts')
2079 self.assertIn('Could not complete processing of contents',
2080 str(e.exception))
Simon Glass91710b32018-07-17 13:25:32 -06002081
Simon Glassc2f1aed2019-07-08 13:18:56 -06002082 def testCbfsOffset(self):
2083 """Test a CBFS with files at particular offsets
2084
2085 Like all CFBS tests, this is just checking the logic that calls
2086 cbfs_util. See cbfs_util_test for fully tests (e.g. test_cbfs_offset()).
2087 """
2088 data = self._DoReadFile('114_cbfs_offset.dts')
2089 size = 0x200
2090
2091 cbfs = cbfs_util.CbfsReader(data)
2092 self.assertEqual(size, cbfs.rom_size)
2093
2094 self.assertIn('u-boot', cbfs.files)
2095 cfile = cbfs.files['u-boot']
2096 self.assertEqual(U_BOOT_DATA, cfile.data)
2097 self.assertEqual(0x40, cfile.cbfs_offset)
2098
2099 self.assertIn('u-boot-dtb', cbfs.files)
2100 cfile2 = cbfs.files['u-boot-dtb']
2101 self.assertEqual(U_BOOT_DTB_DATA, cfile2.data)
2102 self.assertEqual(0x140, cfile2.cbfs_offset)
2103
Simon Glass0f621332019-07-08 14:25:27 -06002104 def testFdtmap(self):
2105 """Test an FDT map can be inserted in the image"""
2106 data = self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
2107 fdtmap_data = data[len(U_BOOT_DATA):]
2108 magic = fdtmap_data[:8]
2109 self.assertEqual('_FDTMAP_', magic)
2110 self.assertEqual(tools.GetBytes(0, 8), fdtmap_data[8:16])
2111
2112 fdt_data = fdtmap_data[16:]
2113 dtb = fdt.Fdt.FromData(fdt_data)
2114 dtb.Scan()
Simon Glass2c6adba2019-07-20 12:23:47 -06002115 props = self._GetPropTree(dtb, BASE_DTB_PROPS, prefix='/')
Simon Glass0f621332019-07-08 14:25:27 -06002116 self.assertEqual({
2117 'image-pos': 0,
2118 'offset': 0,
2119 'u-boot:offset': 0,
2120 'u-boot:size': len(U_BOOT_DATA),
2121 'u-boot:image-pos': 0,
2122 'fdtmap:image-pos': 4,
2123 'fdtmap:offset': 4,
2124 'fdtmap:size': len(fdtmap_data),
2125 'size': len(data),
2126 }, props)
2127
2128 def testFdtmapNoMatch(self):
2129 """Check handling of an FDT map when the section cannot be found"""
2130 self.data = self._DoReadFileRealDtb('115_fdtmap.dts')
2131
2132 # Mangle the section name, which should cause a mismatch between the
2133 # correct FDT path and the one expected by the section
2134 image = control.images['image']
Simon Glasscec34ba2019-07-08 14:25:28 -06002135 image._node.path += '-suffix'
Simon Glass0f621332019-07-08 14:25:27 -06002136 entries = image.GetEntries()
2137 fdtmap = entries['fdtmap']
2138 with self.assertRaises(ValueError) as e:
2139 fdtmap._GetFdtmap()
2140 self.assertIn("Cannot locate node for path '/binman-suffix'",
2141 str(e.exception))
2142
Simon Glasscec34ba2019-07-08 14:25:28 -06002143 def testFdtmapHeader(self):
2144 """Test an FDT map and image header can be inserted in the image"""
2145 data = self.data = self._DoReadFileRealDtb('116_fdtmap_hdr.dts')
2146 fdtmap_pos = len(U_BOOT_DATA)
2147 fdtmap_data = data[fdtmap_pos:]
2148 fdt_data = fdtmap_data[16:]
2149 dtb = fdt.Fdt.FromData(fdt_data)
2150 fdt_size = dtb.GetFdtObj().totalsize()
2151 hdr_data = data[-8:]
2152 self.assertEqual('BinM', hdr_data[:4])
2153 offset = struct.unpack('<I', hdr_data[4:])[0] & 0xffffffff
2154 self.assertEqual(fdtmap_pos - 0x400, offset - (1 << 32))
2155
2156 def testFdtmapHeaderStart(self):
2157 """Test an image header can be inserted at the image start"""
2158 data = self.data = self._DoReadFileRealDtb('117_fdtmap_hdr_start.dts')
2159 fdtmap_pos = 0x100 + len(U_BOOT_DATA)
2160 hdr_data = data[:8]
2161 self.assertEqual('BinM', hdr_data[:4])
2162 offset = struct.unpack('<I', hdr_data[4:])[0]
2163 self.assertEqual(fdtmap_pos, offset)
2164
2165 def testFdtmapHeaderPos(self):
2166 """Test an image header can be inserted at a chosen position"""
2167 data = self.data = self._DoReadFileRealDtb('118_fdtmap_hdr_pos.dts')
2168 fdtmap_pos = 0x100 + len(U_BOOT_DATA)
2169 hdr_data = data[0x80:0x88]
2170 self.assertEqual('BinM', hdr_data[:4])
2171 offset = struct.unpack('<I', hdr_data[4:])[0]
2172 self.assertEqual(fdtmap_pos, offset)
2173
2174 def testHeaderMissingFdtmap(self):
2175 """Test an image header requires an fdtmap"""
2176 with self.assertRaises(ValueError) as e:
2177 self.data = self._DoReadFileRealDtb('119_fdtmap_hdr_missing.dts')
2178 self.assertIn("'image_header' section must have an 'fdtmap' sibling",
2179 str(e.exception))
2180
2181 def testHeaderNoLocation(self):
2182 """Test an image header with a no specified location is detected"""
2183 with self.assertRaises(ValueError) as e:
2184 self.data = self._DoReadFileRealDtb('120_hdr_no_location.dts')
2185 self.assertIn("Invalid location 'None', expected 'start' or 'end'",
2186 str(e.exception))
2187
Simon Glasse61b6f62019-07-08 14:25:37 -06002188 def testEntryExpand(self):
2189 """Test expanding an entry after it is packed"""
2190 data = self._DoReadFile('121_entry_expand.dts')
Simon Glass8c702fb2019-07-20 12:23:57 -06002191 self.assertEqual(b'aaa', data[:3])
2192 self.assertEqual(U_BOOT_DATA, data[3:3 + len(U_BOOT_DATA)])
2193 self.assertEqual(b'aaa', data[-3:])
Simon Glasse61b6f62019-07-08 14:25:37 -06002194
2195 def testEntryExpandBad(self):
2196 """Test expanding an entry after it is packed, twice"""
2197 with self.assertRaises(ValueError) as e:
2198 self._DoReadFile('122_entry_expand_twice.dts')
Simon Glass9d8ee322019-07-20 12:23:58 -06002199 self.assertIn("Image '/binman': Entries changed size after packing",
Simon Glasse61b6f62019-07-08 14:25:37 -06002200 str(e.exception))
2201
2202 def testEntryExpandSection(self):
2203 """Test expanding an entry within a section after it is packed"""
2204 data = self._DoReadFile('123_entry_expand_section.dts')
Simon Glass8c702fb2019-07-20 12:23:57 -06002205 self.assertEqual(b'aaa', data[:3])
2206 self.assertEqual(U_BOOT_DATA, data[3:3 + len(U_BOOT_DATA)])
2207 self.assertEqual(b'aaa', data[-3:])
Simon Glasse61b6f62019-07-08 14:25:37 -06002208
Simon Glass90d29682019-07-08 14:25:38 -06002209 def testCompressDtb(self):
2210 """Test that compress of device-tree files is supported"""
2211 self._CheckLz4()
2212 data = self.data = self._DoReadFileRealDtb('124_compress_dtb.dts')
2213 self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
2214 comp_data = data[len(U_BOOT_DATA):]
2215 orig = self._decompress(comp_data)
2216 dtb = fdt.Fdt.FromData(orig)
2217 dtb.Scan()
2218 props = self._GetPropTree(dtb, ['size', 'uncomp-size'])
2219 expected = {
2220 'u-boot:size': len(U_BOOT_DATA),
2221 'u-boot-dtb:uncomp-size': len(orig),
2222 'u-boot-dtb:size': len(comp_data),
2223 'size': len(data),
2224 }
2225 self.assertEqual(expected, props)
2226
Simon Glass151bbbf2019-07-08 14:25:41 -06002227 def testCbfsUpdateFdt(self):
2228 """Test that we can update the device tree with CBFS offset/size info"""
2229 self._CheckLz4()
2230 data, _, _, out_dtb_fname = self._DoReadFileDtb('125_cbfs_update.dts',
2231 update_dtb=True)
2232 dtb = fdt.Fdt(out_dtb_fname)
2233 dtb.Scan()
Simon Glass2c6adba2019-07-20 12:23:47 -06002234 props = self._GetPropTree(dtb, BASE_DTB_PROPS + ['uncomp-size'])
Simon Glass151bbbf2019-07-08 14:25:41 -06002235 del props['cbfs/u-boot:size']
2236 self.assertEqual({
2237 'offset': 0,
2238 'size': len(data),
2239 'image-pos': 0,
2240 'cbfs:offset': 0,
2241 'cbfs:size': len(data),
2242 'cbfs:image-pos': 0,
2243 'cbfs/u-boot:offset': 0x38,
2244 'cbfs/u-boot:uncomp-size': len(U_BOOT_DATA),
2245 'cbfs/u-boot:image-pos': 0x38,
2246 'cbfs/u-boot-dtb:offset': 0xb8,
2247 'cbfs/u-boot-dtb:size': len(U_BOOT_DATA),
2248 'cbfs/u-boot-dtb:image-pos': 0xb8,
2249 }, props)
2250
Simon Glass3c9b4f22019-07-08 14:25:42 -06002251 def testCbfsBadType(self):
2252 """Test an image header with a no specified location is detected"""
2253 with self.assertRaises(ValueError) as e:
2254 self._DoReadFile('126_cbfs_bad_type.dts')
2255 self.assertIn("Unknown cbfs-type 'badtype'", str(e.exception))
2256
Simon Glass6b156f82019-07-08 14:25:43 -06002257 def testList(self):
2258 """Test listing the files in an image"""
2259 self._CheckLz4()
2260 data = self._DoReadFile('127_list.dts')
2261 image = control.images['image']
2262 entries = image.BuildEntryList()
2263 self.assertEqual(7, len(entries))
2264
2265 ent = entries[0]
2266 self.assertEqual(0, ent.indent)
2267 self.assertEqual('main-section', ent.name)
2268 self.assertEqual('section', ent.etype)
2269 self.assertEqual(len(data), ent.size)
2270 self.assertEqual(0, ent.image_pos)
2271 self.assertEqual(None, ent.uncomp_size)
Simon Glass39dd2152019-07-08 14:25:47 -06002272 self.assertEqual(0, ent.offset)
Simon Glass6b156f82019-07-08 14:25:43 -06002273
2274 ent = entries[1]
2275 self.assertEqual(1, ent.indent)
2276 self.assertEqual('u-boot', ent.name)
2277 self.assertEqual('u-boot', ent.etype)
2278 self.assertEqual(len(U_BOOT_DATA), ent.size)
2279 self.assertEqual(0, ent.image_pos)
2280 self.assertEqual(None, ent.uncomp_size)
2281 self.assertEqual(0, ent.offset)
2282
2283 ent = entries[2]
2284 self.assertEqual(1, ent.indent)
2285 self.assertEqual('section', ent.name)
2286 self.assertEqual('section', ent.etype)
2287 section_size = ent.size
2288 self.assertEqual(0x100, ent.image_pos)
2289 self.assertEqual(None, ent.uncomp_size)
Simon Glass39dd2152019-07-08 14:25:47 -06002290 self.assertEqual(0x100, ent.offset)
Simon Glass6b156f82019-07-08 14:25:43 -06002291
2292 ent = entries[3]
2293 self.assertEqual(2, ent.indent)
2294 self.assertEqual('cbfs', ent.name)
2295 self.assertEqual('cbfs', ent.etype)
2296 self.assertEqual(0x400, ent.size)
2297 self.assertEqual(0x100, ent.image_pos)
2298 self.assertEqual(None, ent.uncomp_size)
2299 self.assertEqual(0, ent.offset)
2300
2301 ent = entries[4]
2302 self.assertEqual(3, ent.indent)
2303 self.assertEqual('u-boot', ent.name)
2304 self.assertEqual('u-boot', ent.etype)
2305 self.assertEqual(len(U_BOOT_DATA), ent.size)
2306 self.assertEqual(0x138, ent.image_pos)
2307 self.assertEqual(None, ent.uncomp_size)
2308 self.assertEqual(0x38, ent.offset)
2309
2310 ent = entries[5]
2311 self.assertEqual(3, ent.indent)
2312 self.assertEqual('u-boot-dtb', ent.name)
2313 self.assertEqual('text', ent.etype)
2314 self.assertGreater(len(COMPRESS_DATA), ent.size)
2315 self.assertEqual(0x178, ent.image_pos)
2316 self.assertEqual(len(COMPRESS_DATA), ent.uncomp_size)
2317 self.assertEqual(0x78, ent.offset)
2318
2319 ent = entries[6]
2320 self.assertEqual(2, ent.indent)
2321 self.assertEqual('u-boot-dtb', ent.name)
2322 self.assertEqual('u-boot-dtb', ent.etype)
2323 self.assertEqual(0x500, ent.image_pos)
2324 self.assertEqual(len(U_BOOT_DTB_DATA), ent.uncomp_size)
2325 dtb_size = ent.size
2326 # Compressing this data expands it since headers are added
2327 self.assertGreater(dtb_size, len(U_BOOT_DTB_DATA))
2328 self.assertEqual(0x400, ent.offset)
2329
2330 self.assertEqual(len(data), 0x100 + section_size)
2331 self.assertEqual(section_size, 0x400 + dtb_size)
2332
Simon Glass8d8bf4e2019-07-08 14:25:44 -06002333 def testFindFdtmap(self):
2334 """Test locating an FDT map in an image"""
2335 self._CheckLz4()
2336 data = self.data = self._DoReadFileRealDtb('128_decode_image.dts')
2337 image = control.images['image']
2338 entries = image.GetEntries()
2339 entry = entries['fdtmap']
2340 self.assertEqual(entry.image_pos, fdtmap.LocateFdtmap(data))
2341
2342 def testFindFdtmapMissing(self):
2343 """Test failing to locate an FDP map"""
2344 data = self._DoReadFile('005_simple.dts')
2345 self.assertEqual(None, fdtmap.LocateFdtmap(data))
2346
Simon Glassed39a3c2019-07-08 14:25:45 -06002347 def testFindImageHeader(self):
2348 """Test locating a image header"""
2349 self._CheckLz4()
Simon Glassb8424fa2019-07-08 14:25:46 -06002350 data = self.data = self._DoReadFileRealDtb('128_decode_image.dts')
Simon Glassed39a3c2019-07-08 14:25:45 -06002351 image = control.images['image']
2352 entries = image.GetEntries()
2353 entry = entries['fdtmap']
2354 # The header should point to the FDT map
2355 self.assertEqual(entry.image_pos, image_header.LocateHeaderOffset(data))
2356
2357 def testFindImageHeaderStart(self):
2358 """Test locating a image header located at the start of an image"""
Simon Glassb8424fa2019-07-08 14:25:46 -06002359 data = self.data = self._DoReadFileRealDtb('117_fdtmap_hdr_start.dts')
Simon Glassed39a3c2019-07-08 14:25:45 -06002360 image = control.images['image']
2361 entries = image.GetEntries()
2362 entry = entries['fdtmap']
2363 # The header should point to the FDT map
2364 self.assertEqual(entry.image_pos, image_header.LocateHeaderOffset(data))
2365
2366 def testFindImageHeaderMissing(self):
2367 """Test failing to locate an image header"""
2368 data = self._DoReadFile('005_simple.dts')
2369 self.assertEqual(None, image_header.LocateHeaderOffset(data))
2370
Simon Glassb8424fa2019-07-08 14:25:46 -06002371 def testReadImage(self):
2372 """Test reading an image and accessing its FDT map"""
2373 self._CheckLz4()
2374 data = self.data = self._DoReadFileRealDtb('128_decode_image.dts')
2375 image_fname = tools.GetOutputFilename('image.bin')
2376 orig_image = control.images['image']
2377 image = Image.FromFile(image_fname)
2378 self.assertEqual(orig_image.GetEntries().keys(),
2379 image.GetEntries().keys())
2380
2381 orig_entry = orig_image.GetEntries()['fdtmap']
2382 entry = image.GetEntries()['fdtmap']
2383 self.assertEquals(orig_entry.offset, entry.offset)
2384 self.assertEquals(orig_entry.size, entry.size)
2385 self.assertEquals(orig_entry.image_pos, entry.image_pos)
2386
2387 def testReadImageNoHeader(self):
2388 """Test accessing an image's FDT map without an image header"""
2389 self._CheckLz4()
2390 data = self._DoReadFileRealDtb('129_decode_image_nohdr.dts')
2391 image_fname = tools.GetOutputFilename('image.bin')
2392 image = Image.FromFile(image_fname)
2393 self.assertTrue(isinstance(image, Image))
Simon Glass072959a2019-07-20 12:23:50 -06002394 self.assertEqual('image', image.image_name[-5:])
Simon Glassb8424fa2019-07-08 14:25:46 -06002395
2396 def testReadImageFail(self):
2397 """Test failing to read an image image's FDT map"""
2398 self._DoReadFile('005_simple.dts')
2399 image_fname = tools.GetOutputFilename('image.bin')
2400 with self.assertRaises(ValueError) as e:
2401 image = Image.FromFile(image_fname)
2402 self.assertIn("Cannot find FDT map in image", str(e.exception))
Simon Glassc2f1aed2019-07-08 13:18:56 -06002403
Simon Glassb2fd11d2019-07-08 14:25:48 -06002404 def testListCmd(self):
2405 """Test listing the files in an image using an Fdtmap"""
2406 self._CheckLz4()
2407 data = self._DoReadFileRealDtb('130_list_fdtmap.dts')
2408
2409 # lz4 compression size differs depending on the version
2410 image = control.images['image']
2411 entries = image.GetEntries()
2412 section_size = entries['section'].size
2413 fdt_size = entries['section'].GetEntries()['u-boot-dtb'].size
2414 fdtmap_offset = entries['fdtmap'].offset
2415
Simon Glassb3d6fc72019-07-20 12:24:10 -06002416 try:
2417 tmpdir, updated_fname = self._SetupImageInTmpdir()
2418 with test_util.capture_sys_output() as (stdout, stderr):
2419 self._DoBinman('ls', '-i', updated_fname)
2420 finally:
2421 shutil.rmtree(tmpdir)
Simon Glassb2fd11d2019-07-08 14:25:48 -06002422 lines = stdout.getvalue().splitlines()
2423 expected = [
2424'Name Image-pos Size Entry-type Offset Uncomp-size',
2425'----------------------------------------------------------------------',
2426'main-section 0 c00 section 0',
2427' u-boot 0 4 u-boot 0',
2428' section 100 %x section 100' % section_size,
2429' cbfs 100 400 cbfs 0',
2430' u-boot 138 4 u-boot 38',
2431' u-boot-dtb 180 10f u-boot-dtb 80 3c9',
2432' u-boot-dtb 500 %x u-boot-dtb 400 3c9' % fdt_size,
Simon Glassee6409b2019-07-20 12:23:44 -06002433' fdtmap %x 3b4 fdtmap %x' %
Simon Glassb2fd11d2019-07-08 14:25:48 -06002434 (fdtmap_offset, fdtmap_offset),
2435' image-header bf8 8 image-header bf8',
2436 ]
2437 self.assertEqual(expected, lines)
2438
2439 def testListCmdFail(self):
2440 """Test failing to list an image"""
2441 self._DoReadFile('005_simple.dts')
Simon Glassb3d6fc72019-07-20 12:24:10 -06002442 try:
2443 tmpdir, updated_fname = self._SetupImageInTmpdir()
2444 with self.assertRaises(ValueError) as e:
2445 self._DoBinman('ls', '-i', updated_fname)
2446 finally:
2447 shutil.rmtree(tmpdir)
Simon Glassb2fd11d2019-07-08 14:25:48 -06002448 self.assertIn("Cannot find FDT map in image", str(e.exception))
2449
2450 def _RunListCmd(self, paths, expected):
2451 """List out entries and check the result
2452
2453 Args:
2454 paths: List of paths to pass to the list command
2455 expected: Expected list of filenames to be returned, in order
2456 """
2457 self._CheckLz4()
2458 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2459 image_fname = tools.GetOutputFilename('image.bin')
2460 image = Image.FromFile(image_fname)
2461 lines = image.GetListEntries(paths)[1]
2462 files = [line[0].strip() for line in lines[1:]]
2463 self.assertEqual(expected, files)
2464
2465 def testListCmdSection(self):
2466 """Test listing the files in a section"""
2467 self._RunListCmd(['section'],
2468 ['section', 'cbfs', 'u-boot', 'u-boot-dtb', 'u-boot-dtb'])
2469
2470 def testListCmdFile(self):
2471 """Test listing a particular file"""
2472 self._RunListCmd(['*u-boot-dtb'], ['u-boot-dtb', 'u-boot-dtb'])
2473
2474 def testListCmdWildcard(self):
2475 """Test listing a wildcarded file"""
2476 self._RunListCmd(['*boot*'],
2477 ['u-boot', 'u-boot', 'u-boot-dtb', 'u-boot-dtb'])
2478
2479 def testListCmdWildcardMulti(self):
2480 """Test listing a wildcarded file"""
2481 self._RunListCmd(['*cb*', '*head*'],
2482 ['cbfs', 'u-boot', 'u-boot-dtb', 'image-header'])
2483
2484 def testListCmdEmpty(self):
2485 """Test listing a wildcarded file"""
2486 self._RunListCmd(['nothing'], [])
2487
2488 def testListCmdPath(self):
2489 """Test listing the files in a sub-entry of a section"""
2490 self._RunListCmd(['section/cbfs'], ['cbfs', 'u-boot', 'u-boot-dtb'])
2491
Simon Glass4c613bf2019-07-08 14:25:50 -06002492 def _RunExtractCmd(self, entry_name, decomp=True):
2493 """Extract an entry from an image
2494
2495 Args:
2496 entry_name: Entry name to extract
2497 decomp: True to decompress the data if compressed, False to leave
2498 it in its raw uncompressed format
2499
2500 Returns:
2501 data from entry
2502 """
2503 self._CheckLz4()
2504 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2505 image_fname = tools.GetOutputFilename('image.bin')
2506 return control.ReadEntry(image_fname, entry_name, decomp)
2507
2508 def testExtractSimple(self):
2509 """Test extracting a single file"""
2510 data = self._RunExtractCmd('u-boot')
2511 self.assertEqual(U_BOOT_DATA, data)
2512
Simon Glass980a2842019-07-08 14:25:52 -06002513 def testExtractSection(self):
2514 """Test extracting the files in a section"""
2515 data = self._RunExtractCmd('section')
2516 cbfs_data = data[:0x400]
2517 cbfs = cbfs_util.CbfsReader(cbfs_data)
2518 self.assertEqual(['u-boot', 'u-boot-dtb', ''], cbfs.files.keys())
2519 dtb_data = data[0x400:]
2520 dtb = self._decompress(dtb_data)
2521 self.assertEqual(EXTRACT_DTB_SIZE, len(dtb))
2522
2523 def testExtractCompressed(self):
2524 """Test extracting compressed data"""
2525 data = self._RunExtractCmd('section/u-boot-dtb')
2526 self.assertEqual(EXTRACT_DTB_SIZE, len(data))
2527
2528 def testExtractRaw(self):
2529 """Test extracting compressed data without decompressing it"""
2530 data = self._RunExtractCmd('section/u-boot-dtb', decomp=False)
2531 dtb = self._decompress(data)
2532 self.assertEqual(EXTRACT_DTB_SIZE, len(dtb))
2533
2534 def testExtractCbfs(self):
2535 """Test extracting CBFS data"""
2536 data = self._RunExtractCmd('section/cbfs/u-boot')
2537 self.assertEqual(U_BOOT_DATA, data)
2538
2539 def testExtractCbfsCompressed(self):
2540 """Test extracting CBFS compressed data"""
2541 data = self._RunExtractCmd('section/cbfs/u-boot-dtb')
2542 self.assertEqual(EXTRACT_DTB_SIZE, len(data))
2543
2544 def testExtractCbfsRaw(self):
2545 """Test extracting CBFS compressed data without decompressing it"""
2546 data = self._RunExtractCmd('section/cbfs/u-boot-dtb', decomp=False)
Simon Glass37fdd142019-07-20 12:24:06 -06002547 dtb = tools.Decompress(data, 'lzma', with_header=False)
Simon Glass980a2842019-07-08 14:25:52 -06002548 self.assertEqual(EXTRACT_DTB_SIZE, len(dtb))
2549
Simon Glass4c613bf2019-07-08 14:25:50 -06002550 def testExtractBadEntry(self):
2551 """Test extracting a bad section path"""
2552 with self.assertRaises(ValueError) as e:
2553 self._RunExtractCmd('section/does-not-exist')
2554 self.assertIn("Entry 'does-not-exist' not found in '/section'",
2555 str(e.exception))
2556
2557 def testExtractMissingFile(self):
2558 """Test extracting file that does not exist"""
2559 with self.assertRaises(IOError) as e:
2560 control.ReadEntry('missing-file', 'name')
2561
2562 def testExtractBadFile(self):
2563 """Test extracting an invalid file"""
2564 fname = os.path.join(self._indir, 'badfile')
2565 tools.WriteFile(fname, b'')
2566 with self.assertRaises(ValueError) as e:
2567 control.ReadEntry(fname, 'name')
2568
Simon Glass980a2842019-07-08 14:25:52 -06002569 def testExtractCmd(self):
2570 """Test extracting a file fron an image on the command line"""
2571 self._CheckLz4()
2572 self._DoReadFileRealDtb('130_list_fdtmap.dts')
Simon Glass980a2842019-07-08 14:25:52 -06002573 fname = os.path.join(self._indir, 'output.extact')
Simon Glassb3d6fc72019-07-20 12:24:10 -06002574 try:
2575 tmpdir, updated_fname = self._SetupImageInTmpdir()
2576 with test_util.capture_sys_output() as (stdout, stderr):
2577 self._DoBinman('extract', '-i', updated_fname, 'u-boot',
2578 '-f', fname)
2579 finally:
2580 shutil.rmtree(tmpdir)
Simon Glass980a2842019-07-08 14:25:52 -06002581 data = tools.ReadFile(fname)
2582 self.assertEqual(U_BOOT_DATA, data)
2583
2584 def testExtractOneEntry(self):
2585 """Test extracting a single entry fron an image """
2586 self._CheckLz4()
2587 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2588 image_fname = tools.GetOutputFilename('image.bin')
2589 fname = os.path.join(self._indir, 'output.extact')
2590 control.ExtractEntries(image_fname, fname, None, ['u-boot'])
2591 data = tools.ReadFile(fname)
2592 self.assertEqual(U_BOOT_DATA, data)
2593
2594 def _CheckExtractOutput(self, decomp):
2595 """Helper to test file output with and without decompression
2596
2597 Args:
2598 decomp: True to decompress entry data, False to output it raw
2599 """
2600 def _CheckPresent(entry_path, expect_data, expect_size=None):
2601 """Check and remove expected file
2602
2603 This checks the data/size of a file and removes the file both from
2604 the outfiles set and from the output directory. Once all files are
2605 processed, both the set and directory should be empty.
2606
2607 Args:
2608 entry_path: Entry path
2609 expect_data: Data to expect in file, or None to skip check
2610 expect_size: Size of data to expect in file, or None to skip
2611 """
2612 path = os.path.join(outdir, entry_path)
2613 data = tools.ReadFile(path)
2614 os.remove(path)
2615 if expect_data:
2616 self.assertEqual(expect_data, data)
2617 elif expect_size:
2618 self.assertEqual(expect_size, len(data))
2619 outfiles.remove(path)
2620
2621 def _CheckDirPresent(name):
2622 """Remove expected directory
2623
2624 This gives an error if the directory does not exist as expected
2625
2626 Args:
2627 name: Name of directory to remove
2628 """
2629 path = os.path.join(outdir, name)
2630 os.rmdir(path)
2631
2632 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2633 image_fname = tools.GetOutputFilename('image.bin')
2634 outdir = os.path.join(self._indir, 'extract')
2635 einfos = control.ExtractEntries(image_fname, None, outdir, [], decomp)
2636
2637 # Create a set of all file that were output (should be 9)
2638 outfiles = set()
2639 for root, dirs, files in os.walk(outdir):
2640 outfiles |= set([os.path.join(root, fname) for fname in files])
2641 self.assertEqual(9, len(outfiles))
2642 self.assertEqual(9, len(einfos))
2643
2644 image = control.images['image']
2645 entries = image.GetEntries()
2646
2647 # Check the 9 files in various ways
2648 section = entries['section']
2649 section_entries = section.GetEntries()
2650 cbfs_entries = section_entries['cbfs'].GetEntries()
2651 _CheckPresent('u-boot', U_BOOT_DATA)
2652 _CheckPresent('section/cbfs/u-boot', U_BOOT_DATA)
2653 dtb_len = EXTRACT_DTB_SIZE
2654 if not decomp:
2655 dtb_len = cbfs_entries['u-boot-dtb'].size
2656 _CheckPresent('section/cbfs/u-boot-dtb', None, dtb_len)
2657 if not decomp:
2658 dtb_len = section_entries['u-boot-dtb'].size
2659 _CheckPresent('section/u-boot-dtb', None, dtb_len)
2660
2661 fdtmap = entries['fdtmap']
2662 _CheckPresent('fdtmap', fdtmap.data)
2663 hdr = entries['image-header']
2664 _CheckPresent('image-header', hdr.data)
2665
2666 _CheckPresent('section/root', section.data)
2667 cbfs = section_entries['cbfs']
2668 _CheckPresent('section/cbfs/root', cbfs.data)
2669 data = tools.ReadFile(image_fname)
2670 _CheckPresent('root', data)
2671
2672 # There should be no files left. Remove all the directories to check.
2673 # If there are any files/dirs remaining, one of these checks will fail.
2674 self.assertEqual(0, len(outfiles))
2675 _CheckDirPresent('section/cbfs')
2676 _CheckDirPresent('section')
2677 _CheckDirPresent('')
2678 self.assertFalse(os.path.exists(outdir))
2679
2680 def testExtractAllEntries(self):
2681 """Test extracting all entries"""
2682 self._CheckLz4()
2683 self._CheckExtractOutput(decomp=True)
2684
2685 def testExtractAllEntriesRaw(self):
2686 """Test extracting all entries without decompressing them"""
2687 self._CheckLz4()
2688 self._CheckExtractOutput(decomp=False)
2689
2690 def testExtractSelectedEntries(self):
2691 """Test extracting some entries"""
2692 self._CheckLz4()
2693 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2694 image_fname = tools.GetOutputFilename('image.bin')
2695 outdir = os.path.join(self._indir, 'extract')
2696 einfos = control.ExtractEntries(image_fname, None, outdir,
2697 ['*cb*', '*head*'])
2698
2699 # File output is tested by testExtractAllEntries(), so just check that
2700 # the expected entries are selected
2701 names = [einfo.name for einfo in einfos]
2702 self.assertEqual(names,
2703 ['cbfs', 'u-boot', 'u-boot-dtb', 'image-header'])
2704
2705 def testExtractNoEntryPaths(self):
2706 """Test extracting some entries"""
2707 self._CheckLz4()
2708 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2709 image_fname = tools.GetOutputFilename('image.bin')
2710 with self.assertRaises(ValueError) as e:
2711 control.ExtractEntries(image_fname, 'fname', None, [])
Simon Glassa772d3f2019-07-20 12:24:14 -06002712 self.assertIn('Must specify an entry path to write with -f',
Simon Glass980a2842019-07-08 14:25:52 -06002713 str(e.exception))
2714
2715 def testExtractTooManyEntryPaths(self):
2716 """Test extracting some entries"""
2717 self._CheckLz4()
2718 self._DoReadFileRealDtb('130_list_fdtmap.dts')
2719 image_fname = tools.GetOutputFilename('image.bin')
2720 with self.assertRaises(ValueError) as e:
2721 control.ExtractEntries(image_fname, 'fname', None, ['a', 'b'])
Simon Glassa772d3f2019-07-20 12:24:14 -06002722 self.assertIn('Must specify exactly one entry path to write with -f',
Simon Glass980a2842019-07-08 14:25:52 -06002723 str(e.exception))
2724
Simon Glass52d06212019-07-08 14:25:53 -06002725 def testPackAlignSection(self):
2726 """Test that sections can have alignment"""
2727 self._DoReadFile('131_pack_align_section.dts')
2728
2729 self.assertIn('image', control.images)
2730 image = control.images['image']
2731 entries = image.GetEntries()
2732 self.assertEqual(3, len(entries))
2733
2734 # First u-boot
2735 self.assertIn('u-boot', entries)
2736 entry = entries['u-boot']
2737 self.assertEqual(0, entry.offset)
2738 self.assertEqual(0, entry.image_pos)
2739 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2740 self.assertEqual(len(U_BOOT_DATA), entry.size)
2741
2742 # Section0
2743 self.assertIn('section0', entries)
2744 section0 = entries['section0']
2745 self.assertEqual(0x10, section0.offset)
2746 self.assertEqual(0x10, section0.image_pos)
2747 self.assertEqual(len(U_BOOT_DATA), section0.size)
2748
2749 # Second u-boot
2750 section_entries = section0.GetEntries()
2751 self.assertIn('u-boot', section_entries)
2752 entry = section_entries['u-boot']
2753 self.assertEqual(0, entry.offset)
2754 self.assertEqual(0x10, entry.image_pos)
2755 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2756 self.assertEqual(len(U_BOOT_DATA), entry.size)
2757
2758 # Section1
2759 self.assertIn('section1', entries)
2760 section1 = entries['section1']
2761 self.assertEqual(0x14, section1.offset)
2762 self.assertEqual(0x14, section1.image_pos)
2763 self.assertEqual(0x20, section1.size)
2764
2765 # Second u-boot
2766 section_entries = section1.GetEntries()
2767 self.assertIn('u-boot', section_entries)
2768 entry = section_entries['u-boot']
2769 self.assertEqual(0, entry.offset)
2770 self.assertEqual(0x14, entry.image_pos)
2771 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2772 self.assertEqual(len(U_BOOT_DATA), entry.size)
2773
2774 # Section2
2775 self.assertIn('section2', section_entries)
2776 section2 = section_entries['section2']
2777 self.assertEqual(0x4, section2.offset)
2778 self.assertEqual(0x18, section2.image_pos)
2779 self.assertEqual(4, section2.size)
2780
2781 # Third u-boot
2782 section_entries = section2.GetEntries()
2783 self.assertIn('u-boot', section_entries)
2784 entry = section_entries['u-boot']
2785 self.assertEqual(0, entry.offset)
2786 self.assertEqual(0x18, entry.image_pos)
2787 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
2788 self.assertEqual(len(U_BOOT_DATA), entry.size)
2789
Simon Glassf8a54bc2019-07-20 12:23:56 -06002790 def _RunReplaceCmd(self, entry_name, data, decomp=True, allow_resize=True,
2791 dts='132_replace.dts'):
Simon Glass072959a2019-07-20 12:23:50 -06002792 """Replace an entry in an image
2793
2794 This writes the entry data to update it, then opens the updated file and
2795 returns the value that it now finds there.
2796
2797 Args:
2798 entry_name: Entry name to replace
2799 data: Data to replace it with
2800 decomp: True to compress the data if needed, False if data is
2801 already compressed so should be used as is
Simon Glassf8a54bc2019-07-20 12:23:56 -06002802 allow_resize: True to allow entries to change size, False to raise
2803 an exception
Simon Glass072959a2019-07-20 12:23:50 -06002804
2805 Returns:
2806 Tuple:
2807 data from entry
2808 data from fdtmap (excluding header)
Simon Glassf8a54bc2019-07-20 12:23:56 -06002809 Image object that was modified
Simon Glass072959a2019-07-20 12:23:50 -06002810 """
Simon Glassf8a54bc2019-07-20 12:23:56 -06002811 dtb_data = self._DoReadFileDtb(dts, use_real_dtb=True,
Simon Glass072959a2019-07-20 12:23:50 -06002812 update_dtb=True)[1]
2813
2814 self.assertIn('image', control.images)
2815 image = control.images['image']
2816 entries = image.GetEntries()
2817 orig_dtb_data = entries['u-boot-dtb'].data
2818 orig_fdtmap_data = entries['fdtmap'].data
2819
2820 image_fname = tools.GetOutputFilename('image.bin')
2821 updated_fname = tools.GetOutputFilename('image-updated.bin')
2822 tools.WriteFile(updated_fname, tools.ReadFile(image_fname))
Simon Glassf8a54bc2019-07-20 12:23:56 -06002823 image = control.WriteEntry(updated_fname, entry_name, data, decomp,
2824 allow_resize)
Simon Glass072959a2019-07-20 12:23:50 -06002825 data = control.ReadEntry(updated_fname, entry_name, decomp)
2826
Simon Glassf8a54bc2019-07-20 12:23:56 -06002827 # The DT data should not change unless resized:
2828 if not allow_resize:
2829 new_dtb_data = entries['u-boot-dtb'].data
2830 self.assertEqual(new_dtb_data, orig_dtb_data)
2831 new_fdtmap_data = entries['fdtmap'].data
2832 self.assertEqual(new_fdtmap_data, orig_fdtmap_data)
Simon Glass072959a2019-07-20 12:23:50 -06002833
Simon Glassf8a54bc2019-07-20 12:23:56 -06002834 return data, orig_fdtmap_data[fdtmap.FDTMAP_HDR_LEN:], image
Simon Glass072959a2019-07-20 12:23:50 -06002835
2836 def testReplaceSimple(self):
2837 """Test replacing a single file"""
2838 expected = b'x' * len(U_BOOT_DATA)
Simon Glassf8a54bc2019-07-20 12:23:56 -06002839 data, expected_fdtmap, _ = self._RunReplaceCmd('u-boot', expected,
2840 allow_resize=False)
Simon Glass072959a2019-07-20 12:23:50 -06002841 self.assertEqual(expected, data)
2842
2843 # Test that the state looks right. There should be an FDT for the fdtmap
2844 # that we jsut read back in, and it should match what we find in the
2845 # 'control' tables. Checking for an FDT that does not exist should
2846 # return None.
2847 path, fdtmap = state.GetFdtContents('fdtmap')
Simon Glassf8a54bc2019-07-20 12:23:56 -06002848 self.assertIsNotNone(path)
Simon Glass072959a2019-07-20 12:23:50 -06002849 self.assertEqual(expected_fdtmap, fdtmap)
2850
2851 dtb = state.GetFdtForEtype('fdtmap')
2852 self.assertEqual(dtb.GetContents(), fdtmap)
2853
2854 missing_path, missing_fdtmap = state.GetFdtContents('missing')
2855 self.assertIsNone(missing_path)
2856 self.assertIsNone(missing_fdtmap)
2857
2858 missing_dtb = state.GetFdtForEtype('missing')
2859 self.assertIsNone(missing_dtb)
2860
2861 self.assertEqual('/binman', state.fdt_path_prefix)
2862
2863 def testReplaceResizeFail(self):
2864 """Test replacing a file by something larger"""
2865 expected = U_BOOT_DATA + b'x'
2866 with self.assertRaises(ValueError) as e:
Simon Glassf8a54bc2019-07-20 12:23:56 -06002867 self._RunReplaceCmd('u-boot', expected, allow_resize=False,
2868 dts='139_replace_repack.dts')
Simon Glass072959a2019-07-20 12:23:50 -06002869 self.assertIn("Node '/u-boot': Entry data size does not match, but resize is disabled",
2870 str(e.exception))
2871
2872 def testReplaceMulti(self):
2873 """Test replacing entry data where multiple images are generated"""
2874 data = self._DoReadFileDtb('133_replace_multi.dts', use_real_dtb=True,
2875 update_dtb=True)[0]
2876 expected = b'x' * len(U_BOOT_DATA)
2877 updated_fname = tools.GetOutputFilename('image-updated.bin')
2878 tools.WriteFile(updated_fname, data)
2879 entry_name = 'u-boot'
Simon Glassf8a54bc2019-07-20 12:23:56 -06002880 control.WriteEntry(updated_fname, entry_name, expected,
2881 allow_resize=False)
Simon Glass072959a2019-07-20 12:23:50 -06002882 data = control.ReadEntry(updated_fname, entry_name)
2883 self.assertEqual(expected, data)
2884
2885 # Check the state looks right.
2886 self.assertEqual('/binman/image', state.fdt_path_prefix)
2887
2888 # Now check we can write the first image
2889 image_fname = tools.GetOutputFilename('first-image.bin')
2890 updated_fname = tools.GetOutputFilename('first-updated.bin')
2891 tools.WriteFile(updated_fname, tools.ReadFile(image_fname))
2892 entry_name = 'u-boot'
Simon Glassf8a54bc2019-07-20 12:23:56 -06002893 control.WriteEntry(updated_fname, entry_name, expected,
2894 allow_resize=False)
Simon Glass072959a2019-07-20 12:23:50 -06002895 data = control.ReadEntry(updated_fname, entry_name)
2896 self.assertEqual(expected, data)
2897
2898 # Check the state looks right.
2899 self.assertEqual('/binman/first-image', state.fdt_path_prefix)
Simon Glass39dd2152019-07-08 14:25:47 -06002900
Simon Glassfb30e292019-07-20 12:23:51 -06002901 def testUpdateFdtAllRepack(self):
2902 """Test that all device trees are updated with offset/size info"""
2903 data = self._DoReadFileRealDtb('134_fdt_update_all_repack.dts')
2904 SECTION_SIZE = 0x300
2905 DTB_SIZE = 602
2906 FDTMAP_SIZE = 608
2907 base_expected = {
2908 'offset': 0,
2909 'size': SECTION_SIZE + DTB_SIZE * 2 + FDTMAP_SIZE,
2910 'image-pos': 0,
2911 'section:offset': 0,
2912 'section:size': SECTION_SIZE,
2913 'section:image-pos': 0,
2914 'section/u-boot-dtb:offset': 4,
2915 'section/u-boot-dtb:size': 636,
2916 'section/u-boot-dtb:image-pos': 4,
2917 'u-boot-spl-dtb:offset': SECTION_SIZE,
2918 'u-boot-spl-dtb:size': DTB_SIZE,
2919 'u-boot-spl-dtb:image-pos': SECTION_SIZE,
2920 'u-boot-tpl-dtb:offset': SECTION_SIZE + DTB_SIZE,
2921 'u-boot-tpl-dtb:image-pos': SECTION_SIZE + DTB_SIZE,
2922 'u-boot-tpl-dtb:size': DTB_SIZE,
2923 'fdtmap:offset': SECTION_SIZE + DTB_SIZE * 2,
2924 'fdtmap:size': FDTMAP_SIZE,
2925 'fdtmap:image-pos': SECTION_SIZE + DTB_SIZE * 2,
2926 }
2927 main_expected = {
2928 'section:orig-size': SECTION_SIZE,
2929 'section/u-boot-dtb:orig-offset': 4,
2930 }
2931
2932 # We expect three device-tree files in the output, with the first one
2933 # within a fixed-size section.
2934 # Read them in sequence. We look for an 'spl' property in the SPL tree,
2935 # and 'tpl' in the TPL tree, to make sure they are distinct from the
2936 # main U-Boot tree. All three should have the same positions and offset
2937 # except that the main tree should include the main_expected properties
2938 start = 4
2939 for item in ['', 'spl', 'tpl', None]:
2940 if item is None:
2941 start += 16 # Move past fdtmap header
2942 dtb = fdt.Fdt.FromData(data[start:])
2943 dtb.Scan()
2944 props = self._GetPropTree(dtb,
2945 BASE_DTB_PROPS + REPACK_DTB_PROPS + ['spl', 'tpl'],
2946 prefix='/' if item is None else '/binman/')
2947 expected = dict(base_expected)
2948 if item:
2949 expected[item] = 0
2950 else:
2951 # Main DTB and fdtdec should include the 'orig-' properties
2952 expected.update(main_expected)
2953 # Helpful for debugging:
2954 #for prop in sorted(props):
2955 #print('prop %s %s %s' % (prop, props[prop], expected[prop]))
2956 self.assertEqual(expected, props)
2957 if item == '':
2958 start = SECTION_SIZE
2959 else:
2960 start += dtb._fdt_obj.totalsize()
2961
Simon Glass11453762019-07-20 12:23:55 -06002962 def testFdtmapHeaderMiddle(self):
2963 """Test an FDT map in the middle of an image when it should be at end"""
2964 with self.assertRaises(ValueError) as e:
2965 self._DoReadFileRealDtb('135_fdtmap_hdr_middle.dts')
2966 self.assertIn("Invalid sibling order 'middle' for image-header: Must be at 'end' to match location",
2967 str(e.exception))
2968
2969 def testFdtmapHeaderStartBad(self):
2970 """Test an FDT map in middle of an image when it should be at start"""
2971 with self.assertRaises(ValueError) as e:
2972 self._DoReadFileRealDtb('136_fdtmap_hdr_startbad.dts')
2973 self.assertIn("Invalid sibling order 'end' for image-header: Must be at 'start' to match location",
2974 str(e.exception))
2975
2976 def testFdtmapHeaderEndBad(self):
2977 """Test an FDT map at the start of an image when it should be at end"""
2978 with self.assertRaises(ValueError) as e:
2979 self._DoReadFileRealDtb('137_fdtmap_hdr_endbad.dts')
2980 self.assertIn("Invalid sibling order 'start' for image-header: Must be at 'end' to match location",
2981 str(e.exception))
2982
2983 def testFdtmapHeaderNoSize(self):
2984 """Test an image header at the end of an image with undefined size"""
2985 self._DoReadFileRealDtb('138_fdtmap_hdr_nosize.dts')
2986
Simon Glassf8a54bc2019-07-20 12:23:56 -06002987 def testReplaceResize(self):
2988 """Test replacing a single file in an entry with a larger file"""
2989 expected = U_BOOT_DATA + b'x'
2990 data, _, image = self._RunReplaceCmd('u-boot', expected,
2991 dts='139_replace_repack.dts')
2992 self.assertEqual(expected, data)
2993
2994 entries = image.GetEntries()
2995 dtb_data = entries['u-boot-dtb'].data
2996 dtb = fdt.Fdt.FromData(dtb_data)
2997 dtb.Scan()
2998
2999 # The u-boot section should now be larger in the dtb
3000 node = dtb.GetNode('/binman/u-boot')
3001 self.assertEqual(len(expected), fdt_util.GetInt(node, 'size'))
3002
3003 # Same for the fdtmap
3004 fdata = entries['fdtmap'].data
3005 fdtb = fdt.Fdt.FromData(fdata[fdtmap.FDTMAP_HDR_LEN:])
3006 fdtb.Scan()
3007 fnode = fdtb.GetNode('/u-boot')
3008 self.assertEqual(len(expected), fdt_util.GetInt(fnode, 'size'))
3009
3010 def testReplaceResizeNoRepack(self):
3011 """Test replacing an entry with a larger file when not allowed"""
3012 expected = U_BOOT_DATA + b'x'
3013 with self.assertRaises(ValueError) as e:
3014 self._RunReplaceCmd('u-boot', expected)
3015 self.assertIn('Entry data size does not match, but allow-repack is not present for this image',
3016 str(e.exception))
3017
Simon Glass9d8ee322019-07-20 12:23:58 -06003018 def testEntryShrink(self):
3019 """Test contracting an entry after it is packed"""
3020 try:
3021 state.SetAllowEntryContraction(True)
3022 data = self._DoReadFileDtb('140_entry_shrink.dts',
3023 update_dtb=True)[0]
3024 finally:
3025 state.SetAllowEntryContraction(False)
3026 self.assertEqual(b'a', data[:1])
3027 self.assertEqual(U_BOOT_DATA, data[1:1 + len(U_BOOT_DATA)])
3028 self.assertEqual(b'a', data[-1:])
3029
3030 def testEntryShrinkFail(self):
3031 """Test not being allowed to contract an entry after it is packed"""
3032 data = self._DoReadFileDtb('140_entry_shrink.dts', update_dtb=True)[0]
3033
3034 # In this case there is a spare byte at the end of the data. The size of
3035 # the contents is only 1 byte but we still have the size before it
3036 # shrunk.
3037 self.assertEqual(b'a\0', data[:2])
3038 self.assertEqual(U_BOOT_DATA, data[2:2 + len(U_BOOT_DATA)])
3039 self.assertEqual(b'a\0', data[-2:])
3040
Simon Glass70e32982019-07-20 12:24:01 -06003041 def testDescriptorOffset(self):
3042 """Test that the Intel descriptor is always placed at at the start"""
3043 data = self._DoReadFileDtb('141_descriptor_offset.dts')
3044 image = control.images['image']
3045 entries = image.GetEntries()
3046 desc = entries['intel-descriptor']
3047 self.assertEqual(0xff800000, desc.offset);
3048 self.assertEqual(0xff800000, desc.image_pos);
3049
Simon Glass37fdd142019-07-20 12:24:06 -06003050 def testReplaceCbfs(self):
3051 """Test replacing a single file in CBFS without changing the size"""
3052 self._CheckLz4()
3053 expected = b'x' * len(U_BOOT_DATA)
3054 data = self._DoReadFileRealDtb('142_replace_cbfs.dts')
3055 updated_fname = tools.GetOutputFilename('image-updated.bin')
3056 tools.WriteFile(updated_fname, data)
3057 entry_name = 'section/cbfs/u-boot'
3058 control.WriteEntry(updated_fname, entry_name, expected,
3059 allow_resize=True)
3060 data = control.ReadEntry(updated_fname, entry_name)
3061 self.assertEqual(expected, data)
3062
3063 def testReplaceResizeCbfs(self):
3064 """Test replacing a single file in CBFS with one of a different size"""
3065 self._CheckLz4()
3066 expected = U_BOOT_DATA + b'x'
3067 data = self._DoReadFileRealDtb('142_replace_cbfs.dts')
3068 updated_fname = tools.GetOutputFilename('image-updated.bin')
3069 tools.WriteFile(updated_fname, data)
3070 entry_name = 'section/cbfs/u-boot'
3071 control.WriteEntry(updated_fname, entry_name, expected,
3072 allow_resize=True)
3073 data = control.ReadEntry(updated_fname, entry_name)
3074 self.assertEqual(expected, data)
3075
Simon Glass30033c22019-07-20 12:24:15 -06003076 def _SetupForReplace(self):
3077 """Set up some files to use to replace entries
3078
3079 This generates an image, copies it to a new file, extracts all the files
3080 in it and updates some of them
3081
3082 Returns:
3083 List
3084 Image filename
3085 Output directory
3086 Expected values for updated entries, each a string
3087 """
3088 data = self._DoReadFileRealDtb('143_replace_all.dts')
3089
3090 updated_fname = tools.GetOutputFilename('image-updated.bin')
3091 tools.WriteFile(updated_fname, data)
3092
3093 outdir = os.path.join(self._indir, 'extract')
3094 einfos = control.ExtractEntries(updated_fname, None, outdir, [])
3095
3096 expected1 = b'x' + U_BOOT_DATA + b'y'
3097 u_boot_fname1 = os.path.join(outdir, 'u-boot')
3098 tools.WriteFile(u_boot_fname1, expected1)
3099
3100 expected2 = b'a' + U_BOOT_DATA + b'b'
3101 u_boot_fname2 = os.path.join(outdir, 'u-boot2')
3102 tools.WriteFile(u_boot_fname2, expected2)
3103
3104 expected_text = b'not the same text'
3105 text_fname = os.path.join(outdir, 'text')
3106 tools.WriteFile(text_fname, expected_text)
3107
3108 dtb_fname = os.path.join(outdir, 'u-boot-dtb')
3109 dtb = fdt.FdtScan(dtb_fname)
3110 node = dtb.GetNode('/binman/text')
3111 node.AddString('my-property', 'the value')
3112 dtb.Sync(auto_resize=True)
3113 dtb.Flush()
3114
3115 return updated_fname, outdir, expected1, expected2, expected_text
3116
3117 def _CheckReplaceMultiple(self, entry_paths):
3118 """Handle replacing the contents of multiple entries
3119
3120 Args:
3121 entry_paths: List of entry paths to replace
3122
3123 Returns:
3124 List
3125 Dict of entries in the image:
3126 key: Entry name
3127 Value: Entry object
3128 Expected values for updated entries, each a string
3129 """
3130 updated_fname, outdir, expected1, expected2, expected_text = (
3131 self._SetupForReplace())
3132 control.ReplaceEntries(updated_fname, None, outdir, entry_paths)
3133
3134 image = Image.FromFile(updated_fname)
3135 image.LoadData()
3136 return image.GetEntries(), expected1, expected2, expected_text
3137
3138 def testReplaceAll(self):
3139 """Test replacing the contents of all entries"""
3140 entries, expected1, expected2, expected_text = (
3141 self._CheckReplaceMultiple([]))
3142 data = entries['u-boot'].data
3143 self.assertEqual(expected1, data)
3144
3145 data = entries['u-boot2'].data
3146 self.assertEqual(expected2, data)
3147
3148 data = entries['text'].data
3149 self.assertEqual(expected_text, data)
3150
3151 # Check that the device tree is updated
3152 data = entries['u-boot-dtb'].data
3153 dtb = fdt.Fdt.FromData(data)
3154 dtb.Scan()
3155 node = dtb.GetNode('/binman/text')
3156 self.assertEqual('the value', node.props['my-property'].value)
3157
3158 def testReplaceSome(self):
3159 """Test replacing the contents of a few entries"""
3160 entries, expected1, expected2, expected_text = (
3161 self._CheckReplaceMultiple(['u-boot2', 'text']))
3162
3163 # This one should not change
3164 data = entries['u-boot'].data
3165 self.assertEqual(U_BOOT_DATA, data)
3166
3167 data = entries['u-boot2'].data
3168 self.assertEqual(expected2, data)
3169
3170 data = entries['text'].data
3171 self.assertEqual(expected_text, data)
3172
3173 def testReplaceCmd(self):
3174 """Test replacing a file fron an image on the command line"""
3175 self._DoReadFileRealDtb('143_replace_all.dts')
3176
3177 try:
3178 tmpdir, updated_fname = self._SetupImageInTmpdir()
3179
3180 fname = os.path.join(tmpdir, 'update-u-boot.bin')
3181 expected = b'x' * len(U_BOOT_DATA)
3182 tools.WriteFile(fname, expected)
3183
3184 self._DoBinman('replace', '-i', updated_fname, 'u-boot', '-f', fname)
3185 data = tools.ReadFile(updated_fname)
3186 self.assertEqual(expected, data[:len(expected)])
3187 map_fname = os.path.join(tmpdir, 'image-updated.map')
3188 self.assertFalse(os.path.exists(map_fname))
3189 finally:
3190 shutil.rmtree(tmpdir)
3191
3192 def testReplaceCmdSome(self):
3193 """Test replacing some files fron an image on the command line"""
3194 updated_fname, outdir, expected1, expected2, expected_text = (
3195 self._SetupForReplace())
3196
3197 self._DoBinman('replace', '-i', updated_fname, '-I', outdir,
3198 'u-boot2', 'text')
3199
3200 tools.PrepareOutputDir(None)
3201 image = Image.FromFile(updated_fname)
3202 image.LoadData()
3203 entries = image.GetEntries()
3204
3205 # This one should not change
3206 data = entries['u-boot'].data
3207 self.assertEqual(U_BOOT_DATA, data)
3208
3209 data = entries['u-boot2'].data
3210 self.assertEqual(expected2, data)
3211
3212 data = entries['text'].data
3213 self.assertEqual(expected_text, data)
3214
3215 def testReplaceMissing(self):
3216 """Test replacing entries where the file is missing"""
3217 updated_fname, outdir, expected1, expected2, expected_text = (
3218 self._SetupForReplace())
3219
3220 # Remove one of the files, to generate a warning
3221 u_boot_fname1 = os.path.join(outdir, 'u-boot')
3222 os.remove(u_boot_fname1)
3223
3224 with test_util.capture_sys_output() as (stdout, stderr):
3225 control.ReplaceEntries(updated_fname, None, outdir, [])
3226 self.assertIn("Skipping entry '/u-boot' from missing file",
3227 stdout.getvalue())
3228
3229 def testReplaceCmdMap(self):
3230 """Test replacing a file fron an image on the command line"""
3231 self._DoReadFileRealDtb('143_replace_all.dts')
3232
3233 try:
3234 tmpdir, updated_fname = self._SetupImageInTmpdir()
3235
3236 fname = os.path.join(self._indir, 'update-u-boot.bin')
3237 expected = b'x' * len(U_BOOT_DATA)
3238 tools.WriteFile(fname, expected)
3239
3240 self._DoBinman('replace', '-i', updated_fname, 'u-boot',
3241 '-f', fname, '-m')
3242 map_fname = os.path.join(tmpdir, 'image-updated.map')
3243 self.assertTrue(os.path.exists(map_fname))
3244 finally:
3245 shutil.rmtree(tmpdir)
3246
3247 def testReplaceNoEntryPaths(self):
3248 """Test replacing an entry without an entry path"""
3249 self._DoReadFileRealDtb('143_replace_all.dts')
3250 image_fname = tools.GetOutputFilename('image.bin')
3251 with self.assertRaises(ValueError) as e:
3252 control.ReplaceEntries(image_fname, 'fname', None, [])
3253 self.assertIn('Must specify an entry path to read with -f',
3254 str(e.exception))
3255
3256 def testReplaceTooManyEntryPaths(self):
3257 """Test extracting some entries"""
3258 self._DoReadFileRealDtb('143_replace_all.dts')
3259 image_fname = tools.GetOutputFilename('image.bin')
3260 with self.assertRaises(ValueError) as e:
3261 control.ReplaceEntries(image_fname, 'fname', None, ['a', 'b'])
3262 self.assertIn('Must specify exactly one entry path to write with -f',
3263 str(e.exception))
3264
Simon Glass0b074d62019-08-24 07:22:48 -06003265 def testPackReset16(self):
3266 """Test that an image with an x86 reset16 region can be created"""
3267 data = self._DoReadFile('144_x86_reset16.dts')
3268 self.assertEqual(X86_RESET16_DATA, data[:len(X86_RESET16_DATA)])
3269
3270 def testPackReset16Spl(self):
3271 """Test that an image with an x86 reset16-spl region can be created"""
3272 data = self._DoReadFile('145_x86_reset16_spl.dts')
3273 self.assertEqual(X86_RESET16_SPL_DATA, data[:len(X86_RESET16_SPL_DATA)])
3274
3275 def testPackReset16Tpl(self):
3276 """Test that an image with an x86 reset16-tpl region can be created"""
3277 data = self._DoReadFile('146_x86_reset16_tpl.dts')
3278 self.assertEqual(X86_RESET16_TPL_DATA, data[:len(X86_RESET16_TPL_DATA)])
3279
Simon Glass232f90c2019-08-24 07:22:50 -06003280 def testPackIntelFit(self):
3281 """Test that an image with an Intel FIT and pointer can be created"""
3282 data = self._DoReadFile('147_intel_fit.dts')
3283 self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
3284 fit = data[16:32];
3285 self.assertEqual(b'_FIT_ \x01\x00\x00\x00\x00\x01\x80}' , fit)
3286 ptr = struct.unpack('<i', data[0x40:0x44])[0]
3287
3288 image = control.images['image']
3289 entries = image.GetEntries()
3290 expected_ptr = entries['intel-fit'].image_pos - (1 << 32)
3291 self.assertEqual(expected_ptr, ptr)
3292
3293 def testPackIntelFitMissing(self):
3294 """Test detection of a FIT pointer with not FIT region"""
3295 with self.assertRaises(ValueError) as e:
3296 self._DoReadFile('148_intel_fit_missing.dts')
3297 self.assertIn("'intel-fit-ptr' section must have an 'intel-fit' sibling",
3298 str(e.exception))
3299
Simon Glassfb30e292019-07-20 12:23:51 -06003300
Simon Glassac599912017-11-12 21:52:22 -07003301if __name__ == "__main__":
3302 unittest.main()