blob: c616d98e0822f3bf8dff81c32a7941640ae27197 [file] [log] [blame]
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -07003#
4# Copyright 2020 The Chromium OS Authors. All rights reserved.
5# Use of this source code is governed by a BSD-style license that can be
6# found in the LICENSE file.
7#
Paul Fagerburge868e832020-01-22 17:14:04 -07008"""Create a new variant of an existing reference board
Paul Fagerburg3b534f92019-11-07 15:05:22 -07009
10This program will call all of the scripts that create the various pieces
11of a new variant. For example to create a new variant of the hatch base
12board, the following scripts are called:
13
Paul Fagerburg5f794bf2020-02-12 13:01:36 -070014* platform/dev/contrib/variant/create_coreboot_variant.sh
Paul Fagerburg3b534f92019-11-07 15:05:22 -070015* platform/dev/contrib/variant/create_coreboot_config.sh
16* private-overlays/baseboard-hatch-private/sys-boot/
17 * coreboot-private-files-hatch/files/add_fitimage.sh
18 * coreboot-private-files-hatch/asset_generation/gen_fit_image.sh
19 * Outside the chroot, because it uses WINE to run the FIT tools
20* platform/dev/contrib/variant/create_initial_ec_image.sh
21* platform/dev/contrib/variant/add_variant_to_yaml.sh
22* private-overlays/overlay-hatch-private/chromeos-base/
23 * chromeos-config-bsp-hatch-private/add_variant.sh
24
25Once the scripts are done, the following repos have changes
26
27* third_party/coreboot
28* third_party/chromiumos-overlay
29* private-overlays/baseboard-hatch-private
30* platform/ec
31* private-overlays/overlay-hatch-private
32* overlays
33
Paul Fagerburge868e832020-01-22 17:14:04 -070034The program has support for multiple reference boards, so the repos, directories,
35and scripts above can change depending on what the reference board is.
Paul Fagerburg3b534f92019-11-07 15:05:22 -070036"""
37
38from __future__ import print_function
39import argparse
Paul Fagerburgbab5dde2020-01-10 15:10:29 -070040import importlib
Paul Fagerburg3b534f92019-11-07 15:05:22 -070041import logging
42import os
43import re
44import shutil
45import subprocess
46import sys
Paul Fagerburg1d043c32020-02-03 08:57:08 -070047from chromite.lib import git
Paul Fagerburga8c7e342020-02-25 13:30:49 -070048from chromite.lib import gerrit
Paul Fagerburgbab5dde2020-01-10 15:10:29 -070049import step_names
Paul Fagerburg3b534f92019-11-07 15:05:22 -070050import variant_status
51
52
53def main():
Paul Fagerburge868e832020-01-22 17:14:04 -070054 """Create a new variant of an existing reference board
Paul Fagerburg3b534f92019-11-07 15:05:22 -070055
56 This program automates the creation of a new variant of an existing
Paul Fagerburge868e832020-01-22 17:14:04 -070057 reference board by calling various scripts that copy the reference board,
58 modify files for the new variant, stage commits, and upload to gerrit.
Paul Fagerburg3b534f92019-11-07 15:05:22 -070059
60 Note that one of the following is required:
61 * --continue
62 * --board=BOARD --variant=VARIANT [--bug=BUG]
63 """
64 board, variant, bug, continue_flag = get_args()
65
66 if not check_flags(board, variant, bug, continue_flag):
67 return False
68
69 status = get_status(board, variant, bug, continue_flag)
70 if status is None:
71 return False
72
73 status.load()
74
Paul Fagerburg5f794bf2020-02-12 13:01:36 -070075 # Where is new_variant.py located?
76 status.my_loc = os.path.dirname(os.path.abspath(__file__))
77
Paul Fagerburgbab5dde2020-01-10 15:10:29 -070078 while status.step is not None:
Paul Fagerburg3b534f92019-11-07 15:05:22 -070079 status.save()
Paul Fagerburgbab5dde2020-01-10 15:10:29 -070080 if not perform_step(status):
81 logging.debug('perform_step returned False; exiting ...')
Paul Fagerburg3b534f92019-11-07 15:05:22 -070082 return False
83
Paul Fagerburgbab5dde2020-01-10 15:10:29 -070084 move_to_next_step(status)
Paul Fagerburg3b534f92019-11-07 15:05:22 -070085
86 return True
87
88
89def get_args():
90 """Parse the command-line arguments
91
92 There doesn't appear to be a way to specify that --continue is
93 mutually exclusive with --board, --variant, and --bug. As a result,
94 all arguments are optional, and another function will apply the logic
95 to check if there is an illegal combination of arguments.
96
97 Returns a list of:
Paul Fagerburge868e832020-01-22 17:14:04 -070098 board Name of the reference board
Paul Fagerburg3b534f92019-11-07 15:05:22 -070099 variant Name of the variant being created
100 bug Text for bug number, if any ('None' otherwise)
101 continue_flag Flag if --continue was specified
102 """
103 parser = argparse.ArgumentParser(
104 description=main.__doc__,
105 formatter_class=argparse.RawTextHelpFormatter)
Paul Fagerburge868e832020-01-22 17:14:04 -0700106 parser.add_argument('--board', type=str, help='Name of the reference board')
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700107 parser.add_argument(
108 '--variant', type=str, help='Name of the new variant to create')
109 parser.add_argument(
110 '--bug', type=str, help='Bug number to reference in commits')
111 parser.add_argument(
112 '--continue', action='store_true',
113 dest='continue_flag', help='Continue the process from where it paused')
114 parser.add_argument(
115 '--verbose', action='store_true',
116 dest='verbose_flag', help='Enable verbose output of progress')
117 args = parser.parse_args()
118
119 if args.verbose_flag:
120 logging.basicConfig(level=logging.DEBUG)
121 else:
122 logging.basicConfig(level=logging.INFO)
123
124 board = args.board
125 if board is not None:
126 board = board.lower()
127
128 variant = args.variant
129 if variant is not None:
130 variant = variant.lower()
131
132 bug = args.bug or 'None'
133
134 return (board, variant, bug, args.continue_flag)
135
136
137def check_flags(board, variant, bug, continue_flag):
138 """Check the flags to ensure no invalid combinations
139
140 We allow any of the following:
141 --continue
142 --board=board_name --variant=variant_name
143 --board=board_name --variant=variant_name --bug=bug_text
144
145 The argument parser does have the functionality to represent the
146 combination of --board and --variant as a single mutually-exclusive
147 argument, so we have to use this function to do the checking.
148
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700149 Args:
150 board: Name of the reference board
151 variant: Name of the variant being created
152 bug: Text for bug number, if any ('None' otherwise)
153 continue_flag: Flag if --continue was specified
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700154
155 Returns:
156 True if the arguments are acceptable, False otherwise
157 """
158 if continue_flag:
159 if board is not None or variant is not None:
160 logging.error('--continue cannot have other options')
161 return False
162
163 if bug != 'None':
164 logging.error('--continue cannot have other options')
165 return False
166 else:
167 if board is None:
168 logging.error('--board must be specified')
169 return False
170
171 if variant is None:
172 logging.error('--variant must be specified')
173 return False
174
175 return True
176
177
178def file_exists(filepath, filename):
179 """Determine if a path and file exists
180
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700181 Args:
182 filepath: Path where build outputs should be found, e.g.
183 /build/hatch/firmware
184 filename: File that should exist in that path, e.g. image-sushi.bin
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700185
186 Returns:
187 True if file exists in that path, False otherwise
188 """
189 fullname = os.path.join(filepath, filename)
190 return os.path.exists(fullname) and os.path.isfile(fullname)
191
192
193def get_status(board, variant, bug, continue_flag):
194 """Create the status file or get the previous status
195
196 This program can stop at several places as we have to wait for CLs
197 to work through CQ or be upstreamed into the chromiumos tree, so just
198 like a git cherry-pick, there is a --continue option to pick up where
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700199 you left off by reading a specially-named status file.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700200
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700201 If --continue is specified, the status file must exist.
202 If the status file exists, then --continue must be specified.
203 When --continue is specified, we read the status file and return
204 with the contents.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700205
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700206 If the status file does not exist, we will create the state file with
207 the board, variant, and (optional) bug details.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700208
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700209 To decouple the list of boards supported from this main program, we
Paul Fagerburge868e832020-01-22 17:14:04 -0700210 try to import a module with the same name as the reference board,
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700211 so --board=hatch means that we import hatch.py. If we can't import
Paul Fagerburge868e832020-01-22 17:14:04 -0700212 the file, then we don't support that reference board.
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700213
214 The board-specific module will set several variables, which we will
215 copy into the object that we return.
216
Paul Fagerburge868e832020-01-22 17:14:04 -0700217 * base - the name of the base board, such as Hatch, Volteer, or Zork.
218 This can be different from the reference board, e.g. the Trembyle
219 reference board in the Zork project.
Paul Fagerburg4d343452020-01-24 15:23:53 -0700220 * coreboot_dir - base directory for coreboot, usually third_party/coreboot
221 but could differ for processors that use a private repo
222 * cb_config_dir - base directory for coreboot configs, usually
223 third_party/chromiumos-overlay/sys-boot/coreboot/files/configs but
224 could differ for processors that use a private repo
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700225 * step_list - list of steps (named in step_names.py) to run in sequence
Paul Fagerburge868e832020-01-22 17:14:04 -0700226 to create the new variant of the reference board
227 * fsp - package name for FSP. This may be None, depending on the
228 processor on the reference board
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700229 * fitimage_pkg - package name for the fitimage
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700230 * fitimage_dir - directory for fitimage; prepend '/mnt/host/source/src/'
231 in chroot, prepend '~/chromiumos/src' outside the chroot
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700232 * workon_pkgs - list of packages to cros_workon
233 * emerge_cmd - the emerge command, e.g. 'emerge-hatch'
234 * emerge_pkgs - list of packages to emerge
235 * yaml_emerge_pkgs - list of packages to emerge just to build the yaml
236 * private_yaml_dir - directory for the private yaml file
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700237 * commits - map of commits for the various steps. Indexed by step name,
238 and the step names used are the same ones in step_names.py
239 * repo_upload_list - list of commits to upload using `repo upload`
240 * coreboot_push_list - list of commits to upload using `git push` to
241 coreboot
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700242
243 Additionally, the following fields will be set:
244
Paul Fagerburge868e832020-01-22 17:14:04 -0700245 * board - the name of the reference board, e.g. 'hatch'
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700246 * variant - the name of the variant, e.g. 'sushi'
247 * bug - optional text for a bug ID, used in the git commit messages.
248 Could be 'None' (as text, not the python None), or something like
249 'b:12345' for buganizer, or 'chromium:12345'
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700250 * step - internal state tracking, what step of the variant creation
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700251 we are at.
252 * yaml_file - internal, just the name of the file where all this data
253 gets saved.
254
255 These data might come from the status file (because we read it), or
256 they might be the initial values after we created the file (because
257 it did not already exist).
258
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700259 Args:
260 board: Name of the reference board
261 variant: Name of the variant being created
262 bug: Text for bug number, if any ('None' otherwise)
263 continue_flag: Flag if --continue was specified
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700264
265 Returns:
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700266 variant_status object with all the data mentioned above
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700267 """
268 status = variant_status.variant_status()
269 if continue_flag:
270 if not status.yaml_file_exists():
271 logging.error(
272 'new_variant is not in progress; nothing to --continue')
273 return None
274 else:
275 if status.yaml_file_exists():
276 logging.error(
277 'new_variant already in progress; did you forget --continue?')
278 return None
279
280 status.board = board
281 status.variant = variant
282 status.bug = bug
Paul Fagerburgdd3e9c32020-01-07 14:00:35 -0700283
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700284 # We're just starting out, so load the appropriate module and copy
285 # all the data from it.
286 try:
287 module = importlib.import_module(board)
288 except ImportError:
Paul Fagerburge868e832020-01-22 17:14:04 -0700289 print('Unsupported board "' + board + '"')
Paul Fagerburgdd3e9c32020-01-07 14:00:35 -0700290 sys.exit(1)
291
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700292 # pylint: disable=bad-whitespace
293 # Allow extra spaces around = so that we can line things up nicely
Paul Fagerburge868e832020-01-22 17:14:04 -0700294 status.base = module.base
Paul Fagerburg4d343452020-01-24 15:23:53 -0700295 status.coreboot_dir = module.coreboot_dir
296 status.cb_config_dir = module.cb_config_dir
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700297 status.emerge_cmd = module.emerge_cmd
298 status.emerge_pkgs = module.emerge_pkgs
299 status.fitimage_dir = module.fitimage_dir
300 status.fitimage_pkg = module.fitimage_pkg
Paul Fagerburg55dabf42020-01-27 15:30:09 -0700301 status.fitimage_cmd = module.fitimage_cmd
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700302 status.fsp = module.fsp
303 status.private_yaml_dir = module.private_yaml_dir
304 status.step_list = module.step_list
305 status.workon_pkgs = module.workon_pkgs
306 status.yaml_emerge_pkgs = module.yaml_emerge_pkgs
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700307 status.coreboot_push_list = module.coreboot_push_list
308 status.repo_upload_list = module.repo_upload_list
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700309 # pylint: enable=bad-whitespace
Paul Fagerburgdd3e9c32020-01-07 14:00:35 -0700310
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700311 # Start at the first entry in the step list
312 status.step = status.step_list[0]
Paul Fagerburgdd3e9c32020-01-07 14:00:35 -0700313
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700314 # Start a blank map for tracking CL data
315 status.commits = {}
316
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700317 status.save()
318
319 return status
320
321
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700322def perform_step(status):
323 """Call the appropriate function for the current step
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700324
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700325 Args:
326 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700327
328 Returns:
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700329 True if the step succeeded, False if it failed
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700330 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700331 # Function to call based on the step
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700332 dispatch = {
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700333 step_names.CB_VARIANT: create_coreboot_variant,
334 step_names.CB_CONFIG: create_coreboot_config,
Paul Fagerburg2fd23f42020-02-07 14:04:48 -0700335 step_names.CRAS_CONFIG: copy_cras_config,
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700336 step_names.ADD_FIT: add_fitimage,
337 step_names.GEN_FIT: gen_fit_image_outside_chroot,
338 step_names.COMMIT_FIT: commit_fitimage,
339 step_names.EC_IMAGE: create_initial_ec_image,
340 step_names.EC_BUILDALL: ec_buildall,
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700341 step_names.ADD_PUB_YAML: add_variant_to_public_yaml,
342 step_names.ADD_PRIV_YAML: add_variant_to_private_yaml,
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700343 step_names.BUILD_YAML: build_yaml,
344 step_names.EMERGE: emerge_all,
345 step_names.PUSH: push_coreboot,
346 step_names.UPLOAD: upload_CLs,
347 step_names.FIND: find_coreboot_upstream,
348 step_names.CQ_DEPEND: add_cq_depends,
349 step_names.CLEAN_UP: clean_up,
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700350 }
351
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700352 if status.step not in dispatch:
353 logging.error('Unknown step "%s", aborting...', status.step)
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700354 sys.exit(1)
355
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700356 return dispatch[status.step](status)
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700357
358
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700359def move_to_next_step(status):
360 """Move to the next step in the list
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700361
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700362 Args:
363 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700364 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700365 if status.step not in status.step_list:
366 logging.error('Unknown step "%s", aborting...', status.step)
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700367 sys.exit(1)
368
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700369 idx = status.step_list.index(status.step)
370 if idx == len(status.step_list)-1:
371 status.step = None
Paul Fagerburgdd3e9c32020-01-07 14:00:35 -0700372 else:
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700373 status.step = status.step_list[idx+1]
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700374
375
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700376def run_process(args, cwd=None, env=None, capture_output=False):
377 """Run a process, log debug messages, return text output of process
378
379 The capture_output parameter allows us to capture the output when we
380 care about it (and not sending it to the screen), or ignoring it when
381 we don't care, and letting the user see the output so they know that
382 the build is still running, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700383
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700384 Args:
385 args: List of the command and its params
386 cwd: If not None, cd to this directory before running
387 env: Environment to use for execution; if needed, get os.environ.copy()
388 and add variables. If None, just use the current environment
389 capture_output: True if we should capture the stdout, false if we
390 just care about success or not.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700391
392 Returns:
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700393 If capture_output == True, we return the text output from running
394 the subprocess as a list of lines, or None if the process failed.
395 If capture_output == False, we return a True if it successed, or
396 None if the process failed.
397
398 The caller can evaluate as a bool, because bool(None) == False, and
399 bool() of a non-empty list is True, or the caller can use the returned
400 text for further processing.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700401 """
402 logging.debug('Run %s', str(args))
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700403 if cwd is not None:
404 logging.debug('cwd = %s', cwd)
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700405 try:
406 if capture_output:
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700407 output = subprocess.run(args, cwd=cwd, env=env, check=True,
408 stderr=subprocess.STDOUT, stdout=subprocess.PIPE).stdout
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700409 else:
410 subprocess.run(args, cwd=cwd, env=env, check=True)
411 # Just something to decode so we don't get an empty list
412 output = b'True'
413
414 logging.debug('process returns 0')
415 # Convert from byte string to ASCII
416 decoded = output.decode('utf-8')
417 # Split into array of individual lines
418 lines = decoded.split('\n')
419 return lines
420 except subprocess.CalledProcessError as err:
421 logging.debug('process returns %s', str(err.returncode))
422 return None
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700423
424
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700425def get_git_commit_data(cwd):
426 """Get the branch name and change id of the current commit
427
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700428 Args:
429 cwd: The current working directory, where we want to get the branch
430 name and change id
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700431
432 Returns:
433 Map with 'dir', 'branch_name' and 'change_id' keys. The 'dir'
434 key maps to the value of os.path.expanduser(cwd)
435 """
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700436 cwd = git.FindGitTopLevel(os.path.expanduser(cwd))
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700437 logging.debug('get_git_commit_data(%s)', cwd)
438
439 branch_name = git.GetCurrentBranch(cwd)
440 if branch_name is None:
441 logging.error('Cannot determine git branch name in %s; exiting', cwd)
442 sys.exit(1)
443 logging.debug('git current branch is %s', branch_name)
444
445 change_id = git.GetChangeId(cwd)
446 if change_id is None:
447 logging.error('Cannot determine Change-Id in %s; exiting', cwd)
448 sys.exit(1)
449 logging.debug('git Change-Id is %s', change_id)
450
451 return {
452 'dir': cwd,
453 'branch_name': branch_name,
454 'change_id': change_id
455 }
456
457
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700458def cros_workon(status, action):
459 """Call cros_workon for all the 9999 ebuilds we'll be touching
460
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700461 Args:
462 status: variant_status object tracking our board, variant, etc.
463 action: 'start' or 'stop'
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700464
465 Returns:
466 True if the call to cros_workon was successful, False if failed
467 """
468
469 # Build up the command from all the packages in the list
Paul Fagerburge868e832020-01-22 17:14:04 -0700470 workon_cmd = ['cros_workon', '--board=' + status.base, action] + status.workon_pkgs
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700471 return bool(run_process(workon_cmd))
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700472
473
474def create_coreboot_variant(status):
Paul Fagerburge868e832020-01-22 17:14:04 -0700475 """Create source files for a new variant of the reference board in coreboot
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700476
477 This function calls create_coreboot_variant.sh to set up a new variant
Paul Fagerburge868e832020-01-22 17:14:04 -0700478 of the reference board.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700479
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700480 Args:
481 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700482
483 Returns:
484 True if everything succeeded, False if something failed
485 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700486 logging.info('Running step create_coreboot_variant')
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700487 cb_src_dir = os.path.join('/mnt/host/source/src/', status.coreboot_dir)
488 environ = os.environ.copy()
489 environ['CB_SRC_DIR'] = cb_src_dir
490 create_coreboot_variant_sh = os.path.join(status.my_loc,
491 'create_coreboot_variant.sh')
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700492 rc = bool(run_process(
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700493 [create_coreboot_variant_sh,
Paul Fagerburge868e832020-01-22 17:14:04 -0700494 status.base,
Paul Fagerburgabb15622020-02-07 15:41:29 -0700495 status.board,
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700496 status.variant,
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700497 status.bug], env=environ))
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700498 if rc:
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700499 status.commits[step_names.CB_VARIANT] = get_git_commit_data(cb_src_dir)
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700500 return rc
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700501
502
503def create_coreboot_config(status):
504 """Create a coreboot configuration for a new variant
505
506 This function calls create_coreboot_config.sh, which will make a copy
507 of coreboot.${BOARD} into coreboot.${VARIANT}.
508
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700509 Args:
510 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700511
512 Returns:
513 True if the script and test build succeeded, False if something failed
514 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700515 logging.info('Running step create_coreboot_config')
Paul Fagerburg4d343452020-01-24 15:23:53 -0700516 environ = os.environ.copy()
517 if status.cb_config_dir is not None:
518 environ['CB_CONFIG_DIR'] = status.cb_config_dir
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700519 create_coreboot_config_sh = os.path.join(status.my_loc,
520 'create_coreboot_config.sh')
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700521 rc = bool(run_process(
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700522 [create_coreboot_config_sh,
Paul Fagerburge868e832020-01-22 17:14:04 -0700523 status.base,
524 status.board,
525 status.variant,
Paul Fagerburg4d343452020-01-24 15:23:53 -0700526 status.bug], env=environ))
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700527 if rc:
528 # Use status.cb_config_dir if defined, or if not, use
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700529 # '/mnt/host/source/src/third_party/chromiumos-overlay'
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700530 if status.cb_config_dir is not None:
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700531 cb_config_dir = os.path.join('/mnt/host/source/src/', status.cb_config_dir)
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700532 else:
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700533 cb_config_dir = '/mnt/host/source/src/third_party/chromiumos-overlay'
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700534 status.commits[step_names.CB_CONFIG] = get_git_commit_data(cb_config_dir)
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700535 return rc
Paul Fagerburge868e832020-01-22 17:14:04 -0700536
537
Paul Fagerburg2fd23f42020-02-07 14:04:48 -0700538def copy_cras_config(status):
539 """Copy the cras config for a new variant
540
541 This is only necessary for the Zork baseboard right now.
542 This function calls copy_cras_config.sh, which will copy the
543 cras config in
544 overlays/overlay-${BASE}/chromeos-base/chromeos-bsp-${BASE}/files/cras-config/${BASE}
545 to .../${VARIANT}
546
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700547 Args:
548 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg2fd23f42020-02-07 14:04:48 -0700549
550 Returns:
551 True if the script and test build succeeded, False if something failed
552 """
553 logging.info('Running step copy_cras_config')
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700554 copy_cras_config_sh = os.path.join(status.my_loc, 'copy_cras_config.sh')
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700555 rc = bool(run_process(
Paul Fagerburg2fd23f42020-02-07 14:04:48 -0700556 [copy_cras_config_sh,
557 status.base,
558 status.board,
559 status.variant,
560 status.bug]))
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700561 if rc:
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700562 status.commits[step_names.CRAS_CONFIG] = get_git_commit_data(
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700563 '/mnt/host/source/src/overlays')
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700564 return rc
Paul Fagerburg2fd23f42020-02-07 14:04:48 -0700565
566
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700567def add_fitimage(status):
568 """Add the source files for a fitimage for the new variant
569
570 This function calls add_fitimage.sh to create a new XSL file for the
Paul Fagerburge868e832020-01-22 17:14:04 -0700571 variant's fitimage, which can override settings from the reference board's
572 XSL. When this is done, the user will have to build the fitimage by running
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700573 gen_fit_image.sh outside of the chroot (and outside of this program's
574 control) because gen_fit_image.sh uses WINE, which is not installed in
575 the chroot. (There is a linux version of FIT, but it requires Open GL,
576 which is also not installed in the chroot.)
577
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700578 Args:
579 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700580
581 Returns:
582 True if the script succeeded, False otherwise
583 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700584 logging.info('Running step add_fitimage')
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700585 add_fitimage_sh = os.path.expanduser(os.path.join(
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700586 '/mnt/host/source/src', status.fitimage_dir, 'files/add_fitimage.sh'))
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700587 rc = bool(run_process(
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700588 [add_fitimage_sh,
589 status.variant,
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700590 status.bug]))
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700591 if rc:
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700592 fitimage_dir = os.path.join('/mnt/host/source/src', status.fitimage_dir)
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700593 status.commits[step_names.COMMIT_FIT] = get_git_commit_data(fitimage_dir)
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700594 return rc
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700595
596
597def gen_fit_image_outside_chroot(status):
598 """Tell the user to run gen_fit_image.sh outside the chroot
599
600 As noted for add_Fitimage(), gen_fit_image.sh cannot run inside the
601 chroot. This function tells the user to run gen_fit_image.sh in
602 their normal environment, and then come back (--continue) when that
603 is done.
604
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700605 Args:
606 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700607
608 Returns:
609 True
610 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700611 logging.info('Running step gen_fit_image_outside_chroot')
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700612 fit_image_files = check_fit_image_files(status)
613 # If the list is empty, then `not` of the list is True, so the files
614 # we need are all present and we can continue.
615 if not fit_image_files:
616 return True
617
618 logging.info('The following files need to be generated:')
619 for filename in fit_image_files:
620 logging.info('* %s', filename)
621 logging.info('The fitimage sources are ready for gen_fit_image.sh to process.')
622 logging.info('gen_fit_image.sh cannot run inside the chroot. Please open a new terminal')
623 logging.info('window, change to the directory where gen_fit_image.sh is located, and run')
Paul Fagerburg55dabf42020-01-27 15:30:09 -0700624 logging.info(status.fitimage_cmd, status.variant)
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700625 logging.info('Then re-start this program with --continue.')
626 logging.info('If your chroot is based in ~/chromiumos, then the folder you want is')
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700627 logging.info('~/chromiumos/src/%s/asset_generation', status.fitimage_dir)
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700628 return False
629
630
631def check_fit_image_files(status):
632 """Check if the fitimage has been generated
633
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700634 This function is not called directly as a step, and so it doesn't need
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700635 to produce any error messages to the user (except with --verbose).
636 gen_fit_image_outside_chroot will call this function to see if the
637 fitimage files exist, and if not, then that function will print the
638 message about how the user needs to run gen_fit_image.sh outside the
639 chroot.
640
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700641 Args:
642 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700643
644 Returns:
645 List of files that *DO NOT* exist and need to be created, [] if
646 all files are present.
647 """
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700648 outputs_dir = os.path.join('/mnt/host/source/src', status.fitimage_dir,
649 'asset_generation/outputs')
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700650 logging.debug('outputs_dir = "%s"', outputs_dir)
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700651
652 files = []
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700653 if not file_exists(outputs_dir, 'fitimage-' + status.variant + '.bin'):
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700654 files.append('fitimage-' + status.variant + '.bin')
655
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700656 if not file_exists(outputs_dir,
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700657 'fitimage-' + status.variant + '-versions.txt'):
658 files.append('fitimage-' + status.variant + '-versions.txt')
659
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700660 if not file_exists(outputs_dir, 'fit.log'):
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700661 files.append('fit.log')
662
663 return files
664
665
666def move_fitimage_file(fitimage_dir, filename):
667 """Move fitimage files from create-place to commit-place
668
669 commit_fitimage needs to move the fitimage files from the place where
670 they were created to a different directory in the tree. This utility
671 function handles joining paths and calling a file move function.
672
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700673 Args:
674 fitimage_dir: Directory where the fitimage files are
675 filename: Name of the file being moved
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700676
677 Returns:
678 True if the move succeeded, False if it failed
679 """
680 src_dir = os.path.join(fitimage_dir, 'asset_generation/outputs')
681 src = os.path.join(src_dir, filename)
682 dest_dir = os.path.join(fitimage_dir, 'files')
683 dest = os.path.join(dest_dir, filename)
684 # If src does not exist and dest does, the move is already done => success!
685 if not file_exists(src_dir, filename) and file_exists(dest_dir, filename):
686 logging.debug('move "%s", "%s" unnecessary because dest exists and'
687 ' src does not exist', src, dest)
688 return True
689
690 logging.debug('move "%s", "%s"', src, dest)
691 return shutil.move(src, dest)
692
693
694def commit_fitimage(status):
695 """Move the fitimage files and add them to a git commit
696
697 This function moves the fitimage binary and -versions files from
698 asset_generation/outputs to files/ and then adds those files and
699 fit.log to the existing git commit.
700
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700701 Args:
702 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700703
704 Returns:
705 True if the copy, git add, and git commit --amend all succeeded.
706 False if something failed.
707 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700708 logging.info('Running step commit_fitimage')
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700709 fitimage_dir = os.path.join('/mnt/host/source/src', status.fitimage_dir)
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700710 logging.debug('fitimage_dir = "%s"', fitimage_dir)
711
712 # The copy operation will check that the source file exists, so no
713 # need to check separately.
714 if not move_fitimage_file(fitimage_dir,
715 'fitimage-' + status.variant + '.bin'):
716 logging.error('Moving fitimage binary failed')
717 return False
718
719 if not move_fitimage_file(fitimage_dir,
720 'fitimage-' + status.variant + '-versions.txt'):
721 logging.error('Moving fitimage versions.txt failed')
722 return False
723
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700724 # TODO(pfagerburg) volteer also needs files/blobs/descriptor-${VARIANT}.bin
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700725 if not bool(run_process(
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700726 ['git', 'add',
727 'asset_generation/outputs/fit.log',
728 'files/fitimage-' + status.variant + '.bin',
729 'files/fitimage-' + status.variant + '-versions.txt'
730 ],
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700731 cwd=fitimage_dir)):
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700732 return False
733
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700734 return bool(run_process(['git', 'commit', '--amend', '--no-edit'],
735 cwd=fitimage_dir))
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700736
737
738def create_initial_ec_image(status):
Paul Fagerburge868e832020-01-22 17:14:04 -0700739 """Create an EC image for the variant as a clone of the reference board
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700740
741 This function calls create_initial_ec_image.sh, which will clone the
Paul Fagerburge868e832020-01-22 17:14:04 -0700742 reference board to create the variant. The shell script will build the
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700743 EC code for the variant, but the repo upload hook insists that we
744 have done a `make buildall` before it will allow an upload, so this
745 function does the buildall.
746
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700747 Args:
748 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700749
750 Returns:
751 True if the script and test build succeeded, False if something failed
752 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700753 logging.info('Running step create_initial_ec_image')
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700754 create_initial_ec_image_sh = os.path.join(status.my_loc,
755 'create_initial_ec_image.sh')
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700756 if not bool(run_process(
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700757 [create_initial_ec_image_sh,
758 status.board,
759 status.variant,
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700760 status.bug])):
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700761 return False
762
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700763 # No need to `if rc:` because we already tested the run_process result above
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700764 status.commits[step_names.EC_IMAGE] = get_git_commit_data(
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700765 '/mnt/host/source/src/platform/ec/board')
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700766
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700767 # create_initial_ec_image.sh will build the ec.bin for this variant
768 # if successful.
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700769 ec = '/mnt/host/source/src/platform/ec'
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700770 logging.debug('ec = "%s"', ec)
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700771 ec_bin = os.path.join('/build', status.base, 'firmware', status.variant,
772 'ec.bin')
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700773 logging.debug('ec.bin = "%s"', ec_bin)
774
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700775 if not file_exists(ec, ec_bin):
776 logging.error('EC binary %s not found', ec_bin)
777 return False
778 return True
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700779
780
781def ec_buildall(status):
782 """Do a make buildall -j for the EC, which is required for repo upload
783
784 The upload hook checks to ensure that the entire EC codebase builds
785 without error, so we have to run make buildall -j before uploading.
786
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700787 Args:
788 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700789
790 Returns:
791 True if the script and test build succeeded, False if something failed
792 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700793 logging.info('Running step ec_buildall')
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700794 del status # unused parameter
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700795 ec = '/mnt/host/source/src/platform/ec'
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700796 logging.debug('ec = "%s"', ec)
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700797 return bool(run_process(['make', 'buildall', '-j'], cwd=ec))
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700798
799
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700800def add_variant_to_public_yaml(status):
801 """Add the new variant to the public model.yaml file
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700802
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700803 This function calls add_variant_to_yaml.sh to add the new variant to
804 the public model.yaml file.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700805
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700806 Args:
807 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700808
809 Returns:
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700810 True if the script succeeded, False is something failed
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700811 """
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700812 logging.info('Running step add_variant_to_public_yaml')
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700813 add_variant_to_yaml_sh = os.path.join(status.my_loc,
814 'add_variant_to_yaml.sh')
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700815 rc = bool(run_process(
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700816 [add_variant_to_yaml_sh,
Paul Fagerburge868e832020-01-22 17:14:04 -0700817 status.base,
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700818 status.variant,
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700819 status.bug]))
820 if rc:
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700821 status.commits[step_names.ADD_PUB_YAML] = get_git_commit_data(
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700822 '/mnt/host/source/src/overlays')
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700823 return rc
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700824
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700825
826def add_variant_to_private_yaml(status):
827 """Add the new variant to the private model.yaml file
828
829 This function calls add_variant.sh to add the new variant to
830 the private model.yaml file.
831
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700832 Args:
833 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700834
835 Returns:
836 True if the script succeeded, False is something failed
837 """
838 logging.info('Running step add_variant_to_private_yaml')
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700839 add_variant_sh = os.path.expanduser(os.path.join(status.private_yaml_dir, 'add_variant.sh'))
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700840 rc = bool(run_process(
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700841 [add_variant_sh,
842 status.variant,
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700843 status.bug]))
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700844 if rc:
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700845 status.commits[step_names.ADD_PRIV_YAML] = get_git_commit_data(status.private_yaml_dir)
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700846 return rc
847
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700848
849
850def build_yaml(status):
851 """Build config files from the yaml files
852
853 This function builds the yaml files into the JSON and C code that
854 mosys and other tools use, then verifies that the new variant's name
855 shows up in all of the output files.
856
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700857 Args:
858 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700859
860 Returns:
861 True if the scripts and build succeeded, False is something failed
862 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700863 logging.info('Running step build_yaml')
864 if not bool(run_process([status.emerge_cmd] + status.yaml_emerge_pkgs)):
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700865 return False
866
867 # Check generated files for occurences of the variant name.
868 # Each file should have at least one occurence, so use `grep -c` to
869 # count the occurrences of the variant name in each file.
870 # The results will be something like this:
871 # config.json:10
872 # yaml/config.c:6
873 # yaml/config.yaml:27
874 # yaml/model.yaml:6
875 # yaml/private-model.yaml:10
876 # If the variant name doesn't show up in the file, then the count
877 # will be 0, so we would see, e.g.
878 # config.json:0
Paul Fagerburge868e832020-01-22 17:14:04 -0700879 # Note that we leave out yaml/model.yaml (the public one) because for
880 # some boards, there is nothing in the public yaml file.
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700881 # We gather the output from grep, then look for any of the strings
882 # ending in :0. If none of them match, then we're good, but if even
883 # one of them ends with :0 then there was a problem with generating
884 # the files from the yaml.
Paul Fagerburge868e832020-01-22 17:14:04 -0700885 chromeos_config = '/build/' + status.base + '/usr/share/chromeos-config'
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700886 logging.debug('chromeos_config = "%s"', chromeos_config)
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700887 grep = run_process(
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700888 ['grep',
Paul Fagerburge868e832020-01-22 17:14:04 -0700889 '-ci',
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700890 status.variant,
891 'config.json',
892 'yaml/config.c',
893 'yaml/config.yaml',
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700894 'yaml/private-model.yaml'], cwd=chromeos_config, capture_output=True)
895
896 if grep is None:
897 return False
898
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700899 return not bool([s for s in grep if re.search(r':0$', s)])
900
901
902def emerge_all(status):
903 """Build the coreboot BIOS and EC code for the new variant
904
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700905 Args:
906 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700907
908 Returns:
909 True if the build succeeded, False if something failed
910 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700911 logging.info('Running step emerge_all')
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700912 cros_workon(status, 'start')
913 environ = os.environ.copy()
914 environ['FW_NAME'] = status.variant
915 # Build up the command for emerge from all the packages in the list
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700916 emerge_cmd_and_params = [status.emerge_cmd] + status.emerge_pkgs
917 if not bool(run_process(emerge_cmd_and_params, env=environ)):
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700918 return False
919
920 cros_workon(status, 'stop')
Paul Fagerburge868e832020-01-22 17:14:04 -0700921 build_path = '/build/' + status.base + '/firmware'
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700922 logging.debug('build_path = "%s"', build_path)
923 if not file_exists(build_path, 'image-' + status.variant + '.bin'):
924 logging.error('emerge failed because image-%s.bin does not exist',
925 status.variant)
926 return False
927
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700928 if not file_exists(build_path, 'image-' + status.variant + '.serial.bin'):
929 logging.error('emerge failed because image-%s.serial.bin does not exist',
930 status.variant)
931 return False
932
933 return True
934
935
936def push_coreboot(status):
937 """Push the coreboot CL to coreboot.org
938
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700939 Args:
940 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700941
942 Returns:
943 True if the build succeeded, False if something failed
944 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700945 logging.info('Running step push_coreboot')
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700946 del status # unused parameter
947 logging.error('TODO (pfagerburg): implement push_coreboot')
948 return True
949
950
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700951def query_gerrit(instance, change_id):
952 """Search a gerrit instance for a specific change_id
953
954 Args:
955 instance: gerrit instance to query. Suitable values come from
956 gerrit.GetCrosInternal() and gerrit.GetCrosExternal()
957 change_id: The change_id to search for
958
959 Returns:
960 CL number if found, None if not
961 """
962 raw = instance.Query(change=change_id, raw=True)
963 if raw:
964 # If the CL was found by change_id, there will be only one,
965 # because the change_id is used to recognize a new patchset
966 # on an existing CL.
967 return raw[0]['number']
968
969 return None
970
971
972def find_change_id(change_id):
973 """Search the public and private ChromeOS gerrit instances for a change-id
974
975 Args:
976 change_id: Change-Id to search for in both gerrit instances
977
978 Returns:
979 Tuple of the gerrit instance ('chromium' or 'chrome-internal') and
980 the CL number if the Change-Id is found.
981 None if not found.
982 """
983 cl_number = query_gerrit(gerrit.GetCrosExternal(), change_id)
984 if cl_number:
985 return 'chromium', cl_number
986 cl_number = query_gerrit(gerrit.GetCrosInternal(), change_id)
987 if cl_number:
988 return 'chrome-internal', cl_number
989 return None
990
991
992def save_cl_data(status, commit_key, cl):
993 """Save the gerrit instance and CL number to the yaml file
994
995 Args:
996 status: variant_status object tracking our board, variant, etc.
997 commit_key: Which key in the commits map we're processing
998 cl: Value returned by find_change_id, should be a tuple
999 of instance_name, cl_number
1000 """
1001 instance_name, cl_number = cl
1002 print(f'Found ({instance_name}, {cl_number}), saving to yaml')
1003 status.commits[commit_key]['gerrit'] = instance_name
1004 status.commits[commit_key]['cl_number'] = cl_number
1005 status.save()
1006
1007
1008def repo_upload(branch_name, cwd):
1009 """Upload a branch to gerrit
1010
1011 This function runs `repo upload` in the specified directory to upload
1012 a branch to gerrit. Because it's operating in a directory and with a
1013 branch name, it could upload more than one commit, which is OK because
1014 we'll look for each commit by change-id before trying to upload in that
1015 directory. For example, this happens in Zork, where the cb_config step
1016 and the cras_config step both have a commit in src/overlays. When we're
1017 processing the cb_config step and we `repo upload` in src/overlays, it
1018 will also upload the commit for cras_config. Then we come around to the
1019 cras_config step, and since we can find a CL with the change-id, we don't
1020 try to upload again.
1021
1022 Args:
1023 branch_name: the name of the branch to upload. Gets passed to
1024 repo upload with the --br flag
1025 cwd: directory where we want to upload. Gets set as the working
1026 directory for executing repo upload.
1027
1028 Returns:
1029 True if repo upload exits with a successful error code, false otherwise
1030 """
1031 return bool(run_process(
1032 ['repo',
1033 'upload',
1034 '.',
1035 '--br=' + branch_name,
1036 '--wip',
1037 '--verify',
1038 '--yes'],
1039 cwd=cwd))
1040
1041
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001042def upload_CLs(status):
1043 """Upload all CLs to chromiumos
1044
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -07001045 Args:
1046 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001047
1048 Returns:
1049 True if the build succeeded, False if something failed
1050 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -07001051 logging.info('Running step upload_CLs')
Paul Fagerburga8c7e342020-02-25 13:30:49 -07001052
1053 for commit_key in status.repo_upload_list:
1054 logging.debug(f'Processing key {commit_key}')
1055 commit = status.commits[commit_key]
1056 if 'gerrit' not in commit or 'cl_number' not in commit:
1057 change_id = commit['change_id']
1058 cl = find_change_id(change_id)
1059 if cl is not None:
1060 save_cl_data(status, commit_key, cl)
1061 else:
1062 logging.debug(f'Not found {change_id}, need to upload')
1063 if not repo_upload(commit['branch_name'], commit['dir']):
1064 branch_name = commit['branch_name']
1065 dirname = commit['dir']
1066 logging.error(f'Repo upload {branch_name} in {dirname} failed!')
1067 return False
1068 cl = find_change_id(change_id)
1069 if cl is None:
1070 logging.error(f'repo upload {commit_key} succeeded, ' \
1071 'but change_id is not found!')
1072 return False
1073 save_cl_data(status, commit_key, cl)
1074 else:
1075 instance_name = commit['gerrit']
1076 cl_number = commit['cl_number']
1077 logging.debug(f'Already uploaded ({instance_name}, {cl_number})')
1078
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001079 return True
1080
1081
1082def find_coreboot_upstream(status):
1083 """Find the coreboot CL after it has been upstreamed to chromiumos
1084
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -07001085 Args:
1086 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001087
1088 Returns:
1089 True if the build succeeded, False if something failed
1090 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -07001091 logging.info('Running step find_coreboot_upstream')
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001092 del status # unused parameter
1093 logging.error('TODO (pfagerburg): implement find_coreboot_upstream')
1094 return True
1095
1096
1097def add_cq_depends(status):
1098 """Add Cq-Depends to all of the CLs in chromiumos
1099
1100 The CL in coreboot needs to be pushed to coreboot.org, get merged,
1101 and then get upstreamed into the chromiumos tree before the other
1102 CLs can cq-depend on it and pass CQ.
1103
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -07001104 Args:
1105 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001106
1107 Returns:
1108 True if the build succeeded, False if something failed
1109 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -07001110 logging.info('Running step add_cq_depends')
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001111 del status # unused parameter
1112 logging.error('TODO (pfagerburg): implement add_cq_depends')
1113 return True
1114
1115
1116def clean_up(status):
1117 """Final clean-up, including delete the status file
1118
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -07001119 Args:
1120 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001121
1122 Returns:
1123 True
1124 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -07001125 logging.info('Running step clean_up')
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001126 status.rm()
1127 return True
1128
1129
1130if __name__ == '__main__':
1131 sys.exit(not int(main()))