blob: 457eb96f854c228a88502e8a1dcffe3fac69678d [file] [log] [blame]
#!/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.
# This script is used to generate the firmware tarball. After generating the
# tarball, please upload the tarball by running:
# $ gsutil cp <tarball>.tbz2 gs://chromeos-localmirror/distfiles/
# And then update chromeos-firmware-<base> ebuild file.
CURRENT_DIR="$(dirname "$(readlink -f "$0")")"
SCRIPT_ROOT="${CURRENT_DIR}/../../scripts"
. "${SCRIPT_ROOT}/common.sh" || exit 1
# The mapping from the board name and the base name. We only support the boards
# listed here.
BOARD_LOOKUP_TABLE="\
poppy wand
soraka staff
meowth whiskers
nocturne whiskers"
DEFINE_string board "" "The board name. e.g. poppy" b
DEFINE_string ro_version "" "The RO version of the target file. e.g. 9790.0.0" r
DEFINE_string rw_version "" "The RW version of the target file. e.g. 9794.0.0" v
DEFINE_string channel "dev" \
"The channel of the target file. One of canary, dev, beta, or stable" c
DEFINE_string signed_key "dev" \
"The signed key of the target file. e.g. dev, premp, premp-v2, mp, mp-v2" s
DEFINE_string detachable_base_name "" \
"The detachable base name. e.g. masterball" d
DEFINE_boolean skip_touchpad_binary "${FLAGS_FALSE}" \
"Set if the touchpad binary is not required" k
FLAGS "$@" || exit 1
eval set -- "${FLAGS_ARGV}"
set -e
# Global variables that are assigned in init() function.
# The temporary working directory.
TMP=""
# The base URL of the downloaded files (RO version).
GS_URL_BASE_RO=""
# The base URL of the downloaded files (RW version).
GS_URL_BASE_RW=""
# The detachable base code name.
BASE_NAME=""
get_base_name() {
local board_name="${1}"
local key
local value
echo "${BOARD_LOOKUP_TABLE}" | while read key value; do
if [[ "${key}" == "${board_name}" ]]; then
echo "${value}"
fi
done
}
init() {
TMP="$(mktemp -d)"
echo "Create temp work directory: ${TMP}"
cd "${TMP}"
if [[ -z "${FLAGS_board}" ]]; then
die_notrace "Please specify the board name using -b"
fi
BASE_NAME="$(get_base_name "${FLAGS_board}")"
if [[ -n "${FLAGS_detachable_base_name}" ]]; then
if [[ -n "${BASE_NAME}" ]]; then
die_notrace "Can't specify base name for non-unibuild project"
fi
BASE_NAME="${FLAGS_detachable_base_name}"
fi
if [[ -z "${BASE_NAME}" ]]; then
die_notrace "The board name is not supported." \
"Please specify the detachable base name using -d for unibuild project."
fi
echo "The base name: ${BASE_NAME}"
if [[ -z "${FLAGS_ro_version}" ]]; then
die_notrace "Please specify a firmware RO version using -r, e.g. 9794.0.0"
fi
if [[ -z "${FLAGS_rw_version}" ]]; then
die_notrace "Please specify a firmware RW version using -v, e.g. 9790.0.0"
fi
if [[ -z "${FLAGS_channel}" ]]; then
die_notrace "Please specify a channel using -c, e.g. canary"
fi
if [[ "${FLAGS_signed_key}" != "dev" ]] &&
[[ "${FLAGS_signed_key}" != premp* ]] &&
[[ "${FLAGS_signed_key}" != mp* ]]; then
die_notrace "Please specify a signed key name using -s, e.g. dev, premp, mp"
fi
local gs_url_base="gs://chromeos-releases/${FLAGS_channel}-channel/${FLAGS_board}"
GS_URL_BASE_RO="${gs_url_base}/${FLAGS_ro_version}"
if ! gsutil ls "${GS_URL_BASE_RO}" > /dev/null; then
die_notrace "${GS_URL_BASE_RO} is not a valid URL. Please check the argument."
fi
GS_URL_BASE_RW="${gs_url_base}/${FLAGS_rw_version}"
if ! gsutil ls "${GS_URL_BASE_RW}" > /dev/null; then
die_notrace "${GS_URL_BASE_RW} is not a valid URL. Please check the argument."
fi
}
cleanup() {
cd "${CURRENT_DIR}"
rm -rf "${TMP}"
}
# get_ec_file_name (ro|rw): Get file name for the EC binary/tarball (using RO or
# RW version depending on parameter).
get_ec_file_name() {
if [[ "${FLAGS_signed_key}" == "dev" ]]; then
echo "ChromeOS-firmware-*.tar.bz2"
else
if [[ "$1" == "ro" ]]; then
echo "chromeos_${FLAGS_ro_version}_${BASE_NAME}_${FLAGS_signed_key}.bin"
else
echo "chromeos_${FLAGS_rw_version}_${BASE_NAME}_${FLAGS_signed_key}.bin"
fi
fi
}
get_tp_tarball_name() {
echo "ChromeOS-accessory_rwsig-*-${FLAGS_rw_version}-${FLAGS_board}.tar.bz2"
}
# download_file (ro|rw) filename: Download a file that may have wildcard from
# either RO or RW version folder in GS, and return the exact file name.
download_file() {
local base
if [[ "$1" == "ro" ]]; then
base="${GS_URL_BASE_RO}"
else
base="${GS_URL_BASE_RW}"
fi
local gs_url="${base}/${2}"
local fw_path="$(gsutil ls "${gs_url}")"
if [[ -z "${fw_path}" ]]; then
die "Please ensure your gsutil works and the firmware version is correct."
fi
gsutil cp "${fw_path}" . > /dev/null
echo "$(basename "${fw_path}")"
}
# Extract EC file from downloaded file ($1) to specified location ($2).
extract_ec_file() {
local ec_path="${BASE_NAME}/ec.bin"
# If the firmware is signed, then the downloaded file is the binary blob,
# instead of a tarball.
if [[ "${1}" == *.bin ]]; then
mv "${1}" "${2}"
else
tar xf "${1}" "${ec_path}"
mv "${ec_path}" "${2}"
fi
}
process_ec_file() {
local ec_ro="ec_ro.bin"
local ec_rw="ec_rw.bin"
extract_ec_file "$(download_file ro "$(get_ec_file_name ro)")" "${ec_ro}"
extract_ec_file "$(download_file rw "$(get_ec_file_name rw)")" "${ec_rw}"
# Use RW firmware version as file name.
local fw_version_rw="$(strings "${ec_rw}" | grep "${BASE_NAME}" | head -n1)"
local new_file="${fw_version_rw}.fw"
# fmap[0]="EC_RW" fmap[1]=offset fmap[2]=size (decimal)
local fmap=($(dump_fmap -p "${ec_ro}" EC_RW))
# Inject RW into the existing RO file.
cp "${ec_ro}" "${new_file}"
dd if="${ec_rw}" of="${new_file}" \
bs=1 skip="${fmap[1]}" seek="${fmap[1]}" count="${fmap[2]}" conv=notrunc
# Verify the resulting image is signed properly.
if ! futility verify --strict "${new_file}" >&2; then
die "Cannot verify ${new_file}."
fi
echo "${new_file}"
}
process_tp_file() {
local real_file_name
if [[ "${FLAGS_skip_touchpad_binary}" == "${FLAGS_TRUE}" ]]; then
return
fi
local downloaded_file
downloaded_file="$(download_file rw "$(get_tp_tarball_name)")"
# Extract the symbolic link first, then extract the target file.
local sym_file_name="touchpad.bin"
tar xf "${downloaded_file}" "${BASE_NAME}/${sym_file_name}"
real_file_name="$(readlink "${BASE_NAME}/${sym_file_name}")"
tar xf "${downloaded_file}" "${BASE_NAME}/${real_file_name}"
mv "${BASE_NAME}/${real_file_name}" "${real_file_name}"
echo "${real_file_name}"
}
main() {
TMP=""
trap cleanup EXIT
init
local ec_file
local tp_file
local tar_args
# Download and extract EC firmware and touchpad firmware.
ec_file="$(process_ec_file)"
tp_file="$(process_tp_file)"
# Pack EC and touchpad firmware and move to the current directory.
local output_tar="${BASE_NAME}_${FLAGS_ro_version}-${FLAGS_rw_version}_${FLAGS_signed_key}.tbz2"
tar_args=()
tar_args+=("${ec_file}")
if [[ -n "${tp_file}" ]]; then
tar_args+=("${tp_file}")
fi
tar jcf "${output_tar}" "${tar_args[@]}"
mv "${output_tar}" "${CURRENT_DIR}"
# Print out the update instruction.
cat <<EOF
${V_BOLD_GREEN}
Successfully generated the EC and touchpad firmware tarball! ${V_VIDOFF}
For the unibuild project:
1. Put the detachable base firmware binary to
overlay-${FLAGS_board}-private/chromeos-base/\
chromeos-bsp-${FLAGS_board}-private/files/detachable_base/\
firmware/${BASE_NAME}.bin
2. If the detachable base has the touchpd
a. Put the touchpad firmware binary to
overlay-${FLAGS_board}-private/chromeos-base/\
chromeos-bsp-${FLAGS_board}-private/files/detachable_base/\
touch/${tp_file}.bin
b. Modify the ebuild overlay-${FLAGS_board}-private/\
chromeos-base/chromeos-bsp-${FLAGS_board}-private/\
chromeos-bsp-${FLAGS_board}-private-0.0.1.ebuild
For the non-unibuild project, \
follow the below steps to upload the EC firmware tarball:
1. Go to CPFE and Click "Uploads - Private"
2. Select the tarball file at "Select Component File"
3. Select "overlay-${FLAGS_board}-private" overlay
4. Enter "chromeos-base/chromeos-firmware-${BASE_NAME}" in \
"Relative path to file"
5. Update the variables of "chromeos-firmware-${BASE_NAME}" ebuild file.
FW_TARBALL="${output_tar}"
EC_FW_NAME="${ec_file}"
TP_FW_NAME="${tp_file}"
EOF
}
main "$@"