blob: c7d13463898bdbc4206bb8c082735a304dfbc11e [file] [log] [blame]
#!/bin/sh
# Copyright (c) 2013 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.
. "$(dirname "$0")/common.sh" || exit 1
# A local die function to print the message and then exit
die() {
echo -e "$@"
exit 1
}
# Assert inside chroot
assert_inside_chroot
# Read command flags
. /usr/share/misc/shflags
DEFINE_string board '' 'which board the firmware is for' 'b'
DEFINE_boolean clean false 'clean up all temporary files' 'c'
DEFINE_boolean debug false 'debug flag' 'd'
DEFINE_string infile '' 'the input (zip) file' 'f'
DEFINE_string issue '' 'the issue number on the issue tracker' 'i'
DEFINE_string revision '' 'the revision number of the firmware' 'r'
PROG=$0
FLAGS_HELP="USAGE: $PROG [flags]"
FLAGS "$@" || exit 1
eval set -- "${FLAGS_ARGV}"
set -e
# Set global variables
infile="$FLAGS_infile"
FW_PATH="opt/google/touchpad/firmware"
FW_MODE=755
FW_OWN="root:root"
TMP_DIR="/tmp/touch_fw"
TMP_RESULT="${TMP_DIR}/login.result"
COOKIE_FILE="${TMP_DIR}/login.cookie"
# Some URLs to set up credentials
AUTH_URL="https://accounts.google.com/ServiceLoginAuth?hl=en&continue="
TRACKER_URL="https%3A%2F%2Fcode.google.com%2Fp%2Fchrome-os-partner"\
"%2Fissues%2Fdetail%3Fid%3D"
issue_auth_url="$AUTH_URL$TRACKER_URL$FLAGS_issue"
# Per board definitions
# Only works for lumpy/cypress for now.
# TODO: work on other boards too.
FW_UPDATE_TOOL_CYPRESS="/sbin/cyapa_fw_update"
CYPRESS_TOOLS="cypress-tools"
# Print the message when debug flag is set.
debug_print() {
if [ $FLAGS_debug = "$FLAGS_TRUE" ]; then
local name=$1
local value=${!name}
echo " (DEBUG) $name: $value"
fi
}
# Print the usage and examples, and then exit.
usage_and_exit() {
flags_help
die "\nExamples:
Specify the issue # and download the firmware from the remote server.
\$ $PROG -i 12345 -b lumpy \n
Convert the iic file in a local zip file to bin file.
\$ $PROG -f /tmp/CYTRA-116001-00-v11.26-Testdrop.zip -b lumpy \n
Specify that it is revision 'r2' and also enable the debug flag.
\$ $PROG -i 12345 -b lumpy -r r2 -d \n
Clean up all temporary files after finished.
\$ $PROG -c \n"
}
# Make sure that exactly an issue number or an local zip file is specified.
check_argument() {
if [ -z "$FLAGS_issue" -a -z "$FLAGS_infile" -o \
"$FLAGS_issue" -a "$FLAGS_infile" ]; then
echo -e "Specify exactly either an issue number or a local zip file.\n"
usage_and_exit
elif [ -z "$FLAGS_board" ]; then
echo -e "You need to specify a board.\n"
usage_and_exit
fi
}
# Set up a temporary directory that only the owner could access.
setup_tmp_dir() {
mkdir -p -m 0700 $TMP_DIR
}
# Prompt the user to type chromium email account and password.
read_user_and_password() {
# Read the user email address and password if not yet.
if [ -z $USR -o -z $PASS ]; then
echo Please type your user name of chromium account.
read -p "Username (without @chromium.org): " USR
read -s -p "Password: " PASS
fi
USR_PASS="Email=${USR}@chromium.org&Passwd=${PASS}"
}
# Get dsh and GALX
get_credential() {
# Try to get dsh and GALX values.
if ! curl -s -c "$COOKIE_FILE" -L -d $USR_PASS $issue_auth_url > \
"$TMP_RESULT"; then
die "Error: curl failed to get $issue_auth_url"
fi
# The dsh value looks like
# name="dsh" id="dsh" value="3039562716843903054"
dsh=`grep -i "dsh" "$TMP_RESULT" | \
sed -n "s/.*value=\"\(-*[0-9]*\)\"/\1/p"`
# The GALX value looks like
# name="GALX"
# value="Bfr17SQrDe4">
galx=`grep -i -A1 "GALX" "$TMP_RESULT" | \
sed -n "s/.*value=\"\(.*\)\".*/\1/p"`
if [ -z dsh -o -z galx ]; then
die "Error: fail to get dsh or galx."
fi
}
# Get the firmware attachment URL from the specified tracker issue.
# And then download the firmware zip file.
download_fw_file() {
# The returned attachment syntax looks like
# &nbsp; <a href="//chrome-os-partner.googlecode.com/issues/attachment?
# aid=172300000000&amp;name=CYTRA-116001-00-v11.27-Testdrop.zip&amp;
# token=E9jFSVjVX9abUmyCrGm0ms0YuBI%3A1359083647918">Download</a>
local attach_str=`curl -s -b "$COOKIE_FILE" -L -d \
"GALX=${galx}&bgresponse=js_disabled&dsh=${dsh}&$USR_PASS" \
$issue_auth_url | \
grep "href=.*CYTRA.*\.zip.*Download" | \
sed -n 's/.*href=\"\(.*\)\">Download.*/\1/p'`
attachment_url="https:"`echo $attach_str | sed 's/\&amp;/\&/g'`
fw_zipfile="${TMP_DIR}/`echo $attachment_url | \
sed -n 's/http.*name=\(CYTRA.*\.zip\)\&token=.*/\1/p'`"
if [ "$attachment_url" = "https:" -a "$fw_zipfile" = "${TMP_DIR}/" ]; then
die "\n Error: either the firmware url or the firmware zip name
cannot be found
\n firmware url: $attachment_url
\n firmware name: $fw_zipfile"
else
echo Downloading the firmware: $fw_zipfile
curl -s -o "$fw_zipfile" "$attachment_url"
fi
}
# Check the existence of the file
check_file_existence() {
local target_file="$1"
if [ ! -f "$target_file" ]; then
die "File does not exist: $target_file"
fi
}
# Get the firmware version from infile.
get_fw_version() {
# The following command will extract the firmware version number from a
# firmware zip file.
#
# "CYTRA-116001-00-v11.26-Testdrop.zip" => 11.26
# "CYTR-116001-00-V11.2.6.zip" => 11.2.6
# "CYTRA-116001-00-v27.zip" => 27
# "CYTRA_103002_00 FW_V1.9.zip.zip" => 1.9
#
# Note:
# A in "CYTRA" is optional
# Either v or V is acceptable
# The firmware version could be something like 11, or 11.26, or 11.2.5, etc.
fw_version=`echo $infile | sed -nr 's/.*CYTRA?.*v([0-9]+[\.0-9]*).*/\1/pi'`
if [ -z $fw_version ]; then
die "Failed to extract the firmware version number from $infile"
fi
echo Firmware version: $fw_version
}
# Get the correct firmware .bin file name.
# It converts any incorrect dashes and underscores to the correct format.
#
# Example: it makes the following name conversion
# from ".../CYTRA_116001_00_v11.27.iic"
# to ".../CYTRA-116001-00_11.27.bin"
#
# Note that the correct format of a bin file should look like
# ${product_id}_${version_number}.bin
# where $product_id is "CYTRA-116001-00", and
# $version_number is "11.27"
# Also note that there is a '_" between $product_id and $version_number.
get_fw_bin_name() {
sed_script="s/(.*)(CYTRA?)[-_]([0-9]+)[-_]([0-9]+)[-_].*\.iic"\
"/\1\2-\3-\4_${fw_version}.bin/pi"
bin_name=`echo $1 | sed -nr $sed_script`
}
# Convert an iic file to a bin file.
convert_iic_to_bin() {
local iic_file="${TMP_DIR}/$1"
get_fw_bin_name $iic_file
test "$FLAGS_revision" && rev="-$FLAGS_revision"
# A top_dir looks like "chromeos-touch-firmware-lumpy-11.27-r1"
top_dir="chromeos-touch-firmware-${FLAGS_board}-${fw_version}${rev}"
relative_bin_file="${top_dir}/${FW_PATH}/$(basename $bin_name)"
bin_file="$(dirname $bin_name)/$relative_bin_file"
mkdir -p "$(dirname $bin_file)"
# Get the firmware update tool ready.
local FW_UPDATE_TOOL="$FW_UPDATE_TOOL_CYPRESS"
# If the firmware upate tool does not exist in the host yet, we need to
# unmerge the package, and then run update_chroot to get the firmware
# update tool installed through the hard-host-depends package.
if [ ! -f $FW_UPDATE_TOOL ]; then
echo $CYPRESS_TOOLS does not exist.
echo We will unmerge $CYPRESS_TOOLS and then run update_chroot.
sudo emerge --unmerge $CYPRESS_TOOLS || \
die "Failed to unmerge '$CYPRESS_TOOLS'"
~/trunk/src/scripts/update_chroot || die "Failed to run 'update_chroot'"
echo "Compile and install $FW_UPDATE_TOOL successfully."
fi
# Convert the iic file to the bin file. Set the proper mode and owner/group.
sudo "$FW_UPDATE_TOOL" -c "$iic_file" -o "$bin_file" > /dev/null
sudo chmod "$FW_MODE" "$bin_file"
sudo chown "$FW_OWN" "$bin_file"
debug_print iic_file
debug_print bin_name
echo "Firmware bin file: $bin_file"
}
# Get the firmware file in .bin format
get_bin_fw_file() {
local zipfile="$1"
local FILE_TYPE=$(file "$zipfile")
# Convert it to lower case for comparison
FILE_TYPE=${FILE_TYPE,,}
if [[ "$FILE_TYPE" = *"zip archive"* ]]; then
# Try to find if there exists the .bin file.
# Otherwise, try to locate the .iic file.
local fw_file=`zipinfo -1 $zipfile | grep .bin`
if [ $fw_file ]; then
echo Find firmware bin file: $fw_file
unzip -q -o -d "$TMP_DIR" $zipfile $fw_file
else
local fw_file=`zipinfo -1 $zipfile | grep .iic`
if [ $fw_file ]; then
unzip -q -o -d "$TMP_DIR" $zipfile $fw_file
convert_iic_to_bin $fw_file
else
echo Neither .bin nor .iic file could be found in $zipfile
fi
fi
else
die "Error: '$zipfile' is not a zip file."
fi
}
create_tbz2() {
local target_file="$1"
local tarball_name="chromeos-touch-firmware"
local work_dir=$PWD
tarball="${TMP_DIR}/${tarball_name}-${FLAGS_board}-${fw_version}${rev}.tbz2"
debug_print target_file
cd "$TMP_DIR"
sudo tar --owner=root --group=root --mode="$FW_MODE" -cjf "$tarball" \
"$target_file"
cd $work_dir
echo -e "\nTarball created: ${tarball}"
echo -e "You could upload this tarball to the Binary Components Server:"
echo -e " https://www.google.com/chromeos/partner/fe/ \n"
echo -e "Type '$PROG -c' to clean up all temporary files" \
"after uploading the files.\n"
}
# Clean up unnecessary files in the tmp directory.
# This function is invoked automatically after the tarball is created.
clean_up_tmp_files() {
# Keep only .tbz2 and .bin files.
find "$TMP_DIR" -type f -not -iregex ".*tbz2\|.*bin" | xargs rm
}
# Clean up the whole tmp directory.
# This function is invoked when '-c' clean up flag is specified.
clean_up_tmp_dir() {
rm -fr "$TMP_DIR"
die "Clean up all temporary files in '$TMP_DIR'."
}
# main program begins here.
# -------------------------
if [ $FLAGS_clean = $FLAGS_TRUE ]; then
clean_up_tmp_dir
fi
check_argument
setup_tmp_dir
# If an issue number is given, get the firmware zip file from a remote server.
# This is executed only when '-i' command flag is specified.
# If '-f' command flag is specified, skip this block.
if [ $FLAGS_issue ]; then
read_user_and_password
get_credential
download_fw_file
infile=$fw_zipfile
fi
# Now we have the local zip file.
debug_print infile
check_file_existence $infile
get_fw_version
get_bin_fw_file $infile
create_tbz2 "$relative_bin_file"
# Clean up some unnecessary temporary files.
# Keep the created tarball and the .bin firmware file.
clean_up_tmp_files