blob: 7de5096352be9229b8d294ff4afe4f4429042851 [file] [log] [blame]
Mike Frysingerf1ba7ad2022-09-12 05:42:57 -04001# Copyright 2013 The ChromiumOS Authors
Simon Glass02741682013-05-26 07:07:58 -07002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""crosfw - Chrome OS Firmware build/flash script.
6
7Builds a firmware image for any board and writes it to the board. The image
8can be pure upstream or include Chrome OS components (-V). Some device
9tree parameters can be provided, including silent console (-C) and secure
10boot (-S). Use -i for a faster incremental build. The image is written to
11the board by default using USB/em100 (or sdcard with -x). Use -b to specify
12the board to build. Options can be added to ~/.crosfwrc - see the script for
13details.
14
15It can also flash SPI by writing a 'magic flasher' U-Boot with a payload
16to the board.
17
Simon Glass02741682013-05-26 07:07:58 -070018The script is normally run from within the U-Boot directory which is
19.../src/third_party/u-boot/files
20
21Example 1: Build upstream image for coreboot and write to a 'link':
22
Simon Glass77cc6ea2023-02-12 08:04:43 -070023 crosfw link
Simon Glass02741682013-05-26 07:07:58 -070024
Simon Glass77cc6ea2023-02-12 08:04:43 -070025Example 2: Build verified boot image (V) for daisy/snow.
Simon Glass02741682013-05-26 07:07:58 -070026
Simon Glass77cc6ea2023-02-12 08:04:43 -070027 crosfw daisy -V
Simon Glass02741682013-05-26 07:07:58 -070028
Simon Glass77cc6ea2023-02-12 08:04:43 -070029You can force a reconfigure with -f and a full distclean with -F.
Simon Glass02741682013-05-26 07:07:58 -070030
Simon Glass77cc6ea2023-02-12 08:04:43 -070031To increase verbosity use the -v and --debug options.
Simon Glass02741682013-05-26 07:07:58 -070032
Simon Glass77cc6ea2023-02-12 08:04:43 -070033This script does not use an ebuild. It does a similar thing to the
Simon Glass02741682013-05-26 07:07:58 -070034chromeos-u-boot ebuild, and runs cros_bundle_firmware to produce various
35types of image, a little like the chromeos-bootimage ebuild.
36
37The purpose of this script is to make it easier and faster to perform
38common firmware build tasks without changing boards, manually updating
39device tree files or lots of USE flags and complexity in the ebuilds.
40
41This script has been tested with snow, link and peach_pit. It builds for
42peach_pit by default. Note that it will also build any upstream ARM
Simon Glass77cc6ea2023-02-12 08:04:43 -070043board - e.g. "snapper9260" will build an image for that board.
Simon Glass02741682013-05-26 07:07:58 -070044
45Mostly you can use the script inside and outside the chroot. The main
46limitation is that dut-control doesn't really work outside the chroot,
47so writing the image to the board over USB is not possible, nor can the
48board be automatically reset on x86 platforms.
49
50For an incremental build (faster), run with -i
51
52To get faster clean builds, install ccache, and create ~/.crosfwrc with
53this line:
54
Simon Glass6ddc7f12013-07-18 15:22:41 -060055 USE_CCACHE = True
Simon Glass02741682013-05-26 07:07:58 -070056
57(make sure ~/.ccache is not on NFS, or set CCACHE_DIR)
58
59Other options are the default board to build, and verbosity (0-4), e.g.:
60
Simon Glass6ddc7f12013-07-18 15:22:41 -060061 DEFAULT_BOARD = 'daisy'
62 VERBOSE = 1
Simon Glass02741682013-05-26 07:07:58 -070063
64It is possible to use multiple servo boards, each on its own port. Add
65these lines to your ~/.crosfwrc to set the servo port to use for each
66board:
67
68 SERVO_PORT['link'] = 8888
69 SERVO_PORT['daisy'] = 9999
70 SERVO_PORT['peach_pit'] = 7777
71
Simon Glassb89ae892013-07-18 15:23:35 -060072All builds appear in the <outdir>/<board> subdirectory and images are written
73to <outdir>/<uboard>/out, where <uboard> is the U-Boot name for the board (in
74the U-Boot boards.cfg file)
75
76The value for <outdir> defaults to /tmp/crosfw but can be configured in your
77~/.crosfwrc file, e.g.:"
78
79 OUT_DIR = '/tmp/u-boot'
Simon Glass02741682013-05-26 07:07:58 -070080
81For the -a option here are some useful options:
82
83--add-blob cros-splash /dev/null
84--gbb-flags -force-dev-switch-on
85--add-node-enable /spi@131b0000/cros-ecp@0 1
86--verify --full-erase
87--bootcmd "cros_test sha"
88--gbb-flags -force-dev-switch-on
Mike Frysinger0246c1f2021-12-14 01:17:17 -050089--bmpblk ~/chromiumos/src/third_party/u-boot/bmp.bin
Simon Glass02741682013-05-26 07:07:58 -070090
91For example: -a "--gbb-flags -force-dev-switch-on"
92
93Note the standard bmpblk is at:
Mike Frysinger0246c1f2021-12-14 01:17:17 -050094 ~/chromiumos/src/third_party/chromiumos-overlay/sys-boot/
95 chromeos-bootimage/files/bmpblk.bin
Simon Glass02741682013-05-26 07:07:58 -070096"""
97
98import glob
Chris McDonald59650c32021-07-20 15:29:28 -060099import logging
Simon Glass02741682013-05-26 07:07:58 -0700100import os
Simon Glassf78c9b52023-02-14 06:58:10 -0700101from pathlib import Path
Simon Glass02741682013-05-26 07:07:58 -0700102import re
Mike Frysinger66d32cd2019-12-17 14:55:29 -0500103import subprocess
Simon Glass02741682013-05-26 07:07:58 -0700104import sys
105
Simon Glass02741682013-05-26 07:07:58 -0700106from chromite.lib import commandline
Chris McDonald59650c32021-07-20 15:29:28 -0600107from chromite.lib import constants
Simon Glass02741682013-05-26 07:07:58 -0700108from chromite.lib import cros_build_lib
109from chromite.lib import osutils
110from chromite.lib import parallel
111
112
113arch = None
114board = None
115compiler = None
116default_board = None
Simon Glass02741682013-05-26 07:07:58 -0700117in_chroot = True
118
Alex Klein1699fab2022-09-08 08:46:06 -0600119kwargs = {
120 "print_cmd": False,
121 "check": False,
Simon Glassdee7d6b2023-02-10 11:35:18 -0700122 "encoding": "utf-8",
Alex Klein1699fab2022-09-08 08:46:06 -0600123}
Simon Glass02741682013-05-26 07:07:58 -0700124
Alex Klein1699fab2022-09-08 08:46:06 -0600125outdir = ""
Simon Glass02741682013-05-26 07:07:58 -0700126
Alex Klein1699fab2022-09-08 08:46:06 -0600127# If you have multiple boards connected on different servo ports, put lines
Simon Glass02741682013-05-26 07:07:58 -0700128# like 'SERVO_PORT{"peach_pit"} = 7777' in your ~/.crosfwrc
129SERVO_PORT = {}
130
Alex Klein1699fab2022-09-08 08:46:06 -0600131src_root = os.path.join(constants.SOURCE_ROOT, "src")
Simon Glass02741682013-05-26 07:07:58 -0700132in_chroot = cros_build_lib.IsInsideChroot()
133
Alex Klein1699fab2022-09-08 08:46:06 -0600134uboard = ""
Simon Glass02741682013-05-26 07:07:58 -0700135
Alex Klein1699fab2022-09-08 08:46:06 -0600136default_board = "peach_pit"
Simon Glass02741682013-05-26 07:07:58 -0700137use_ccache = False
Simon Glass02741682013-05-26 07:07:58 -0700138
139# Special cases for the U-Boot board config, the SOCs and default device tree
140# since the naming is not always consistent.
141# x86 has a lot of boards, but to U-Boot they are all the same
142UBOARDS = {
Alex Klein1699fab2022-09-08 08:46:06 -0600143 "daisy": "smdk5250",
144 "peach": "smdk5420",
Simon Glass02741682013-05-26 07:07:58 -0700145}
Alex Klein1699fab2022-09-08 08:46:06 -0600146for b in [
147 "alex",
148 "butterfly",
149 "emeraldlake2",
150 "link",
151 "lumpy",
152 "parrot",
153 "stout",
154 "stumpy",
155]:
156 UBOARDS[b] = "coreboot-x86"
157 UBOARDS["chromeos_%s" % b] = "chromeos_coreboot"
Simon Glass02741682013-05-26 07:07:58 -0700158
159SOCS = {
Alex Klein1699fab2022-09-08 08:46:06 -0600160 "coreboot-x86": "",
161 "chromeos_coreboot": "",
162 "daisy": "exynos5250-",
163 "peach": "exynos5420-",
Simon Glass02741682013-05-26 07:07:58 -0700164}
165
166DEFAULT_DTS = {
Alex Klein1699fab2022-09-08 08:46:06 -0600167 "daisy": "snow",
168 "daisy_spring": "spring",
169 "peach_pit": "peach-pit",
Simon Glass02741682013-05-26 07:07:58 -0700170}
171
Alex Klein1699fab2022-09-08 08:46:06 -0600172OUT_DIR = "/tmp/crosfw"
Simon Glassb89ae892013-07-18 15:23:35 -0600173
Alex Klein1699fab2022-09-08 08:46:06 -0600174rc_file = os.path.expanduser("~/.crosfwrc")
Simon Glass02741682013-05-26 07:07:58 -0700175if os.path.exists(rc_file):
Mike Frysinger31fdddd2023-02-24 15:50:55 -0500176 with open(rc_file, "rb") as fp:
Alex Klein1699fab2022-09-08 08:46:06 -0600177 # pylint: disable=exec-used
178 exec(compile(fp.read(), rc_file, "exec"))
Simon Glass02741682013-05-26 07:07:58 -0700179
180
Simon Glass02741682013-05-26 07:07:58 -0700181def Dumper(flag, infile, outfile):
Alex Klein1699fab2022-09-08 08:46:06 -0600182 """Run objdump on an input file.
Simon Glass02741682013-05-26 07:07:58 -0700183
Alex Klein1699fab2022-09-08 08:46:06 -0600184 Args:
185 flag: Flag to pass objdump (e.g. '-d').
186 infile: Input file to process.
187 outfile: Output file to write to.
188 """
189 result = cros_build_lib.run(
190 [CompilerTool("objdump"), flag, infile], stdout=outfile, **kwargs
191 )
192 if result.returncode:
193 sys.exit()
Simon Glass02741682013-05-26 07:07:58 -0700194
195
196def CompilerTool(tool):
Alex Klein1699fab2022-09-08 08:46:06 -0600197 """Returns the cross-compiler tool filename.
Simon Glass02741682013-05-26 07:07:58 -0700198
Alex Klein1699fab2022-09-08 08:46:06 -0600199 Args:
200 tool: Tool name to return, e.g. 'size'.
Simon Glass02741682013-05-26 07:07:58 -0700201
Alex Klein1699fab2022-09-08 08:46:06 -0600202 Returns:
203 Filename of requested tool.
204 """
205 return "%s%s" % (compiler, tool)
Simon Glass02741682013-05-26 07:07:58 -0700206
207
208def ParseCmdline(argv):
Alex Klein1699fab2022-09-08 08:46:06 -0600209 """Parse all command line options.
Simon Glass02741682013-05-26 07:07:58 -0700210
Alex Klein1699fab2022-09-08 08:46:06 -0600211 Args:
212 argv: Arguments to parse.
Simon Glass02741682013-05-26 07:07:58 -0700213
Alex Klein1699fab2022-09-08 08:46:06 -0600214 Returns:
215 The parsed options object
216 """
Simon Glass95a316d2023-02-10 11:31:47 -0700217 parser = commandline.ArgumentParser(
218 description=__doc__, default_log_level="notice"
219 )
Alex Klein1699fab2022-09-08 08:46:06 -0600220 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600221 "-B",
222 "--build",
223 action="store_false",
224 default=True,
225 help="Don't build U-Boot, just configure device tree",
226 )
227 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600228 "--dt",
Alex Klein1699fab2022-09-08 08:46:06 -0600229 help="Select name of device tree file to use",
230 )
231 parser.add_argument(
Simon Glasse94b4a42023-02-15 06:35:55 -0700232 "--dtb",
233 type="file_exists",
234 help="Select a binary .dtb, passed to the U-Boot build using EXT_DTB",
235 )
236 parser.add_argument(
Simon Glass77cc6ea2023-02-12 08:04:43 -0700237 "-f",
238 "--force-reconfig",
Alex Klein1699fab2022-09-08 08:46:06 -0600239 action="store_true",
240 default=False,
Simon Glass77cc6ea2023-02-12 08:04:43 -0700241 help="Reconfigure before building",
242 )
243 parser.add_argument(
244 "-F",
245 "--force-distclean",
246 action="store_true",
247 default=False,
248 help="Run distclean and reconfigure before building",
Alex Klein1699fab2022-09-08 08:46:06 -0600249 )
250 parser.add_argument(
Simon Glass73a2f482023-02-15 06:18:50 -0700251 "-j",
252 "--jobs",
253 type=int,
254 default=os.cpu_count(),
255 help="Select the number of CPUs to use (defaults to all)",
256 )
257 parser.add_argument(
Simon Glass37da44f2023-02-15 06:30:58 -0700258 "-I",
259 "--in-tree",
260 action="store_true",
261 default=False,
262 help="Build in-tree",
263 )
264 parser.add_argument(
Simon Glassd080aa72023-02-14 07:04:52 -0700265 "-L",
266 "--no-lto",
267 dest="lto",
268 action="store_false",
269 default=True,
270 help="Disable Link-time Optimisation (LTO) when building",
271 )
272 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600273 "-O",
274 "--objdump",
275 action="store_true",
276 default=False,
277 help="Write disassembly output",
278 )
279 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600280 "-t",
281 "--trace",
282 action="store_true",
283 default=False,
284 help="Enable trace support",
285 )
286 parser.add_argument(
Simon Glassa68488c2023-02-09 16:53:47 -0700287 "-T",
288 "--target",
289 nargs="?",
290 default="all",
291 help="Select target to build",
292 )
293 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600294 "-V",
295 "--verified",
296 action="store_true",
297 default=False,
298 help="Include Chrome OS verified boot components",
299 )
300 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600301 "-z",
302 "--size",
303 action="store_true",
304 default=False,
305 help="Display U-Boot image size",
306 )
307 parser.add_argument(
Simon Glassa68488c2023-02-09 16:53:47 -0700308 "board",
309 type=str,
310 default=default_board,
311 help="Select board to build (daisy/peach_pit/link)",
Alex Klein1699fab2022-09-08 08:46:06 -0600312 )
313 return parser.parse_args(argv)
Simon Glass02741682013-05-26 07:07:58 -0700314
315
Simon Glassc1a323a2016-08-04 20:29:51 -0600316def FindCompiler(gcc, cros_prefix):
Alex Klein1699fab2022-09-08 08:46:06 -0600317 """Look up the compiler for an architecture.
Simon Glassc1a323a2016-08-04 20:29:51 -0600318
Alex Klein1699fab2022-09-08 08:46:06 -0600319 Args:
320 gcc: GCC architecture, either 'arm' or 'aarch64'
321 cros_prefix: Full Chromium OS toolchain prefix
322 """
323 if in_chroot:
324 # Use the Chromium OS toolchain.
325 prefix = cros_prefix
326 else:
327 prefix = glob.glob("/opt/linaro/gcc-linaro-%s-linux-*/bin/*gcc" % gcc)
328 if not prefix:
329 cros_build_lib.Die(
330 """Please install an %s toolchain for your machine.
Simon Glassc1a323a2016-08-04 20:29:51 -0600331Install a Linaro toolchain from:
332https://launchpad.net/linaro-toolchain-binaries
Alex Klein1699fab2022-09-08 08:46:06 -0600333or see cros/commands/cros_chrome_sdk.py."""
334 % gcc
335 )
336 prefix = re.sub("gcc$", "", prefix[0])
337 return prefix
Simon Glassc1a323a2016-08-04 20:29:51 -0600338
339
Simon Glass02741682013-05-26 07:07:58 -0700340def SetupBuild(options):
Alex Klein1699fab2022-09-08 08:46:06 -0600341 """Set up parameters needed for the build.
Simon Glass02741682013-05-26 07:07:58 -0700342
Alex Klein1699fab2022-09-08 08:46:06 -0600343 This checks the current environment and options and sets up various things
344 needed for the build, including 'base' which holds the base flags for
345 passing to the U-Boot Makefile.
Simon Glass02741682013-05-26 07:07:58 -0700346
Alex Klein1699fab2022-09-08 08:46:06 -0600347 Args:
348 options: Command line options
Simon Glass02741682013-05-26 07:07:58 -0700349
Alex Klein1699fab2022-09-08 08:46:06 -0600350 Returns:
351 Base flags to use for U-Boot, as a list.
352 """
353 # pylint: disable=global-statement
Simon Glass826b1df2023-03-02 05:46:45 -0700354 global arch, board, compiler, outdir, uboard
Simon Glass02741682013-05-26 07:07:58 -0700355
Simon Glass9674afc2023-02-10 11:21:30 -0700356 logging.info("Building for %s", options.board)
Simon Glass02741682013-05-26 07:07:58 -0700357
Alex Klein1699fab2022-09-08 08:46:06 -0600358 # Separate out board_variant string: "peach_pit" becomes "peach", "pit".
359 # But don't mess up upstream boards which use _ in their name.
360 parts = options.board.split("_")
361 if parts[0] in ["daisy", "peach"]:
362 board = parts[0]
Simon Glass02741682013-05-26 07:07:58 -0700363 else:
Alex Klein1699fab2022-09-08 08:46:06 -0600364 board = options.board
Simon Glass02741682013-05-26 07:07:58 -0700365
Alex Klein1699fab2022-09-08 08:46:06 -0600366 # To allow this to be run from 'cros_sdk'
367 if in_chroot:
368 os.chdir(os.path.join(src_root, "third_party", "u-boot", "files"))
Simon Glass02741682013-05-26 07:07:58 -0700369
Alex Klein1699fab2022-09-08 08:46:06 -0600370 base_board = board
Simon Glass02741682013-05-26 07:07:58 -0700371
Alex Klein1699fab2022-09-08 08:46:06 -0600372 if options.verified:
373 base_board = "chromeos_%s" % base_board
Simon Glass02741682013-05-26 07:07:58 -0700374
Alex Klein1699fab2022-09-08 08:46:06 -0600375 uboard = UBOARDS.get(base_board, base_board)
Simon Glass9674afc2023-02-10 11:21:30 -0700376 logging.info("U-Boot board is %s", uboard)
Simon Glass02741682013-05-26 07:07:58 -0700377
Alex Klein1699fab2022-09-08 08:46:06 -0600378 # Pull out some information from the U-Boot boards config file
Alex Klein1699fab2022-09-08 08:46:06 -0600379 (PRE_KBUILD, PRE_KCONFIG, KCONFIG) = range(3)
380 if os.path.exists("MAINTAINERS"):
381 board_format = PRE_KBUILD
382 else:
383 board_format = PRE_KCONFIG
Mike Frysinger31fdddd2023-02-24 15:50:55 -0500384 with open("boards.cfg", encoding="utf-8") as f:
Alex Klein1699fab2022-09-08 08:46:06 -0600385 for line in f:
386 if "genboardscfg" in line:
387 board_format = KCONFIG
388 if uboard in line:
389 if line[0] == "#":
390 continue
391 fields = line.split()
392 if not fields:
393 continue
Simon Glassa44a1f92023-02-09 16:31:34 -0700394 target = fields[6]
395 # Make sure this is the right target.
396 if target != uboard:
397 continue
Alex Klein1699fab2022-09-08 08:46:06 -0600398 arch = fields[1]
399 fields += [None, None, None]
Simon Glass826b1df2023-03-02 05:46:45 -0700400 if board_format in (PRE_KCONFIG, KCONFIG):
Alex Klein1699fab2022-09-08 08:46:06 -0600401 target = fields[0]
Alex Klein1699fab2022-09-08 08:46:06 -0600402 if not arch:
403 cros_build_lib.Die(
404 "Selected board '%s' not found in boards.cfg." % board
405 )
Simon Glass02741682013-05-26 07:07:58 -0700406
Alex Klein1699fab2022-09-08 08:46:06 -0600407 vboot = os.path.join("build", board, "usr")
Simon Glass4158d732023-02-17 11:38:31 -0700408 if arch == "sandbox":
409 compiler = ""
410 elif in_chroot:
Simon Glassa44a1f92023-02-09 16:31:34 -0700411 if arch == "x86":
412 compiler = "i686-cros-linux-gnu-"
413 elif arch == "arm":
414 compiler = FindCompiler(arch, "armv7a-cros-linux-gnueabihf-")
415 elif arch == "aarch64":
416 compiler = FindCompiler(arch, "aarch64-cros-linux-gnu-")
Alex Klein1699fab2022-09-08 08:46:06 -0600417 else:
Simon Glassa44a1f92023-02-09 16:31:34 -0700418 result = cros_build_lib.run(
419 ["buildman", "-A", "--boards", options.board],
420 capture_output=True,
Simon Glassa44a1f92023-02-09 16:31:34 -0700421 **kwargs,
422 )
423 compiler = result.stdout.strip()
424 if not compiler:
425 cros_build_lib.Die("Selected arch '%s' not supported.", arch)
Simon Glass02741682013-05-26 07:07:58 -0700426
Alex Klein1699fab2022-09-08 08:46:06 -0600427 base = [
428 "make",
Simon Glass73a2f482023-02-15 06:18:50 -0700429 "-j%d" % options.jobs,
Alex Klein1699fab2022-09-08 08:46:06 -0600430 "CROSS_COMPILE=%s" % compiler,
431 "--no-print-directory",
432 "HOSTSTRIP=true",
Alex Klein1699fab2022-09-08 08:46:06 -0600433 "QEMU_ARCH=",
Simon Glass0c0617f2023-02-19 18:32:16 -0700434 "KCONFIG_NOSILENTUPDATE=1",
Alex Klein1699fab2022-09-08 08:46:06 -0600435 ]
Simon Glassf665da62023-02-15 06:40:51 -0700436 if options.dt:
437 base.append(f"DEVICE_TREE={options.dt}")
Simon Glass37da44f2023-02-15 06:30:58 -0700438 if not options.in_tree:
439 outdir = os.path.join(OUT_DIR, uboard)
440 base.append(f"O={outdir}")
Simon Glassd080aa72023-02-14 07:04:52 -0700441 if not options.lto:
442 base.append("NO_LTO=1")
Simon Glasse94b4a42023-02-15 06:35:55 -0700443 if options.dtb:
444 base.append(f"EXT_DTB={options.dtb}")
Simon Glassd080aa72023-02-14 07:04:52 -0700445
Simon Glass95a316d2023-02-10 11:31:47 -0700446 # Enable quiet output at INFO level, everything at DEBUG level
447 if logging.getLogger().getEffectiveLevel() <= logging.DEBUG:
Alex Klein1699fab2022-09-08 08:46:06 -0600448 base.append("V=1")
Simon Glass95a316d2023-02-10 11:31:47 -0700449 elif logging.getLogger().getEffectiveLevel() >= logging.NOTICE:
450 base.append("-s")
Simon Glass02741682013-05-26 07:07:58 -0700451
Alex Klein1699fab2022-09-08 08:46:06 -0600452 if options.verified:
453 base += [
454 "VBOOT=%s" % vboot,
455 "MAKEFLAGS_VBOOT=DEBUG=1",
456 "QUIET=1",
457 "CFLAGS_EXTRA_VBOOT=-DUNROLL_LOOPS",
458 "VBOOT_SOURCE=%s/platform/vboot_reference" % src_root,
459 ]
460 base.append("VBOOT_DEBUG=1")
461
Alex Klein1699fab2022-09-08 08:46:06 -0600462 base.append("BUILD_ROM=1")
463 if options.trace:
464 base.append("FTRACE=1")
Alex Klein1699fab2022-09-08 08:46:06 -0600465
Simon Glass77cc6ea2023-02-12 08:04:43 -0700466 if not options.force_reconfig:
Alex Klein1699fab2022-09-08 08:46:06 -0600467 config_mk = "%s/include/autoconf.mk" % outdir
468 if not os.path.exists(config_mk):
Simon Glass77cc6ea2023-02-12 08:04:43 -0700469 logging.warning("No build found for %s - adding -f", board)
470 options.force_reconfig = True
Alex Klein1699fab2022-09-08 08:46:06 -0600471
472 config_mk = "include/autoconf.mk"
473 if os.path.exists(config_mk):
Simon Glass37da44f2023-02-15 06:30:58 -0700474 logging.warning("Warning: '%s' exists, try 'make mrproper'", config_mk)
Alex Klein1699fab2022-09-08 08:46:06 -0600475
Alex Klein1699fab2022-09-08 08:46:06 -0600476 return base
Simon Glass02741682013-05-26 07:07:58 -0700477
478
Simon Glassf78c9b52023-02-14 06:58:10 -0700479def CheckConfigChange() -> bool:
480 """See if we need to reconfigure due to config files changing
481
482 Checks if any defconfig or Kconfig file has changed in the source tree
483 since the last time U-Boot was configured for this build. For simplicity,
484 any defconfig change will trigger this, not just one for the board being
485 built, since the cost of a reconfigure is fairly small.
486
487 Returns:
488 True if any config file has changed since U-Boot was last configured
489 """
490 fname = os.path.join(outdir, ".config")
491 ref_time = os.path.getctime(fname)
492 for p in Path.cwd().glob("configs/*"):
493 if p.stat().st_ctime > ref_time:
494 logging.warning("config/ dir has changed - adding -f")
495 return True
496
497 for p in Path.cwd().glob("**/Kconfig*"):
498 if p.stat().st_ctime > ref_time:
499 logging.warning("Kconfig file(s) changed - adding -f")
500 return True
501
502 return False
503
504
Simon Glass02741682013-05-26 07:07:58 -0700505def RunBuild(options, base, target, queue):
Alex Klein1699fab2022-09-08 08:46:06 -0600506 """Run the U-Boot build.
Simon Glass02741682013-05-26 07:07:58 -0700507
Alex Klein1699fab2022-09-08 08:46:06 -0600508 Args:
509 options: Command line options.
510 base: Base U-Boot flags.
511 target: Target to build.
512 queue: A parallel queue to add jobs to.
513 """
Simon Glass9674afc2023-02-10 11:21:30 -0700514 logging.info("U-Boot build flags: %s", " ".join(base))
Simon Glass02741682013-05-26 07:07:58 -0700515
Simon Glass77cc6ea2023-02-12 08:04:43 -0700516 if options.force_distclean:
517 options.force_reconfig = True
Alex Klein1699fab2022-09-08 08:46:06 -0600518 # Ignore any error from this, some older U-Boots fail on this.
Simon Glassdee7d6b2023-02-10 11:35:18 -0700519 cros_build_lib.run(base + ["distclean"], capture_output=True, **kwargs)
Simon Glass77cc6ea2023-02-12 08:04:43 -0700520
Simon Glassf78c9b52023-02-14 06:58:10 -0700521 if not options.force_reconfig:
522 options.force_reconfig = CheckConfigChange()
523
Simon Glass77cc6ea2023-02-12 08:04:43 -0700524 # Reconfigure U-Boot.
525 if options.force_reconfig:
Alex Klein1699fab2022-09-08 08:46:06 -0600526 if os.path.exists("tools/genboardscfg.py"):
527 mtarget = "defconfig"
528 else:
529 mtarget = "config"
530 cmd = base + ["%s_%s" % (uboard, mtarget)]
531 result = cros_build_lib.run(
532 cmd, stdout=True, stderr=subprocess.STDOUT, **kwargs
533 )
Simon Glassdee7d6b2023-02-10 11:35:18 -0700534 if (
535 result.returncode
536 or logging.getLogger().getEffectiveLevel() <= logging.DEBUG
537 ):
538 print(f"cmd: {result.cmdstr}")
539 print(result.stdout, file=sys.stderr)
540 if result.returncode:
541 sys.exit(result.returncode)
Simon Glass02741682013-05-26 07:07:58 -0700542
Alex Klein1699fab2022-09-08 08:46:06 -0600543 # Do the actual build.
544 if options.build:
545 result = cros_build_lib.run(
Simon Glass0c0617f2023-02-19 18:32:16 -0700546 base + [target],
547 input="",
Simon Glassc12ccd72023-03-01 13:35:29 -0700548 capture_output=True,
Simon Glass0c0617f2023-02-19 18:32:16 -0700549 **kwargs,
Alex Klein1699fab2022-09-08 08:46:06 -0600550 )
Simon Glassdee7d6b2023-02-10 11:35:18 -0700551 if (
552 result.returncode
553 or logging.getLogger().getEffectiveLevel() <= logging.INFO
Simon Glassc12ccd72023-03-01 13:35:29 -0700554 or result.stderr
Simon Glassdee7d6b2023-02-10 11:35:18 -0700555 ):
Alex Klein1699fab2022-09-08 08:46:06 -0600556 # The build failed, so output the results to stderr.
Simon Glassc12ccd72023-03-01 13:35:29 -0700557 print(f"cmd: {result.cmdstr}", file=sys.stderr)
558 print(result.stderr, file=sys.stderr)
559
560 # Note that stdout and stderr are separated here, so warnings
561 # associated with a file will appear separately from any output
562 # from the build system
563 if logging.getLogger().getEffectiveLevel() <= logging.INFO:
564 print(result.stdout)
Simon Glassdee7d6b2023-02-10 11:35:18 -0700565 if result.returncode:
566 sys.exit(result.returncode)
Simon Glass02741682013-05-26 07:07:58 -0700567
Alex Klein1699fab2022-09-08 08:46:06 -0600568 files = ["%s/u-boot" % outdir]
569 spl = glob.glob("%s/spl/u-boot-spl" % outdir)
570 if spl:
571 files += spl
572 if options.size:
573 result = cros_build_lib.run([CompilerTool("size")] + files, **kwargs)
574 if result.returncode:
575 sys.exit()
Simon Glass02741682013-05-26 07:07:58 -0700576
Alex Klein1699fab2022-09-08 08:46:06 -0600577 # Create disassembly files .dis and .Dis (full dump)
578 for f in files:
579 base = os.path.splitext(f)[0]
580 if options.objdump:
581 queue.put(("-d", f, base + ".dis"))
582 queue.put(("-D", f, base + ".Dis"))
583 else:
584 # Remove old files which otherwise might be confusing
585 osutils.SafeUnlink(base + ".dis")
586 osutils.SafeUnlink(base + ".Dis")
Simon Glass02741682013-05-26 07:07:58 -0700587
Simon Glass9674afc2023-02-10 11:21:30 -0700588 logging.info("Output directory %s", outdir)
Simon Glass02741682013-05-26 07:07:58 -0700589
590
Simon Glass02741682013-05-26 07:07:58 -0700591def main(argv):
Simon Glasse6201d72023-02-09 16:42:22 -0700592 """Main function for script to build firmware.
Simon Glass02741682013-05-26 07:07:58 -0700593
Alex Klein1699fab2022-09-08 08:46:06 -0600594 Args:
595 argv: Program arguments.
596 """
597 options = ParseCmdline(argv)
598 base = SetupBuild(options)
Simon Glass02741682013-05-26 07:07:58 -0700599
Alex Klein1699fab2022-09-08 08:46:06 -0600600 with parallel.BackgroundTaskRunner(Dumper) as queue:
601 RunBuild(options, base, options.target, queue)
Simon Glass02741682013-05-26 07:07:58 -0700602
Alex Klein1699fab2022-09-08 08:46:06 -0600603 if options.objdump:
Simon Glass9674afc2023-02-10 11:21:30 -0700604 logging.info("Writing diasssembly files")