blob: 3f940f4de18536ea4619bfc4060376a29b216e88 [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
Mike Frysinger66d32cd2019-12-17 14:55:29 -0500102import subprocess
Simon Glass02741682013-05-26 07:07:58 -0700103import sys
Simon Glass313cc8a2023-06-21 10:24:39 +0100104from typing import Any, Dict, List
Simon Glass02741682013-05-26 07:07:58 -0700105
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
Alex Klein1699fab2022-09-08 08:46:06 -0600118outdir = ""
Simon Glass02741682013-05-26 07:07:58 -0700119
Alex Klein1699fab2022-09-08 08:46:06 -0600120# If you have multiple boards connected on different servo ports, put lines
Simon Glass02741682013-05-26 07:07:58 -0700121# like 'SERVO_PORT{"peach_pit"} = 7777' in your ~/.crosfwrc
122SERVO_PORT = {}
123
Alex Klein1699fab2022-09-08 08:46:06 -0600124src_root = os.path.join(constants.SOURCE_ROOT, "src")
Simon Glass02741682013-05-26 07:07:58 -0700125in_chroot = cros_build_lib.IsInsideChroot()
126
Alex Klein1699fab2022-09-08 08:46:06 -0600127uboard = ""
Simon Glass02741682013-05-26 07:07:58 -0700128
Alex Klein1699fab2022-09-08 08:46:06 -0600129default_board = "peach_pit"
Simon Glass02741682013-05-26 07:07:58 -0700130use_ccache = False
Simon Glass02741682013-05-26 07:07:58 -0700131
132# Special cases for the U-Boot board config, the SOCs and default device tree
133# since the naming is not always consistent.
134# x86 has a lot of boards, but to U-Boot they are all the same
135UBOARDS = {
Alex Klein1699fab2022-09-08 08:46:06 -0600136 "daisy": "smdk5250",
137 "peach": "smdk5420",
Simon Glass02741682013-05-26 07:07:58 -0700138}
Alex Klein1699fab2022-09-08 08:46:06 -0600139for b in [
140 "alex",
141 "butterfly",
142 "emeraldlake2",
143 "link",
144 "lumpy",
145 "parrot",
146 "stout",
147 "stumpy",
148]:
149 UBOARDS[b] = "coreboot-x86"
150 UBOARDS["chromeos_%s" % b] = "chromeos_coreboot"
Simon Glass02741682013-05-26 07:07:58 -0700151
Alex Klein1699fab2022-09-08 08:46:06 -0600152OUT_DIR = "/tmp/crosfw"
Simon Glassb89ae892013-07-18 15:23:35 -0600153
Alex Klein1699fab2022-09-08 08:46:06 -0600154rc_file = os.path.expanduser("~/.crosfwrc")
Simon Glass02741682013-05-26 07:07:58 -0700155if os.path.exists(rc_file):
Mike Frysinger31fdddd2023-02-24 15:50:55 -0500156 with open(rc_file, "rb") as fp:
Alex Klein1699fab2022-09-08 08:46:06 -0600157 # pylint: disable=exec-used
158 exec(compile(fp.read(), rc_file, "exec"))
Simon Glass02741682013-05-26 07:07:58 -0700159
160
Simon Glass313cc8a2023-06-21 10:24:39 +0100161def run(cmd: List[str], **kwargs: Dict[Any, Any]):
162 """Run a command with the common settings.
163
164 Args:
165 cmd: Command + arguments to run.
166 **kwargs: keyword arguments to pass on to cros_build_lib.run().
167
168 Returns:
169 A CompletedProcess object.
170 """
171 kwargs.setdefault("print_cmd", False)
172 kwargs.setdefault("check", False)
173 kwargs.setdefault("encoding", "utf-8")
174 return cros_build_lib.run(cmd, **kwargs)
175
176
Simon Glass02741682013-05-26 07:07:58 -0700177def Dumper(flag, infile, outfile):
Alex Klein1699fab2022-09-08 08:46:06 -0600178 """Run objdump on an input file.
Simon Glass02741682013-05-26 07:07:58 -0700179
Alex Klein1699fab2022-09-08 08:46:06 -0600180 Args:
Trent Apted66736d82023-05-25 10:38:28 +1000181 flag: Flag to pass objdump (e.g. '-d').
182 infile: Input file to process.
183 outfile: Output file to write to.
Alex Klein1699fab2022-09-08 08:46:06 -0600184 """
Simon Glass313cc8a2023-06-21 10:24:39 +0100185 result = run([CompilerTool("objdump"), flag, infile], stdout=outfile)
Alex Klein1699fab2022-09-08 08:46:06 -0600186 if result.returncode:
187 sys.exit()
Simon Glass02741682013-05-26 07:07:58 -0700188
189
190def CompilerTool(tool):
Alex Klein1699fab2022-09-08 08:46:06 -0600191 """Returns the cross-compiler tool filename.
Simon Glass02741682013-05-26 07:07:58 -0700192
Alex Klein1699fab2022-09-08 08:46:06 -0600193 Args:
Trent Apted66736d82023-05-25 10:38:28 +1000194 tool: Tool name to return, e.g. 'size'.
Simon Glass02741682013-05-26 07:07:58 -0700195
Alex Klein1699fab2022-09-08 08:46:06 -0600196 Returns:
Trent Apted66736d82023-05-25 10:38:28 +1000197 Filename of requested tool.
Alex Klein1699fab2022-09-08 08:46:06 -0600198 """
199 return "%s%s" % (compiler, tool)
Simon Glass02741682013-05-26 07:07:58 -0700200
201
202def ParseCmdline(argv):
Alex Klein1699fab2022-09-08 08:46:06 -0600203 """Parse all command line options.
Simon Glass02741682013-05-26 07:07:58 -0700204
Alex Klein1699fab2022-09-08 08:46:06 -0600205 Args:
Trent Apted66736d82023-05-25 10:38:28 +1000206 argv: Arguments to parse.
Simon Glass02741682013-05-26 07:07:58 -0700207
Alex Klein1699fab2022-09-08 08:46:06 -0600208 Returns:
Trent Apted66736d82023-05-25 10:38:28 +1000209 The parsed options object
Alex Klein1699fab2022-09-08 08:46:06 -0600210 """
Simon Glass95a316d2023-02-10 11:31:47 -0700211 parser = commandline.ArgumentParser(
212 description=__doc__, default_log_level="notice"
213 )
Alex Klein1699fab2022-09-08 08:46:06 -0600214 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600215 "-B",
216 "--build",
217 action="store_false",
218 default=True,
219 help="Don't build U-Boot, just configure device tree",
220 )
221 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600222 "--dt",
Alex Klein1699fab2022-09-08 08:46:06 -0600223 help="Select name of device tree file to use",
224 )
225 parser.add_argument(
Simon Glasse94b4a42023-02-15 06:35:55 -0700226 "--dtb",
227 type="file_exists",
228 help="Select a binary .dtb, passed to the U-Boot build using EXT_DTB",
229 )
230 parser.add_argument(
Simon Glass77cc6ea2023-02-12 08:04:43 -0700231 "-f",
232 "--force-reconfig",
Alex Klein1699fab2022-09-08 08:46:06 -0600233 action="store_true",
234 default=False,
Simon Glass77cc6ea2023-02-12 08:04:43 -0700235 help="Reconfigure before building",
236 )
237 parser.add_argument(
238 "-F",
239 "--force-distclean",
240 action="store_true",
241 default=False,
242 help="Run distclean and reconfigure before building",
Alex Klein1699fab2022-09-08 08:46:06 -0600243 )
244 parser.add_argument(
Simon Glass73a2f482023-02-15 06:18:50 -0700245 "-j",
246 "--jobs",
247 type=int,
248 default=os.cpu_count(),
249 help="Select the number of CPUs to use (defaults to all)",
250 )
251 parser.add_argument(
Simon Glass37da44f2023-02-15 06:30:58 -0700252 "-I",
253 "--in-tree",
254 action="store_true",
255 default=False,
256 help="Build in-tree",
257 )
258 parser.add_argument(
Simon Glassd080aa72023-02-14 07:04:52 -0700259 "-L",
260 "--no-lto",
261 dest="lto",
262 action="store_false",
263 default=True,
264 help="Disable Link-time Optimisation (LTO) when building",
265 )
266 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600267 "-O",
268 "--objdump",
269 action="store_true",
270 default=False,
271 help="Write disassembly output",
272 )
273 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600274 "-t",
275 "--trace",
276 action="store_true",
277 default=False,
278 help="Enable trace support",
279 )
280 parser.add_argument(
Simon Glassa68488c2023-02-09 16:53:47 -0700281 "-T",
282 "--target",
283 nargs="?",
284 default="all",
285 help="Select target to build",
286 )
287 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600288 "-V",
289 "--verified",
290 action="store_true",
291 default=False,
292 help="Include Chrome OS verified boot components",
293 )
294 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600295 "-z",
296 "--size",
297 action="store_true",
298 default=False,
299 help="Display U-Boot image size",
300 )
301 parser.add_argument(
Simon Glassa68488c2023-02-09 16:53:47 -0700302 "board",
303 type=str,
304 default=default_board,
305 help="Select board to build (daisy/peach_pit/link)",
Alex Klein1699fab2022-09-08 08:46:06 -0600306 )
307 return parser.parse_args(argv)
Simon Glass02741682013-05-26 07:07:58 -0700308
309
310def SetupBuild(options):
Alex Klein1699fab2022-09-08 08:46:06 -0600311 """Set up parameters needed for the build.
Simon Glass02741682013-05-26 07:07:58 -0700312
Alex Klein1699fab2022-09-08 08:46:06 -0600313 This checks the current environment and options and sets up various things
314 needed for the build, including 'base' which holds the base flags for
315 passing to the U-Boot Makefile.
Simon Glass02741682013-05-26 07:07:58 -0700316
Alex Klein1699fab2022-09-08 08:46:06 -0600317 Args:
Trent Apted66736d82023-05-25 10:38:28 +1000318 options: Command line options
Simon Glass02741682013-05-26 07:07:58 -0700319
Alex Klein1699fab2022-09-08 08:46:06 -0600320 Returns:
Trent Apted66736d82023-05-25 10:38:28 +1000321 Base flags to use for U-Boot, as a list.
Alex Klein1699fab2022-09-08 08:46:06 -0600322 """
323 # pylint: disable=global-statement
Simon Glass826b1df2023-03-02 05:46:45 -0700324 global arch, board, compiler, outdir, uboard
Simon Glass02741682013-05-26 07:07:58 -0700325
Simon Glass9674afc2023-02-10 11:21:30 -0700326 logging.info("Building for %s", options.board)
Simon Glass02741682013-05-26 07:07:58 -0700327
Alex Klein1699fab2022-09-08 08:46:06 -0600328 # Separate out board_variant string: "peach_pit" becomes "peach", "pit".
329 # But don't mess up upstream boards which use _ in their name.
330 parts = options.board.split("_")
331 if parts[0] in ["daisy", "peach"]:
332 board = parts[0]
Simon Glass02741682013-05-26 07:07:58 -0700333 else:
Alex Klein1699fab2022-09-08 08:46:06 -0600334 board = options.board
Simon Glass02741682013-05-26 07:07:58 -0700335
Alex Klein1699fab2022-09-08 08:46:06 -0600336 # To allow this to be run from 'cros_sdk'
337 if in_chroot:
338 os.chdir(os.path.join(src_root, "third_party", "u-boot", "files"))
Simon Glass02741682013-05-26 07:07:58 -0700339
Alex Klein1699fab2022-09-08 08:46:06 -0600340 base_board = board
Simon Glass02741682013-05-26 07:07:58 -0700341
Alex Klein1699fab2022-09-08 08:46:06 -0600342 if options.verified:
343 base_board = "chromeos_%s" % base_board
Simon Glass02741682013-05-26 07:07:58 -0700344
Alex Klein1699fab2022-09-08 08:46:06 -0600345 uboard = UBOARDS.get(base_board, base_board)
Simon Glass9674afc2023-02-10 11:21:30 -0700346 logging.info("U-Boot board is %s", uboard)
Simon Glass02741682013-05-26 07:07:58 -0700347
Alex Klein1699fab2022-09-08 08:46:06 -0600348 # Pull out some information from the U-Boot boards config file
Alex Klein1699fab2022-09-08 08:46:06 -0600349 (PRE_KBUILD, PRE_KCONFIG, KCONFIG) = range(3)
350 if os.path.exists("MAINTAINERS"):
351 board_format = PRE_KBUILD
352 else:
353 board_format = PRE_KCONFIG
Simon Glass0b847c42023-06-15 11:37:19 +0100354
355 # Create the boards.cfg file if missing.
Simon Glassadb6b8a2023-07-31 13:53:20 -0600356 if not os.path.exists("boards.cfg"):
357 run(["buildman", "-R", "boards.cfg"])
Simon Glass0b847c42023-06-15 11:37:19 +0100358
Mike Frysinger31fdddd2023-02-24 15:50:55 -0500359 with open("boards.cfg", encoding="utf-8") as f:
Alex Klein1699fab2022-09-08 08:46:06 -0600360 for line in f:
361 if "genboardscfg" in line:
362 board_format = KCONFIG
363 if uboard in line:
364 if line[0] == "#":
365 continue
366 fields = line.split()
367 if not fields:
368 continue
Simon Glassa44a1f92023-02-09 16:31:34 -0700369 target = fields[6]
370 # Make sure this is the right target.
371 if target != uboard:
372 continue
Alex Klein1699fab2022-09-08 08:46:06 -0600373 arch = fields[1]
374 fields += [None, None, None]
Simon Glass826b1df2023-03-02 05:46:45 -0700375 if board_format in (PRE_KCONFIG, KCONFIG):
Alex Klein1699fab2022-09-08 08:46:06 -0600376 target = fields[0]
Alex Klein1699fab2022-09-08 08:46:06 -0600377 if not arch:
378 cros_build_lib.Die(
379 "Selected board '%s' not found in boards.cfg." % board
380 )
Simon Glass02741682013-05-26 07:07:58 -0700381
Alex Klein1699fab2022-09-08 08:46:06 -0600382 vboot = os.path.join("build", board, "usr")
Simon Glass4158d732023-02-17 11:38:31 -0700383 if arch == "sandbox":
384 compiler = ""
385 elif in_chroot:
Simon Glassa44a1f92023-02-09 16:31:34 -0700386 if arch == "x86":
387 compiler = "i686-cros-linux-gnu-"
388 elif arch == "arm":
Simon Glassa3456622023-03-02 05:46:45 -0700389 compiler = "armv7a-cros-linux-gnueabihf-"
Simon Glassa44a1f92023-02-09 16:31:34 -0700390 elif arch == "aarch64":
Simon Glassa3456622023-03-02 05:46:45 -0700391 compiler = "aarch64-cros-linux-gnu-"
Alex Klein1699fab2022-09-08 08:46:06 -0600392 else:
Simon Glass313cc8a2023-06-21 10:24:39 +0100393 result = run(
Simon Glassa44a1f92023-02-09 16:31:34 -0700394 ["buildman", "-A", "--boards", options.board],
395 capture_output=True,
Simon Glassa44a1f92023-02-09 16:31:34 -0700396 )
397 compiler = result.stdout.strip()
398 if not compiler:
399 cros_build_lib.Die("Selected arch '%s' not supported.", arch)
Simon Glass02741682013-05-26 07:07:58 -0700400
Alex Klein1699fab2022-09-08 08:46:06 -0600401 base = [
402 "make",
Simon Glass73a2f482023-02-15 06:18:50 -0700403 "-j%d" % options.jobs,
Alex Klein1699fab2022-09-08 08:46:06 -0600404 "CROSS_COMPILE=%s" % compiler,
405 "--no-print-directory",
406 "HOSTSTRIP=true",
Alex Klein1699fab2022-09-08 08:46:06 -0600407 "QEMU_ARCH=",
Simon Glass0c0617f2023-02-19 18:32:16 -0700408 "KCONFIG_NOSILENTUPDATE=1",
Alex Klein1699fab2022-09-08 08:46:06 -0600409 ]
Simon Glassf665da62023-02-15 06:40:51 -0700410 if options.dt:
411 base.append(f"DEVICE_TREE={options.dt}")
Simon Glass37da44f2023-02-15 06:30:58 -0700412 if not options.in_tree:
413 outdir = os.path.join(OUT_DIR, uboard)
414 base.append(f"O={outdir}")
Simon Glassd080aa72023-02-14 07:04:52 -0700415 if not options.lto:
416 base.append("NO_LTO=1")
Simon Glasse94b4a42023-02-15 06:35:55 -0700417 if options.dtb:
418 base.append(f"EXT_DTB={options.dtb}")
Simon Glassd080aa72023-02-14 07:04:52 -0700419
Simon Glass95a316d2023-02-10 11:31:47 -0700420 # Enable quiet output at INFO level, everything at DEBUG level
421 if logging.getLogger().getEffectiveLevel() <= logging.DEBUG:
Alex Klein1699fab2022-09-08 08:46:06 -0600422 base.append("V=1")
Simon Glass95a316d2023-02-10 11:31:47 -0700423 elif logging.getLogger().getEffectiveLevel() >= logging.NOTICE:
424 base.append("-s")
Simon Glass02741682013-05-26 07:07:58 -0700425
Alex Klein1699fab2022-09-08 08:46:06 -0600426 if options.verified:
427 base += [
428 "VBOOT=%s" % vboot,
429 "MAKEFLAGS_VBOOT=DEBUG=1",
430 "QUIET=1",
431 "CFLAGS_EXTRA_VBOOT=-DUNROLL_LOOPS",
432 "VBOOT_SOURCE=%s/platform/vboot_reference" % src_root,
433 ]
434 base.append("VBOOT_DEBUG=1")
435
Alex Klein1699fab2022-09-08 08:46:06 -0600436 base.append("BUILD_ROM=1")
437 if options.trace:
438 base.append("FTRACE=1")
Alex Klein1699fab2022-09-08 08:46:06 -0600439
Simon Glass77cc6ea2023-02-12 08:04:43 -0700440 if not options.force_reconfig:
Alex Klein1699fab2022-09-08 08:46:06 -0600441 config_mk = "%s/include/autoconf.mk" % outdir
442 if not os.path.exists(config_mk):
Simon Glass77cc6ea2023-02-12 08:04:43 -0700443 logging.warning("No build found for %s - adding -f", board)
444 options.force_reconfig = True
Alex Klein1699fab2022-09-08 08:46:06 -0600445
446 config_mk = "include/autoconf.mk"
447 if os.path.exists(config_mk):
Simon Glass37da44f2023-02-15 06:30:58 -0700448 logging.warning("Warning: '%s' exists, try 'make mrproper'", config_mk)
Alex Klein1699fab2022-09-08 08:46:06 -0600449
Alex Klein1699fab2022-09-08 08:46:06 -0600450 return base
Simon Glass02741682013-05-26 07:07:58 -0700451
452
Simon Glassf78c9b52023-02-14 06:58:10 -0700453def CheckConfigChange() -> bool:
454 """See if we need to reconfigure due to config files changing
455
456 Checks if any defconfig or Kconfig file has changed in the source tree
457 since the last time U-Boot was configured for this build. For simplicity,
458 any defconfig change will trigger this, not just one for the board being
459 built, since the cost of a reconfigure is fairly small.
460
461 Returns:
462 True if any config file has changed since U-Boot was last configured
463 """
464 fname = os.path.join(outdir, ".config")
465 ref_time = os.path.getctime(fname)
466 for p in Path.cwd().glob("configs/*"):
467 if p.stat().st_ctime > ref_time:
468 logging.warning("config/ dir has changed - adding -f")
469 return True
470
471 for p in Path.cwd().glob("**/Kconfig*"):
472 if p.stat().st_ctime > ref_time:
473 logging.warning("Kconfig file(s) changed - adding -f")
474 return True
475
476 return False
477
478
Simon Glass02741682013-05-26 07:07:58 -0700479def RunBuild(options, base, target, queue):
Alex Klein1699fab2022-09-08 08:46:06 -0600480 """Run the U-Boot build.
Simon Glass02741682013-05-26 07:07:58 -0700481
Alex Klein1699fab2022-09-08 08:46:06 -0600482 Args:
Trent Apted66736d82023-05-25 10:38:28 +1000483 options: Command line options.
484 base: Base U-Boot flags.
485 target: Target to build.
486 queue: A parallel queue to add jobs to.
Alex Klein1699fab2022-09-08 08:46:06 -0600487 """
Simon Glass9674afc2023-02-10 11:21:30 -0700488 logging.info("U-Boot build flags: %s", " ".join(base))
Simon Glass02741682013-05-26 07:07:58 -0700489
Simon Glass77cc6ea2023-02-12 08:04:43 -0700490 if options.force_distclean:
491 options.force_reconfig = True
Alex Klein1699fab2022-09-08 08:46:06 -0600492 # Ignore any error from this, some older U-Boots fail on this.
Simon Glass313cc8a2023-06-21 10:24:39 +0100493 run(base + ["distclean"], capture_output=True)
Simon Glass77cc6ea2023-02-12 08:04:43 -0700494
Simon Glassf78c9b52023-02-14 06:58:10 -0700495 if not options.force_reconfig:
496 options.force_reconfig = CheckConfigChange()
497
Simon Glass77cc6ea2023-02-12 08:04:43 -0700498 # Reconfigure U-Boot.
499 if options.force_reconfig:
Alex Klein1699fab2022-09-08 08:46:06 -0600500 if os.path.exists("tools/genboardscfg.py"):
501 mtarget = "defconfig"
502 else:
503 mtarget = "config"
504 cmd = base + ["%s_%s" % (uboard, mtarget)]
Simon Glass313cc8a2023-06-21 10:24:39 +0100505 result = run(cmd, stdout=True, stderr=subprocess.STDOUT)
Simon Glassdee7d6b2023-02-10 11:35:18 -0700506 if (
507 result.returncode
508 or logging.getLogger().getEffectiveLevel() <= logging.DEBUG
509 ):
510 print(f"cmd: {result.cmdstr}")
511 print(result.stdout, file=sys.stderr)
512 if result.returncode:
513 sys.exit(result.returncode)
Simon Glass02741682013-05-26 07:07:58 -0700514
Alex Klein1699fab2022-09-08 08:46:06 -0600515 # Do the actual build.
516 if options.build:
Simon Glass313cc8a2023-06-21 10:24:39 +0100517 result = run(base + [target], input="", capture_output=True)
Simon Glassdee7d6b2023-02-10 11:35:18 -0700518 if (
519 result.returncode
520 or logging.getLogger().getEffectiveLevel() <= logging.INFO
Simon Glassc12ccd72023-03-01 13:35:29 -0700521 or result.stderr
Simon Glassdee7d6b2023-02-10 11:35:18 -0700522 ):
Alex Klein1699fab2022-09-08 08:46:06 -0600523 # The build failed, so output the results to stderr.
Simon Glassc12ccd72023-03-01 13:35:29 -0700524 print(f"cmd: {result.cmdstr}", file=sys.stderr)
525 print(result.stderr, file=sys.stderr)
526
527 # Note that stdout and stderr are separated here, so warnings
528 # associated with a file will appear separately from any output
529 # from the build system
530 if logging.getLogger().getEffectiveLevel() <= logging.INFO:
531 print(result.stdout)
Simon Glassdee7d6b2023-02-10 11:35:18 -0700532 if result.returncode:
533 sys.exit(result.returncode)
Simon Glass02741682013-05-26 07:07:58 -0700534
Alex Klein1699fab2022-09-08 08:46:06 -0600535 files = ["%s/u-boot" % outdir]
536 spl = glob.glob("%s/spl/u-boot-spl" % outdir)
537 if spl:
538 files += spl
539 if options.size:
Simon Glass313cc8a2023-06-21 10:24:39 +0100540 result = run([CompilerTool("size")] + files)
Alex Klein1699fab2022-09-08 08:46:06 -0600541 if result.returncode:
542 sys.exit()
Simon Glass02741682013-05-26 07:07:58 -0700543
Alex Klein1699fab2022-09-08 08:46:06 -0600544 # Create disassembly files .dis and .Dis (full dump)
545 for f in files:
546 base = os.path.splitext(f)[0]
547 if options.objdump:
548 queue.put(("-d", f, base + ".dis"))
549 queue.put(("-D", f, base + ".Dis"))
550 else:
551 # Remove old files which otherwise might be confusing
552 osutils.SafeUnlink(base + ".dis")
553 osutils.SafeUnlink(base + ".Dis")
Simon Glass02741682013-05-26 07:07:58 -0700554
Simon Glass9674afc2023-02-10 11:21:30 -0700555 logging.info("Output directory %s", outdir)
Simon Glass02741682013-05-26 07:07:58 -0700556
557
Simon Glass02741682013-05-26 07:07:58 -0700558def main(argv):
Simon Glasse6201d72023-02-09 16:42:22 -0700559 """Main function for script to build firmware.
Simon Glass02741682013-05-26 07:07:58 -0700560
Alex Klein1699fab2022-09-08 08:46:06 -0600561 Args:
Trent Apted66736d82023-05-25 10:38:28 +1000562 argv: Program arguments.
Alex Klein1699fab2022-09-08 08:46:06 -0600563 """
564 options = ParseCmdline(argv)
565 base = SetupBuild(options)
Simon Glass02741682013-05-26 07:07:58 -0700566
Alex Klein1699fab2022-09-08 08:46:06 -0600567 with parallel.BackgroundTaskRunner(Dumper) as queue:
568 RunBuild(options, base, options.target, queue)
Simon Glass02741682013-05-26 07:07:58 -0700569
Alex Klein1699fab2022-09-08 08:46:06 -0600570 if options.objdump:
Simon Glass9674afc2023-02-10 11:21:30 -0700571 logging.info("Writing diasssembly files")