blob: dfb97782dd817f46e5b65baf58180229b64bced5 [file] [log] [blame]
Andrew McRae0809eb52020-06-18 00:13:36 +10001#!/bin/bash
2# Copyright 2020 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5#
6# TODO(amcrae): Refactor to use common.sh
7#
8# Script to update base firmware in a program's config, and then
9# regenerate the configs of projects that are part of the program.
10# Also updates the firmware manifest, and uploads all of the changes
11# for review.
12#
13# Usage:
14# ./update_program_fw program release [ reviewer ]
15# E.g:
16# ./update_program_fw puff 13291 amcrae@google.com
17#
18# Environment variables:
19# SRC = base of repo tree (default is ~/trunk/src)
20# HOME = home directory
21#
22# Variables
23#
24TEMPDIR=$(mktemp -d -t fw-XXXXXXXXXX)
25CMDNAME=$(basename "$0")
26SRC="${SRC:-/mnt/host/source/src}"
27PATH="${PATH}:${SRC}/config/bin"
28DIGITS="[1-9][0-9][0-9][0-9][0-9]"
29PROG=""
30BRANCH=""
31REVIEWER=""
32PROGRAM_CL=""
33PROGRAM="program.star"
34EDITOR="ex -s"; export EDITOR
35#
36# Common functions
37#
38cleanup() {
39 rm -rf "${TEMPDIR}"
40}
41
42trap "exit 1" HUP INT PIPE QUIT TERM
43trap 'cleanup' EXIT
44
45usage() {
46 if [[ "$#" -ge 1 ]]; then
47 echo "$*"
48 fi
49 echo "Usage: ${CMDNAME} program-name release [ reviewer ]"
50 echo "e.g:"
51 echo " ${CMDNAME} puff 13271 amcrae@google.com"
52 exit 1
53}
54#
55# Abort the update, and clean up branches and CLs
56#
57abort() {
58 echo "$*"
59 echo "Aborting..."
60 CLS=$(gerrit -i --raw search "owner:me status:open hashtag:${BRANCH}")
61 if [[ -n "${CLS}" ]]; then
62 echo "Abandoning uploaded CLs"
63 gerrit -i abandon "${CLS}"
64 fi
65 "cros_workon-${PROG}" stop "chromeos-base/chromeos-firmware-${PROG}"
66 "cros_workon-${PROG}" stop "chromeos-base/chromeos-config-bsp-${PROG}-private"
67 repo abandon "${BRANCH}"
68 exit 1
69}
70#
71# Extract a CL number from the file containing
72# the output of repo upload
73#
74getcl() {
75 CL=$(grep -o "https://chrome-internal-review.googlesource.com/c/chromeos/$1/+/[0-9][0-9]*" "$2")
76 if [[ -z "${CL}" ]]; then
77 cat "$2"
78 abort CL number not found in repo upload output
79 fi
80 echo "${CL}" | grep -o "[0-9][0-9]*"
81}
82#
83# If not on this branch, start a branch
84#
85branch() {
86 if ! (git branch --show-current | grep -q "${BRANCH}"); then
87 repo start "${BRANCH}"
88 else
89 echo "${BRANCH} already exists, skipping repo start"
90 fi
91}
92#
93# Return true if repo has changes.
94changed() {
95 [[ -n $(git status -s) ]]
96}
97#
98# Add a Cq-Depend line to a commit.
99# Use ex as a line editor to insert it.
100#
101amend() {
102 git commit --amend <<EOF
103/^Change-Id/
104i
105$1
106.
107wq
108EOF
109}
110#
111# Validate arguments
112#
113if [[ "$#" -lt 2 ]] || [[ "$#" -gt 3 ]]; then
114 usage
115fi
116#
117# Program must exist as a directory
118#
119PROG="$1"
120PROGDIR="${SRC}/program/${PROG}"
121if [[ ! -d "${PROGDIR}" ]]; then
122 usage "${PROG} is not a valid program (${PROGDIR} missing)"
123fi
124# Release must be a 5 digit number
125RELEASE="$2"
126if [[ ! "${RELEASE}" =~ ^${DIGITS}$ ]]; then
127 usage "release must be a 5 digit number"
128fi
129#
130# Check for reviewer argument.
131#
132if [[ "$#" -eq 3 ]]; then
133 REVIEWER=$3
134fi
135BRANCH="update_${PROG}_fw_${RELEASE}"
136#
137# Update the firmware version in the program config
138# From now on, all errors should invoke 'abort'
139# so that the branches and CLs are cleaned up.
140#
141cd "${PROGDIR}" || exit 1
142branch
143sed "/^ *major_version = ${DIGITS}$/s/${DIGITS}/${RELEASE}/" "${PROGRAM}" > "${TEMPDIR}/new-${PROGRAM}"
144#
145# Verify that only 1-5 characters have changed.
146#
147DIFF=$(cmp -l "${PROGRAM}" "${TEMPDIR}/new-${PROGRAM}" | wc -l)
148if [[ "${DIFF}" -gt 5 ]]; then
149 diff "${PROGRAM}" "new-${TEMPDIR}/${PROGRAM}"
150 abort "${PROGDIR}/${PROGRAM} update error"
151 exit 1
152fi
153#
154# If program config has changed, create a CL.
155#
156if [[ "${DIFF}" -ne 0 ]]; then
157 cp "${TEMPDIR}/new-${PROGRAM}" "${PROGRAM}"
158 git add .
159 git commit -F - <<EOF
160${PROG}: Update firmware to ${RELEASE}
161
162BUG=none
163TEST=FAFT tests on ${PROG}
164EOF
165 repo upload -y "--ht=${BRANCH}" --cbr . > "${TEMPDIR}/upload.output" 2>&1
166 PROGRAM_CL=$(getcl "program/${PROG}" "${TEMPDIR}/upload.output")
167fi
168#
169# Now walk through the projects and regenerate the configs.
170# Create and upload a CL and capture the CL number and project directory
171# if the project has changed.
172#
173PROJ_CLS=()
174PROJ_DIRS=()
175for PDIR in "${SRC}/project/${PROG}"/*; do
176 PROJ=$(basename "${PDIR}")
177 cd "${PDIR}" || abort "Missing directory: ${PDIR}"
178 branch
179 ./config.star || abort "Generate config failed for ${PROJ}"
180 check_config > "${TEMPDIR}/check_config-${PROJ}.output" || abort "check_config failed for ${PROJ}"
181 #
182 # Check if any files changed.
183 #
184 if changed; then
185 git add .
186 git commit -F - <<EOF
187${PROJ}: Update firmware to ${RELEASE}
188BUG=none
189TEST=FAFT tests on ${PROG}
190EOF
191 repo upload -y "--ht=${BRANCH}" --cbr . > "${TEMPDIR}/upload.${PROJ}.output" 2>&1
192 P_CL=$(getcl "project/${PROG}/${PROJ}" "${TEMPDIR}/upload.${PROJ}.output")
193 PROJ_CLS+=("${P_CL}")
194 PROJ_DIRS+=("${PDIR}")
195 fi
196done
197#
198# Create a Cq-Depend line with all the project CLs
199#
200if [[ -n "${PROJ_CLS[*]}" ]];then
201 SEP=" "
202 PROG_CQD="Cq-Depend:"
203 for CL in "${PROJ_CLS[@]}"; do
204 PROG_CQD="${PROG_CQD}${SEP}chrome-internal:${CL}"
205 SEP=", "
206 done
207 #
208 # Add the Cq-Depend line to the program CL commit message.
209 #
210 cd "${PROGDIR}" || abort "Missing directory: ${PROGDIR}"
211 amend "${PROG_CQD}"
212 repo upload --cbr .
213fi
214#
215# All the boxster configs have been uploaded.
216# Now run the update script and update the firmware manifest.
217#
218# Build base coreboot files
219# TODO: Should be selective here.
220#
221echo "Running emerge for coreboot. This may take a while..."
222if ! ("emerge-${PROG}" --quiet-build chromeos-ec coreboot depthcharge vboot_reference \
223 libpayload chromeos-bootimage coreboot-private-files \
224 "coreboot-private-files-${PROG}"); then
225 abort "emerge for coreboot failed!"
226fi
227echo "emerge of coreboot successful"
228OVERLAY="${SRC}/private-overlays/overlay-${PROG}-private/chromeos-base/chromeos-firmware-${PROG}"
229EB9999="chromeos-firmware-${PROG}-9999.ebuild"
230#
231# Remove any previous attempts to build the firmware.
232#
233"cros_workon-${PROG}" stop "chromeos-base/chromeos-firmware-${PROG}"
234"cros_workon-${PROG}" stop "chromeos-base/chromeos-config-bsp-${PROG}-private"
235cd "${OVERLAY}" || abort "Missing directory: ${OVERLAY}"
236branch
237cd "${SRC}/platform/dev/contrib" || abort "Missing directory: ${SRC}/platform/dev/contrib"
238if ! (./cros_update_firmware -q "--board=${PROG}"); then
239 abort "cros_update_firmware failed for ${PROG}"
240 exit 1
241fi
242cd "${OVERLAY}" || abort "Missing directory: ${OVERLAY}"
243#
244# If files have been updated, then create a CL for the changes.
245#
246OVERLAY_CL=""
247if changed; then
248 #
249 # Bump the version in the ebuild file. Relies on the format
250 # of the version so that the last number is at the end of the line.
251 #
252 CURVERS=$(grep "VERSION=REVBUMP" "${EB9999}" | grep -o "[0-9][0-9]*$")
253 NEXTVERS=$((CURVERS + 1))
254 sed "/VERSION=REVBUMP/s/${CURVERS}$/${NEXTVERS}/" "${EB9999}" > "${TEMPDIR}/new-${EB9999}"
255 cp "${TEMPDIR}/new-${EB9999}" "${EB9999}"
256 git add .
257 git commit -F - <<EOF
258${PROG}: Update firmware to ${RELEASE}
259
260BUG=none
261TEST=FAFT tests on ${PROG}
262
263${CQD}
264EOF
265 #
266 # Upload with no-verify since the file lines are too long.
267 #
268 repo upload "--ht=${BRANCH}" -y --no-verify --cbr . > "${TEMPDIR}/overlay.output" 2>&1
269 OVERLAY_CL=$(getcl "overlays/overlay-${PROG}-private" "${TEMPDIR}/overlay.output")
270 #
271 # Go back and amend all the project commit messages with a Cq-Depend on
272 # the program and overlay CLs.
273 #
274 CQD="Cq-Depend: chrome-internal:${OVERLAY_CL}"
275 if [[ -n "${PROGRAM_CL}" ]]; then
276 CQD="${CQD}, chrome-internal:${PROGRAM_CL}"
277 fi
278 for DIR in "${PROJ_DIRS[@]}"; do
279 cd "${DIR}" || abort "Missing directory: ${DIR}"
280 amend "${CQD}"
281 repo upload --cbr .
282 done
283fi
284#
285# Send all of the CLs to the CQ for a dry run.
286#
287ALL_CLS=$(gerrit -i --raw search "owner:me status:open hashtag:${BRANCH}")
288if [[ -z "${ALL_CLS}" ]]; then
289 echo "No changes required for program ${PROG}"
290 repo abandon "${BRANCH}"
291 exit 0
292fi
293for cl in ${ALL_CLS}; do
294 gerrit -i label-cq "${cl}" 1
295 gerrit -i label-v "${cl}" 1
296 gerrit -i label-as "${cl}" 1
297done
298#
299# If reviewer is set, then add them to the CLs
300#
301if [[ -n "${REVIEWER}" ]]; then
302 echo "Sending CLs ${ALL_CLS} to ${REVIEWER} for review"
303 for cl in ${ALL_CLS}; do
304 gerrit -i reviewers "${cl}" "${REVIEWER}"
305 done
306else
307 echo "Send CLs for review by running:"
308 echo " for cl in ${ALL_CLS}; do gerrit -i reviewers \$cl <reviewer>; done"
309fi
310#
311# Final instructions.
312#
313echo "Run:"
314echo " /build/${PROG}/usr/sbin/chromeos-firmwareupdate --manifest"
315echo "to verify firmware update"
316echo "When submitted, cleanup by running:"
317echo "repo abandon ${BRANCH}"