update_program_fw: Add support for zork
Add support for zork, which requires the features:
- per-project firmware versions
- different coreboot packages
v2:
- Add --test for TEST= string
- Add --dryrun for dumping parameters
- Validate bug string.
BUG=none
TEST=Run script on zork/morphius and puff/faffy
Change-Id: Ia3649db9855c7efc97e7d32d7db0340ee1a27747
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/dev-util/+/2269557
Reviewed-by: Andrew McRae <amcrae@chromium.org>
Reviewed-by: Rob Barnes <robbarnes@google.com>
Commit-Queue: Andrew McRae <amcrae@chromium.org>
Tested-by: Andrew McRae <amcrae@chromium.org>
diff --git a/contrib/update_program_fw b/contrib/update_program_fw
index 465603a..bc8a7fa 100755
--- a/contrib/update_program_fw
+++ b/contrib/update_program_fw
@@ -14,13 +14,16 @@
# E.g:
# ./update_program_fw --board=puff --release=13291 --reviewer=amcrae@google.com
#
+# TODO:
+# - Handle minor version
+#
CONTRIB_DIR=$(dirname "$(readlink -f "$0")")
. "${CONTRIB_DIR}/common.sh" || exit 1
FLAGS_HELP="
Command to update the firmware version for a board.
-Updates the master_version firmware configuration for a board's
+Updates the firmware version configuration for a board's
master configuration (program.star) and for selected projects
that include the master configuration.
@@ -34,12 +37,20 @@
An optional reviewer can be specified to send all the CLs to.
"
# Flags
-DEFINE_string board "${DEFAULT_BOARD}" "Which board (program) the firmware is for" b
-DEFINE_integer release 0 "The firmware release to update to" r
-DEFINE_string project "${DEFAULT_PROJECT}" "Which projects this release is for (defaults to all)" p
+DEFINE_string board "${DEFAULT_BOARD}" "Which board (program) the firmware is for (e.g 'puff')" b
+DEFINE_integer release 0 "The firmware release to update to (e.g 13310)" r
+DEFINE_string project "${DEFAULT_PROJECT}" "Which projects this release is for (defaults to all), e.g 'duffy'" p
DEFINE_string bug "none" "The bug to reference in the CL e.g b:12345"
-DEFINE_string skip "${DEFAULT_SKIP}" "Skip these projects" s
+DEFINE_string skip "${DEFAULT_SKIP}" "Skip these projects (comma separated list)" s
+DEFINE_boolean build "${FLAGS_TRUE}" "Attempt to build coreboot"
+DEFINE_boolean program "${FLAGS_TRUE}" "Update the version in the base program.star"
DEFINE_string reviewer "${DEFAULT_REVIEWER}" "The reviewer to send the CLs to (optional)"
+DEFINE_string test "none" "The 'TEST=' string added to the commit message"
+DEFINE_boolean dryrun "${FLAGS_FALSE}" "Do not perform any actions, just validate and print arguments"
+
+# Set before flag processing
+COMMAND=$(basename "$0")
+CMDARGS="$*"
# Parse command line
FLAGS "$@" || exit 1
@@ -55,9 +66,9 @@
DIGITS="[1-9][0-9][0-9][0-9][0-9]"
BRANCH=""
PROGRAM_CL=""
-PROGRAM="program.star"
-BASENAME=$(basename "$0")
-COMMAND="${BASENAME} $@"
+MAJORV=" major_version = "
+ANY_MV="${MAJORV}${DIGITS}"
+NEW_MV="${MAJORV}${FLAGS_release}"
#
# Common functions
#
@@ -83,8 +94,7 @@
die "$*"
}
#
-# Extract a CL number from the file containing
-# the output of repo upload
+# Extract a CL number from the file containing the output of repo upload
#
getcl() {
CL=$(grep -o "https://chrome-internal-review.googlesource.com/c/chromeos/$1/+/[0-9][0-9]*" "$2")
@@ -106,6 +116,7 @@
}
#
# Return true if repo has changes.
+#
changed() {
[[ -n $(git status -s) ]]
}
@@ -118,6 +129,15 @@
git commit -q --amend -F "${TEMPDIR}/amend-msg"
}
#
+# Confirm that $1 is a valid project
+#
+check_project() {
+ PDIR="${GCLIENT_ROOT}/src/project/${FLAGS_board}/${1}"
+ if [[ ! -d "${PDIR}" ]]; then
+ die "${P} is not a valid project (${PDIR} missing)"
+ fi
+}
+#
# Return true if $1 is in list $2
#
in_list() {
@@ -129,6 +149,38 @@
return 1
}
#
+# Return 0 if file has version in it.
+#
+has_version() {
+ (grep -q "${ANY_MV}" "${1}")
+}
+#
+# Update the major version in the file passed.
+# return 0 if version updated.
+# return 1 if version not in file, or unchanged.
+#
+update_version() {
+ # Check for major_version in file.
+ if ! (has_version "${1}") ;then
+ return 1
+ fi
+ local nf="${TEMPDIR}/new-${1}"
+ sed "/${ANY_MV}/s/${ANY_MV}/${NEW_MV}/" "${1}" > "${nf}"
+ #
+ # Verify that only 1-5 characters have changed.
+ #
+ DIFF=$(cmp -l "${1}" "${nf}" | wc -l)
+ if [[ "${DIFF}" -gt 5 ]]; then
+ diff "${1}" "{nf}}"
+ abort "${1} update error"
+ fi
+ if [[ "${DIFF}" == 0 ]]; then
+ return 1
+ fi
+ cp "${nf}" "${1}"
+ return 0
+}
+#
# Validate arguments
#
if [[ -z "${FLAGS_board}" ]]; then
@@ -167,6 +219,10 @@
if [[ -n "${FLAGS_skip}" ]]; then
PROJECTS=()
IFS=',' read -r -a SKIP_ARRAY <<< "${FLAGS_skip}"
+ # Validate skipped projects
+ for S in "${SKIP_ARRAY[@]}"; do
+ check_project "${S}"
+ done
SKIPPED="${SKIP_ARRAY[*]}"
for P in "${PROJLIST[@]}"; do
if ! (in_list "${P}" "${SKIPPED}"); then
@@ -177,23 +233,28 @@
PROJECTS=("${PROJLIST[@]}")
fi
#
+# Valid bug number (if any).
+# Must be of the form b:nnnnn or chromium:nnnnn
+#
+if [[ "${FLAGS_bug}" != "none" ]]; then
+ BG="b:[0-9]+|chromium:[0-9]+"
+ BGRE="^(${BG})(,(${BG}))*$"
+ if [[ ! "${FLAGS_bug}" =~ ${BGRE} ]]; then
+ echo "Bug must be of the form b:nnn or chromium:nnn"
+ die "A comma separated list is allowed"
+ fi
+fi
+#
# Validate project list and file locations.
#
for P in "${PROJECTS[@]}"; do
- PDIR="${GCLIENT_ROOT}/src/project/${FLAGS_board}/${P}"
- if [[ ! -d "${PDIR}" ]]; then
- die "${P} is not a valid project (${PDIR} missing)"
- fi
+ check_project "${P}"
done
-# Validate project overlay location
OVERLAY="${GCLIENT_ROOT}/src/private-overlays/overlay-${FLAGS_board}-private/chromeos-base/chromeos-firmware-${FLAGS_board}"
-if [[ ! -d "${OVERLAY}" ]]; then
- die "${OVERLAY}: invalid directory"
-fi
-# Validate ebuild file
+# Validate project overlay and ebuild file
EB9999="chromeos-firmware-${FLAGS_board}-9999.ebuild"
if [[ ! -f "${OVERLAY}/${EB9999}" ]]; then
- die "${OVERLAY}/${EB9999}: missing file"
+ die "${OVERLAY}/${EB9999}: overlay error"
fi
# Make sure dev/contrib is accessible
DEVCONTRIB="${GCLIENT_ROOT}/src/platform/dev/contrib"
@@ -201,6 +262,46 @@
die "${DEVCONTRIB}: invalid directory"
fi
#
+# If requesting dry run, dump arguments and exit.
+#
+if [[ "${FLAGS_dryrun}" -eq "${FLAGS_TRUE}" ]]; then
+ echo "Dry run requested, invoked as:"
+ echo "${COMMAND} ${CMDARGS}"
+ echo "Program (board) to be updated: ${FLAGS_board}"
+ echo -n "Projects to be updated are: "
+ for PROJ in "${PROJECTS[@]}"; do
+ echo -n " ${PROJ}"
+ done
+ if [[ -n "${SKIPPED}" ]]; then
+ echo -n " (skipped:"
+ for S in "${SKIPPED[@]}"; do
+ echo -n " ${S}"
+ done
+ echo -n ")"
+ fi
+ echo
+ echo "Release number of upgrade: ${FLAGS_release}"
+ echo "BUG string used in commit: ${FLAGS_bug}"
+ echo "TEST string used in commit: ${FLAGS_test}"
+ echo "Reviewer assigned to CLs: ${FLAGS_reviewer:-None}"
+ echo -n "Coreboot build enabled: "
+ if [[ "${FLAGS_build}" -eq "${FLAGS_FALSE}" ]]; then
+ echo "no"
+ else
+ echo "yes"
+ fi
+ echo "repo branch to be used is: ${BRANCH}"
+ exit 0
+fi
+if [[ "${FLAGS_build}" -eq "${FLAGS_FALSE}" ]]; then
+ echo
+ echo "******************************************"
+ echo "* You have elected not to build coreboot *"
+ echo "* This assumes coreboot is already built *"
+ echo "******************************************"
+ echo
+fi
+#
# Create a temp directory.
TEMPDIR=$(mktemp -d -t fw-XXXXXXXXXX)
@@ -208,44 +309,39 @@
trap 'cleanup' EXIT
#
-# Update the firmware version in the program config
# From now on, all errors should invoke 'abort'
# so that the branches and CLs are cleaned up on exit.
#
-cd "${PROGDIR}"
-echo "Updating ${PROGRAM} for board ${FLAGS_board}"
-branch
-sed "/^ *major_version = ${DIGITS}$/s/${DIGITS}/${FLAGS_release}/" "${PROGRAM}" > "${TEMPDIR}/new-${PROGRAM}"
+# If required, update the firmware version in the program's program.star file
#
-# Verify that only 1-5 characters have changed.
-#
-DIFF=$(cmp -l "${PROGRAM}" "${TEMPDIR}/new-${PROGRAM}" | wc -l)
-if [[ "${DIFF}" -gt 5 ]]; then
- diff "${PROGRAM}" "new-${TEMPDIR}/${PROGRAM}"
- abort "${PROGDIR}/${PROGRAM} update error"
-fi
-#
-# If program config has changed, create a CL.
-#
-if [[ "${DIFF}" -ne 0 ]]; then
- cp "${TEMPDIR}/new-${PROGRAM}" "${PROGRAM}"
- git add .
- git commit -q -F - <<EOF
-${FLAGS_board}: Update firmware to ${FLAGS_release}
+if [[ "${FLAGS_program}" -eq "${FLAGS_TRUE}" ]]; then
+ cd "${PROGDIR}"
+ echo "Updating program.star for board ${FLAGS_board}"
+ branch
+ if (update_version "program.star") ;then
+ #
+ # If config has changed, create a CL.
+ #
+ git add .
+ git commit -q -F - <<EOF
+${FLAGS_board}: Update program firmware to ${FLAGS_release}
-Autogenerated by: ${COMMAND}
+Autogenerated by:
+${COMMAND} ${CMDARGS}
BUG=${FLAGS_bug}
-TEST=FAFT tests on ${FLAGS_board}
+TEST=${FLAGS_test}
EOF
- if ! repo upload -y "--ht=${BRANCH}" --cbr . > "${TEMPDIR}/upload.output" 2>&1 ;then
- cat "${TEMPDIR}/upload.output"
- abort "repo upload failed"
+ if ! repo upload -y "--ht=${BRANCH}" --cbr . > "${TEMPDIR}/upload.output" 2>&1 ;then
+ cat "${TEMPDIR}/upload.output"
+ abort "repo upload failed"
+ fi
+ PROGRAM_CL=$(getcl "program/${FLAGS_board}" "${TEMPDIR}/upload.output")
fi
- PROGRAM_CL=$(getcl "program/${FLAGS_board}" "${TEMPDIR}/upload.output")
fi
#
-# Now walk through the projects and regenerate the configs.
+# Now walk through the projects and update the version (if present)
+# and regenerate the configs.
# Create and upload a CL and capture the CL number and project directory
# if the project has changed.
#
@@ -256,6 +352,7 @@
PDIR="${GCLIENT_ROOT}/src/project/${FLAGS_board}/${PROJ}"
cd "${PDIR}"
branch
+ update_version "config.star" || true
./config.star || abort "Generate config failed for ${PROJ}"
check_config > "${TEMPDIR}/check_config-${PROJ}.output" || abort "check_config failed for ${PROJ}"
#
@@ -267,10 +364,11 @@
git commit -q -F - <<EOF
${PROJ}: Update firmware to ${FLAGS_release}
-Autogenerated by: ${COMMAND}
+Autogenerated by:
+${COMMAND} ${CMDARGS}
BUG=${FLAGS_bug}
-TEST=FAFT tests on ${FLAGS_board}
+TEST=${FLAGS_test}
EOF
if ! repo upload -y "--ht=${BRANCH}" --cbr . > "${TEMPDIR}/upload.${PROJ}.output" 2>&1 ;then
cat "${TEMPDIR}/upload.${PROJ}.output"
@@ -308,15 +406,33 @@
# Now run the update script and update the firmware manifest.
#
# Build base coreboot files
-# TODO: Should be selective here.
#
-echo "Running emerge for coreboot. This may take a while..."
-if ! ("emerge-${FLAGS_board}" --quiet-build chromeos-ec coreboot depthcharge vboot_reference \
- libpayload chromeos-bootimage coreboot-private-files \
- "coreboot-private-files-${FLAGS_board}"); then
- abort "emerge for coreboot failed!"
+if [[ "${FLAGS_build}" -eq "${FLAGS_TRUE}" ]]; then
+ echo "Running coreboot build. This may take a while..."
+ #
+ # Attempt to customise the coreboot build depending on the platform.
+ #
+ case "${FLAGS_board}" in
+ "zork")
+ PACKAGES=(coreboot-zork chromeos-bootimage)
+ ;;
+ "puff")
+ PACKAGES=(chromeos-ec coreboot depthcharge vboot_reference libpayload chromeos-bootimage coreboot-private-files intel-cmlfsp coreboot-private-files-puff)
+ ;;
+ *)
+ # Use general packages
+ echo "Taking a guess at coreboot packages for ${FLAGS_board}"
+ echo "If the coreboot build fails, this script may have to be customized for this board"
+ PACKAGES=(coreboot depthcharge vboot_reference libpayload chromeos-bootimage)
+ ;;
+ esac
+ if ! ("emerge-${FLAGS_board}" --quiet-build "${PACKAGES[@]}"); then
+ abort "coreboot build failed!"
+ fi
+ echo "coreboot build successful"
+else
+ echo "Coreboot build not attempted"
fi
-echo "emerge of coreboot successful"
EB9999="chromeos-firmware-${FLAGS_board}-9999.ebuild"
#
# Remove any previous attempts to build the firmware.
@@ -346,10 +462,11 @@
git commit -q -F - <<EOF
${FLAGS_board}: Update firmware to ${FLAGS_release}
-Autogenerated by: ${COMMAND}
+Autogenerated by:
+${COMMAND} ${CMDARGS}
BUG=${FLAGS_bug}
-TEST=FAFT tests on ${FLAGS_board}
+TEST=${FLAGS_test}
${PROG_CQD}
EOF