blob: 8e419645a6d564b13e457fca692916eecedaacf3 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001# SPDX-License-Identifier: GPL-2.0+
Simon Glass4f443042016-11-25 20:15:52 -07002# Copyright (c) 2016 Google, Inc
3# Written by Simon Glass <sjg@chromium.org>
4#
Simon Glass4f443042016-11-25 20:15:52 -07005# To run a single test, change to this directory, and:
6#
7# python -m unittest func_test.TestFunctional.testHelp
8
Simon Glassfdc34362020-07-09 18:39:45 -06009import collections
Simon Glass16287932020-04-17 18:09:03 -060010import gzip
Simon Glasse0e5df92018-09-14 04:57:31 -060011import hashlib
Simon Glass4f443042016-11-25 20:15:52 -070012from optparse import OptionParser
13import os
Simon Glassfdc34362020-07-09 18:39:45 -060014import re
Simon Glass4f443042016-11-25 20:15:52 -070015import shutil
16import struct
17import sys
18import tempfile
19import unittest
Simon Glass56ee85e2022-01-09 20:13:57 -070020import unittest.mock
21import urllib.error
Simon Glass4f443042016-11-25 20:15:52 -070022
Simon Glass386c63c2022-01-09 20:13:50 -070023from binman import bintool
Simon Glass16287932020-04-17 18:09:03 -060024from binman import cbfs_util
25from binman import cmdline
26from binman import control
27from binman import elf
28from binman import elf_test
Simon Glass75989722021-11-23 21:08:59 -070029from binman import fip_util
Simon Glass16287932020-04-17 18:09:03 -060030from binman import fmap_util
Simon Glass16287932020-04-17 18:09:03 -060031from binman import state
32from dtoc import fdt
33from dtoc import fdt_util
34from binman.etype import fdtmap
35from binman.etype import image_header
Simon Glass07237982020-08-05 13:27:47 -060036from binman.image import Image
Simon Glass4583c002023-02-23 18:18:04 -070037from u_boot_pylib import command
38from u_boot_pylib import test_util
39from u_boot_pylib import tools
40from u_boot_pylib import tout
Simon Glass4f443042016-11-25 20:15:52 -070041
42# Contents of test files, corresponding to different entry types
Simon Glassc6c10e72019-05-17 22:00:46 -060043U_BOOT_DATA = b'1234'
44U_BOOT_IMG_DATA = b'img'
Alper Nebi Yasak367ecbf2022-06-18 15:13:11 +030045U_BOOT_SPL_DATA = b'56780123456789abcdefghijklm'
46U_BOOT_TPL_DATA = b'tpl9876543210fedcbazywvuts'
Simon Glass6ad24522022-02-28 07:16:54 -070047U_BOOT_VPL_DATA = b'vpl76543210fedcbazywxyz_'
Simon Glassc6c10e72019-05-17 22:00:46 -060048BLOB_DATA = b'89'
49ME_DATA = b'0abcd'
50VGA_DATA = b'vga'
Sughosh Ganub6176112023-08-22 23:09:59 +053051EFI_CAPSULE_DATA = b'efi'
Simon Glassc6c10e72019-05-17 22:00:46 -060052U_BOOT_DTB_DATA = b'udtb'
53U_BOOT_SPL_DTB_DATA = b'spldtb'
54U_BOOT_TPL_DTB_DATA = b'tpldtb'
Simon Glass6ad24522022-02-28 07:16:54 -070055U_BOOT_VPL_DTB_DATA = b'vpldtb'
Simon Glassc6c10e72019-05-17 22:00:46 -060056X86_START16_DATA = b'start16'
57X86_START16_SPL_DATA = b'start16spl'
58X86_START16_TPL_DATA = b'start16tpl'
Simon Glass2250ee62019-08-24 07:22:48 -060059X86_RESET16_DATA = b'reset16'
60X86_RESET16_SPL_DATA = b'reset16spl'
61X86_RESET16_TPL_DATA = b'reset16tpl'
Simon Glassc6c10e72019-05-17 22:00:46 -060062PPC_MPC85XX_BR_DATA = b'ppcmpc85xxbr'
63U_BOOT_NODTB_DATA = b'nodtb with microcode pointer somewhere in here'
64U_BOOT_SPL_NODTB_DATA = b'splnodtb with microcode pointer somewhere in here'
65U_BOOT_TPL_NODTB_DATA = b'tplnodtb with microcode pointer somewhere in here'
Simon Glass6ad24522022-02-28 07:16:54 -070066U_BOOT_VPL_NODTB_DATA = b'vplnodtb'
Alper Nebi Yasak21353312022-02-08 01:08:04 +030067U_BOOT_EXP_DATA = U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA
68U_BOOT_SPL_EXP_DATA = U_BOOT_SPL_NODTB_DATA + U_BOOT_SPL_DTB_DATA
69U_BOOT_TPL_EXP_DATA = U_BOOT_TPL_NODTB_DATA + U_BOOT_TPL_DTB_DATA
Simon Glassc6c10e72019-05-17 22:00:46 -060070FSP_DATA = b'fsp'
71CMC_DATA = b'cmc'
72VBT_DATA = b'vbt'
73MRC_DATA = b'mrc'
Simon Glassbb748372018-07-17 13:25:33 -060074TEXT_DATA = 'text'
75TEXT_DATA2 = 'text2'
76TEXT_DATA3 = 'text3'
Simon Glassc6c10e72019-05-17 22:00:46 -060077CROS_EC_RW_DATA = b'ecrw'
78GBB_DATA = b'gbbd'
79BMPBLK_DATA = b'bmp'
80VBLOCK_DATA = b'vblk'
81FILES_DATA = (b"sorry I'm late\nOh, don't bother apologising, I'm " +
82 b"sorry you're alive\n")
Simon Glassff5c7e32019-07-08 13:18:42 -060083COMPRESS_DATA = b'compress xxxxxxxxxxxxxxxxxxxxxx data'
Simon Glass8f5ef892020-10-26 17:40:25 -060084COMPRESS_DATA_BIG = COMPRESS_DATA * 2
Simon Glassc6c10e72019-05-17 22:00:46 -060085REFCODE_DATA = b'refcode'
Simon Glassea0fff92019-08-24 07:23:07 -060086FSP_M_DATA = b'fsp_m'
Simon Glassbc6a88f2019-10-20 21:31:35 -060087FSP_S_DATA = b'fsp_s'
Simon Glass998d1482019-10-20 21:31:36 -060088FSP_T_DATA = b'fsp_t'
Simon Glassdc2f81a2020-09-01 05:13:58 -060089ATF_BL31_DATA = b'bl31'
Roger Quadros47f420a2022-02-19 20:50:04 +020090TEE_OS_DATA = b'this is some tee OS data'
Simon Glass75989722021-11-23 21:08:59 -070091ATF_BL2U_DATA = b'bl2u'
Bin Meng4c4d6072021-05-10 20:23:33 +080092OPENSBI_DATA = b'opensbi'
Samuel Holland18bd4552020-10-21 21:12:15 -050093SCP_DATA = b'scp'
Jonas Karlman05b978b2023-02-25 19:01:33 +000094ROCKCHIP_TPL_DATA = b'rockchip-tpl'
Simon Glass6cf99532020-09-01 05:13:59 -060095TEST_FDT1_DATA = b'fdt1'
96TEST_FDT2_DATA = b'test-fdt2'
Simon Glassfb91d562020-09-06 10:35:33 -060097ENV_DATA = b'var1=1\nvar2="2"'
Christian Taedcke289e6002023-07-17 09:05:54 +020098ENCRYPTED_IV_DATA = b'123456'
99ENCRYPTED_KEY_DATA = b'abcde'
Philippe Reynesb1c50932022-03-28 22:57:04 +0200100PRE_LOAD_MAGIC = b'UBSH'
101PRE_LOAD_VERSION = 0x11223344.to_bytes(4, 'big')
102PRE_LOAD_HDR_SIZE = 0x00001000.to_bytes(4, 'big')
Neha Malcom Francis6c66ccf2023-07-22 00:14:24 +0530103TI_BOARD_CONFIG_DATA = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Neha Malcom Francis78144822023-07-22 00:14:25 +0530104TI_UNSECURE_DATA = b'unsecuredata'
Simon Glass6cf99532020-09-01 05:13:59 -0600105
106# Subdirectory of the input dir to use to put test FDTs
107TEST_FDT_SUBDIR = 'fdts'
Simon Glassec127af2018-07-17 13:25:39 -0600108
Simon Glass6ccbfcd2019-07-20 12:23:47 -0600109# The expected size for the device tree in some tests
Simon Glassf667e452019-07-08 14:25:50 -0600110EXTRACT_DTB_SIZE = 0x3c9
111
Simon Glass6ccbfcd2019-07-20 12:23:47 -0600112# Properties expected to be in the device tree when update_dtb is used
113BASE_DTB_PROPS = ['offset', 'size', 'image-pos']
114
Simon Glass12bb1a92019-07-20 12:23:51 -0600115# Extra properties expected to be in the device tree when allow-repack is used
116REPACK_DTB_PROPS = ['orig-offset', 'orig-size']
117
Stefan Herbrechtsmeiercbe2e752022-08-19 16:25:28 +0200118# Supported compression bintools
Stefan Herbrechtsmeiercd15b642022-08-19 16:25:38 +0200119COMP_BINTOOLS = ['bzip2', 'gzip', 'lz4', 'lzma_alone', 'lzop', 'xz', 'zstd']
Simon Glass4f443042016-11-25 20:15:52 -0700120
Simon Glass2f80c5e2023-01-07 14:07:14 -0700121TEE_ADDR = 0x5678
122
Sughosh Ganub6176112023-08-22 23:09:59 +0530123# Firmware Management Protocol(FMP) GUID
124FW_MGMT_GUID = 'edd5cb6d2de8444cbda17194199ad92a'
125# Image GUID specified in the DTS
126CAPSULE_IMAGE_GUID = '52cfd7092007104791d108469b7fe9c8'
127
Simon Glass4f443042016-11-25 20:15:52 -0700128class TestFunctional(unittest.TestCase):
129 """Functional tests for binman
130
131 Most of these use a sample .dts file to build an image and then check
132 that it looks correct. The sample files are in the test/ subdirectory
133 and are numbered.
134
135 For each entry type a very small test file is created using fixed
136 string contents. This makes it easy to test that things look right, and
137 debug problems.
138
139 In some cases a 'real' file must be used - these are also supplied in
140 the test/ diurectory.
141 """
142 @classmethod
Simon Glassb986b3b2019-08-24 07:22:43 -0600143 def setUpClass(cls):
Simon Glass4d5994f2017-11-12 21:52:20 -0700144 global entry
Simon Glass16287932020-04-17 18:09:03 -0600145 from binman import entry
Simon Glass4d5994f2017-11-12 21:52:20 -0700146
Simon Glass4f443042016-11-25 20:15:52 -0700147 # Handle the case where argv[0] is 'python'
Simon Glassb986b3b2019-08-24 07:22:43 -0600148 cls._binman_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
149 cls._binman_pathname = os.path.join(cls._binman_dir, 'binman')
Simon Glass4f443042016-11-25 20:15:52 -0700150
151 # Create a temporary directory for input files
Simon Glassb986b3b2019-08-24 07:22:43 -0600152 cls._indir = tempfile.mkdtemp(prefix='binmant.')
Simon Glass4f443042016-11-25 20:15:52 -0700153
154 # Create some test files
155 TestFunctional._MakeInputFile('u-boot.bin', U_BOOT_DATA)
156 TestFunctional._MakeInputFile('u-boot.img', U_BOOT_IMG_DATA)
157 TestFunctional._MakeInputFile('spl/u-boot-spl.bin', U_BOOT_SPL_DATA)
Simon Glassb8ef5b62018-07-17 13:25:48 -0600158 TestFunctional._MakeInputFile('tpl/u-boot-tpl.bin', U_BOOT_TPL_DATA)
Simon Glass6ad24522022-02-28 07:16:54 -0700159 TestFunctional._MakeInputFile('vpl/u-boot-vpl.bin', U_BOOT_VPL_DATA)
Simon Glass4f443042016-11-25 20:15:52 -0700160 TestFunctional._MakeInputFile('blobfile', BLOB_DATA)
Simon Glasse0ff8552016-11-25 20:15:53 -0700161 TestFunctional._MakeInputFile('me.bin', ME_DATA)
162 TestFunctional._MakeInputFile('vga.bin', VGA_DATA)
Simon Glassb986b3b2019-08-24 07:22:43 -0600163 cls._ResetDtbs()
Simon Glass2250ee62019-08-24 07:22:48 -0600164
Jagdish Gediya9d368f32018-09-03 21:35:08 +0530165 TestFunctional._MakeInputFile('u-boot-br.bin', PPC_MPC85XX_BR_DATA)
Simon Glass2250ee62019-08-24 07:22:48 -0600166
Simon Glass5e239182019-08-24 07:22:49 -0600167 TestFunctional._MakeInputFile('u-boot-x86-start16.bin', X86_START16_DATA)
168 TestFunctional._MakeInputFile('spl/u-boot-x86-start16-spl.bin',
Simon Glass87722132017-11-12 21:52:26 -0700169 X86_START16_SPL_DATA)
Simon Glass5e239182019-08-24 07:22:49 -0600170 TestFunctional._MakeInputFile('tpl/u-boot-x86-start16-tpl.bin',
Simon Glass35b384c2018-09-14 04:57:10 -0600171 X86_START16_TPL_DATA)
Simon Glass2250ee62019-08-24 07:22:48 -0600172
173 TestFunctional._MakeInputFile('u-boot-x86-reset16.bin',
174 X86_RESET16_DATA)
175 TestFunctional._MakeInputFile('spl/u-boot-x86-reset16-spl.bin',
176 X86_RESET16_SPL_DATA)
177 TestFunctional._MakeInputFile('tpl/u-boot-x86-reset16-tpl.bin',
178 X86_RESET16_TPL_DATA)
179
Simon Glass4f443042016-11-25 20:15:52 -0700180 TestFunctional._MakeInputFile('u-boot-nodtb.bin', U_BOOT_NODTB_DATA)
Simon Glass6b187df2017-11-12 21:52:27 -0700181 TestFunctional._MakeInputFile('spl/u-boot-spl-nodtb.bin',
182 U_BOOT_SPL_NODTB_DATA)
Simon Glassf0253632018-09-14 04:57:32 -0600183 TestFunctional._MakeInputFile('tpl/u-boot-tpl-nodtb.bin',
184 U_BOOT_TPL_NODTB_DATA)
Simon Glass6ad24522022-02-28 07:16:54 -0700185 TestFunctional._MakeInputFile('vpl/u-boot-vpl-nodtb.bin',
186 U_BOOT_VPL_NODTB_DATA)
Simon Glassda229092016-11-25 20:15:56 -0700187 TestFunctional._MakeInputFile('fsp.bin', FSP_DATA)
188 TestFunctional._MakeInputFile('cmc.bin', CMC_DATA)
Bin Meng59ea8c22017-08-15 22:41:54 -0700189 TestFunctional._MakeInputFile('vbt.bin', VBT_DATA)
Simon Glassca4f4ff2017-11-12 21:52:28 -0700190 TestFunctional._MakeInputFile('mrc.bin', MRC_DATA)
Simon Glassec127af2018-07-17 13:25:39 -0600191 TestFunctional._MakeInputFile('ecrw.bin', CROS_EC_RW_DATA)
Simon Glass0ef87aa2018-07-17 13:25:44 -0600192 TestFunctional._MakeInputDir('devkeys')
193 TestFunctional._MakeInputFile('bmpblk.bin', BMPBLK_DATA)
Simon Glass3ae192c2018-10-01 12:22:31 -0600194 TestFunctional._MakeInputFile('refcode.bin', REFCODE_DATA)
Simon Glassea0fff92019-08-24 07:23:07 -0600195 TestFunctional._MakeInputFile('fsp_m.bin', FSP_M_DATA)
Simon Glassbc6a88f2019-10-20 21:31:35 -0600196 TestFunctional._MakeInputFile('fsp_s.bin', FSP_S_DATA)
Simon Glass998d1482019-10-20 21:31:36 -0600197 TestFunctional._MakeInputFile('fsp_t.bin', FSP_T_DATA)
Simon Glass4f443042016-11-25 20:15:52 -0700198
Simon Glass53e22bf2019-08-24 07:22:53 -0600199 cls._elf_testdir = os.path.join(cls._indir, 'elftest')
200 elf_test.BuildElfTestFiles(cls._elf_testdir)
201
Simon Glasse0ff8552016-11-25 20:15:53 -0700202 # ELF file with a '_dt_ucode_base_size' symbol
Simon Glassf514d8f2019-08-24 07:22:54 -0600203 TestFunctional._MakeInputFile('u-boot',
Simon Glassc1aa66e2022-01-29 14:14:04 -0700204 tools.read_file(cls.ElfTestFile('u_boot_ucode_ptr')))
Simon Glasse0ff8552016-11-25 20:15:53 -0700205
206 # Intel flash descriptor file
Simon Glass0ba4b3d2020-07-09 18:39:41 -0600207 cls._SetupDescriptor()
Simon Glasse0ff8552016-11-25 20:15:53 -0700208
Simon Glassb986b3b2019-08-24 07:22:43 -0600209 shutil.copytree(cls.TestFile('files'),
210 os.path.join(cls._indir, 'files'))
Simon Glass0a98b282018-09-14 04:57:28 -0600211
Neha Malcom Francis6c66ccf2023-07-22 00:14:24 +0530212 shutil.copytree(cls.TestFile('yaml'),
213 os.path.join(cls._indir, 'yaml'))
214
Simon Glass83d73c22018-09-14 04:57:26 -0600215 TestFunctional._MakeInputFile('compress', COMPRESS_DATA)
Simon Glass8f5ef892020-10-26 17:40:25 -0600216 TestFunctional._MakeInputFile('compress_big', COMPRESS_DATA_BIG)
Simon Glassdc2f81a2020-09-01 05:13:58 -0600217 TestFunctional._MakeInputFile('bl31.bin', ATF_BL31_DATA)
Roger Quadros47f420a2022-02-19 20:50:04 +0200218 TestFunctional._MakeInputFile('tee-pager.bin', TEE_OS_DATA)
Simon Glass75989722021-11-23 21:08:59 -0700219 TestFunctional._MakeInputFile('bl2u.bin', ATF_BL2U_DATA)
Bin Meng4c4d6072021-05-10 20:23:33 +0800220 TestFunctional._MakeInputFile('fw_dynamic.bin', OPENSBI_DATA)
Samuel Holland18bd4552020-10-21 21:12:15 -0500221 TestFunctional._MakeInputFile('scp.bin', SCP_DATA)
Jonas Karlman05b978b2023-02-25 19:01:33 +0000222 TestFunctional._MakeInputFile('rockchip-tpl.bin', ROCKCHIP_TPL_DATA)
Neha Malcom Francis78144822023-07-22 00:14:25 +0530223 TestFunctional._MakeInputFile('ti_unsecure.bin', TI_UNSECURE_DATA)
Sughosh Ganub6176112023-08-22 23:09:59 +0530224 TestFunctional._MakeInputFile('capsule_input.bin', EFI_CAPSULE_DATA)
Simon Glass83d73c22018-09-14 04:57:26 -0600225
Simon Glass6cf99532020-09-01 05:13:59 -0600226 # Add a few .dtb files for testing
227 TestFunctional._MakeInputFile('%s/test-fdt1.dtb' % TEST_FDT_SUBDIR,
228 TEST_FDT1_DATA)
229 TestFunctional._MakeInputFile('%s/test-fdt2.dtb' % TEST_FDT_SUBDIR,
230 TEST_FDT2_DATA)
231
Simon Glassfb91d562020-09-06 10:35:33 -0600232 TestFunctional._MakeInputFile('env.txt', ENV_DATA)
233
Simon Glass40c8bdd2022-03-05 20:19:12 -0700234 # ELF file with two sections in different parts of memory, used for both
235 # ATF and OP_TEE
236 TestFunctional._MakeInputFile('bl31.elf',
237 tools.read_file(cls.ElfTestFile('elf_sections')))
238 TestFunctional._MakeInputFile('tee.elf',
239 tools.read_file(cls.ElfTestFile('elf_sections')))
240
Simon Glass2f80c5e2023-01-07 14:07:14 -0700241 # Newer OP_TEE file in v1 binary format
242 cls.make_tee_bin('tee.bin')
243
Christian Taedcke289e6002023-07-17 09:05:54 +0200244 # test files for encrypted tests
245 TestFunctional._MakeInputFile('encrypted-file.iv', ENCRYPTED_IV_DATA)
246 TestFunctional._MakeInputFile('encrypted-file.key', ENCRYPTED_KEY_DATA)
247
Stefan Herbrechtsmeiercbe2e752022-08-19 16:25:28 +0200248 cls.comp_bintools = {}
249 for name in COMP_BINTOOLS:
250 cls.comp_bintools[name] = bintool.Bintool.create(name)
Simon Glassac62fba2019-07-08 13:18:53 -0600251
Simon Glass4f443042016-11-25 20:15:52 -0700252 @classmethod
Simon Glassb986b3b2019-08-24 07:22:43 -0600253 def tearDownClass(cls):
Simon Glass4f443042016-11-25 20:15:52 -0700254 """Remove the temporary input directory and its contents"""
Simon Glassb986b3b2019-08-24 07:22:43 -0600255 if cls.preserve_indir:
256 print('Preserving input dir: %s' % cls._indir)
Simon Glassd5164a72019-07-08 13:18:49 -0600257 else:
Simon Glassb986b3b2019-08-24 07:22:43 -0600258 if cls._indir:
259 shutil.rmtree(cls._indir)
260 cls._indir = None
Simon Glass4f443042016-11-25 20:15:52 -0700261
Simon Glassd5164a72019-07-08 13:18:49 -0600262 @classmethod
Simon Glass8acce602019-07-08 13:18:50 -0600263 def setup_test_args(cls, preserve_indir=False, preserve_outdirs=False,
Simon Glass53cd5d92019-07-08 14:25:29 -0600264 toolpath=None, verbosity=None):
Simon Glassd5164a72019-07-08 13:18:49 -0600265 """Accept arguments controlling test execution
266
267 Args:
268 preserve_indir: Preserve the shared input directory used by all
269 tests in this class.
270 preserve_outdir: Preserve the output directories used by tests. Each
271 test has its own, so this is normally only useful when running a
272 single test.
Simon Glass8acce602019-07-08 13:18:50 -0600273 toolpath: ist of paths to use for tools
Simon Glassd5164a72019-07-08 13:18:49 -0600274 """
275 cls.preserve_indir = preserve_indir
276 cls.preserve_outdirs = preserve_outdirs
Simon Glass8acce602019-07-08 13:18:50 -0600277 cls.toolpath = toolpath
Simon Glass53cd5d92019-07-08 14:25:29 -0600278 cls.verbosity = verbosity
Simon Glassd5164a72019-07-08 13:18:49 -0600279
Stefan Herbrechtsmeiercbe2e752022-08-19 16:25:28 +0200280 def _CheckBintool(self, bintool):
281 if not bintool.is_present():
282 self.skipTest('%s not available' % bintool.name)
283
Simon Glassac62fba2019-07-08 13:18:53 -0600284 def _CheckLz4(self):
Stefan Herbrechtsmeiercbe2e752022-08-19 16:25:28 +0200285 bintool = self.comp_bintools['lz4']
286 self._CheckBintool(bintool)
Simon Glassac62fba2019-07-08 13:18:53 -0600287
Simon Glassbf574f12019-07-20 12:24:09 -0600288 def _CleanupOutputDir(self):
289 """Remove the temporary output directory"""
290 if self.preserve_outdirs:
291 print('Preserving output dir: %s' % tools.outdir)
292 else:
Simon Glassc1aa66e2022-01-29 14:14:04 -0700293 tools._finalise_for_test()
Simon Glassbf574f12019-07-20 12:24:09 -0600294
Simon Glass4f443042016-11-25 20:15:52 -0700295 def setUp(self):
296 # Enable this to turn on debugging output
Simon Glassf3385a52022-01-29 14:14:15 -0700297 # tout.init(tout.DEBUG)
Simon Glass4f443042016-11-25 20:15:52 -0700298 command.test_result = None
299
300 def tearDown(self):
301 """Remove the temporary output directory"""
Simon Glassbf574f12019-07-20 12:24:09 -0600302 self._CleanupOutputDir()
Simon Glass4f443042016-11-25 20:15:52 -0700303
Simon Glassf86a7362019-07-20 12:24:10 -0600304 def _SetupImageInTmpdir(self):
305 """Set up the output image in a new temporary directory
306
307 This is used when an image has been generated in the output directory,
308 but we want to run binman again. This will create a new output
309 directory and fail to delete the original one.
310
311 This creates a new temporary directory, copies the image to it (with a
312 new name) and removes the old output directory.
313
314 Returns:
315 Tuple:
316 Temporary directory to use
317 New image filename
318 """
Simon Glassc1aa66e2022-01-29 14:14:04 -0700319 image_fname = tools.get_output_filename('image.bin')
Simon Glassf86a7362019-07-20 12:24:10 -0600320 tmpdir = tempfile.mkdtemp(prefix='binman.')
321 updated_fname = os.path.join(tmpdir, 'image-updated.bin')
Simon Glassc1aa66e2022-01-29 14:14:04 -0700322 tools.write_file(updated_fname, tools.read_file(image_fname))
Simon Glassf86a7362019-07-20 12:24:10 -0600323 self._CleanupOutputDir()
324 return tmpdir, updated_fname
325
Simon Glassb8ef5b62018-07-17 13:25:48 -0600326 @classmethod
Simon Glassb986b3b2019-08-24 07:22:43 -0600327 def _ResetDtbs(cls):
Simon Glassb8ef5b62018-07-17 13:25:48 -0600328 TestFunctional._MakeInputFile('u-boot.dtb', U_BOOT_DTB_DATA)
329 TestFunctional._MakeInputFile('spl/u-boot-spl.dtb', U_BOOT_SPL_DTB_DATA)
330 TestFunctional._MakeInputFile('tpl/u-boot-tpl.dtb', U_BOOT_TPL_DTB_DATA)
Simon Glass6ad24522022-02-28 07:16:54 -0700331 TestFunctional._MakeInputFile('vpl/u-boot-vpl.dtb', U_BOOT_VPL_DTB_DATA)
Simon Glassb8ef5b62018-07-17 13:25:48 -0600332
Simon Glass4f443042016-11-25 20:15:52 -0700333 def _RunBinman(self, *args, **kwargs):
334 """Run binman using the command line
335
336 Args:
337 Arguments to pass, as a list of strings
338 kwargs: Arguments to pass to Command.RunPipe()
339 """
Simon Glassd9800692022-01-29 14:14:05 -0700340 result = command.run_pipe([[self._binman_pathname] + list(args)],
Simon Glass4f443042016-11-25 20:15:52 -0700341 capture=True, capture_stderr=True, raise_on_error=False)
342 if result.return_code and kwargs.get('raise_on_error', True):
343 raise Exception("Error running '%s': %s" % (' '.join(args),
344 result.stdout + result.stderr))
345 return result
346
Simon Glass53cd5d92019-07-08 14:25:29 -0600347 def _DoBinman(self, *argv):
Simon Glass4f443042016-11-25 20:15:52 -0700348 """Run binman using directly (in the same process)
349
350 Args:
351 Arguments to pass, as a list of strings
352 Returns:
353 Return value (0 for success)
354 """
Simon Glass53cd5d92019-07-08 14:25:29 -0600355 argv = list(argv)
356 args = cmdline.ParseArgs(argv)
357 args.pager = 'binman-invalid-pager'
358 args.build_dir = self._indir
Simon Glass4f443042016-11-25 20:15:52 -0700359
360 # For testing, you can force an increase in verbosity here
Simon Glass53cd5d92019-07-08 14:25:29 -0600361 # args.verbosity = tout.DEBUG
362 return control.Binman(args)
Simon Glass4f443042016-11-25 20:15:52 -0700363
Simon Glass53af22a2018-07-17 13:25:32 -0600364 def _DoTestFile(self, fname, debug=False, map=False, update_dtb=False,
Simon Glasseb833d82019-04-25 21:58:34 -0600365 entry_args=None, images=None, use_real_dtb=False,
Simon Glass63aeaeb2021-03-18 20:25:05 +1300366 use_expanded=False, verbosity=None, allow_missing=False,
Heiko Thierya89c8f22022-01-06 11:49:41 +0100367 allow_fake_blobs=False, extra_indirs=None, threads=None,
Simon Glass4f9ee832022-01-09 20:14:09 -0700368 test_section_timeout=False, update_fdt_in_elf=None,
Andrew Davis15432ea2023-07-22 00:14:44 +0530369 force_missing_bintools='', ignore_missing=False, output_dir=None):
Simon Glass4f443042016-11-25 20:15:52 -0700370 """Run binman with a given test file
371
372 Args:
Simon Glass741f2d62018-10-01 12:22:30 -0600373 fname: Device-tree source filename to use (e.g. 005_simple.dts)
Simon Glass7ae5f312018-06-01 09:38:19 -0600374 debug: True to enable debugging output
Simon Glass3b0c3822018-06-01 09:38:20 -0600375 map: True to output map files for the images
Simon Glass3ab95982018-08-01 15:22:37 -0600376 update_dtb: Update the offset and size of each entry in the device
Simon Glass16b8d6b2018-07-06 10:27:42 -0600377 tree before packing it into the image
Simon Glass0bfa7b02018-09-14 04:57:12 -0600378 entry_args: Dict of entry args to supply to binman
379 key: arg name
380 value: value of that arg
381 images: List of image names to build
Simon Glasse9d336d2020-09-01 05:13:55 -0600382 use_real_dtb: True to use the test file as the contents of
383 the u-boot-dtb entry. Normally this is not needed and the
384 test contents (the U_BOOT_DTB_DATA string) can be used.
385 But in some test we need the real contents.
Simon Glass63aeaeb2021-03-18 20:25:05 +1300386 use_expanded: True to use expanded entries where available, e.g.
387 'u-boot-expanded' instead of 'u-boot'
Simon Glasse9d336d2020-09-01 05:13:55 -0600388 verbosity: Verbosity level to use (0-3, None=don't set it)
389 allow_missing: Set the '--allow-missing' flag so that missing
390 external binaries just produce a warning instead of an error
Heiko Thierya89c8f22022-01-06 11:49:41 +0100391 allow_fake_blobs: Set the '--fake-ext-blobs' flag
Simon Glass6cf99532020-09-01 05:13:59 -0600392 extra_indirs: Extra input directories to add using -I
Simon Glassc69d19c2021-07-06 10:36:37 -0600393 threads: Number of threads to use (None for default, 0 for
394 single-threaded)
Simon Glass7115f002021-11-03 21:09:17 -0600395 test_section_timeout: True to force the first time to timeout, as
396 used in testThreadTimeout()
Simon Glass0427bed2021-11-03 21:09:18 -0600397 update_fdt_in_elf: Value to pass with --update-fdt-in-elf=xxx
Simon Glass4f9ee832022-01-09 20:14:09 -0700398 force_missing_tools (str): comma-separated list of bintools to
399 regard as missing
Andrew Davis15432ea2023-07-22 00:14:44 +0530400 output_dir: Specific output directory to use for image using -O
Simon Glass7115f002021-11-03 21:09:17 -0600401
402 Returns:
403 int return code, 0 on success
Simon Glass4f443042016-11-25 20:15:52 -0700404 """
Simon Glass53cd5d92019-07-08 14:25:29 -0600405 args = []
Simon Glass7fe91732017-11-13 18:55:00 -0700406 if debug:
407 args.append('-D')
Simon Glass53cd5d92019-07-08 14:25:29 -0600408 if verbosity is not None:
409 args.append('-v%d' % verbosity)
410 elif self.verbosity:
411 args.append('-v%d' % self.verbosity)
412 if self.toolpath:
413 for path in self.toolpath:
414 args += ['--toolpath', path]
Simon Glassc69d19c2021-07-06 10:36:37 -0600415 if threads is not None:
416 args.append('-T%d' % threads)
417 if test_section_timeout:
418 args.append('--test-section-timeout')
Simon Glass53cd5d92019-07-08 14:25:29 -0600419 args += ['build', '-p', '-I', self._indir, '-d', self.TestFile(fname)]
Simon Glass3b0c3822018-06-01 09:38:20 -0600420 if map:
421 args.append('-m')
Simon Glass16b8d6b2018-07-06 10:27:42 -0600422 if update_dtb:
Simon Glass2569e102019-07-08 13:18:47 -0600423 args.append('-u')
Simon Glass93d17412018-09-14 04:57:23 -0600424 if not use_real_dtb:
425 args.append('--fake-dtb')
Simon Glass63aeaeb2021-03-18 20:25:05 +1300426 if not use_expanded:
427 args.append('--no-expanded')
Simon Glass53af22a2018-07-17 13:25:32 -0600428 if entry_args:
Simon Glass50979152019-05-14 15:53:41 -0600429 for arg, value in entry_args.items():
Simon Glass53af22a2018-07-17 13:25:32 -0600430 args.append('-a%s=%s' % (arg, value))
Simon Glass4f9f1052020-07-09 18:39:38 -0600431 if allow_missing:
432 args.append('-M')
Simon Glassb38da152022-11-09 19:14:42 -0700433 if ignore_missing:
434 args.append('-W')
Heiko Thierya89c8f22022-01-06 11:49:41 +0100435 if allow_fake_blobs:
436 args.append('--fake-ext-blobs')
Simon Glass4f9ee832022-01-09 20:14:09 -0700437 if force_missing_bintools:
438 args += ['--force-missing-bintools', force_missing_bintools]
Simon Glass0427bed2021-11-03 21:09:18 -0600439 if update_fdt_in_elf:
440 args += ['--update-fdt-in-elf', update_fdt_in_elf]
Simon Glass0bfa7b02018-09-14 04:57:12 -0600441 if images:
442 for image in images:
443 args += ['-i', image]
Simon Glass6cf99532020-09-01 05:13:59 -0600444 if extra_indirs:
445 for indir in extra_indirs:
446 args += ['-I', indir]
Andrew Davis15432ea2023-07-22 00:14:44 +0530447 if output_dir:
448 args += ['-O', output_dir]
Simon Glass7fe91732017-11-13 18:55:00 -0700449 return self._DoBinman(*args)
Simon Glass4f443042016-11-25 20:15:52 -0700450
451 def _SetupDtb(self, fname, outfile='u-boot.dtb'):
Simon Glasse0ff8552016-11-25 20:15:53 -0700452 """Set up a new test device-tree file
453
454 The given file is compiled and set up as the device tree to be used
455 for ths test.
456
457 Args:
458 fname: Filename of .dts file to read
Simon Glass7ae5f312018-06-01 09:38:19 -0600459 outfile: Output filename for compiled device-tree binary
Simon Glasse0ff8552016-11-25 20:15:53 -0700460
461 Returns:
Simon Glass7ae5f312018-06-01 09:38:19 -0600462 Contents of device-tree binary
Simon Glasse0ff8552016-11-25 20:15:53 -0700463 """
Simon Glassa004f292019-07-20 12:23:49 -0600464 tmpdir = tempfile.mkdtemp(prefix='binmant.')
465 dtb = fdt_util.EnsureCompiled(self.TestFile(fname), tmpdir)
Simon Glass1d0ebf72019-05-14 15:53:42 -0600466 with open(dtb, 'rb') as fd:
Simon Glass4f443042016-11-25 20:15:52 -0700467 data = fd.read()
468 TestFunctional._MakeInputFile(outfile, data)
Simon Glassa004f292019-07-20 12:23:49 -0600469 shutil.rmtree(tmpdir)
Simon Glasse0e62752018-10-01 21:12:41 -0600470 return data
Simon Glass4f443042016-11-25 20:15:52 -0700471
Simon Glass6ad24522022-02-28 07:16:54 -0700472 def _GetDtbContentsForSpls(self, dtb_data, name):
473 """Create a version of the main DTB for SPL / TPL / VPL
Simon Glass6ed45ba2018-09-14 04:57:24 -0600474
475 For testing we don't actually have different versions of the DTB. With
476 U-Boot we normally run fdtgrep to remove unwanted nodes, but for tests
477 we don't normally have any unwanted nodes.
478
479 We still want the DTBs for SPL and TPL to be different though, since
480 otherwise it is confusing to know which one we are looking at. So add
481 an 'spl' or 'tpl' property to the top-level node.
Simon Glasse9d336d2020-09-01 05:13:55 -0600482
483 Args:
484 dtb_data: dtb data to modify (this should be a value devicetree)
485 name: Name of a new property to add
486
487 Returns:
488 New dtb data with the property added
Simon Glass6ed45ba2018-09-14 04:57:24 -0600489 """
490 dtb = fdt.Fdt.FromData(dtb_data)
491 dtb.Scan()
492 dtb.GetNode('/binman').AddZeroProp(name)
493 dtb.Sync(auto_resize=True)
494 dtb.Pack()
495 return dtb.GetContents()
496
Simon Glass63aeaeb2021-03-18 20:25:05 +1300497 def _DoReadFileDtb(self, fname, use_real_dtb=False, use_expanded=False,
498 map=False, update_dtb=False, entry_args=None,
Simon Glassc69d19c2021-07-06 10:36:37 -0600499 reset_dtbs=True, extra_indirs=None, threads=None):
Simon Glass4f443042016-11-25 20:15:52 -0700500 """Run binman and return the resulting image
501
502 This runs binman with a given test file and then reads the resulting
503 output file. It is a shortcut function since most tests need to do
504 these steps.
505
506 Raises an assertion failure if binman returns a non-zero exit code.
507
508 Args:
Simon Glass741f2d62018-10-01 12:22:30 -0600509 fname: Device-tree source filename to use (e.g. 005_simple.dts)
Simon Glass4f443042016-11-25 20:15:52 -0700510 use_real_dtb: True to use the test file as the contents of
511 the u-boot-dtb entry. Normally this is not needed and the
512 test contents (the U_BOOT_DTB_DATA string) can be used.
513 But in some test we need the real contents.
Simon Glass63aeaeb2021-03-18 20:25:05 +1300514 use_expanded: True to use expanded entries where available, e.g.
515 'u-boot-expanded' instead of 'u-boot'
Simon Glass3b0c3822018-06-01 09:38:20 -0600516 map: True to output map files for the images
Simon Glass3ab95982018-08-01 15:22:37 -0600517 update_dtb: Update the offset and size of each entry in the device
Simon Glass16b8d6b2018-07-06 10:27:42 -0600518 tree before packing it into the image
Simon Glasse9d336d2020-09-01 05:13:55 -0600519 entry_args: Dict of entry args to supply to binman
520 key: arg name
521 value: value of that arg
522 reset_dtbs: With use_real_dtb the test dtb is overwritten by this
523 function. If reset_dtbs is True, then the original test dtb
524 is written back before this function finishes
Simon Glass6cf99532020-09-01 05:13:59 -0600525 extra_indirs: Extra input directories to add using -I
Simon Glassc69d19c2021-07-06 10:36:37 -0600526 threads: Number of threads to use (None for default, 0 for
527 single-threaded)
Simon Glasse0ff8552016-11-25 20:15:53 -0700528
529 Returns:
530 Tuple:
531 Resulting image contents
532 Device tree contents
Simon Glass3b0c3822018-06-01 09:38:20 -0600533 Map data showing contents of image (or None if none)
Simon Glassea6922e2018-07-17 13:25:27 -0600534 Output device tree binary filename ('u-boot.dtb' path)
Simon Glass4f443042016-11-25 20:15:52 -0700535 """
Simon Glasse0ff8552016-11-25 20:15:53 -0700536 dtb_data = None
Simon Glass4f443042016-11-25 20:15:52 -0700537 # Use the compiled test file as the u-boot-dtb input
538 if use_real_dtb:
Simon Glasse0ff8552016-11-25 20:15:53 -0700539 dtb_data = self._SetupDtb(fname)
Simon Glass6ed45ba2018-09-14 04:57:24 -0600540
541 # For testing purposes, make a copy of the DT for SPL and TPL. Add
542 # a node indicating which it is, so aid verification.
Simon Glass6ad24522022-02-28 07:16:54 -0700543 for name in ['spl', 'tpl', 'vpl']:
Simon Glass6ed45ba2018-09-14 04:57:24 -0600544 dtb_fname = '%s/u-boot-%s.dtb' % (name, name)
545 outfile = os.path.join(self._indir, dtb_fname)
546 TestFunctional._MakeInputFile(dtb_fname,
Simon Glass6ad24522022-02-28 07:16:54 -0700547 self._GetDtbContentsForSpls(dtb_data, name))
Simon Glass4f443042016-11-25 20:15:52 -0700548
549 try:
Simon Glass53af22a2018-07-17 13:25:32 -0600550 retcode = self._DoTestFile(fname, map=map, update_dtb=update_dtb,
Simon Glass6cf99532020-09-01 05:13:59 -0600551 entry_args=entry_args, use_real_dtb=use_real_dtb,
Simon Glassc69d19c2021-07-06 10:36:37 -0600552 use_expanded=use_expanded, extra_indirs=extra_indirs,
553 threads=threads)
Simon Glass4f443042016-11-25 20:15:52 -0700554 self.assertEqual(0, retcode)
Simon Glassc1aa66e2022-01-29 14:14:04 -0700555 out_dtb_fname = tools.get_output_filename('u-boot.dtb.out')
Simon Glass4f443042016-11-25 20:15:52 -0700556
557 # Find the (only) image, read it and return its contents
558 image = control.images['image']
Simon Glassc1aa66e2022-01-29 14:14:04 -0700559 image_fname = tools.get_output_filename('image.bin')
Simon Glass16b8d6b2018-07-06 10:27:42 -0600560 self.assertTrue(os.path.exists(image_fname))
Simon Glass3b0c3822018-06-01 09:38:20 -0600561 if map:
Simon Glassc1aa66e2022-01-29 14:14:04 -0700562 map_fname = tools.get_output_filename('image.map')
Simon Glass3b0c3822018-06-01 09:38:20 -0600563 with open(map_fname) as fd:
564 map_data = fd.read()
565 else:
566 map_data = None
Simon Glass1d0ebf72019-05-14 15:53:42 -0600567 with open(image_fname, 'rb') as fd:
Simon Glass16b8d6b2018-07-06 10:27:42 -0600568 return fd.read(), dtb_data, map_data, out_dtb_fname
Simon Glass4f443042016-11-25 20:15:52 -0700569 finally:
570 # Put the test file back
Simon Glass6ed45ba2018-09-14 04:57:24 -0600571 if reset_dtbs and use_real_dtb:
Simon Glassb8ef5b62018-07-17 13:25:48 -0600572 self._ResetDtbs()
Simon Glass4f443042016-11-25 20:15:52 -0700573
Simon Glass3c081312019-07-08 14:25:26 -0600574 def _DoReadFileRealDtb(self, fname):
575 """Run binman with a real .dtb file and return the resulting data
576
577 Args:
578 fname: DT source filename to use (e.g. 082_fdt_update_all.dts)
579
580 Returns:
581 Resulting image contents
582 """
583 return self._DoReadFileDtb(fname, use_real_dtb=True, update_dtb=True)[0]
584
Simon Glasse0ff8552016-11-25 20:15:53 -0700585 def _DoReadFile(self, fname, use_real_dtb=False):
Simon Glass7ae5f312018-06-01 09:38:19 -0600586 """Helper function which discards the device-tree binary
587
588 Args:
Simon Glass741f2d62018-10-01 12:22:30 -0600589 fname: Device-tree source filename to use (e.g. 005_simple.dts)
Simon Glass7ae5f312018-06-01 09:38:19 -0600590 use_real_dtb: True to use the test file as the contents of
591 the u-boot-dtb entry. Normally this is not needed and the
592 test contents (the U_BOOT_DTB_DATA string) can be used.
593 But in some test we need the real contents.
Simon Glassea6922e2018-07-17 13:25:27 -0600594
595 Returns:
596 Resulting image contents
Simon Glass7ae5f312018-06-01 09:38:19 -0600597 """
Simon Glasse0ff8552016-11-25 20:15:53 -0700598 return self._DoReadFileDtb(fname, use_real_dtb)[0]
599
Simon Glass4f443042016-11-25 20:15:52 -0700600 @classmethod
Simon Glassb986b3b2019-08-24 07:22:43 -0600601 def _MakeInputFile(cls, fname, contents):
Simon Glass4f443042016-11-25 20:15:52 -0700602 """Create a new test input file, creating directories as needed
603
604 Args:
Simon Glass3ab95982018-08-01 15:22:37 -0600605 fname: Filename to create
Simon Glass4f443042016-11-25 20:15:52 -0700606 contents: File contents to write in to the file
607 Returns:
608 Full pathname of file created
609 """
Simon Glassb986b3b2019-08-24 07:22:43 -0600610 pathname = os.path.join(cls._indir, fname)
Simon Glass4f443042016-11-25 20:15:52 -0700611 dirname = os.path.dirname(pathname)
612 if dirname and not os.path.exists(dirname):
613 os.makedirs(dirname)
614 with open(pathname, 'wb') as fd:
615 fd.write(contents)
616 return pathname
617
618 @classmethod
Simon Glassb986b3b2019-08-24 07:22:43 -0600619 def _MakeInputDir(cls, dirname):
Simon Glass0ef87aa2018-07-17 13:25:44 -0600620 """Create a new test input directory, creating directories as needed
621
622 Args:
623 dirname: Directory name to create
624
625 Returns:
626 Full pathname of directory created
627 """
Simon Glassb986b3b2019-08-24 07:22:43 -0600628 pathname = os.path.join(cls._indir, dirname)
Simon Glass0ef87aa2018-07-17 13:25:44 -0600629 if not os.path.exists(pathname):
630 os.makedirs(pathname)
631 return pathname
632
633 @classmethod
Simon Glassb986b3b2019-08-24 07:22:43 -0600634 def _SetupSplElf(cls, src_fname='bss_data'):
Simon Glass11ae93e2018-10-01 21:12:47 -0600635 """Set up an ELF file with a '_dt_ucode_base_size' symbol
636
637 Args:
638 Filename of ELF file to use as SPL
639 """
Simon Glassc9a0b272019-08-24 07:22:59 -0600640 TestFunctional._MakeInputFile('spl/u-boot-spl',
Simon Glassc1aa66e2022-01-29 14:14:04 -0700641 tools.read_file(cls.ElfTestFile(src_fname)))
Simon Glass11ae93e2018-10-01 21:12:47 -0600642
643 @classmethod
Simon Glass2090f1e2019-08-24 07:23:00 -0600644 def _SetupTplElf(cls, src_fname='bss_data'):
645 """Set up an ELF file with a '_dt_ucode_base_size' symbol
646
647 Args:
648 Filename of ELF file to use as TPL
649 """
650 TestFunctional._MakeInputFile('tpl/u-boot-tpl',
Simon Glassc1aa66e2022-01-29 14:14:04 -0700651 tools.read_file(cls.ElfTestFile(src_fname)))
Simon Glass2090f1e2019-08-24 07:23:00 -0600652
653 @classmethod
Simon Glass6ad24522022-02-28 07:16:54 -0700654 def _SetupVplElf(cls, src_fname='bss_data'):
655 """Set up an ELF file with a '_dt_ucode_base_size' symbol
656
657 Args:
658 Filename of ELF file to use as VPL
659 """
660 TestFunctional._MakeInputFile('vpl/u-boot-vpl',
661 tools.read_file(cls.ElfTestFile(src_fname)))
662
663 @classmethod
Lukas Funke8c1fbd12023-07-18 13:53:13 +0200664 def _SetupPmuFwlElf(cls, src_fname='bss_data'):
665 """Set up an ELF file with a '_dt_ucode_base_size' symbol
666
667 Args:
668 Filename of ELF file to use as VPL
669 """
670 TestFunctional._MakeInputFile('pmu-firmware.elf',
671 tools.read_file(cls.ElfTestFile(src_fname)))
672
673 @classmethod
Simon Glass0ba4b3d2020-07-09 18:39:41 -0600674 def _SetupDescriptor(cls):
675 with open(cls.TestFile('descriptor.bin'), 'rb') as fd:
676 TestFunctional._MakeInputFile('descriptor.bin', fd.read())
677
678 @classmethod
Simon Glassb986b3b2019-08-24 07:22:43 -0600679 def TestFile(cls, fname):
680 return os.path.join(cls._binman_dir, 'test', fname)
Simon Glass4f443042016-11-25 20:15:52 -0700681
Simon Glass53e22bf2019-08-24 07:22:53 -0600682 @classmethod
683 def ElfTestFile(cls, fname):
684 return os.path.join(cls._elf_testdir, fname)
685
Simon Glass2f80c5e2023-01-07 14:07:14 -0700686 @classmethod
687 def make_tee_bin(cls, fname, paged_sz=0, extra_data=b''):
688 init_sz, start_hi, start_lo, dummy = (len(U_BOOT_DATA), 0, TEE_ADDR, 0)
689 data = b'OPTE\x01xxx' + struct.pack('<5I', init_sz, start_hi, start_lo,
690 dummy, paged_sz) + U_BOOT_DATA
691 data += extra_data
692 TestFunctional._MakeInputFile(fname, data)
693
Simon Glass4f443042016-11-25 20:15:52 -0700694 def AssertInList(self, grep_list, target):
695 """Assert that at least one of a list of things is in a target
696
697 Args:
698 grep_list: List of strings to check
699 target: Target string
700 """
701 for grep in grep_list:
702 if grep in target:
703 return
Simon Glass1fc62de2019-05-17 22:00:50 -0600704 self.fail("Error: '%s' not found in '%s'" % (grep_list, target))
Simon Glass4f443042016-11-25 20:15:52 -0700705
706 def CheckNoGaps(self, entries):
707 """Check that all entries fit together without gaps
708
709 Args:
710 entries: List of entries to check
711 """
Simon Glass3ab95982018-08-01 15:22:37 -0600712 offset = 0
Simon Glass4f443042016-11-25 20:15:52 -0700713 for entry in entries.values():
Simon Glass3ab95982018-08-01 15:22:37 -0600714 self.assertEqual(offset, entry.offset)
715 offset += entry.size
Simon Glass4f443042016-11-25 20:15:52 -0700716
Simon Glasse0ff8552016-11-25 20:15:53 -0700717 def GetFdtLen(self, dtb):
Simon Glass7ae5f312018-06-01 09:38:19 -0600718 """Get the totalsize field from a device-tree binary
Simon Glasse0ff8552016-11-25 20:15:53 -0700719
720 Args:
Simon Glass7ae5f312018-06-01 09:38:19 -0600721 dtb: Device-tree binary contents
Simon Glasse0ff8552016-11-25 20:15:53 -0700722
723 Returns:
Simon Glass7ae5f312018-06-01 09:38:19 -0600724 Total size of device-tree binary, from the header
Simon Glasse0ff8552016-11-25 20:15:53 -0700725 """
726 return struct.unpack('>L', dtb[4:8])[0]
727
Simon Glass086cec92019-07-08 14:25:27 -0600728 def _GetPropTree(self, dtb, prop_names, prefix='/binman/'):
Simon Glass16b8d6b2018-07-06 10:27:42 -0600729 def AddNode(node, path):
730 if node.name != '/':
731 path += '/' + node.name
Simon Glass086cec92019-07-08 14:25:27 -0600732 for prop in node.props.values():
733 if prop.name in prop_names:
734 prop_path = path + ':' + prop.name
735 tree[prop_path[len(prefix):]] = fdt_util.fdt32_to_cpu(
736 prop.value)
Simon Glass16b8d6b2018-07-06 10:27:42 -0600737 for subnode in node.subnodes:
Simon Glass16b8d6b2018-07-06 10:27:42 -0600738 AddNode(subnode, path)
739
740 tree = {}
Simon Glass16b8d6b2018-07-06 10:27:42 -0600741 AddNode(dtb.GetRoot(), '')
742 return tree
743
Ivan Mikhaylov5b34efe2023-03-08 01:13:40 +0000744 def _CheckSign(self, fit, key):
745 try:
746 tools.run('fit_check_sign', '-k', key, '-f', fit)
747 except:
748 self.fail('Expected signed FIT container')
749 return False
750 return True
751
Simon Glass4f443042016-11-25 20:15:52 -0700752 def testRun(self):
753 """Test a basic run with valid args"""
754 result = self._RunBinman('-h')
755
756 def testFullHelp(self):
757 """Test that the full help is displayed with -H"""
758 result = self._RunBinman('-H')
Simon Glass61adb2d2021-03-18 20:25:13 +1300759 help_file = os.path.join(self._binman_dir, 'README.rst')
Tom Rini3759df02018-01-16 15:29:50 -0500760 # Remove possible extraneous strings
761 extra = '::::::::::::::\n' + help_file + '\n::::::::::::::\n'
762 gothelp = result.stdout.replace(extra, '')
763 self.assertEqual(len(gothelp), os.path.getsize(help_file))
Simon Glass4f443042016-11-25 20:15:52 -0700764 self.assertEqual(0, len(result.stderr))
765 self.assertEqual(0, result.return_code)
766
767 def testFullHelpInternal(self):
768 """Test that the full help is displayed with -H"""
769 try:
770 command.test_result = command.CommandResult()
771 result = self._DoBinman('-H')
Simon Glass61adb2d2021-03-18 20:25:13 +1300772 help_file = os.path.join(self._binman_dir, 'README.rst')
Simon Glass4f443042016-11-25 20:15:52 -0700773 finally:
774 command.test_result = None
775
776 def testHelp(self):
777 """Test that the basic help is displayed with -h"""
778 result = self._RunBinman('-h')
779 self.assertTrue(len(result.stdout) > 200)
780 self.assertEqual(0, len(result.stderr))
781 self.assertEqual(0, result.return_code)
782
Simon Glass4f443042016-11-25 20:15:52 -0700783 def testBoard(self):
784 """Test that we can run it with a specific board"""
Simon Glass741f2d62018-10-01 12:22:30 -0600785 self._SetupDtb('005_simple.dts', 'sandbox/u-boot.dtb')
Simon Glass4f443042016-11-25 20:15:52 -0700786 TestFunctional._MakeInputFile('sandbox/u-boot.bin', U_BOOT_DATA)
Simon Glass63aeaeb2021-03-18 20:25:05 +1300787 result = self._DoBinman('build', '-n', '-b', 'sandbox')
Simon Glass4f443042016-11-25 20:15:52 -0700788 self.assertEqual(0, result)
789
790 def testNeedBoard(self):
791 """Test that we get an error when no board ius supplied"""
792 with self.assertRaises(ValueError) as e:
Simon Glass53cd5d92019-07-08 14:25:29 -0600793 result = self._DoBinman('build')
Simon Glass4f443042016-11-25 20:15:52 -0700794 self.assertIn("Must provide a board to process (use -b <board>)",
795 str(e.exception))
796
797 def testMissingDt(self):
Simon Glass7ae5f312018-06-01 09:38:19 -0600798 """Test that an invalid device-tree file generates an error"""
Simon Glass4f443042016-11-25 20:15:52 -0700799 with self.assertRaises(Exception) as e:
Simon Glass53cd5d92019-07-08 14:25:29 -0600800 self._RunBinman('build', '-d', 'missing_file')
Simon Glass4f443042016-11-25 20:15:52 -0700801 # We get one error from libfdt, and a different one from fdtget.
802 self.AssertInList(["Couldn't open blob from 'missing_file'",
803 'No such file or directory'], str(e.exception))
804
805 def testBrokenDt(self):
Simon Glass7ae5f312018-06-01 09:38:19 -0600806 """Test that an invalid device-tree source file generates an error
Simon Glass4f443042016-11-25 20:15:52 -0700807
808 Since this is a source file it should be compiled and the error
809 will come from the device-tree compiler (dtc).
810 """
811 with self.assertRaises(Exception) as e:
Simon Glass53cd5d92019-07-08 14:25:29 -0600812 self._RunBinman('build', '-d', self.TestFile('001_invalid.dts'))
Simon Glass4f443042016-11-25 20:15:52 -0700813 self.assertIn("FATAL ERROR: Unable to parse input tree",
814 str(e.exception))
815
816 def testMissingNode(self):
817 """Test that a device tree without a 'binman' node generates an error"""
818 with self.assertRaises(Exception) as e:
Simon Glass53cd5d92019-07-08 14:25:29 -0600819 self._DoBinman('build', '-d', self.TestFile('002_missing_node.dts'))
Simon Glass4f443042016-11-25 20:15:52 -0700820 self.assertIn("does not have a 'binman' node", str(e.exception))
821
822 def testEmpty(self):
823 """Test that an empty binman node works OK (i.e. does nothing)"""
Simon Glass53cd5d92019-07-08 14:25:29 -0600824 result = self._RunBinman('build', '-d', self.TestFile('003_empty.dts'))
Simon Glass4f443042016-11-25 20:15:52 -0700825 self.assertEqual(0, len(result.stderr))
826 self.assertEqual(0, result.return_code)
827
828 def testInvalidEntry(self):
829 """Test that an invalid entry is flagged"""
830 with self.assertRaises(Exception) as e:
Simon Glass53cd5d92019-07-08 14:25:29 -0600831 result = self._RunBinman('build', '-d',
Simon Glass741f2d62018-10-01 12:22:30 -0600832 self.TestFile('004_invalid_entry.dts'))
Simon Glass4f443042016-11-25 20:15:52 -0700833 self.assertIn("Unknown entry type 'not-a-valid-type' in node "
834 "'/binman/not-a-valid-type'", str(e.exception))
835
836 def testSimple(self):
837 """Test a simple binman with a single file"""
Simon Glass741f2d62018-10-01 12:22:30 -0600838 data = self._DoReadFile('005_simple.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700839 self.assertEqual(U_BOOT_DATA, data)
840
Simon Glass7fe91732017-11-13 18:55:00 -0700841 def testSimpleDebug(self):
842 """Test a simple binman run with debugging enabled"""
Simon Glasse2705fa2019-07-08 14:25:53 -0600843 self._DoTestFile('005_simple.dts', debug=True)
Simon Glass7fe91732017-11-13 18:55:00 -0700844
Simon Glass4f443042016-11-25 20:15:52 -0700845 def testDual(self):
846 """Test that we can handle creating two images
847
848 This also tests image padding.
849 """
Simon Glass741f2d62018-10-01 12:22:30 -0600850 retcode = self._DoTestFile('006_dual_image.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700851 self.assertEqual(0, retcode)
852
853 image = control.images['image1']
Simon Glass8beb11e2019-07-08 14:25:47 -0600854 self.assertEqual(len(U_BOOT_DATA), image.size)
Simon Glassc1aa66e2022-01-29 14:14:04 -0700855 fname = tools.get_output_filename('image1.bin')
Simon Glass4f443042016-11-25 20:15:52 -0700856 self.assertTrue(os.path.exists(fname))
Simon Glass1d0ebf72019-05-14 15:53:42 -0600857 with open(fname, 'rb') as fd:
Simon Glass4f443042016-11-25 20:15:52 -0700858 data = fd.read()
859 self.assertEqual(U_BOOT_DATA, data)
860
861 image = control.images['image2']
Simon Glass8beb11e2019-07-08 14:25:47 -0600862 self.assertEqual(3 + len(U_BOOT_DATA) + 5, image.size)
Simon Glassc1aa66e2022-01-29 14:14:04 -0700863 fname = tools.get_output_filename('image2.bin')
Simon Glass4f443042016-11-25 20:15:52 -0700864 self.assertTrue(os.path.exists(fname))
Simon Glass1d0ebf72019-05-14 15:53:42 -0600865 with open(fname, 'rb') as fd:
Simon Glass4f443042016-11-25 20:15:52 -0700866 data = fd.read()
867 self.assertEqual(U_BOOT_DATA, data[3:7])
Simon Glassc1aa66e2022-01-29 14:14:04 -0700868 self.assertEqual(tools.get_bytes(0, 3), data[:3])
869 self.assertEqual(tools.get_bytes(0, 5), data[7:])
Simon Glass4f443042016-11-25 20:15:52 -0700870
871 def testBadAlign(self):
872 """Test that an invalid alignment value is detected"""
873 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -0600874 self._DoTestFile('007_bad_align.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700875 self.assertIn("Node '/binman/u-boot': Alignment 23 must be a power "
876 "of two", str(e.exception))
877
878 def testPackSimple(self):
879 """Test that packing works as expected"""
Simon Glass741f2d62018-10-01 12:22:30 -0600880 retcode = self._DoTestFile('008_pack.dts')
Simon Glass4f443042016-11-25 20:15:52 -0700881 self.assertEqual(0, retcode)
882 self.assertIn('image', control.images)
883 image = control.images['image']
Simon Glass8f1da502018-06-01 09:38:12 -0600884 entries = image.GetEntries()
Simon Glass4f443042016-11-25 20:15:52 -0700885 self.assertEqual(5, len(entries))
886
887 # First u-boot
888 self.assertIn('u-boot', entries)
889 entry = entries['u-boot']
Simon Glass3ab95982018-08-01 15:22:37 -0600890 self.assertEqual(0, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700891 self.assertEqual(len(U_BOOT_DATA), entry.size)
892
893 # Second u-boot, aligned to 16-byte boundary
894 self.assertIn('u-boot-align', entries)
895 entry = entries['u-boot-align']
Simon Glass3ab95982018-08-01 15:22:37 -0600896 self.assertEqual(16, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700897 self.assertEqual(len(U_BOOT_DATA), entry.size)
898
899 # Third u-boot, size 23 bytes
900 self.assertIn('u-boot-size', entries)
901 entry = entries['u-boot-size']
Simon Glass3ab95982018-08-01 15:22:37 -0600902 self.assertEqual(20, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700903 self.assertEqual(len(U_BOOT_DATA), entry.contents_size)
904 self.assertEqual(23, entry.size)
905
906 # Fourth u-boot, placed immediate after the above
907 self.assertIn('u-boot-next', entries)
908 entry = entries['u-boot-next']
Simon Glass3ab95982018-08-01 15:22:37 -0600909 self.assertEqual(43, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700910 self.assertEqual(len(U_BOOT_DATA), entry.size)
911
Simon Glass3ab95982018-08-01 15:22:37 -0600912 # Fifth u-boot, placed at a fixed offset
Simon Glass4f443042016-11-25 20:15:52 -0700913 self.assertIn('u-boot-fixed', entries)
914 entry = entries['u-boot-fixed']
Simon Glass3ab95982018-08-01 15:22:37 -0600915 self.assertEqual(61, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700916 self.assertEqual(len(U_BOOT_DATA), entry.size)
917
Simon Glass8beb11e2019-07-08 14:25:47 -0600918 self.assertEqual(65, image.size)
Simon Glass4f443042016-11-25 20:15:52 -0700919
920 def testPackExtra(self):
921 """Test that extra packing feature works as expected"""
Simon Glass4eec34c2020-10-26 17:40:10 -0600922 data, _, _, out_dtb_fname = self._DoReadFileDtb('009_pack_extra.dts',
923 update_dtb=True)
Simon Glass4f443042016-11-25 20:15:52 -0700924
Simon Glass4f443042016-11-25 20:15:52 -0700925 self.assertIn('image', control.images)
926 image = control.images['image']
Simon Glass8f1da502018-06-01 09:38:12 -0600927 entries = image.GetEntries()
Samuel Hollandb01ae032023-01-21 17:25:16 -0600928 self.assertEqual(6, len(entries))
Simon Glass4f443042016-11-25 20:15:52 -0700929
Samuel Hollandb01ae032023-01-21 17:25:16 -0600930 # First u-boot with padding before and after (included in minimum size)
Simon Glass4f443042016-11-25 20:15:52 -0700931 self.assertIn('u-boot', entries)
932 entry = entries['u-boot']
Simon Glass3ab95982018-08-01 15:22:37 -0600933 self.assertEqual(0, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700934 self.assertEqual(3, entry.pad_before)
935 self.assertEqual(3 + 5 + len(U_BOOT_DATA), entry.size)
Simon Glassef439ed2020-10-26 17:40:08 -0600936 self.assertEqual(U_BOOT_DATA, entry.data)
Simon Glassc1aa66e2022-01-29 14:14:04 -0700937 self.assertEqual(tools.get_bytes(0, 3) + U_BOOT_DATA +
938 tools.get_bytes(0, 5), data[:entry.size])
Simon Glassef439ed2020-10-26 17:40:08 -0600939 pos = entry.size
Simon Glass4f443042016-11-25 20:15:52 -0700940
941 # Second u-boot has an aligned size, but it has no effect
942 self.assertIn('u-boot-align-size-nop', entries)
943 entry = entries['u-boot-align-size-nop']
Simon Glassef439ed2020-10-26 17:40:08 -0600944 self.assertEqual(pos, entry.offset)
945 self.assertEqual(len(U_BOOT_DATA), entry.size)
946 self.assertEqual(U_BOOT_DATA, entry.data)
947 self.assertEqual(U_BOOT_DATA, data[pos:pos + entry.size])
948 pos += entry.size
Simon Glass4f443042016-11-25 20:15:52 -0700949
950 # Third u-boot has an aligned size too
951 self.assertIn('u-boot-align-size', entries)
952 entry = entries['u-boot-align-size']
Simon Glassef439ed2020-10-26 17:40:08 -0600953 self.assertEqual(pos, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700954 self.assertEqual(32, entry.size)
Simon Glassef439ed2020-10-26 17:40:08 -0600955 self.assertEqual(U_BOOT_DATA, entry.data)
Simon Glassc1aa66e2022-01-29 14:14:04 -0700956 self.assertEqual(U_BOOT_DATA + tools.get_bytes(0, 32 - len(U_BOOT_DATA)),
Simon Glassef439ed2020-10-26 17:40:08 -0600957 data[pos:pos + entry.size])
958 pos += entry.size
Simon Glass4f443042016-11-25 20:15:52 -0700959
960 # Fourth u-boot has an aligned end
961 self.assertIn('u-boot-align-end', entries)
962 entry = entries['u-boot-align-end']
Simon Glass3ab95982018-08-01 15:22:37 -0600963 self.assertEqual(48, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700964 self.assertEqual(16, entry.size)
Simon Glassef439ed2020-10-26 17:40:08 -0600965 self.assertEqual(U_BOOT_DATA, entry.data[:len(U_BOOT_DATA)])
Simon Glassc1aa66e2022-01-29 14:14:04 -0700966 self.assertEqual(U_BOOT_DATA + tools.get_bytes(0, 16 - len(U_BOOT_DATA)),
Simon Glassef439ed2020-10-26 17:40:08 -0600967 data[pos:pos + entry.size])
968 pos += entry.size
Simon Glass4f443042016-11-25 20:15:52 -0700969
970 # Fifth u-boot immediately afterwards
971 self.assertIn('u-boot-align-both', entries)
972 entry = entries['u-boot-align-both']
Simon Glass3ab95982018-08-01 15:22:37 -0600973 self.assertEqual(64, entry.offset)
Simon Glass4f443042016-11-25 20:15:52 -0700974 self.assertEqual(64, entry.size)
Simon Glassef439ed2020-10-26 17:40:08 -0600975 self.assertEqual(U_BOOT_DATA, entry.data[:len(U_BOOT_DATA)])
Simon Glassc1aa66e2022-01-29 14:14:04 -0700976 self.assertEqual(U_BOOT_DATA + tools.get_bytes(0, 64 - len(U_BOOT_DATA)),
Simon Glassef439ed2020-10-26 17:40:08 -0600977 data[pos:pos + entry.size])
Simon Glass4f443042016-11-25 20:15:52 -0700978
Samuel Hollandb01ae032023-01-21 17:25:16 -0600979 # Sixth u-boot with both minimum size and aligned size
980 self.assertIn('u-boot-min-size', entries)
981 entry = entries['u-boot-min-size']
982 self.assertEqual(128, entry.offset)
983 self.assertEqual(32, entry.size)
984 self.assertEqual(U_BOOT_DATA, entry.data[:len(U_BOOT_DATA)])
985 self.assertEqual(U_BOOT_DATA + tools.get_bytes(0, 32 - len(U_BOOT_DATA)),
986 data[pos:pos + entry.size])
987
Simon Glass4f443042016-11-25 20:15:52 -0700988 self.CheckNoGaps(entries)
Samuel Hollandb01ae032023-01-21 17:25:16 -0600989 self.assertEqual(160, image.size)
Simon Glass4f443042016-11-25 20:15:52 -0700990
Simon Glass4eec34c2020-10-26 17:40:10 -0600991 dtb = fdt.Fdt(out_dtb_fname)
992 dtb.Scan()
993 props = self._GetPropTree(dtb, ['size', 'offset', 'image-pos'])
994 expected = {
995 'image-pos': 0,
996 'offset': 0,
Samuel Hollandb01ae032023-01-21 17:25:16 -0600997 'size': 160,
Simon Glass4eec34c2020-10-26 17:40:10 -0600998
999 'u-boot:image-pos': 0,
1000 'u-boot:offset': 0,
1001 'u-boot:size': 3 + 5 + len(U_BOOT_DATA),
1002
1003 'u-boot-align-size-nop:image-pos': 12,
1004 'u-boot-align-size-nop:offset': 12,
1005 'u-boot-align-size-nop:size': 4,
1006
1007 'u-boot-align-size:image-pos': 16,
1008 'u-boot-align-size:offset': 16,
1009 'u-boot-align-size:size': 32,
1010
1011 'u-boot-align-end:image-pos': 48,
1012 'u-boot-align-end:offset': 48,
1013 'u-boot-align-end:size': 16,
1014
1015 'u-boot-align-both:image-pos': 64,
1016 'u-boot-align-both:offset': 64,
1017 'u-boot-align-both:size': 64,
Samuel Hollandb01ae032023-01-21 17:25:16 -06001018
1019 'u-boot-min-size:image-pos': 128,
1020 'u-boot-min-size:offset': 128,
1021 'u-boot-min-size:size': 32,
Simon Glass4eec34c2020-10-26 17:40:10 -06001022 }
1023 self.assertEqual(expected, props)
1024
Simon Glass4f443042016-11-25 20:15:52 -07001025 def testPackAlignPowerOf2(self):
1026 """Test that invalid entry alignment is detected"""
1027 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001028 self._DoTestFile('010_pack_align_power2.dts')
Simon Glass4f443042016-11-25 20:15:52 -07001029 self.assertIn("Node '/binman/u-boot': Alignment 5 must be a power "
1030 "of two", str(e.exception))
1031
1032 def testPackAlignSizePowerOf2(self):
1033 """Test that invalid entry size alignment is detected"""
1034 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001035 self._DoTestFile('011_pack_align_size_power2.dts')
Simon Glass4f443042016-11-25 20:15:52 -07001036 self.assertIn("Node '/binman/u-boot': Alignment size 55 must be a "
1037 "power of two", str(e.exception))
1038
1039 def testPackInvalidAlign(self):
Simon Glass3ab95982018-08-01 15:22:37 -06001040 """Test detection of an offset that does not match its alignment"""
Simon Glass4f443042016-11-25 20:15:52 -07001041 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001042 self._DoTestFile('012_pack_inv_align.dts')
Simon Glass3ab95982018-08-01 15:22:37 -06001043 self.assertIn("Node '/binman/u-boot': Offset 0x5 (5) does not match "
Simon Glass4f443042016-11-25 20:15:52 -07001044 "align 0x4 (4)", str(e.exception))
1045
1046 def testPackInvalidSizeAlign(self):
1047 """Test that invalid entry size alignment is detected"""
1048 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001049 self._DoTestFile('013_pack_inv_size_align.dts')
Simon Glass4f443042016-11-25 20:15:52 -07001050 self.assertIn("Node '/binman/u-boot': Size 0x5 (5) does not match "
1051 "align-size 0x4 (4)", str(e.exception))
1052
1053 def testPackOverlap(self):
1054 """Test that overlapping regions are detected"""
1055 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001056 self._DoTestFile('014_pack_overlap.dts')
Simon Glass3ab95982018-08-01 15:22:37 -06001057 self.assertIn("Node '/binman/u-boot-align': Offset 0x3 (3) overlaps "
Simon Glass4f443042016-11-25 20:15:52 -07001058 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
1059 str(e.exception))
1060
1061 def testPackEntryOverflow(self):
1062 """Test that entries that overflow their size are detected"""
1063 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001064 self._DoTestFile('015_pack_overflow.dts')
Simon Glass4f443042016-11-25 20:15:52 -07001065 self.assertIn("Node '/binman/u-boot': Entry contents size is 0x4 (4) "
1066 "but entry size is 0x3 (3)", str(e.exception))
1067
1068 def testPackImageOverflow(self):
1069 """Test that entries which overflow the image size are detected"""
1070 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001071 self._DoTestFile('016_pack_image_overflow.dts')
Simon Glass8f1da502018-06-01 09:38:12 -06001072 self.assertIn("Section '/binman': contents size 0x4 (4) exceeds section "
Simon Glass4f443042016-11-25 20:15:52 -07001073 "size 0x3 (3)", str(e.exception))
1074
1075 def testPackImageSize(self):
1076 """Test that the image size can be set"""
Simon Glass741f2d62018-10-01 12:22:30 -06001077 retcode = self._DoTestFile('017_pack_image_size.dts')
Simon Glass4f443042016-11-25 20:15:52 -07001078 self.assertEqual(0, retcode)
1079 self.assertIn('image', control.images)
1080 image = control.images['image']
Simon Glass8beb11e2019-07-08 14:25:47 -06001081 self.assertEqual(7, image.size)
Simon Glass4f443042016-11-25 20:15:52 -07001082
1083 def testPackImageSizeAlign(self):
1084 """Test that image size alignemnt works as expected"""
Simon Glass741f2d62018-10-01 12:22:30 -06001085 retcode = self._DoTestFile('018_pack_image_align.dts')
Simon Glass4f443042016-11-25 20:15:52 -07001086 self.assertEqual(0, retcode)
1087 self.assertIn('image', control.images)
1088 image = control.images['image']
Simon Glass8beb11e2019-07-08 14:25:47 -06001089 self.assertEqual(16, image.size)
Simon Glass4f443042016-11-25 20:15:52 -07001090
1091 def testPackInvalidImageAlign(self):
1092 """Test that invalid image alignment is detected"""
1093 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001094 self._DoTestFile('019_pack_inv_image_align.dts')
Simon Glass8f1da502018-06-01 09:38:12 -06001095 self.assertIn("Section '/binman': Size 0x7 (7) does not match "
Simon Glass4f443042016-11-25 20:15:52 -07001096 "align-size 0x8 (8)", str(e.exception))
1097
Simon Glass8d2ef3e2022-02-11 13:23:21 -07001098 def testPackAlignPowerOf2Inv(self):
Simon Glass4f443042016-11-25 20:15:52 -07001099 """Test that invalid image alignment is detected"""
1100 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001101 self._DoTestFile('020_pack_inv_image_align_power2.dts')
Simon Glass8beb11e2019-07-08 14:25:47 -06001102 self.assertIn("Image '/binman': Alignment size 131 must be a power of "
Simon Glass4f443042016-11-25 20:15:52 -07001103 "two", str(e.exception))
1104
1105 def testImagePadByte(self):
1106 """Test that the image pad byte can be specified"""
Simon Glass11ae93e2018-10-01 21:12:47 -06001107 self._SetupSplElf()
Simon Glass741f2d62018-10-01 12:22:30 -06001108 data = self._DoReadFile('021_image_pad.dts')
Simon Glassc1aa66e2022-01-29 14:14:04 -07001109 self.assertEqual(U_BOOT_SPL_DATA + tools.get_bytes(0xff, 1) +
Simon Glasse6d85ff2019-05-14 15:53:47 -06001110 U_BOOT_DATA, data)
Simon Glass4f443042016-11-25 20:15:52 -07001111
1112 def testImageName(self):
1113 """Test that image files can be named"""
Simon Glass741f2d62018-10-01 12:22:30 -06001114 retcode = self._DoTestFile('022_image_name.dts')
Simon Glass4f443042016-11-25 20:15:52 -07001115 self.assertEqual(0, retcode)
1116 image = control.images['image1']
Simon Glassc1aa66e2022-01-29 14:14:04 -07001117 fname = tools.get_output_filename('test-name')
Simon Glass4f443042016-11-25 20:15:52 -07001118 self.assertTrue(os.path.exists(fname))
1119
1120 image = control.images['image2']
Simon Glassc1aa66e2022-01-29 14:14:04 -07001121 fname = tools.get_output_filename('test-name.xx')
Simon Glass4f443042016-11-25 20:15:52 -07001122 self.assertTrue(os.path.exists(fname))
1123
1124 def testBlobFilename(self):
1125 """Test that generic blobs can be provided by filename"""
Simon Glass741f2d62018-10-01 12:22:30 -06001126 data = self._DoReadFile('023_blob.dts')
Simon Glass4f443042016-11-25 20:15:52 -07001127 self.assertEqual(BLOB_DATA, data)
1128
1129 def testPackSorted(self):
1130 """Test that entries can be sorted"""
Simon Glass11ae93e2018-10-01 21:12:47 -06001131 self._SetupSplElf()
Simon Glass741f2d62018-10-01 12:22:30 -06001132 data = self._DoReadFile('024_sorted.dts')
Simon Glassc1aa66e2022-01-29 14:14:04 -07001133 self.assertEqual(tools.get_bytes(0, 1) + U_BOOT_SPL_DATA +
1134 tools.get_bytes(0, 2) + U_BOOT_DATA, data)
Simon Glass4f443042016-11-25 20:15:52 -07001135
Simon Glass3ab95982018-08-01 15:22:37 -06001136 def testPackZeroOffset(self):
1137 """Test that an entry at offset 0 is not given a new offset"""
Marek Vasutfadad3a2023-07-18 07:23:58 -06001138 self._SetupSplElf()
Simon Glass4f443042016-11-25 20:15:52 -07001139 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001140 self._DoTestFile('025_pack_zero_size.dts')
Simon Glass3ab95982018-08-01 15:22:37 -06001141 self.assertIn("Node '/binman/u-boot-spl': Offset 0x0 (0) overlaps "
Simon Glass4f443042016-11-25 20:15:52 -07001142 "with previous entry '/binman/u-boot' ending at 0x4 (4)",
1143 str(e.exception))
1144
1145 def testPackUbootDtb(self):
1146 """Test that a device tree can be added to U-Boot"""
Simon Glass741f2d62018-10-01 12:22:30 -06001147 data = self._DoReadFile('026_pack_u_boot_dtb.dts')
Simon Glass4f443042016-11-25 20:15:52 -07001148 self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA, data)
Simon Glasse0ff8552016-11-25 20:15:53 -07001149
1150 def testPackX86RomNoSize(self):
1151 """Test that the end-at-4gb property requires a size property"""
Marek Vasutfadad3a2023-07-18 07:23:58 -06001152 self._SetupSplElf()
Simon Glasse0ff8552016-11-25 20:15:53 -07001153 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001154 self._DoTestFile('027_pack_4gb_no_size.dts')
Simon Glass8beb11e2019-07-08 14:25:47 -06001155 self.assertIn("Image '/binman': Section size must be provided when "
Simon Glasse0ff8552016-11-25 20:15:53 -07001156 "using end-at-4gb", str(e.exception))
1157
Jagdish Gediya94b57db2018-09-03 21:35:07 +05301158 def test4gbAndSkipAtStartTogether(self):
1159 """Test that the end-at-4gb and skip-at-size property can't be used
1160 together"""
Marek Vasutfadad3a2023-07-18 07:23:58 -06001161 self._SetupSplElf()
Jagdish Gediya94b57db2018-09-03 21:35:07 +05301162 with self.assertRaises(ValueError) as e:
Simon Glassdfdd2b62019-08-24 07:23:02 -06001163 self._DoTestFile('098_4gb_and_skip_at_start_together.dts')
Simon Glass8beb11e2019-07-08 14:25:47 -06001164 self.assertIn("Image '/binman': Provide either 'end-at-4gb' or "
Jagdish Gediya94b57db2018-09-03 21:35:07 +05301165 "'skip-at-start'", str(e.exception))
1166
Simon Glasse0ff8552016-11-25 20:15:53 -07001167 def testPackX86RomOutside(self):
Simon Glass3ab95982018-08-01 15:22:37 -06001168 """Test that the end-at-4gb property checks for offset boundaries"""
Marek Vasutfadad3a2023-07-18 07:23:58 -06001169 self._SetupSplElf()
Simon Glasse0ff8552016-11-25 20:15:53 -07001170 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001171 self._DoTestFile('028_pack_4gb_outside.dts')
Simon Glasse6bed4f2020-10-26 17:40:05 -06001172 self.assertIn("Node '/binman/u-boot': Offset 0x0 (0) size 0x4 (4) "
1173 "is outside the section '/binman' starting at "
1174 '0xffffffe0 (4294967264) of size 0x20 (32)',
Simon Glasse0ff8552016-11-25 20:15:53 -07001175 str(e.exception))
1176
1177 def testPackX86Rom(self):
1178 """Test that a basic x86 ROM can be created"""
Simon Glass11ae93e2018-10-01 21:12:47 -06001179 self._SetupSplElf()
Simon Glass9255f3c2019-08-24 07:23:01 -06001180 data = self._DoReadFile('029_x86_rom.dts')
Simon Glassc1aa66e2022-01-29 14:14:04 -07001181 self.assertEqual(U_BOOT_DATA + tools.get_bytes(0, 3) + U_BOOT_SPL_DATA +
1182 tools.get_bytes(0, 2), data)
Simon Glasse0ff8552016-11-25 20:15:53 -07001183
1184 def testPackX86RomMeNoDesc(self):
1185 """Test that an invalid Intel descriptor entry is detected"""
Simon Glass0ba4b3d2020-07-09 18:39:41 -06001186 try:
Simon Glass52b10dd2020-07-25 15:11:19 -06001187 TestFunctional._MakeInputFile('descriptor-empty.bin', b'')
Simon Glass0ba4b3d2020-07-09 18:39:41 -06001188 with self.assertRaises(ValueError) as e:
Simon Glass52b10dd2020-07-25 15:11:19 -06001189 self._DoTestFile('163_x86_rom_me_empty.dts')
Simon Glass0ba4b3d2020-07-09 18:39:41 -06001190 self.assertIn("Node '/binman/intel-descriptor': Cannot find Intel Flash Descriptor (FD) signature",
1191 str(e.exception))
1192 finally:
1193 self._SetupDescriptor()
Simon Glasse0ff8552016-11-25 20:15:53 -07001194
1195 def testPackX86RomBadDesc(self):
1196 """Test that the Intel requires a descriptor entry"""
1197 with self.assertRaises(ValueError) as e:
Simon Glass9255f3c2019-08-24 07:23:01 -06001198 self._DoTestFile('030_x86_rom_me_no_desc.dts')
Simon Glass3ab95982018-08-01 15:22:37 -06001199 self.assertIn("Node '/binman/intel-me': No offset set with "
1200 "offset-unset: should another entry provide this correct "
1201 "offset?", str(e.exception))
Simon Glasse0ff8552016-11-25 20:15:53 -07001202
1203 def testPackX86RomMe(self):
1204 """Test that an x86 ROM with an ME region can be created"""
Simon Glass9255f3c2019-08-24 07:23:01 -06001205 data = self._DoReadFile('031_x86_rom_me.dts')
Simon Glassc1aa66e2022-01-29 14:14:04 -07001206 expected_desc = tools.read_file(self.TestFile('descriptor.bin'))
Simon Glassc5ac1382019-07-08 13:18:54 -06001207 if data[:0x1000] != expected_desc:
1208 self.fail('Expected descriptor binary at start of image')
Simon Glasse0ff8552016-11-25 20:15:53 -07001209 self.assertEqual(ME_DATA, data[0x1000:0x1000 + len(ME_DATA)])
1210
1211 def testPackVga(self):
1212 """Test that an image with a VGA binary can be created"""
Simon Glass9255f3c2019-08-24 07:23:01 -06001213 data = self._DoReadFile('032_intel_vga.dts')
Simon Glasse0ff8552016-11-25 20:15:53 -07001214 self.assertEqual(VGA_DATA, data[:len(VGA_DATA)])
1215
1216 def testPackStart16(self):
1217 """Test that an image with an x86 start16 region can be created"""
Simon Glass9255f3c2019-08-24 07:23:01 -06001218 data = self._DoReadFile('033_x86_start16.dts')
Simon Glasse0ff8552016-11-25 20:15:53 -07001219 self.assertEqual(X86_START16_DATA, data[:len(X86_START16_DATA)])
1220
Jagdish Gediya9d368f32018-09-03 21:35:08 +05301221 def testPackPowerpcMpc85xxBootpgResetvec(self):
1222 """Test that an image with powerpc-mpc85xx-bootpg-resetvec can be
1223 created"""
Simon Glassdfdd2b62019-08-24 07:23:02 -06001224 data = self._DoReadFile('150_powerpc_mpc85xx_bootpg_resetvec.dts')
Jagdish Gediya9d368f32018-09-03 21:35:08 +05301225 self.assertEqual(PPC_MPC85XX_BR_DATA, data[:len(PPC_MPC85XX_BR_DATA)])
1226
Simon Glass736bb0a2018-07-06 10:27:17 -06001227 def _RunMicrocodeTest(self, dts_fname, nodtb_data, ucode_second=False):
Simon Glassadc57012018-07-06 10:27:16 -06001228 """Handle running a test for insertion of microcode
1229
1230 Args:
1231 dts_fname: Name of test .dts file
1232 nodtb_data: Data that we expect in the first section
Simon Glass736bb0a2018-07-06 10:27:17 -06001233 ucode_second: True if the microsecond entry is second instead of
1234 third
Simon Glassadc57012018-07-06 10:27:16 -06001235
1236 Returns:
1237 Tuple:
1238 Contents of first region (U-Boot or SPL)
Simon Glass3ab95982018-08-01 15:22:37 -06001239 Offset and size components of microcode pointer, as inserted
Simon Glassadc57012018-07-06 10:27:16 -06001240 in the above (two 4-byte words)
1241 """
Simon Glass6b187df2017-11-12 21:52:27 -07001242 data = self._DoReadFile(dts_fname, True)
Simon Glasse0ff8552016-11-25 20:15:53 -07001243
1244 # Now check the device tree has no microcode
Simon Glass736bb0a2018-07-06 10:27:17 -06001245 if ucode_second:
1246 ucode_content = data[len(nodtb_data):]
1247 ucode_pos = len(nodtb_data)
1248 dtb_with_ucode = ucode_content[16:]
1249 fdt_len = self.GetFdtLen(dtb_with_ucode)
1250 else:
1251 dtb_with_ucode = data[len(nodtb_data):]
1252 fdt_len = self.GetFdtLen(dtb_with_ucode)
1253 ucode_content = dtb_with_ucode[fdt_len:]
1254 ucode_pos = len(nodtb_data) + fdt_len
Simon Glassc1aa66e2022-01-29 14:14:04 -07001255 fname = tools.get_output_filename('test.dtb')
Simon Glasse0ff8552016-11-25 20:15:53 -07001256 with open(fname, 'wb') as fd:
Simon Glassadc57012018-07-06 10:27:16 -06001257 fd.write(dtb_with_ucode)
Simon Glassec3f3782017-05-27 07:38:29 -06001258 dtb = fdt.FdtScan(fname)
1259 ucode = dtb.GetNode('/microcode')
Simon Glasse0ff8552016-11-25 20:15:53 -07001260 self.assertTrue(ucode)
1261 for node in ucode.subnodes:
1262 self.assertFalse(node.props.get('data'))
1263
Simon Glasse0ff8552016-11-25 20:15:53 -07001264 # Check that the microcode appears immediately after the Fdt
1265 # This matches the concatenation of the data properties in
Simon Glass87722132017-11-12 21:52:26 -07001266 # the /microcode/update@xxx nodes in 34_x86_ucode.dts.
Simon Glasse0ff8552016-11-25 20:15:53 -07001267 ucode_data = struct.pack('>4L', 0x12345678, 0x12345679, 0xabcd0000,
1268 0x78235609)
Simon Glassadc57012018-07-06 10:27:16 -06001269 self.assertEqual(ucode_data, ucode_content[:len(ucode_data)])
Simon Glasse0ff8552016-11-25 20:15:53 -07001270
1271 # Check that the microcode pointer was inserted. It should match the
Simon Glass3ab95982018-08-01 15:22:37 -06001272 # expected offset and size
Simon Glasse0ff8552016-11-25 20:15:53 -07001273 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
1274 len(ucode_data))
Simon Glass736bb0a2018-07-06 10:27:17 -06001275 u_boot = data[:len(nodtb_data)]
1276 return u_boot, pos_and_size
Simon Glass6b187df2017-11-12 21:52:27 -07001277
1278 def testPackUbootMicrocode(self):
1279 """Test that x86 microcode can be handled correctly
1280
1281 We expect to see the following in the image, in order:
1282 u-boot-nodtb.bin with a microcode pointer inserted at the correct
1283 place
1284 u-boot.dtb with the microcode removed
1285 the microcode
1286 """
Simon Glass741f2d62018-10-01 12:22:30 -06001287 first, pos_and_size = self._RunMicrocodeTest('034_x86_ucode.dts',
Simon Glass6b187df2017-11-12 21:52:27 -07001288 U_BOOT_NODTB_DATA)
Simon Glassc6c10e72019-05-17 22:00:46 -06001289 self.assertEqual(b'nodtb with microcode' + pos_and_size +
1290 b' somewhere in here', first)
Simon Glasse0ff8552016-11-25 20:15:53 -07001291
Simon Glass160a7662017-05-27 07:38:26 -06001292 def _RunPackUbootSingleMicrocode(self):
Simon Glasse0ff8552016-11-25 20:15:53 -07001293 """Test that x86 microcode can be handled correctly
1294
1295 We expect to see the following in the image, in order:
1296 u-boot-nodtb.bin with a microcode pointer inserted at the correct
1297 place
1298 u-boot.dtb with the microcode
1299 an empty microcode region
1300 """
1301 # We need the libfdt library to run this test since only that allows
1302 # finding the offset of a property. This is required by
1303 # Entry_u_boot_dtb_with_ucode.ObtainContents().
Simon Glass741f2d62018-10-01 12:22:30 -06001304 data = self._DoReadFile('035_x86_single_ucode.dts', True)
Simon Glasse0ff8552016-11-25 20:15:53 -07001305
1306 second = data[len(U_BOOT_NODTB_DATA):]
1307
1308 fdt_len = self.GetFdtLen(second)
1309 third = second[fdt_len:]
1310 second = second[:fdt_len]
1311
Simon Glass160a7662017-05-27 07:38:26 -06001312 ucode_data = struct.pack('>2L', 0x12345678, 0x12345679)
1313 self.assertIn(ucode_data, second)
1314 ucode_pos = second.find(ucode_data) + len(U_BOOT_NODTB_DATA)
Simon Glasse0ff8552016-11-25 20:15:53 -07001315
Simon Glass160a7662017-05-27 07:38:26 -06001316 # Check that the microcode pointer was inserted. It should match the
Simon Glass3ab95982018-08-01 15:22:37 -06001317 # expected offset and size
Simon Glass160a7662017-05-27 07:38:26 -06001318 pos_and_size = struct.pack('<2L', 0xfffffe00 + ucode_pos,
1319 len(ucode_data))
1320 first = data[:len(U_BOOT_NODTB_DATA)]
Simon Glassc6c10e72019-05-17 22:00:46 -06001321 self.assertEqual(b'nodtb with microcode' + pos_and_size +
1322 b' somewhere in here', first)
Simon Glassc49deb82016-11-25 20:15:54 -07001323
Simon Glass75db0862016-11-25 20:15:55 -07001324 def testPackUbootSingleMicrocode(self):
1325 """Test that x86 microcode can be handled correctly with fdt_normal.
1326 """
Simon Glass160a7662017-05-27 07:38:26 -06001327 self._RunPackUbootSingleMicrocode()
Simon Glass75db0862016-11-25 20:15:55 -07001328
Simon Glassc49deb82016-11-25 20:15:54 -07001329 def testUBootImg(self):
1330 """Test that u-boot.img can be put in a file"""
Simon Glass741f2d62018-10-01 12:22:30 -06001331 data = self._DoReadFile('036_u_boot_img.dts')
Simon Glassc49deb82016-11-25 20:15:54 -07001332 self.assertEqual(U_BOOT_IMG_DATA, data)
Simon Glass75db0862016-11-25 20:15:55 -07001333
1334 def testNoMicrocode(self):
1335 """Test that a missing microcode region is detected"""
1336 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001337 self._DoReadFile('037_x86_no_ucode.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -07001338 self.assertIn("Node '/binman/u-boot-dtb-with-ucode': No /microcode "
1339 "node found in ", str(e.exception))
1340
1341 def testMicrocodeWithoutNode(self):
1342 """Test that a missing u-boot-dtb-with-ucode node is detected"""
1343 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001344 self._DoReadFile('038_x86_ucode_missing_node.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -07001345 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1346 "microcode region u-boot-dtb-with-ucode", str(e.exception))
1347
1348 def testMicrocodeWithoutNode2(self):
1349 """Test that a missing u-boot-ucode node is detected"""
1350 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001351 self._DoReadFile('039_x86_ucode_missing_node2.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -07001352 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot find "
1353 "microcode region u-boot-ucode", str(e.exception))
1354
1355 def testMicrocodeWithoutPtrInElf(self):
1356 """Test that a U-Boot binary without the microcode symbol is detected"""
1357 # ELF file without a '_dt_ucode_base_size' symbol
Simon Glass75db0862016-11-25 20:15:55 -07001358 try:
Simon Glassbccd91d2019-08-24 07:22:55 -06001359 TestFunctional._MakeInputFile('u-boot',
Simon Glassc1aa66e2022-01-29 14:14:04 -07001360 tools.read_file(self.ElfTestFile('u_boot_no_ucode_ptr')))
Simon Glass75db0862016-11-25 20:15:55 -07001361
1362 with self.assertRaises(ValueError) as e:
Simon Glass160a7662017-05-27 07:38:26 -06001363 self._RunPackUbootSingleMicrocode()
Simon Glass75db0862016-11-25 20:15:55 -07001364 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Cannot locate "
1365 "_dt_ucode_base_size symbol in u-boot", str(e.exception))
1366
1367 finally:
1368 # Put the original file back
Simon Glassf514d8f2019-08-24 07:22:54 -06001369 TestFunctional._MakeInputFile('u-boot',
Simon Glassc1aa66e2022-01-29 14:14:04 -07001370 tools.read_file(self.ElfTestFile('u_boot_ucode_ptr')))
Simon Glass75db0862016-11-25 20:15:55 -07001371
1372 def testMicrocodeNotInImage(self):
1373 """Test that microcode must be placed within the image"""
1374 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001375 self._DoReadFile('040_x86_ucode_not_in_image.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -07001376 self.assertIn("Node '/binman/u-boot-with-ucode-ptr': Microcode "
1377 "pointer _dt_ucode_base_size at fffffe14 is outside the "
Simon Glass25ac0e62018-06-01 09:38:14 -06001378 "section ranging from 00000000 to 0000002e", str(e.exception))
Simon Glass75db0862016-11-25 20:15:55 -07001379
1380 def testWithoutMicrocode(self):
1381 """Test that we can cope with an image without microcode (e.g. qemu)"""
Simon Glassbccd91d2019-08-24 07:22:55 -06001382 TestFunctional._MakeInputFile('u-boot',
Simon Glassc1aa66e2022-01-29 14:14:04 -07001383 tools.read_file(self.ElfTestFile('u_boot_no_ucode_ptr')))
Simon Glass741f2d62018-10-01 12:22:30 -06001384 data, dtb, _, _ = self._DoReadFileDtb('044_x86_optional_ucode.dts', True)
Simon Glass75db0862016-11-25 20:15:55 -07001385
1386 # Now check the device tree has no microcode
1387 self.assertEqual(U_BOOT_NODTB_DATA, data[:len(U_BOOT_NODTB_DATA)])
1388 second = data[len(U_BOOT_NODTB_DATA):]
1389
1390 fdt_len = self.GetFdtLen(second)
1391 self.assertEqual(dtb, second[:fdt_len])
1392
1393 used_len = len(U_BOOT_NODTB_DATA) + fdt_len
1394 third = data[used_len:]
Simon Glassc1aa66e2022-01-29 14:14:04 -07001395 self.assertEqual(tools.get_bytes(0, 0x200 - used_len), third)
Simon Glass75db0862016-11-25 20:15:55 -07001396
1397 def testUnknownPosSize(self):
1398 """Test that microcode must be placed within the image"""
1399 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001400 self._DoReadFile('041_unknown_pos_size.dts', True)
Simon Glass3ab95982018-08-01 15:22:37 -06001401 self.assertIn("Section '/binman': Unable to set offset/size for unknown "
Simon Glass75db0862016-11-25 20:15:55 -07001402 "entry 'invalid-entry'", str(e.exception))
Simon Glassda229092016-11-25 20:15:56 -07001403
1404 def testPackFsp(self):
1405 """Test that an image with a FSP binary can be created"""
Simon Glass9255f3c2019-08-24 07:23:01 -06001406 data = self._DoReadFile('042_intel_fsp.dts')
Simon Glassda229092016-11-25 20:15:56 -07001407 self.assertEqual(FSP_DATA, data[:len(FSP_DATA)])
1408
1409 def testPackCmc(self):
Bin Meng59ea8c22017-08-15 22:41:54 -07001410 """Test that an image with a CMC binary can be created"""
Simon Glass9255f3c2019-08-24 07:23:01 -06001411 data = self._DoReadFile('043_intel_cmc.dts')
Simon Glassda229092016-11-25 20:15:56 -07001412 self.assertEqual(CMC_DATA, data[:len(CMC_DATA)])
Bin Meng59ea8c22017-08-15 22:41:54 -07001413
1414 def testPackVbt(self):
1415 """Test that an image with a VBT binary can be created"""
Simon Glass9255f3c2019-08-24 07:23:01 -06001416 data = self._DoReadFile('046_intel_vbt.dts')
Bin Meng59ea8c22017-08-15 22:41:54 -07001417 self.assertEqual(VBT_DATA, data[:len(VBT_DATA)])
Simon Glass9fc60b42017-11-12 21:52:22 -07001418
Simon Glass56509842017-11-12 21:52:25 -07001419 def testSplBssPad(self):
1420 """Test that we can pad SPL's BSS with zeros"""
Simon Glass6b187df2017-11-12 21:52:27 -07001421 # ELF file with a '__bss_size' symbol
Simon Glass11ae93e2018-10-01 21:12:47 -06001422 self._SetupSplElf()
Simon Glass741f2d62018-10-01 12:22:30 -06001423 data = self._DoReadFile('047_spl_bss_pad.dts')
Simon Glassc1aa66e2022-01-29 14:14:04 -07001424 self.assertEqual(U_BOOT_SPL_DATA + tools.get_bytes(0, 10) + U_BOOT_DATA,
Simon Glasse6d85ff2019-05-14 15:53:47 -06001425 data)
Simon Glass56509842017-11-12 21:52:25 -07001426
Simon Glass86af5112018-10-01 21:12:42 -06001427 def testSplBssPadMissing(self):
1428 """Test that a missing symbol is detected"""
Simon Glass11ae93e2018-10-01 21:12:47 -06001429 self._SetupSplElf('u_boot_ucode_ptr')
Simon Glassb50e5612017-11-13 18:54:54 -07001430 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001431 self._DoReadFile('047_spl_bss_pad.dts')
Simon Glassb50e5612017-11-13 18:54:54 -07001432 self.assertIn('Expected __bss_size symbol in spl/u-boot-spl',
1433 str(e.exception))
1434
Simon Glass87722132017-11-12 21:52:26 -07001435 def testPackStart16Spl(self):
Simon Glass35b384c2018-09-14 04:57:10 -06001436 """Test that an image with an x86 start16 SPL region can be created"""
Simon Glass9255f3c2019-08-24 07:23:01 -06001437 data = self._DoReadFile('048_x86_start16_spl.dts')
Simon Glass87722132017-11-12 21:52:26 -07001438 self.assertEqual(X86_START16_SPL_DATA, data[:len(X86_START16_SPL_DATA)])
1439
Simon Glass736bb0a2018-07-06 10:27:17 -06001440 def _PackUbootSplMicrocode(self, dts, ucode_second=False):
1441 """Helper function for microcode tests
Simon Glass6b187df2017-11-12 21:52:27 -07001442
1443 We expect to see the following in the image, in order:
1444 u-boot-spl-nodtb.bin with a microcode pointer inserted at the
1445 correct place
1446 u-boot.dtb with the microcode removed
1447 the microcode
Simon Glass736bb0a2018-07-06 10:27:17 -06001448
1449 Args:
1450 dts: Device tree file to use for test
1451 ucode_second: True if the microsecond entry is second instead of
1452 third
Simon Glass6b187df2017-11-12 21:52:27 -07001453 """
Simon Glass11ae93e2018-10-01 21:12:47 -06001454 self._SetupSplElf('u_boot_ucode_ptr')
Simon Glass736bb0a2018-07-06 10:27:17 -06001455 first, pos_and_size = self._RunMicrocodeTest(dts, U_BOOT_SPL_NODTB_DATA,
1456 ucode_second=ucode_second)
Simon Glassc6c10e72019-05-17 22:00:46 -06001457 self.assertEqual(b'splnodtb with microc' + pos_and_size +
1458 b'ter somewhere in here', first)
Simon Glass6b187df2017-11-12 21:52:27 -07001459
Simon Glass736bb0a2018-07-06 10:27:17 -06001460 def testPackUbootSplMicrocode(self):
1461 """Test that x86 microcode can be handled correctly in SPL"""
Marek Vasutfadad3a2023-07-18 07:23:58 -06001462 self._SetupSplElf()
Simon Glass741f2d62018-10-01 12:22:30 -06001463 self._PackUbootSplMicrocode('049_x86_ucode_spl.dts')
Simon Glass736bb0a2018-07-06 10:27:17 -06001464
1465 def testPackUbootSplMicrocodeReorder(self):
1466 """Test that order doesn't matter for microcode entries
1467
1468 This is the same as testPackUbootSplMicrocode but when we process the
1469 u-boot-ucode entry we have not yet seen the u-boot-dtb-with-ucode
1470 entry, so we reply on binman to try later.
1471 """
Simon Glass741f2d62018-10-01 12:22:30 -06001472 self._PackUbootSplMicrocode('058_x86_ucode_spl_needs_retry.dts',
Simon Glass736bb0a2018-07-06 10:27:17 -06001473 ucode_second=True)
1474
Simon Glassca4f4ff2017-11-12 21:52:28 -07001475 def testPackMrc(self):
1476 """Test that an image with an MRC binary can be created"""
Simon Glass741f2d62018-10-01 12:22:30 -06001477 data = self._DoReadFile('050_intel_mrc.dts')
Simon Glassca4f4ff2017-11-12 21:52:28 -07001478 self.assertEqual(MRC_DATA, data[:len(MRC_DATA)])
1479
Simon Glass47419ea2017-11-13 18:54:55 -07001480 def testSplDtb(self):
1481 """Test that an image with spl/u-boot-spl.dtb can be created"""
Marek Vasutfadad3a2023-07-18 07:23:58 -06001482 self._SetupSplElf()
Simon Glass741f2d62018-10-01 12:22:30 -06001483 data = self._DoReadFile('051_u_boot_spl_dtb.dts')
Simon Glass47419ea2017-11-13 18:54:55 -07001484 self.assertEqual(U_BOOT_SPL_DTB_DATA, data[:len(U_BOOT_SPL_DTB_DATA)])
1485
Simon Glass4e6fdbe2017-11-13 18:54:56 -07001486 def testSplNoDtb(self):
1487 """Test that an image with spl/u-boot-spl-nodtb.bin can be created"""
Simon Glass0fe44dc2021-04-25 08:39:32 +12001488 self._SetupSplElf()
Simon Glass741f2d62018-10-01 12:22:30 -06001489 data = self._DoReadFile('052_u_boot_spl_nodtb.dts')
Simon Glass4e6fdbe2017-11-13 18:54:56 -07001490 self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)])
1491
Simon Glass3d433382021-03-21 18:24:30 +13001492 def checkSymbols(self, dts, base_data, u_boot_offset, entry_args=None,
Simon Glass4649bea2023-07-18 07:23:54 -06001493 use_expanded=False, no_write_symbols=False):
Simon Glassf5898822021-03-18 20:24:56 +13001494 """Check the image contains the expected symbol values
1495
1496 Args:
1497 dts: Device tree file to use for test
1498 base_data: Data before and after 'u-boot' section
1499 u_boot_offset: Offset of 'u-boot' section in image
Simon Glass3d433382021-03-21 18:24:30 +13001500 entry_args: Dict of entry args to supply to binman
1501 key: arg name
1502 value: value of that arg
1503 use_expanded: True to use expanded entries where available, e.g.
1504 'u-boot-expanded' instead of 'u-boot'
Simon Glassf5898822021-03-18 20:24:56 +13001505 """
Simon Glass1542c8b2019-08-24 07:22:56 -06001506 elf_fname = self.ElfTestFile('u_boot_binman_syms')
Simon Glass19790632017-11-13 18:55:01 -07001507 syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
1508 addr = elf.GetSymbolAddress(elf_fname, '__image_copy_start')
Alper Nebi Yasak367ecbf2022-06-18 15:13:11 +03001509 self.assertEqual(syms['_binman_sym_magic'].address, addr)
Simon Glassf5898822021-03-18 20:24:56 +13001510 self.assertEqual(syms['_binman_u_boot_spl_any_prop_offset'].address,
Alper Nebi Yasak367ecbf2022-06-18 15:13:11 +03001511 addr + 4)
Simon Glass19790632017-11-13 18:55:01 -07001512
Simon Glass11ae93e2018-10-01 21:12:47 -06001513 self._SetupSplElf('u_boot_binman_syms')
Simon Glass3d433382021-03-21 18:24:30 +13001514 data = self._DoReadFileDtb(dts, entry_args=entry_args,
1515 use_expanded=use_expanded)[0]
Simon Glassf5898822021-03-18 20:24:56 +13001516 # The image should contain the symbols from u_boot_binman_syms.c
1517 # Note that image_pos is adjusted by the base address of the image,
1518 # which is 0x10 in our test image
Alper Nebi Yasak367ecbf2022-06-18 15:13:11 +03001519 sym_values = struct.pack('<LLQLL', elf.BINMAN_SYM_MAGIC_VALUE,
1520 0x00, u_boot_offset + len(U_BOOT_DATA),
Simon Glassf5898822021-03-18 20:24:56 +13001521 0x10 + u_boot_offset, 0x04)
Simon Glass4649bea2023-07-18 07:23:54 -06001522 if no_write_symbols:
1523 expected = (base_data +
1524 tools.get_bytes(0xff, 0x38 - len(base_data)) +
1525 U_BOOT_DATA + base_data)
1526 else:
1527 expected = (sym_values + base_data[24:] +
1528 tools.get_bytes(0xff, 1) + U_BOOT_DATA + sym_values +
1529 base_data[24:])
Simon Glass19790632017-11-13 18:55:01 -07001530 self.assertEqual(expected, data)
1531
Simon Glassf5898822021-03-18 20:24:56 +13001532 def testSymbols(self):
1533 """Test binman can assign symbols embedded in U-Boot"""
Alper Nebi Yasak367ecbf2022-06-18 15:13:11 +03001534 self.checkSymbols('053_symbols.dts', U_BOOT_SPL_DATA, 0x1c)
Simon Glassf5898822021-03-18 20:24:56 +13001535
1536 def testSymbolsNoDtb(self):
1537 """Test binman can assign symbols embedded in U-Boot SPL"""
Simon Glasse9e0db82021-03-21 18:24:29 +13001538 self.checkSymbols('196_symbols_nodtb.dts',
Simon Glassf5898822021-03-18 20:24:56 +13001539 U_BOOT_SPL_NODTB_DATA + U_BOOT_SPL_DTB_DATA,
1540 0x38)
1541
Simon Glassdd57c132018-06-01 09:38:11 -06001542 def testPackUnitAddress(self):
1543 """Test that we support multiple binaries with the same name"""
Simon Glass741f2d62018-10-01 12:22:30 -06001544 data = self._DoReadFile('054_unit_address.dts')
Simon Glassdd57c132018-06-01 09:38:11 -06001545 self.assertEqual(U_BOOT_DATA + U_BOOT_DATA, data)
1546
Simon Glass18546952018-06-01 09:38:16 -06001547 def testSections(self):
1548 """Basic test of sections"""
Simon Glass741f2d62018-10-01 12:22:30 -06001549 data = self._DoReadFile('055_sections.dts')
Simon Glassc1aa66e2022-01-29 14:14:04 -07001550 expected = (U_BOOT_DATA + tools.get_bytes(ord('!'), 12) +
1551 U_BOOT_DATA + tools.get_bytes(ord('a'), 12) +
1552 U_BOOT_DATA + tools.get_bytes(ord('&'), 4))
Simon Glass18546952018-06-01 09:38:16 -06001553 self.assertEqual(expected, data)
Simon Glass9fc60b42017-11-12 21:52:22 -07001554
Simon Glass3b0c3822018-06-01 09:38:20 -06001555 def testMap(self):
1556 """Tests outputting a map of the images"""
Simon Glass741f2d62018-10-01 12:22:30 -06001557 _, _, map_data, _ = self._DoReadFileDtb('055_sections.dts', map=True)
Simon Glass1be70d22018-07-17 13:25:49 -06001558 self.assertEqual('''ImagePos Offset Size Name
Simon Glass193d3db2023-02-07 14:34:18 -0700155900000000 00000000 00000028 image
Simon Glass1be70d22018-07-17 13:25:49 -0600156000000000 00000000 00000010 section@0
156100000000 00000000 00000004 u-boot
156200000010 00000010 00000010 section@1
156300000010 00000000 00000004 u-boot
156400000020 00000020 00000004 section@2
156500000020 00000000 00000004 u-boot
Simon Glass3b0c3822018-06-01 09:38:20 -06001566''', map_data)
1567
Simon Glassc8d48ef2018-06-01 09:38:21 -06001568 def testNamePrefix(self):
1569 """Tests that name prefixes are used"""
Simon Glass741f2d62018-10-01 12:22:30 -06001570 _, _, map_data, _ = self._DoReadFileDtb('056_name_prefix.dts', map=True)
Simon Glass1be70d22018-07-17 13:25:49 -06001571 self.assertEqual('''ImagePos Offset Size Name
Simon Glass193d3db2023-02-07 14:34:18 -0700157200000000 00000000 00000028 image
Simon Glass1be70d22018-07-17 13:25:49 -0600157300000000 00000000 00000010 section@0
157400000000 00000000 00000004 ro-u-boot
157500000010 00000010 00000010 section@1
157600000010 00000000 00000004 rw-u-boot
Simon Glassc8d48ef2018-06-01 09:38:21 -06001577''', map_data)
1578
Simon Glass736bb0a2018-07-06 10:27:17 -06001579 def testUnknownContents(self):
1580 """Test that obtaining the contents works as expected"""
1581 with self.assertRaises(ValueError) as e:
Simon Glass741f2d62018-10-01 12:22:30 -06001582 self._DoReadFile('057_unknown_contents.dts', True)
Simon Glass8beb11e2019-07-08 14:25:47 -06001583 self.assertIn("Image '/binman': Internal error: Could not complete "
Simon Glass16287932020-04-17 18:09:03 -06001584 "processing of contents: remaining ["
1585 "<binman.etype._testing.Entry__testing ", str(e.exception))
Simon Glass736bb0a2018-07-06 10:27:17 -06001586
Simon Glass5c890232018-07-06 10:27:19 -06001587 def testBadChangeSize(self):
1588 """Test that trying to change the size of an entry fails"""
Simon Glassc52c9e72019-07-08 14:25:37 -06001589 try:
1590 state.SetAllowEntryExpansion(False)
1591 with self.assertRaises(ValueError) as e:
1592 self._DoReadFile('059_change_size.dts', True)
Simon Glass79d3c582019-07-20 12:23:57 -06001593 self.assertIn("Node '/binman/_testing': Cannot update entry size from 2 to 3",
Simon Glassc52c9e72019-07-08 14:25:37 -06001594 str(e.exception))
1595 finally:
1596 state.SetAllowEntryExpansion(True)
Simon Glass5c890232018-07-06 10:27:19 -06001597
Simon Glass16b8d6b2018-07-06 10:27:42 -06001598 def testUpdateFdt(self):
Simon Glass3ab95982018-08-01 15:22:37 -06001599 """Test that we can update the device tree with offset/size info"""
Simon Glass741f2d62018-10-01 12:22:30 -06001600 _, _, _, out_dtb_fname = self._DoReadFileDtb('060_fdt_update.dts',
Simon Glass16b8d6b2018-07-06 10:27:42 -06001601 update_dtb=True)
Simon Glasscee02e62018-07-17 13:25:52 -06001602 dtb = fdt.Fdt(out_dtb_fname)
1603 dtb.Scan()
Simon Glass12bb1a92019-07-20 12:23:51 -06001604 props = self._GetPropTree(dtb, BASE_DTB_PROPS + REPACK_DTB_PROPS)
Simon Glass16b8d6b2018-07-06 10:27:42 -06001605 self.assertEqual({
Simon Glassdbf6be92018-08-01 15:22:42 -06001606 'image-pos': 0,
Simon Glass8122f392018-07-17 13:25:28 -06001607 'offset': 0,
Simon Glass3ab95982018-08-01 15:22:37 -06001608 '_testing:offset': 32,
Simon Glass79d3c582019-07-20 12:23:57 -06001609 '_testing:size': 2,
Simon Glassdbf6be92018-08-01 15:22:42 -06001610 '_testing:image-pos': 32,
Simon Glass3ab95982018-08-01 15:22:37 -06001611 'section@0/u-boot:offset': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001612 'section@0/u-boot:size': len(U_BOOT_DATA),
Simon Glassdbf6be92018-08-01 15:22:42 -06001613 'section@0/u-boot:image-pos': 0,
Simon Glass3ab95982018-08-01 15:22:37 -06001614 'section@0:offset': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001615 'section@0:size': 16,
Simon Glassdbf6be92018-08-01 15:22:42 -06001616 'section@0:image-pos': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001617
Simon Glass3ab95982018-08-01 15:22:37 -06001618 'section@1/u-boot:offset': 0,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001619 'section@1/u-boot:size': len(U_BOOT_DATA),
Simon Glassdbf6be92018-08-01 15:22:42 -06001620 'section@1/u-boot:image-pos': 16,
Simon Glass3ab95982018-08-01 15:22:37 -06001621 'section@1:offset': 16,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001622 'section@1:size': 16,
Simon Glassdbf6be92018-08-01 15:22:42 -06001623 'section@1:image-pos': 16,
Simon Glass16b8d6b2018-07-06 10:27:42 -06001624 'size': <