blob: 6034d4c9738ffea95dc3a5fb3603279764052a59 [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
117family = None
118in_chroot = True
119
Alex Klein1699fab2022-09-08 08:46:06 -0600120kwargs = {
121 "print_cmd": False,
122 "check": False,
Simon Glassdee7d6b2023-02-10 11:35:18 -0700123 "encoding": "utf-8",
Alex Klein1699fab2022-09-08 08:46:06 -0600124}
Simon Glass02741682013-05-26 07:07:58 -0700125
Alex Klein1699fab2022-09-08 08:46:06 -0600126outdir = ""
Simon Glass02741682013-05-26 07:07:58 -0700127
Alex Klein1699fab2022-09-08 08:46:06 -0600128# If you have multiple boards connected on different servo ports, put lines
Simon Glass02741682013-05-26 07:07:58 -0700129# like 'SERVO_PORT{"peach_pit"} = 7777' in your ~/.crosfwrc
130SERVO_PORT = {}
131
132smdk = None
Alex Klein1699fab2022-09-08 08:46:06 -0600133src_root = os.path.join(constants.SOURCE_ROOT, "src")
Simon Glass02741682013-05-26 07:07:58 -0700134in_chroot = cros_build_lib.IsInsideChroot()
135
Alex Klein1699fab2022-09-08 08:46:06 -0600136uboard = ""
Simon Glass02741682013-05-26 07:07:58 -0700137
Alex Klein1699fab2022-09-08 08:46:06 -0600138default_board = "peach_pit"
Simon Glass02741682013-05-26 07:07:58 -0700139use_ccache = False
140vendor = None
Simon Glass02741682013-05-26 07:07:58 -0700141
142# Special cases for the U-Boot board config, the SOCs and default device tree
143# since the naming is not always consistent.
144# x86 has a lot of boards, but to U-Boot they are all the same
145UBOARDS = {
Alex Klein1699fab2022-09-08 08:46:06 -0600146 "daisy": "smdk5250",
147 "peach": "smdk5420",
Simon Glass02741682013-05-26 07:07:58 -0700148}
Alex Klein1699fab2022-09-08 08:46:06 -0600149for b in [
150 "alex",
151 "butterfly",
152 "emeraldlake2",
153 "link",
154 "lumpy",
155 "parrot",
156 "stout",
157 "stumpy",
158]:
159 UBOARDS[b] = "coreboot-x86"
160 UBOARDS["chromeos_%s" % b] = "chromeos_coreboot"
Simon Glass02741682013-05-26 07:07:58 -0700161
162SOCS = {
Alex Klein1699fab2022-09-08 08:46:06 -0600163 "coreboot-x86": "",
164 "chromeos_coreboot": "",
165 "daisy": "exynos5250-",
166 "peach": "exynos5420-",
Simon Glass02741682013-05-26 07:07:58 -0700167}
168
169DEFAULT_DTS = {
Alex Klein1699fab2022-09-08 08:46:06 -0600170 "daisy": "snow",
171 "daisy_spring": "spring",
172 "peach_pit": "peach-pit",
Simon Glass02741682013-05-26 07:07:58 -0700173}
174
Alex Klein1699fab2022-09-08 08:46:06 -0600175OUT_DIR = "/tmp/crosfw"
Simon Glassb89ae892013-07-18 15:23:35 -0600176
Alex Klein1699fab2022-09-08 08:46:06 -0600177rc_file = os.path.expanduser("~/.crosfwrc")
Simon Glass02741682013-05-26 07:07:58 -0700178if os.path.exists(rc_file):
Mike Frysinger31fdddd2023-02-24 15:50:55 -0500179 with open(rc_file, "rb") as fp:
Alex Klein1699fab2022-09-08 08:46:06 -0600180 # pylint: disable=exec-used
181 exec(compile(fp.read(), rc_file, "exec"))
Simon Glass02741682013-05-26 07:07:58 -0700182
183
Simon Glass02741682013-05-26 07:07:58 -0700184def Dumper(flag, infile, outfile):
Alex Klein1699fab2022-09-08 08:46:06 -0600185 """Run objdump on an input file.
Simon Glass02741682013-05-26 07:07:58 -0700186
Alex Klein1699fab2022-09-08 08:46:06 -0600187 Args:
188 flag: Flag to pass objdump (e.g. '-d').
189 infile: Input file to process.
190 outfile: Output file to write to.
191 """
192 result = cros_build_lib.run(
193 [CompilerTool("objdump"), flag, infile], stdout=outfile, **kwargs
194 )
195 if result.returncode:
196 sys.exit()
Simon Glass02741682013-05-26 07:07:58 -0700197
198
199def CompilerTool(tool):
Alex Klein1699fab2022-09-08 08:46:06 -0600200 """Returns the cross-compiler tool filename.
Simon Glass02741682013-05-26 07:07:58 -0700201
Alex Klein1699fab2022-09-08 08:46:06 -0600202 Args:
203 tool: Tool name to return, e.g. 'size'.
Simon Glass02741682013-05-26 07:07:58 -0700204
Alex Klein1699fab2022-09-08 08:46:06 -0600205 Returns:
206 Filename of requested tool.
207 """
208 return "%s%s" % (compiler, tool)
Simon Glass02741682013-05-26 07:07:58 -0700209
210
211def ParseCmdline(argv):
Alex Klein1699fab2022-09-08 08:46:06 -0600212 """Parse all command line options.
Simon Glass02741682013-05-26 07:07:58 -0700213
Alex Klein1699fab2022-09-08 08:46:06 -0600214 Args:
215 argv: Arguments to parse.
Simon Glass02741682013-05-26 07:07:58 -0700216
Alex Klein1699fab2022-09-08 08:46:06 -0600217 Returns:
218 The parsed options object
219 """
Simon Glass95a316d2023-02-10 11:31:47 -0700220 parser = commandline.ArgumentParser(
221 description=__doc__, default_log_level="notice"
222 )
Alex Klein1699fab2022-09-08 08:46:06 -0600223 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600224 "-B",
225 "--build",
226 action="store_false",
227 default=True,
228 help="Don't build U-Boot, just configure device tree",
229 )
230 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600231 "--dt",
Alex Klein1699fab2022-09-08 08:46:06 -0600232 help="Select name of device tree file to use",
233 )
234 parser.add_argument(
Simon Glasse94b4a42023-02-15 06:35:55 -0700235 "--dtb",
236 type="file_exists",
237 help="Select a binary .dtb, passed to the U-Boot build using EXT_DTB",
238 )
239 parser.add_argument(
Simon Glass77cc6ea2023-02-12 08:04:43 -0700240 "-f",
241 "--force-reconfig",
Alex Klein1699fab2022-09-08 08:46:06 -0600242 action="store_true",
243 default=False,
Simon Glass77cc6ea2023-02-12 08:04:43 -0700244 help="Reconfigure before building",
245 )
246 parser.add_argument(
247 "-F",
248 "--force-distclean",
249 action="store_true",
250 default=False,
251 help="Run distclean and reconfigure before building",
Alex Klein1699fab2022-09-08 08:46:06 -0600252 )
253 parser.add_argument(
Simon Glass73a2f482023-02-15 06:18:50 -0700254 "-j",
255 "--jobs",
256 type=int,
257 default=os.cpu_count(),
258 help="Select the number of CPUs to use (defaults to all)",
259 )
260 parser.add_argument(
Simon Glass37da44f2023-02-15 06:30:58 -0700261 "-I",
262 "--in-tree",
263 action="store_true",
264 default=False,
265 help="Build in-tree",
266 )
267 parser.add_argument(
Simon Glassd080aa72023-02-14 07:04:52 -0700268 "-L",
269 "--no-lto",
270 dest="lto",
271 action="store_false",
272 default=True,
273 help="Disable Link-time Optimisation (LTO) when building",
274 )
275 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600276 "-O",
277 "--objdump",
278 action="store_true",
279 default=False,
280 help="Write disassembly output",
281 )
282 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600283 "-t",
284 "--trace",
285 action="store_true",
286 default=False,
287 help="Enable trace support",
288 )
289 parser.add_argument(
Simon Glassa68488c2023-02-09 16:53:47 -0700290 "-T",
291 "--target",
292 nargs="?",
293 default="all",
294 help="Select target to build",
295 )
296 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600297 "-V",
298 "--verified",
299 action="store_true",
300 default=False,
301 help="Include Chrome OS verified boot components",
302 )
303 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600304 "-z",
305 "--size",
306 action="store_true",
307 default=False,
308 help="Display U-Boot image size",
309 )
310 parser.add_argument(
Simon Glassa68488c2023-02-09 16:53:47 -0700311 "board",
312 type=str,
313 default=default_board,
314 help="Select board to build (daisy/peach_pit/link)",
Alex Klein1699fab2022-09-08 08:46:06 -0600315 )
316 return parser.parse_args(argv)
Simon Glass02741682013-05-26 07:07:58 -0700317
318
Simon Glassc1a323a2016-08-04 20:29:51 -0600319def FindCompiler(gcc, cros_prefix):
Alex Klein1699fab2022-09-08 08:46:06 -0600320 """Look up the compiler for an architecture.
Simon Glassc1a323a2016-08-04 20:29:51 -0600321
Alex Klein1699fab2022-09-08 08:46:06 -0600322 Args:
323 gcc: GCC architecture, either 'arm' or 'aarch64'
324 cros_prefix: Full Chromium OS toolchain prefix
325 """
326 if in_chroot:
327 # Use the Chromium OS toolchain.
328 prefix = cros_prefix
329 else:
330 prefix = glob.glob("/opt/linaro/gcc-linaro-%s-linux-*/bin/*gcc" % gcc)
331 if not prefix:
332 cros_build_lib.Die(
333 """Please install an %s toolchain for your machine.
Simon Glassc1a323a2016-08-04 20:29:51 -0600334Install a Linaro toolchain from:
335https://launchpad.net/linaro-toolchain-binaries
Alex Klein1699fab2022-09-08 08:46:06 -0600336or see cros/commands/cros_chrome_sdk.py."""
337 % gcc
338 )
339 prefix = re.sub("gcc$", "", prefix[0])
340 return prefix
Simon Glassc1a323a2016-08-04 20:29:51 -0600341
342
Simon Glass02741682013-05-26 07:07:58 -0700343def SetupBuild(options):
Alex Klein1699fab2022-09-08 08:46:06 -0600344 """Set up parameters needed for the build.
Simon Glass02741682013-05-26 07:07:58 -0700345
Alex Klein1699fab2022-09-08 08:46:06 -0600346 This checks the current environment and options and sets up various things
347 needed for the build, including 'base' which holds the base flags for
348 passing to the U-Boot Makefile.
Simon Glass02741682013-05-26 07:07:58 -0700349
Alex Klein1699fab2022-09-08 08:46:06 -0600350 Args:
351 options: Command line options
Simon Glass02741682013-05-26 07:07:58 -0700352
Alex Klein1699fab2022-09-08 08:46:06 -0600353 Returns:
354 Base flags to use for U-Boot, as a list.
355 """
356 # pylint: disable=global-statement
Simon Glass95a316d2023-02-10 11:31:47 -0700357 global arch, board, compiler, family, outdir, smdk, uboard, vendor
Simon Glass02741682013-05-26 07:07:58 -0700358
Simon Glass9674afc2023-02-10 11:21:30 -0700359 logging.info("Building for %s", options.board)
Simon Glass02741682013-05-26 07:07:58 -0700360
Alex Klein1699fab2022-09-08 08:46:06 -0600361 # Separate out board_variant string: "peach_pit" becomes "peach", "pit".
362 # But don't mess up upstream boards which use _ in their name.
363 parts = options.board.split("_")
364 if parts[0] in ["daisy", "peach"]:
365 board = parts[0]
Simon Glass02741682013-05-26 07:07:58 -0700366 else:
Alex Klein1699fab2022-09-08 08:46:06 -0600367 board = options.board
Simon Glass02741682013-05-26 07:07:58 -0700368
Alex Klein1699fab2022-09-08 08:46:06 -0600369 # To allow this to be run from 'cros_sdk'
370 if in_chroot:
371 os.chdir(os.path.join(src_root, "third_party", "u-boot", "files"))
Simon Glass02741682013-05-26 07:07:58 -0700372
Alex Klein1699fab2022-09-08 08:46:06 -0600373 base_board = board
Simon Glass02741682013-05-26 07:07:58 -0700374
Alex Klein1699fab2022-09-08 08:46:06 -0600375 if options.verified:
376 base_board = "chromeos_%s" % base_board
Simon Glass02741682013-05-26 07:07:58 -0700377
Alex Klein1699fab2022-09-08 08:46:06 -0600378 uboard = UBOARDS.get(base_board, base_board)
Simon Glass9674afc2023-02-10 11:21:30 -0700379 logging.info("U-Boot board is %s", uboard)
Simon Glass02741682013-05-26 07:07:58 -0700380
Alex Klein1699fab2022-09-08 08:46:06 -0600381 # Pull out some information from the U-Boot boards config file
382 family = None
383 (PRE_KBUILD, PRE_KCONFIG, KCONFIG) = range(3)
384 if os.path.exists("MAINTAINERS"):
385 board_format = PRE_KBUILD
386 else:
387 board_format = PRE_KCONFIG
Mike Frysinger31fdddd2023-02-24 15:50:55 -0500388 with open("boards.cfg", encoding="utf-8") as f:
Alex Klein1699fab2022-09-08 08:46:06 -0600389 for line in f:
390 if "genboardscfg" in line:
391 board_format = KCONFIG
392 if uboard in line:
393 if line[0] == "#":
394 continue
395 fields = line.split()
396 if not fields:
397 continue
Simon Glassa44a1f92023-02-09 16:31:34 -0700398 target = fields[6]
399 # Make sure this is the right target.
400 if target != uboard:
401 continue
Alex Klein1699fab2022-09-08 08:46:06 -0600402 arch = fields[1]
403 fields += [None, None, None]
404 if board_format == PRE_KBUILD:
405 smdk = fields[3]
406 vendor = fields[4]
407 family = fields[5]
Alex Klein1699fab2022-09-08 08:46:06 -0600408 elif board_format in (PRE_KCONFIG, KCONFIG):
409 smdk = fields[5]
410 vendor = fields[4]
411 family = fields[3]
412 target = fields[0]
Alex Klein1699fab2022-09-08 08:46:06 -0600413 if not arch:
414 cros_build_lib.Die(
415 "Selected board '%s' not found in boards.cfg." % board
416 )
Simon Glass02741682013-05-26 07:07:58 -0700417
Alex Klein1699fab2022-09-08 08:46:06 -0600418 vboot = os.path.join("build", board, "usr")
Simon Glass4158d732023-02-17 11:38:31 -0700419 if arch == "sandbox":
420 compiler = ""
421 elif in_chroot:
Simon Glassa44a1f92023-02-09 16:31:34 -0700422 if arch == "x86":
423 compiler = "i686-cros-linux-gnu-"
424 elif arch == "arm":
425 compiler = FindCompiler(arch, "armv7a-cros-linux-gnueabihf-")
426 elif arch == "aarch64":
427 compiler = FindCompiler(arch, "aarch64-cros-linux-gnu-")
Alex Klein1699fab2022-09-08 08:46:06 -0600428 else:
Simon Glassa44a1f92023-02-09 16:31:34 -0700429 result = cros_build_lib.run(
430 ["buildman", "-A", "--boards", options.board],
431 capture_output=True,
Simon Glassa44a1f92023-02-09 16:31:34 -0700432 **kwargs,
433 )
434 compiler = result.stdout.strip()
435 if not compiler:
436 cros_build_lib.Die("Selected arch '%s' not supported.", arch)
Simon Glass02741682013-05-26 07:07:58 -0700437
Alex Klein1699fab2022-09-08 08:46:06 -0600438 base = [
439 "make",
Simon Glass73a2f482023-02-15 06:18:50 -0700440 "-j%d" % options.jobs,
Alex Klein1699fab2022-09-08 08:46:06 -0600441 "CROSS_COMPILE=%s" % compiler,
442 "--no-print-directory",
443 "HOSTSTRIP=true",
Alex Klein1699fab2022-09-08 08:46:06 -0600444 "QEMU_ARCH=",
Simon Glass0c0617f2023-02-19 18:32:16 -0700445 "KCONFIG_NOSILENTUPDATE=1",
Alex Klein1699fab2022-09-08 08:46:06 -0600446 ]
Simon Glassf665da62023-02-15 06:40:51 -0700447 if options.dt:
448 base.append(f"DEVICE_TREE={options.dt}")
Simon Glass37da44f2023-02-15 06:30:58 -0700449 if not options.in_tree:
450 outdir = os.path.join(OUT_DIR, uboard)
451 base.append(f"O={outdir}")
Simon Glassd080aa72023-02-14 07:04:52 -0700452 if not options.lto:
453 base.append("NO_LTO=1")
Simon Glasse94b4a42023-02-15 06:35:55 -0700454 if options.dtb:
455 base.append(f"EXT_DTB={options.dtb}")
Simon Glassd080aa72023-02-14 07:04:52 -0700456
Simon Glass95a316d2023-02-10 11:31:47 -0700457 # Enable quiet output at INFO level, everything at DEBUG level
458 if logging.getLogger().getEffectiveLevel() <= logging.DEBUG:
Alex Klein1699fab2022-09-08 08:46:06 -0600459 base.append("V=1")
Simon Glass95a316d2023-02-10 11:31:47 -0700460 elif logging.getLogger().getEffectiveLevel() >= logging.NOTICE:
461 base.append("-s")
Simon Glass02741682013-05-26 07:07:58 -0700462
Alex Klein1699fab2022-09-08 08:46:06 -0600463 if options.verified:
464 base += [
465 "VBOOT=%s" % vboot,
466 "MAKEFLAGS_VBOOT=DEBUG=1",
467 "QUIET=1",
468 "CFLAGS_EXTRA_VBOOT=-DUNROLL_LOOPS",
469 "VBOOT_SOURCE=%s/platform/vboot_reference" % src_root,
470 ]
471 base.append("VBOOT_DEBUG=1")
472
Alex Klein1699fab2022-09-08 08:46:06 -0600473 base.append("BUILD_ROM=1")
474 if options.trace:
475 base.append("FTRACE=1")
Alex Klein1699fab2022-09-08 08:46:06 -0600476
Simon Glass77cc6ea2023-02-12 08:04:43 -0700477 if not options.force_reconfig:
Alex Klein1699fab2022-09-08 08:46:06 -0600478 config_mk = "%s/include/autoconf.mk" % outdir
479 if not os.path.exists(config_mk):
Simon Glass77cc6ea2023-02-12 08:04:43 -0700480 logging.warning("No build found for %s - adding -f", board)
481 options.force_reconfig = True
Alex Klein1699fab2022-09-08 08:46:06 -0600482
483 config_mk = "include/autoconf.mk"
484 if os.path.exists(config_mk):
Simon Glass37da44f2023-02-15 06:30:58 -0700485 logging.warning("Warning: '%s' exists, try 'make mrproper'", config_mk)
Alex Klein1699fab2022-09-08 08:46:06 -0600486
Alex Klein1699fab2022-09-08 08:46:06 -0600487 return base
Simon Glass02741682013-05-26 07:07:58 -0700488
489
Simon Glassf78c9b52023-02-14 06:58:10 -0700490def CheckConfigChange() -> bool:
491 """See if we need to reconfigure due to config files changing
492
493 Checks if any defconfig or Kconfig file has changed in the source tree
494 since the last time U-Boot was configured for this build. For simplicity,
495 any defconfig change will trigger this, not just one for the board being
496 built, since the cost of a reconfigure is fairly small.
497
498 Returns:
499 True if any config file has changed since U-Boot was last configured
500 """
501 fname = os.path.join(outdir, ".config")
502 ref_time = os.path.getctime(fname)
503 for p in Path.cwd().glob("configs/*"):
504 if p.stat().st_ctime > ref_time:
505 logging.warning("config/ dir has changed - adding -f")
506 return True
507
508 for p in Path.cwd().glob("**/Kconfig*"):
509 if p.stat().st_ctime > ref_time:
510 logging.warning("Kconfig file(s) changed - adding -f")
511 return True
512
513 return False
514
515
Simon Glass02741682013-05-26 07:07:58 -0700516def RunBuild(options, base, target, queue):
Alex Klein1699fab2022-09-08 08:46:06 -0600517 """Run the U-Boot build.
Simon Glass02741682013-05-26 07:07:58 -0700518
Alex Klein1699fab2022-09-08 08:46:06 -0600519 Args:
520 options: Command line options.
521 base: Base U-Boot flags.
522 target: Target to build.
523 queue: A parallel queue to add jobs to.
524 """
Simon Glass9674afc2023-02-10 11:21:30 -0700525 logging.info("U-Boot build flags: %s", " ".join(base))
Simon Glass02741682013-05-26 07:07:58 -0700526
Simon Glass77cc6ea2023-02-12 08:04:43 -0700527 if options.force_distclean:
528 options.force_reconfig = True
Alex Klein1699fab2022-09-08 08:46:06 -0600529 # Ignore any error from this, some older U-Boots fail on this.
Simon Glassdee7d6b2023-02-10 11:35:18 -0700530 cros_build_lib.run(base + ["distclean"], capture_output=True, **kwargs)
Simon Glass77cc6ea2023-02-12 08:04:43 -0700531
Simon Glassf78c9b52023-02-14 06:58:10 -0700532 if not options.force_reconfig:
533 options.force_reconfig = CheckConfigChange()
534
Simon Glass77cc6ea2023-02-12 08:04:43 -0700535 # Reconfigure U-Boot.
536 if options.force_reconfig:
Alex Klein1699fab2022-09-08 08:46:06 -0600537 if os.path.exists("tools/genboardscfg.py"):
538 mtarget = "defconfig"
539 else:
540 mtarget = "config"
541 cmd = base + ["%s_%s" % (uboard, mtarget)]
542 result = cros_build_lib.run(
543 cmd, stdout=True, stderr=subprocess.STDOUT, **kwargs
544 )
Simon Glassdee7d6b2023-02-10 11:35:18 -0700545 if (
546 result.returncode
547 or logging.getLogger().getEffectiveLevel() <= logging.DEBUG
548 ):
549 print(f"cmd: {result.cmdstr}")
550 print(result.stdout, file=sys.stderr)
551 if result.returncode:
552 sys.exit(result.returncode)
Simon Glass02741682013-05-26 07:07:58 -0700553
Alex Klein1699fab2022-09-08 08:46:06 -0600554 # Do the actual build.
555 if options.build:
556 result = cros_build_lib.run(
Simon Glass0c0617f2023-02-19 18:32:16 -0700557 base + [target],
558 input="",
559 stdout=True,
560 stderr=subprocess.STDOUT,
561 **kwargs,
Alex Klein1699fab2022-09-08 08:46:06 -0600562 )
Simon Glassdee7d6b2023-02-10 11:35:18 -0700563 if (
564 result.returncode
565 or logging.getLogger().getEffectiveLevel() <= logging.INFO
566 ):
Alex Klein1699fab2022-09-08 08:46:06 -0600567 # The build failed, so output the results to stderr.
Simon Glassdee7d6b2023-02-10 11:35:18 -0700568 print(f"cmd: {result.cmdstr}")
569 print(result.stdout, file=sys.stderr)
570 if result.returncode:
571 sys.exit(result.returncode)
Simon Glass02741682013-05-26 07:07:58 -0700572
Alex Klein1699fab2022-09-08 08:46:06 -0600573 files = ["%s/u-boot" % outdir]
574 spl = glob.glob("%s/spl/u-boot-spl" % outdir)
575 if spl:
576 files += spl
577 if options.size:
578 result = cros_build_lib.run([CompilerTool("size")] + files, **kwargs)
579 if result.returncode:
580 sys.exit()
Simon Glass02741682013-05-26 07:07:58 -0700581
Alex Klein1699fab2022-09-08 08:46:06 -0600582 # Create disassembly files .dis and .Dis (full dump)
583 for f in files:
584 base = os.path.splitext(f)[0]
585 if options.objdump:
586 queue.put(("-d", f, base + ".dis"))
587 queue.put(("-D", f, base + ".Dis"))
588 else:
589 # Remove old files which otherwise might be confusing
590 osutils.SafeUnlink(base + ".dis")
591 osutils.SafeUnlink(base + ".Dis")
Simon Glass02741682013-05-26 07:07:58 -0700592
Simon Glass9674afc2023-02-10 11:21:30 -0700593 logging.info("Output directory %s", outdir)
Simon Glass02741682013-05-26 07:07:58 -0700594
595
Simon Glass02741682013-05-26 07:07:58 -0700596def main(argv):
Simon Glasse6201d72023-02-09 16:42:22 -0700597 """Main function for script to build firmware.
Simon Glass02741682013-05-26 07:07:58 -0700598
Alex Klein1699fab2022-09-08 08:46:06 -0600599 Args:
600 argv: Program arguments.
601 """
602 options = ParseCmdline(argv)
603 base = SetupBuild(options)
Simon Glass02741682013-05-26 07:07:58 -0700604
Alex Klein1699fab2022-09-08 08:46:06 -0600605 with parallel.BackgroundTaskRunner(Dumper) as queue:
606 RunBuild(options, base, options.target, queue)
Simon Glass02741682013-05-26 07:07:58 -0700607
Alex Klein1699fab2022-09-08 08:46:06 -0600608 if options.objdump:
Simon Glass9674afc2023-02-10 11:21:30 -0700609 logging.info("Writing diasssembly files")