| #!/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 |
| DEFINE_boolean append_srcuris "${FLAGS_TRUE}" "Only applicable when the project |
| flag is set. Append firmware uris to srcuris instead of overwriting. This is |
| usually needed if you have limited access to project config repos, so |
| overwriting would delete some uris." |
| |
| # 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 |
| local current_workon_pkg_list start_pkg result i |
| local emerge_flags=() |
| [[ "$3" == "${FLAGS_TRUE}" ]] && emerge_flags+=("--quiet-build") |
| local append_srcuris="$4" |
| |
| set -e |
| |
| # query the current working package |
| mapfile -t current_workon_pkg_list < <(cros workon --board="${board}" list) |
| |
| local config_packages=(chromeos-base/chromeos-config) |
| |
| # checking various use flags to include appropriate packages |
| local all_use_flags=$(portageq-${board} envvar USE) |
| local use_flag pkg |
| for use_flag in ${all_use_flags}; do |
| case "${use_flag}" in |
| has_chromeos_config_bsp* ) |
| without_has="${use_flag//has_/}" |
| pkg="chromeos-base/${without_has//_/-}" |
| if equery-"${board}" which "${pkg}" >/dev/null 2>&1; then |
| config_packages+=("${pkg}") |
| fi |
| ;; |
| esac |
| done |
| |
| start_pkg=("${config_packages[@]}") |
| start_pkg+=("chromeos-firmware-${board}") |
| |
| 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 "${emerge_flags[@]}" "${config_packages[@]}" |
| |
| # If the append_srcuris and project flags are set, append uris that aren't |
| # already in srcuris. Otherwise, overwrite srcuris. |
| if [[ -n "${project}" && "${append_srcuris}" == "${FLAGS_TRUE}" ]]; then |
| for uri in $(cros_config_host -c "${yaml_config}" get-firmware-uris); do |
| if ! grep -q "${uri}" "${srcuris}"; then |
| # Append uri to the last line of srcuris (srcuris should be a file with |
| # one line per-uri). |
| echo "${uri}" >> "${srcuris}" |
| fi |
| done |
| else |
| # Put each uri on its own line for easier merging in git. |
| cros_config_host -c "${yaml_config}" get-firmware-uris | tr ' ' '\n' > "${srcuris}" |
| fi |
| |
| 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 "${emerge_flags[@]}" "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}" "${FLAGS_append_srcuris}" |
| } |
| |
| main "$@" |