| #!/bin/bash | 
 | # Copyright 2017 The Chromium OS Authors. All rights reserved. | 
 | # Use of this source code is governed by a BSD-style license that can be | 
 | # found in the LICENSE file. | 
 |  | 
 | # Loads script libraries. | 
 | CONTRIB_DIR=$(dirname "$(readlink -f "$0")") | 
 | . "${CONTRIB_DIR}/common.sh" || exit 1 | 
 |  | 
 | FLAGS_HELP=" | 
 | Command to rebuild firmware after a config change. | 
 |  | 
 | After you make a change to the firmware version in the master configuration, | 
 | run this script to test it. It will rebuild the master configuration, update | 
 | the Manifest and build the new firmware. You can then submit your CL to update | 
 | the master configuration, safe in the knowledge that you have tested it. | 
 |  | 
 | Usage: | 
 |    cros_update_firmware <board> [project] | 
 |  | 
 | where <board> is the board whose firmware needs updating (e.g. 'coral'). | 
 |       [project] is the project the board belongs to. | 
 | " | 
 |  | 
 | # Flags | 
 | DEFINE_string board "${DEFAULT_BOARD}" "Which board the firmware is for" b | 
 | DEFINE_string project "${DEFAULT_PROJECT}" "Which project this board is for" p | 
 | DEFINE_boolean quiet "${FLAGS_FALSE}" "Reduce emerge build output" q | 
 |  | 
 | # Parse command line. | 
 | FLAGS "$@" || exit 1 | 
 | eval set -- "${FLAGS_ARGV}" | 
 | set -e | 
 |  | 
 | # Script must be run inside the chroot. | 
 | assert_inside_chroot | 
 |  | 
 | start_workon() { | 
 |   local board="$1" | 
 |   local pkg item | 
 |   if [[ -z "$2" ]]; then | 
 |     echo "Empty package.  Skipping..." | 
 |     return 1 | 
 |   fi | 
 |   pkg=$(cros workon --board="${board}" info "$2" | cut -d ' ' -f 1) | 
 |   shift 2 | 
 |   for item in "$@"; do | 
 |     if [[ "${pkg}" == "${item}" ]]; then | 
 |       echo "Already workon ${pkg}.  Skipping..." | 
 |       return 1 | 
 |     fi | 
 |   done | 
 |   cros workon --board="${board}" start "${pkg}" | 
 |   return $? | 
 | } | 
 |  | 
 | stop_workon() { | 
 |   cros workon --board="$1" stop "$2" | 
 | } | 
 |  | 
 | update_firmware() { | 
 |   local board="$1" | 
 |   local project="$2" | 
 |   local base ebuild srcuris cfg_bsp_pkg cfg_bsp_baseboard_pkg | 
 |   local current_workon_pkg_list start_pkg result i quiet | 
 |   [[ "$3" == "${FLAGS_TRUE}" ]] && quiet="--quiet-build" | 
 |  | 
 |   set -e | 
 |  | 
 |   # query the current working package | 
 |   mapfile -t current_workon_pkg_list < <(cros workon --board="${board}" list) | 
 |  | 
 |   # check if chromeos-config-bsp is a virtual package | 
 |   cfg_bsp_pkg="chromeos-config-bsp" | 
 |   equery-"${board}" w chromeos-base/chromeos-config-bsp > /dev/null 2>&1 \ | 
 |     || cfg_bsp_pkg="chromeos-config-bsp-${board}-private" | 
 |   # check if chromeos-config-bsp-baseboard is in use | 
 |   cfg_bsp_baseboard_pkg="chromeos-config-bsp-baseboard" | 
 |   equery-"${board}" w chromeos-base/chromeos-config-bsp-baseboard \ | 
 |     > /dev/null 2>&1 || cfg_bsp_baseboard_pkg= | 
 |  | 
 |   start_pkg=("${cfg_bsp_pkg}") | 
 |   start_pkg+=("chromeos-firmware-${board}") | 
 |   start_pkg+=("${cfg_bsp_baseboard_pkg}") | 
 |  | 
 |   for i in "${!start_pkg[@]}"; do | 
 |     result[i]=0 | 
 |     start_workon "${board}" "${start_pkg[i]}" "${current_workon_pkg_list[@]}" \ | 
 |        || result[i]=$? | 
 |   done | 
 |  | 
 |   overlay="${GCLIENT_ROOT}/src/private-overlays/overlay-${board}-private" | 
 |   metadata="${overlay}/metadata" | 
 |   edb_cache="/var/cache/edb/dep/mnt/host/source/src/private-overlays/overlay-${board}-private" | 
 |   base="${overlay}/chromeos-base" | 
 |   ebuild="${base}/chromeos-firmware-${board}/chromeos-firmware-${board}-9999.ebuild" | 
 |   srcuris="${base}/chromeos-firmware-${board}/files/srcuris" | 
 |   yaml_config="/build/${board}/usr/share/chromeos-config/yaml/config.yaml" | 
 |  | 
 |   # Check project config repo exists -- if so generate the config first. | 
 |   if [[ -d "${GCLIENT_ROOT}/src/project/${project}" ]]; then | 
 |     pushd "${GCLIENT_ROOT}/src/project/${project}" > /dev/null | 
 |     for brd in *; do | 
 |       if [[ -d "${brd}" && -x "${brd}/config/bin/gen_config" && -f "${brd}/config.star" ]]; then | 
 |         pushd "${brd}" > /dev/null | 
 |         ./config/bin/gen_config config.star | 
 |         popd > /dev/null | 
 |       fi | 
 |     done | 
 |     popd > /dev/null | 
 |   fi | 
 |  | 
 |   "emerge-${board}" -j ${quiet} ${cfg_bsp_baseboard_pkg} "${cfg_bsp_pkg}" chromeos-config | 
 |   cros_config_host -c "${yaml_config}" get-firmware-uris > "${srcuris}" | 
 |   touch "${ebuild}" | 
 |  | 
 |   # Clean metadata cache to make sure SRC_URI is fetched from ${srcuris} | 
 |   # instead from portage cache which maybe out of sync. | 
 |   # Note: this workaround is needed because we break the SRC_URI API contract | 
 |   # which is supposed to be a static (see | 
 |   # https://devmanual.gentoo.org/general-concepts/portage-cache/index.html). | 
 |   # TODO(crbug.com/927917): find a different way to generate SRC_URI and remove | 
 |   # these cache cleanup code. | 
 |   rm -rf "${metadata}/cache" "${metadata}/md5-cache" "${edb_cache}" | 
 |   "ebuild-${board}" "${ebuild}" manifest | 
 |   "emerge-${board}" -j ${quiet} "chromeos-firmware-${board}" | 
 |  | 
 |   for i in "${!result[@]}"; do | 
 |     if [[ "${result[i]}" -eq "0" ]]; then | 
 |       stop_workon "${board}" "${start_pkg[i]}" | 
 |     fi | 
 |   done | 
 | } | 
 |  | 
 | main() { | 
 |   if [[ -z "${FLAGS_board}" ]]; then | 
 |     die "-b or --board required." | 
 |   fi | 
 |  | 
 |   update_firmware "${FLAGS_board}" "${FLAGS_project}" "${FLAGS_quiet}" | 
 | } | 
 |  | 
 | main "$@" |