blob: 08b4e2fc445caf5e1af0c02e8ecbdf926cb1f980 [file] [log] [blame]
Mike Frysinger3424c802018-08-16 15:00:32 -04001#!/bin/bash
2# Copyright 2017 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# Script to automate firmware update process for a board.
7# It works only when the private overlay and firmware ebuild
8# file for the board are already in place.
9
10# Loads script libraries.
11CONTRIB_DIR=$(dirname "$(readlink -f "$0")")
12. "${CONTRIB_DIR}/common.sh" || exit 1
13
14# Flags.
15DEFINE_string board "${DEFAULT_BOARD}" "Which board the firmware is for" b
16DEFINE_string fw_version "" "Firmware version of the new firmware" v
17DEFINE_string output_dir "" "Output directory" o
18DEFINE_boolean rw_only "${FLAGS_FALSE}" "Only update RW image"
19DEFINE_boolean dev "${FLAGS_FALSE}" "Use image.dev.bin as the main firmware binary"
20
21FLAGS_HELP="Update chromeos-firmware-${board} ebuild file and tarball in BCS for the new firmware.
22
23USAGE: $0 [flags] args
24
25For example:
26
27To uprev kevin ro/rw firmware to 8785.178.0, run:
28$ ./uprev_firmware -b kevin -v 8785.178.0
29
30To uprev chell rw firmware to 7820.288.0, run:
31$ ./uprev_firmware -b chell -v 7820.288.0 --rw_only
32"
33
34# Parse command line.
35FLAGS "$@" || exit 1
36eval set -- "${FLAGS_ARGV}"
37set -e
38
39# Script must run inside the chroot.
40assert_inside_chroot
41
42# Sanity check the arguments and initialize global variables.
43init() {
44 TMP=$(mktemp -d --suffix=.uprev_firmware)
45
46 if [[ -z "${FLAGS_board}" ]]; then
47 die "-b or --board required."
48 fi
49
50 # Uppercase the 1st letter of the board name.
51 BOARD_NAME=${FLAGS_board^}
52
53 if [[ -z "${FLAGS_fw_version}" ]]; then
54 die "Please specify a firmware version using -v"
55 fi
56
57 if [[ -z "${FLAGS_output_dir}" ]]; then
58 info "${TMP} is used as your default output directory\n"
59 FLAGS_output_dir=${TMP}
60 fi
61
62 if [[ ! -d "${FLAGS_output_dir}" ]]; then
63 die "The output directory does not exist\n"
64 fi
65 FLAGS_output_dir=$(realpath "${FLAGS_output_dir}")
66
67 if [[ ! -d "/build/${FLAGS_board}" ]]; then
68 die "Please setup board for ${FLAGS_board} first"
69 fi
70
71 OVERLAY_DIR="${GCLIENT_ROOT}/src/private-overlays/\
72overlay-${FLAGS_board}-private"
73 if [[ ! -d "${OVERLAY_DIR}" ]]; then
74 die "The private overlay is not found: ${OVERLAY_DIR}"
75 fi
76
77 EBUILD_DIR="${OVERLAY_DIR}/chromeos-base/chromeos-firmware-${FLAGS_board}"
78 if [[ ! -d "${EBUILD_DIR}" ]]; then
79 die "The directory doesn't exist: ${EBUILD_DIR}"
80 fi
81
82 EBUILD_FILE="${EBUILD_DIR}/chromeos-firmware-${FLAGS_board}-9999.ebuild"
83 if [[ ! -f "${EBUILD_FILE}" ]]; then
84 die "Please create the initial firmware ebuild manually:\n" \
85 "${EBUILD_FILE}"
86 fi
87
88 if [[ "${FLAGS_dev}" -eq "${FLAGS_TRUE}" ]]; then
89 MAIN_FW_TAR_NAME="${BOARD_NAME}.${FLAGS_fw_version}.DEV_IMAGE_DO_NOT_SHIP\
90.tbz2"
91 else
92 MAIN_FW_TAR_NAME="${BOARD_NAME}.${FLAGS_fw_version}.tbz2"
93 fi
94 EC_FW_TAR_NAME="${BOARD_NAME}_EC.${FLAGS_fw_version}.tbz2"
95 PD_FW_TAR_NAME="${BOARD_NAME}_PD.${FLAGS_fw_version}.tbz2"
96}
97
98# Clean up function when exit.
99cleanup() {
100 rm -rf "${TMP}"
101}
102
103# Prepare new firmware tarballs to upload to BCS
104prepare_fw_tarball() {
105 local build_dir="gs://chromeos-releases/canary-channel/\
106${FLAGS_board}/${FLAGS_fw_version}"
107 local build_fw_tar_path=$(gsutil ls "${build_dir}/ChromeOS-firmware-*")
108 local build_fw_tar_name=$(basename "${build_fw_tar_path}")
109
110 if [[ -z "${build_fw_tar_path}" ]]; then
111 die "Please ensure your gsutil works and the firmware version is correct"
112 fi
113
114 # Download the firmware tarball.
115 gsutil cp "${build_fw_tar_path}" "${TMP}/."
116 tar -xvf "${TMP}/${build_fw_tar_name}" -C "${TMP}"
117 if [[ "${FLAGS_dev}" -eq "${FLAGS_TRUE}" ]]; then
118 mv "${TMP}/image.dev.bin" "${TMP}/image.bin"
119 warn "You are uploading a developer image with serial output." \
120 "Please only do this during early bring-up. Dogfooding should always be" \
121 "done with production images since timing differences in developer"\
122 "images can hide bugs and the production image must be sufficiently" \
123 "tested before shipping.\n"
124 fi
125 # Make new tarballs for EC/AP FW binaries.
126 tar -jcvf "${TMP}/${MAIN_FW_TAR_NAME}" -C "${TMP}" image.bin
127 if [[ "${FLAGS_rw_only}" -eq "${FLAGS_FALSE}" ]]; then
128 tar -jcvf "${TMP}/${EC_FW_TAR_NAME}" -C "${TMP}" ec.bin
129 # Do this for PD FW as well (if available).
130 if [ -d "${TMP}/${FLAGS_board}_pd" ]; then
131 tar -jcvf "${TMP}/${PD_FW_TAR_NAME}" -C "${TMP}/${FLAGS_board}_pd" ec.bin
132 else
133 PD_FW_TAR_NAME=
134 fi
135 fi
136
137 if [[ "${TMP}" != "${FLAGS_output_dir}" ]]; then
138 mv "${TMP}/${MAIN_FW_TAR_NAME}" "${FLAGS_output_dir}"
139 if [[ "${FLAGS_rw_only}" -eq "${FLAGS_FALSE}" ]]; then
140 mv "${TMP}/${EC_FW_TAR_NAME}" "${FLAGS_output_dir}"
141 if [[ -z "${PD_FW_TAR_NAME}" ]]; then
142 mv "${TMP}/${PD_FW_TAR_NAME}" "${FLAGS_output_dir}"
143 fi
144 fi
145 fi
146
147 local file_list="${FLAGS_output_dir}/${MAIN_FW_TAR_NAME}\n"
148 if [[ "${FLAGS_rw_only}" -eq "${FLAGS_FALSE}" ]]; then
149 file_list+=" ${FLAGS_output_dir}/${EC_FW_TAR_NAME}\n"
150 if [ -n "${PD_FW_TAR_NAME}" ]; then
151 file_list+=" ${FLAGS_output_dir}/${PD_FW_TAR_NAME}\n"
152 fi
153 fi
154
155 info "Your tarballs are ready at\n" \
156 "${file_list}" \
157 "To continue, please upload them to BCS manually through CPFE:\n" \
158 "https://www.google.com/chromeos/partner/fe/#bcUpload:type=PRIVATE\n"
159}
160
161# Update the firmware ebuild file in the device private overlay
162update_fw_ebuild() {
163 local keyword_main_fw="MAIN_IMAGE=\"bcs:\/\/${BOARD_NAME}"
164 local keyword_main_rw_fw="CROS_FIRMWARE_MAIN_RW_IMAGE="
165 local keyword_ec_fw="EC_IMAGE=\"bcs:\/\/${BOARD_NAME}"
166 local keyword_pd_fw="PD_IMAGE=\"bcs:\/\/${BOARD_NAME}"
167 local main_fw_line=$(grep -i "${keyword_main_fw}" "${EBUILD_FILE}")
168 local main_rw_fw_line=$(grep -i "${keyword_main_rw_fw}" "${EBUILD_FILE}")
169 local ec_fw_line=$(grep -i "${keyword_ec_fw}" "${EBUILD_FILE}")
170 local pd_fw_line=$(grep -i "${keyword_pd_fw}" "${EBUILD_FILE}")
171 local old_main_fw_tar_name="${main_fw_line#*bcs://}"
172 old_main_fw_tar_name="${old_main_fw_tar_name%'"'}"
173 local old_ec_fw_tar_name="${ec_fw_line#*bcs://}"
174 old_ec_fw_tar_name="${old_ec_fw_tar_name%'"'}"
175 local old_pd_fw_tar_name="${pd_fw_line#*bcs://}"
176 old_pd_fw_tar_name="${old_pd_fw_tar_name%'"'}"
177
178 # Check if the repo is clean.
179 local git_output="$(git --git-dir="${OVERLAY_DIR}/.git" \
180 --work-tree="${OVERLAY_DIR}" status --porcelain)"
181 if [[ -n ${git_output} ]]; then
182 die "Please clean your repo first: ${OVERLAY_DIR}"
183 fi
184
185 # Update the fw ebuild file.
186 if [[ -n "${main_rw_fw_line}" ]]; then
187 sed -i "/${keyword_main_rw_fw}/d" "${EBUILD_FILE}"
188 fi
189 if [[ "${FLAGS_rw_only}" -eq "${FLAGS_FALSE}" ]]; then
190 sed -i -e "s/${old_main_fw_tar_name}/${MAIN_FW_TAR_NAME}/" \
191 -e "s/${old_ec_fw_tar_name}/${EC_FW_TAR_NAME}/" "${EBUILD_FILE}"
192 main_rw_fw_line="${keyword_main_rw_fw}\"\""
193 if [[ -n "${PD_FW_TAR_NAME}" ]]; then
194 sed -i -e "s/${old_pd_fw_tar_name}/${PD_FW_TAR_NAME}/" \
195 "${EBUILD_FILE}"
196 fi
197 else
198 main_rw_fw_line="${keyword_main_rw_fw}\"\
199bcs:\/\/${MAIN_FW_TAR_NAME}\""
200 fi
201 # Create a new line for CROS_FIRMWARE_MAIN_RW_IMAGE
202 sed -i "/${keyword_main_fw}/a ${main_rw_fw_line}" "${EBUILD_FILE}"
203
204 # Update the manifest.
205 ebuild-"${FLAGS_board}" "${EBUILD_FILE}" manifest
206 info "Ebuild files and manifest are updated at:\n${EBUILD_DIR}\n"
207}
208
209# Build the firmware updater and verify the firmware version
210verify_fw_updater() {
211 local fw_updater="/build/${FLAGS_board}/usr/sbin/chromeos-firmwareupdate"
212 local fw_updater_bios_version
213 cros_workon-"${FLAGS_board}" start "chromeos-firmware-${FLAGS_board}"
214 emerge-"${FLAGS_board}" "chromeos-firmware-${FLAGS_board}"
215 cros_workon-"${FLAGS_board}" stop "chromeos-firmware-${FLAGS_board}"
216 if [[ ! -f "${fw_updater}" ]]; then
217 die "Firmware updater is not found at ${fw_updater}"
218 fi
219 if [[ "${FLAGS_rw_only}" -eq "${FLAGS_TRUE}" ]]; then
220 fw_updater_bios_version=$(${fw_updater} -V | grep "BIOS (RW) version")
221 else
222 fw_updater_bios_version=$(${fw_updater} -V | grep "BIOS version")
223 fi
224 fw_updater_bios_version="${fw_updater_bios_version#*Google_}"
225 fw_updater_bios_version="${fw_updater_bios_version,,}"
226 if [[ "${FLAGS_board}.${FLAGS_fw_version}" != \
227 "${fw_updater_bios_version}" ]]; then
228 die "The firmware version in the updater is incorrect"
229 fi
230 info "The firmware version in the updater is verified:" \
231 "${FLAGS_fw_version}\nPlease commit your change.\n"
232}
233
234main() {
235 TMP=""
236 trap cleanup EXIT
237
238 if [[ "$#" -ne 0 ]]; then
239 flags_help
240 exit 1
241 fi
242
243 init
244 prepare_fw_tarball
245
246 local sure
247 read -p "Please confirm that you've uploaded the tarballs to BCS [y/N]:" sure
248 if [[ "${sure}" != "y" ]]; then
249 die "Aborted..."
250 fi
251 update_fw_ebuild
252 verify_fw_updater
253}
254
255main "$@"