blob: 5555201dad3da01583e040fdcca570da82a18761 [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
Alex Klein1699fab2022-09-08 08:46:06 -0600159OUT_DIR = "/tmp/crosfw"
Simon Glassb89ae892013-07-18 15:23:35 -0600160
Alex Klein1699fab2022-09-08 08:46:06 -0600161rc_file = os.path.expanduser("~/.crosfwrc")
Simon Glass02741682013-05-26 07:07:58 -0700162if os.path.exists(rc_file):
Mike Frysinger31fdddd2023-02-24 15:50:55 -0500163 with open(rc_file, "rb") as fp:
Alex Klein1699fab2022-09-08 08:46:06 -0600164 # pylint: disable=exec-used
165 exec(compile(fp.read(), rc_file, "exec"))
Simon Glass02741682013-05-26 07:07:58 -0700166
167
Simon Glass02741682013-05-26 07:07:58 -0700168def Dumper(flag, infile, outfile):
Alex Klein1699fab2022-09-08 08:46:06 -0600169 """Run objdump on an input file.
Simon Glass02741682013-05-26 07:07:58 -0700170
Alex Klein1699fab2022-09-08 08:46:06 -0600171 Args:
172 flag: Flag to pass objdump (e.g. '-d').
173 infile: Input file to process.
174 outfile: Output file to write to.
175 """
176 result = cros_build_lib.run(
177 [CompilerTool("objdump"), flag, infile], stdout=outfile, **kwargs
178 )
179 if result.returncode:
180 sys.exit()
Simon Glass02741682013-05-26 07:07:58 -0700181
182
183def CompilerTool(tool):
Alex Klein1699fab2022-09-08 08:46:06 -0600184 """Returns the cross-compiler tool filename.
Simon Glass02741682013-05-26 07:07:58 -0700185
Alex Klein1699fab2022-09-08 08:46:06 -0600186 Args:
187 tool: Tool name to return, e.g. 'size'.
Simon Glass02741682013-05-26 07:07:58 -0700188
Alex Klein1699fab2022-09-08 08:46:06 -0600189 Returns:
190 Filename of requested tool.
191 """
192 return "%s%s" % (compiler, tool)
Simon Glass02741682013-05-26 07:07:58 -0700193
194
195def ParseCmdline(argv):
Alex Klein1699fab2022-09-08 08:46:06 -0600196 """Parse all command line options.
Simon Glass02741682013-05-26 07:07:58 -0700197
Alex Klein1699fab2022-09-08 08:46:06 -0600198 Args:
199 argv: Arguments to parse.
Simon Glass02741682013-05-26 07:07:58 -0700200
Alex Klein1699fab2022-09-08 08:46:06 -0600201 Returns:
202 The parsed options object
203 """
Simon Glass95a316d2023-02-10 11:31:47 -0700204 parser = commandline.ArgumentParser(
205 description=__doc__, default_log_level="notice"
206 )
Alex Klein1699fab2022-09-08 08:46:06 -0600207 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600208 "-B",
209 "--build",
210 action="store_false",
211 default=True,
212 help="Don't build U-Boot, just configure device tree",
213 )
214 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600215 "--dt",
Alex Klein1699fab2022-09-08 08:46:06 -0600216 help="Select name of device tree file to use",
217 )
218 parser.add_argument(
Simon Glasse94b4a42023-02-15 06:35:55 -0700219 "--dtb",
220 type="file_exists",
221 help="Select a binary .dtb, passed to the U-Boot build using EXT_DTB",
222 )
223 parser.add_argument(
Simon Glass77cc6ea2023-02-12 08:04:43 -0700224 "-f",
225 "--force-reconfig",
Alex Klein1699fab2022-09-08 08:46:06 -0600226 action="store_true",
227 default=False,
Simon Glass77cc6ea2023-02-12 08:04:43 -0700228 help="Reconfigure before building",
229 )
230 parser.add_argument(
231 "-F",
232 "--force-distclean",
233 action="store_true",
234 default=False,
235 help="Run distclean and reconfigure before building",
Alex Klein1699fab2022-09-08 08:46:06 -0600236 )
237 parser.add_argument(
Simon Glass73a2f482023-02-15 06:18:50 -0700238 "-j",
239 "--jobs",
240 type=int,
241 default=os.cpu_count(),
242 help="Select the number of CPUs to use (defaults to all)",
243 )
244 parser.add_argument(
Simon Glass37da44f2023-02-15 06:30:58 -0700245 "-I",
246 "--in-tree",
247 action="store_true",
248 default=False,
249 help="Build in-tree",
250 )
251 parser.add_argument(
Simon Glassd080aa72023-02-14 07:04:52 -0700252 "-L",
253 "--no-lto",
254 dest="lto",
255 action="store_false",
256 default=True,
257 help="Disable Link-time Optimisation (LTO) when building",
258 )
259 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600260 "-O",
261 "--objdump",
262 action="store_true",
263 default=False,
264 help="Write disassembly output",
265 )
266 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600267 "-t",
268 "--trace",
269 action="store_true",
270 default=False,
271 help="Enable trace support",
272 )
273 parser.add_argument(
Simon Glassa68488c2023-02-09 16:53:47 -0700274 "-T",
275 "--target",
276 nargs="?",
277 default="all",
278 help="Select target to build",
279 )
280 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600281 "-V",
282 "--verified",
283 action="store_true",
284 default=False,
285 help="Include Chrome OS verified boot components",
286 )
287 parser.add_argument(
Alex Klein1699fab2022-09-08 08:46:06 -0600288 "-z",
289 "--size",
290 action="store_true",
291 default=False,
292 help="Display U-Boot image size",
293 )
294 parser.add_argument(
Simon Glassa68488c2023-02-09 16:53:47 -0700295 "board",
296 type=str,
297 default=default_board,
298 help="Select board to build (daisy/peach_pit/link)",
Alex Klein1699fab2022-09-08 08:46:06 -0600299 )
300 return parser.parse_args(argv)
Simon Glass02741682013-05-26 07:07:58 -0700301
302
Simon Glassc1a323a2016-08-04 20:29:51 -0600303def FindCompiler(gcc, cros_prefix):
Alex Klein1699fab2022-09-08 08:46:06 -0600304 """Look up the compiler for an architecture.
Simon Glassc1a323a2016-08-04 20:29:51 -0600305
Alex Klein1699fab2022-09-08 08:46:06 -0600306 Args:
307 gcc: GCC architecture, either 'arm' or 'aarch64'
308 cros_prefix: Full Chromium OS toolchain prefix
309 """
310 if in_chroot:
311 # Use the Chromium OS toolchain.
312 prefix = cros_prefix
313 else:
314 prefix = glob.glob("/opt/linaro/gcc-linaro-%s-linux-*/bin/*gcc" % gcc)
315 if not prefix:
316 cros_build_lib.Die(
317 """Please install an %s toolchain for your machine.
Simon Glassc1a323a2016-08-04 20:29:51 -0600318Install a Linaro toolchain from:
319https://launchpad.net/linaro-toolchain-binaries
Alex Klein1699fab2022-09-08 08:46:06 -0600320or see cros/commands/cros_chrome_sdk.py."""
321 % gcc
322 )
323 prefix = re.sub("gcc$", "", prefix[0])
324 return prefix
Simon Glassc1a323a2016-08-04 20:29:51 -0600325
326
Simon Glass02741682013-05-26 07:07:58 -0700327def SetupBuild(options):
Alex Klein1699fab2022-09-08 08:46:06 -0600328 """Set up parameters needed for the build.
Simon Glass02741682013-05-26 07:07:58 -0700329
Alex Klein1699fab2022-09-08 08:46:06 -0600330 This checks the current environment and options and sets up various things
331 needed for the build, including 'base' which holds the base flags for
332 passing to the U-Boot Makefile.
Simon Glass02741682013-05-26 07:07:58 -0700333
Alex Klein1699fab2022-09-08 08:46:06 -0600334 Args:
335 options: Command line options
Simon Glass02741682013-05-26 07:07:58 -0700336
Alex Klein1699fab2022-09-08 08:46:06 -0600337 Returns:
338 Base flags to use for U-Boot, as a list.
339 """
340 # pylint: disable=global-statement
Simon Glass826b1df2023-03-02 05:46:45 -0700341 global arch, board, compiler, outdir, uboard
Simon Glass02741682013-05-26 07:07:58 -0700342
Simon Glass9674afc2023-02-10 11:21:30 -0700343 logging.info("Building for %s", options.board)
Simon Glass02741682013-05-26 07:07:58 -0700344
Alex Klein1699fab2022-09-08 08:46:06 -0600345 # Separate out board_variant string: "peach_pit" becomes "peach", "pit".
346 # But don't mess up upstream boards which use _ in their name.
347 parts = options.board.split("_")
348 if parts[0] in ["daisy", "peach"]:
349 board = parts[0]
Simon Glass02741682013-05-26 07:07:58 -0700350 else:
Alex Klein1699fab2022-09-08 08:46:06 -0600351 board = options.board
Simon Glass02741682013-05-26 07:07:58 -0700352
Alex Klein1699fab2022-09-08 08:46:06 -0600353 # To allow this to be run from 'cros_sdk'
354 if in_chroot:
355 os.chdir(os.path.join(src_root, "third_party", "u-boot", "files"))
Simon Glass02741682013-05-26 07:07:58 -0700356
Alex Klein1699fab2022-09-08 08:46:06 -0600357 base_board = board
Simon Glass02741682013-05-26 07:07:58 -0700358
Alex Klein1699fab2022-09-08 08:46:06 -0600359 if options.verified:
360 base_board = "chromeos_%s" % base_board
Simon Glass02741682013-05-26 07:07:58 -0700361
Alex Klein1699fab2022-09-08 08:46:06 -0600362 uboard = UBOARDS.get(base_board, base_board)
Simon Glass9674afc2023-02-10 11:21:30 -0700363 logging.info("U-Boot board is %s", uboard)
Simon Glass02741682013-05-26 07:07:58 -0700364
Alex Klein1699fab2022-09-08 08:46:06 -0600365 # Pull out some information from the U-Boot boards config file
Alex Klein1699fab2022-09-08 08:46:06 -0600366 (PRE_KBUILD, PRE_KCONFIG, KCONFIG) = range(3)
367 if os.path.exists("MAINTAINERS"):
368 board_format = PRE_KBUILD
369 else:
370 board_format = PRE_KCONFIG
Mike Frysinger31fdddd2023-02-24 15:50:55 -0500371 with open("boards.cfg", encoding="utf-8") as f:
Alex Klein1699fab2022-09-08 08:46:06 -0600372 for line in f:
373 if "genboardscfg" in line:
374 board_format = KCONFIG
375 if uboard in line:
376 if line[0] == "#":
377 continue
378 fields = line.split()
379 if not fields:
380 continue
Simon Glassa44a1f92023-02-09 16:31:34 -0700381 target = fields[6]
382 # Make sure this is the right target.
383 if target != uboard:
384 continue
Alex Klein1699fab2022-09-08 08:46:06 -0600385 arch = fields[1]
386 fields += [None, None, None]
Simon Glass826b1df2023-03-02 05:46:45 -0700387 if board_format in (PRE_KCONFIG, KCONFIG):
Alex Klein1699fab2022-09-08 08:46:06 -0600388 target = fields[0]
Alex Klein1699fab2022-09-08 08:46:06 -0600389 if not arch:
390 cros_build_lib.Die(
391 "Selected board '%s' not found in boards.cfg." % board
392 )
Simon Glass02741682013-05-26 07:07:58 -0700393
Alex Klein1699fab2022-09-08 08:46:06 -0600394 vboot = os.path.join("build", board, "usr")
Simon Glass4158d732023-02-17 11:38:31 -0700395 if arch == "sandbox":
396 compiler = ""
397 elif in_chroot:
Simon Glassa44a1f92023-02-09 16:31:34 -0700398 if arch == "x86":
399 compiler = "i686-cros-linux-gnu-"
400 elif arch == "arm":
401 compiler = FindCompiler(arch, "armv7a-cros-linux-gnueabihf-")
402 elif arch == "aarch64":
403 compiler = FindCompiler(arch, "aarch64-cros-linux-gnu-")
Alex Klein1699fab2022-09-08 08:46:06 -0600404 else:
Simon Glassa44a1f92023-02-09 16:31:34 -0700405 result = cros_build_lib.run(
406 ["buildman", "-A", "--boards", options.board],
407 capture_output=True,
Simon Glassa44a1f92023-02-09 16:31:34 -0700408 **kwargs,
409 )
410 compiler = result.stdout.strip()
411 if not compiler:
412 cros_build_lib.Die("Selected arch '%s' not supported.", arch)
Simon Glass02741682013-05-26 07:07:58 -0700413
Alex Klein1699fab2022-09-08 08:46:06 -0600414 base = [
415 "make",
Simon Glass73a2f482023-02-15 06:18:50 -0700416 "-j%d" % options.jobs,
Alex Klein1699fab2022-09-08 08:46:06 -0600417 "CROSS_COMPILE=%s" % compiler,
418 "--no-print-directory",
419 "HOSTSTRIP=true",
Alex Klein1699fab2022-09-08 08:46:06 -0600420 "QEMU_ARCH=",
Simon Glass0c0617f2023-02-19 18:32:16 -0700421 "KCONFIG_NOSILENTUPDATE=1",
Alex Klein1699fab2022-09-08 08:46:06 -0600422 ]
Simon Glassf665da62023-02-15 06:40:51 -0700423 if options.dt:
424 base.append(f"DEVICE_TREE={options.dt}")
Simon Glass37da44f2023-02-15 06:30:58 -0700425 if not options.in_tree:
426 outdir = os.path.join(OUT_DIR, uboard)
427 base.append(f"O={outdir}")
Simon Glassd080aa72023-02-14 07:04:52 -0700428 if not options.lto:
429 base.append("NO_LTO=1")
Simon Glasse94b4a42023-02-15 06:35:55 -0700430 if options.dtb:
431 base.append(f"EXT_DTB={options.dtb}")
Simon Glassd080aa72023-02-14 07:04:52 -0700432
Simon Glass95a316d2023-02-10 11:31:47 -0700433 # Enable quiet output at INFO level, everything at DEBUG level
434 if logging.getLogger().getEffectiveLevel() <= logging.DEBUG:
Alex Klein1699fab2022-09-08 08:46:06 -0600435 base.append("V=1")
Simon Glass95a316d2023-02-10 11:31:47 -0700436 elif logging.getLogger().getEffectiveLevel() >= logging.NOTICE:
437 base.append("-s")
Simon Glass02741682013-05-26 07:07:58 -0700438
Alex Klein1699fab2022-09-08 08:46:06 -0600439 if options.verified:
440 base += [
441 "VBOOT=%s" % vboot,
442 "MAKEFLAGS_VBOOT=DEBUG=1",
443 "QUIET=1",
444 "CFLAGS_EXTRA_VBOOT=-DUNROLL_LOOPS",
445 "VBOOT_SOURCE=%s/platform/vboot_reference" % src_root,
446 ]
447 base.append("VBOOT_DEBUG=1")
448
Alex Klein1699fab2022-09-08 08:46:06 -0600449 base.append("BUILD_ROM=1")
450 if options.trace:
451 base.append("FTRACE=1")
Alex Klein1699fab2022-09-08 08:46:06 -0600452
Simon Glass77cc6ea2023-02-12 08:04:43 -0700453 if not options.force_reconfig:
Alex Klein1699fab2022-09-08 08:46:06 -0600454 config_mk = "%s/include/autoconf.mk" % outdir
455 if not os.path.exists(config_mk):
Simon Glass77cc6ea2023-02-12 08:04:43 -0700456 logging.warning("No build found for %s - adding -f", board)
457 options.force_reconfig = True
Alex Klein1699fab2022-09-08 08:46:06 -0600458
459 config_mk = "include/autoconf.mk"
460 if os.path.exists(config_mk):
Simon Glass37da44f2023-02-15 06:30:58 -0700461 logging.warning("Warning: '%s' exists, try 'make mrproper'", config_mk)
Alex Klein1699fab2022-09-08 08:46:06 -0600462
Alex Klein1699fab2022-09-08 08:46:06 -0600463 return base
Simon Glass02741682013-05-26 07:07:58 -0700464
465
Simon Glassf78c9b52023-02-14 06:58:10 -0700466def CheckConfigChange() -> bool:
467 """See if we need to reconfigure due to config files changing
468
469 Checks if any defconfig or Kconfig file has changed in the source tree
470 since the last time U-Boot was configured for this build. For simplicity,
471 any defconfig change will trigger this, not just one for the board being
472 built, since the cost of a reconfigure is fairly small.
473
474 Returns:
475 True if any config file has changed since U-Boot was last configured
476 """
477 fname = os.path.join(outdir, ".config")
478 ref_time = os.path.getctime(fname)
479 for p in Path.cwd().glob("configs/*"):
480 if p.stat().st_ctime > ref_time:
481 logging.warning("config/ dir has changed - adding -f")
482 return True
483
484 for p in Path.cwd().glob("**/Kconfig*"):
485 if p.stat().st_ctime > ref_time:
486 logging.warning("Kconfig file(s) changed - adding -f")
487 return True
488
489 return False
490
491
Simon Glass02741682013-05-26 07:07:58 -0700492def RunBuild(options, base, target, queue):
Alex Klein1699fab2022-09-08 08:46:06 -0600493 """Run the U-Boot build.
Simon Glass02741682013-05-26 07:07:58 -0700494
Alex Klein1699fab2022-09-08 08:46:06 -0600495 Args:
496 options: Command line options.
497 base: Base U-Boot flags.
498 target: Target to build.
499 queue: A parallel queue to add jobs to.
500 """
Simon Glass9674afc2023-02-10 11:21:30 -0700501 logging.info("U-Boot build flags: %s", " ".join(base))
Simon Glass02741682013-05-26 07:07:58 -0700502
Simon Glass77cc6ea2023-02-12 08:04:43 -0700503 if options.force_distclean:
504 options.force_reconfig = True
Alex Klein1699fab2022-09-08 08:46:06 -0600505 # Ignore any error from this, some older U-Boots fail on this.
Simon Glassdee7d6b2023-02-10 11:35:18 -0700506 cros_build_lib.run(base + ["distclean"], capture_output=True, **kwargs)
Simon Glass77cc6ea2023-02-12 08:04:43 -0700507
Simon Glassf78c9b52023-02-14 06:58:10 -0700508 if not options.force_reconfig:
509 options.force_reconfig = CheckConfigChange()
510
Simon Glass77cc6ea2023-02-12 08:04:43 -0700511 # Reconfigure U-Boot.
512 if options.force_reconfig:
Alex Klein1699fab2022-09-08 08:46:06 -0600513 if os.path.exists("tools/genboardscfg.py"):
514 mtarget = "defconfig"
515 else:
516 mtarget = "config"
517 cmd = base + ["%s_%s" % (uboard, mtarget)]
518 result = cros_build_lib.run(
519 cmd, stdout=True, stderr=subprocess.STDOUT, **kwargs
520 )
Simon Glassdee7d6b2023-02-10 11:35:18 -0700521 if (
522 result.returncode
523 or logging.getLogger().getEffectiveLevel() <= logging.DEBUG
524 ):
525 print(f"cmd: {result.cmdstr}")
526 print(result.stdout, file=sys.stderr)
527 if result.returncode:
528 sys.exit(result.returncode)
Simon Glass02741682013-05-26 07:07:58 -0700529
Alex Klein1699fab2022-09-08 08:46:06 -0600530 # Do the actual build.
531 if options.build:
532 result = cros_build_lib.run(
Simon Glass0c0617f2023-02-19 18:32:16 -0700533 base + [target],
534 input="",
Simon Glassc12ccd72023-03-01 13:35:29 -0700535 capture_output=True,
Simon Glass0c0617f2023-02-19 18:32:16 -0700536 **kwargs,
Alex Klein1699fab2022-09-08 08:46:06 -0600537 )
Simon Glassdee7d6b2023-02-10 11:35:18 -0700538 if (
539 result.returncode
540 or logging.getLogger().getEffectiveLevel() <= logging.INFO
Simon Glassc12ccd72023-03-01 13:35:29 -0700541 or result.stderr
Simon Glassdee7d6b2023-02-10 11:35:18 -0700542 ):
Alex Klein1699fab2022-09-08 08:46:06 -0600543 # The build failed, so output the results to stderr.
Simon Glassc12ccd72023-03-01 13:35:29 -0700544 print(f"cmd: {result.cmdstr}", file=sys.stderr)
545 print(result.stderr, file=sys.stderr)
546
547 # Note that stdout and stderr are separated here, so warnings
548 # associated with a file will appear separately from any output
549 # from the build system
550 if logging.getLogger().getEffectiveLevel() <= logging.INFO:
551 print(result.stdout)
Simon Glassdee7d6b2023-02-10 11:35:18 -0700552 if result.returncode:
553 sys.exit(result.returncode)
Simon Glass02741682013-05-26 07:07:58 -0700554
Alex Klein1699fab2022-09-08 08:46:06 -0600555 files = ["%s/u-boot" % outdir]
556 spl = glob.glob("%s/spl/u-boot-spl" % outdir)
557 if spl:
558 files += spl
559 if options.size:
560 result = cros_build_lib.run([CompilerTool("size")] + files, **kwargs)
561 if result.returncode:
562 sys.exit()
Simon Glass02741682013-05-26 07:07:58 -0700563
Alex Klein1699fab2022-09-08 08:46:06 -0600564 # Create disassembly files .dis and .Dis (full dump)
565 for f in files:
566 base = os.path.splitext(f)[0]
567 if options.objdump:
568 queue.put(("-d", f, base + ".dis"))
569 queue.put(("-D", f, base + ".Dis"))
570 else:
571 # Remove old files which otherwise might be confusing
572 osutils.SafeUnlink(base + ".dis")
573 osutils.SafeUnlink(base + ".Dis")
Simon Glass02741682013-05-26 07:07:58 -0700574
Simon Glass9674afc2023-02-10 11:21:30 -0700575 logging.info("Output directory %s", outdir)
Simon Glass02741682013-05-26 07:07:58 -0700576
577
Simon Glass02741682013-05-26 07:07:58 -0700578def main(argv):
Simon Glasse6201d72023-02-09 16:42:22 -0700579 """Main function for script to build firmware.
Simon Glass02741682013-05-26 07:07:58 -0700580
Alex Klein1699fab2022-09-08 08:46:06 -0600581 Args:
582 argv: Program arguments.
583 """
584 options = ParseCmdline(argv)
585 base = SetupBuild(options)
Simon Glass02741682013-05-26 07:07:58 -0700586
Alex Klein1699fab2022-09-08 08:46:06 -0600587 with parallel.BackgroundTaskRunner(Dumper) as queue:
588 RunBuild(options, base, options.target, queue)
Simon Glass02741682013-05-26 07:07:58 -0700589
Alex Klein1699fab2022-09-08 08:46:06 -0600590 if options.objdump:
Simon Glass9674afc2023-02-10 11:21:30 -0700591 logging.info("Writing diasssembly files")