blob: fd1c016c664188f039e20ab5376adb7256bd2698 [file] [log] [blame]
#!/bin/sh
# Copyright (c) 2010 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.
# Version information. Please keep this in head of the updater.
SHELLBALL_FWVERSION="REPLACE_FWVERSION"
SHELLBALL_ECVERSION="REPLACE_ECVERSION"
# All scripts should die on error unless commands are specifically excepted
# by prefixing with '!' or surrounded by 'set +e' / 'set -e'.
set -e
# Clean up on regular or error exits.
trap clean_temp EXIT
# Global variables
ORIGINAL_PARAMS="$@"
# Set by make_temp function and removed by clean_temp
TMP_DIR=
# Set by allow_temp_exec and will invoke unmount in clean_temp
IS_NEED_UMOUNT=
# Decides if we need to print verbose messages
IS_VERBOSE=
# The default script to be invoked from extracted resource
SCRIPT=./updater.sh
LEGACY_SCRIPT=./legacy_updater.sh
IGNORE_TAG_FILE='/root/.leave_firmware_alone'
force_flag=""
# Prints a message and return an error code.
error_exit() {
echo $1
exit 1
}
# Prints messages if $IS_VERBOSE is not empty.
verbose_message() {
if [ -n "$IS_VERBOSE" ]; then
echo "$*"
fi
}
# Untar the file to a temp directory, then chdir to that directory.
untar_and_chdir() {
SELF="$1"
verbose_message "Extract to $TMP_DIR ..."
uudecode -o - "$SELF" | tar -C "$TMP_DIR" -zxf -
if [ ! -x "$TMP_DIR" -o ! -d "$TMP_DIR" ]; then
error_exit "Create temp directory $TMP_DIR failed ..."
fi
if ! cd "$TMP_DIR"; then
error_exit "Cannot chdir to $TMP_DIR ..."
fi
}
make_temp() {
TMP_DIR=$(mktemp -d)
}
allow_temp_exec() {
if [ -z "$TMP_DIR" ]; then
error_exit "allow_temp_exec: Temp folder is empty."
fi
# TODO(hungte) check if we really need to re-mount tmp.
verbose_message "Bind mounting tmp path exec ..."
mount --bind "$TMP_DIR" "$TMP_DIR"
mount -o remount,exec "$TMP_DIR"
IS_NEED_UMOUNT=1
}
clean_temp() {
verbose_message "clean_temp is invoked."
if [ -z "$TMP_DIR" ]; then
return
fi
# It is safer to always use SPI(Main) for the system flashrom bus target
flashrom -p internal:bus=spi >/dev/null 2>&1 || true
# Attempt to cd to OLDPWD
if ! cd - >/dev/null 2>&1; then
verbose_message "Failed to cd -. chdir'd to /"
cd /
fi
if [ -n "$IS_NEED_UMOUNT" ]; then
verbose_message "Unmount temporary folder $TMP_DIR..."
umount "$TMP_DIR"
fi
verbose_message "Clean up $TMP_DIR ..."
rm -rf "$TMP_DIR"
TMP_DIR=""
}
SELF="$0"
case "$1" in
-V)
# Quick way to provide version information
uudecode -o - "$SELF" | tar zxO ./VERSION
exit 0
;;
--sb_check)
make_temp
untar_and_chdir "$SELF"
md5sum -c VERSION
ret=$?
exit $ret
;;
--sb_extract)
make_temp
echo "The resources are extracted into: $TMP_DIR"
untar_and_chdir "$SELF"
# Don't remove the temporary folder on exit.
TMP_DIR=""
exit 0
;;
--mode=devstartup)
# This command is inside the stub for quick launch.
fw_version="$(crossystem fwid)"
ec_info="$(mosys -k ec info 2>/dev/null)" || ec_info=""
ec_version="$(eval "$ec_info"; echo "$fw_version")"
notify_update=0
verbose_message "ec_version: $ec_version ; ec_info: $ec_info"
if [ "$SHELLBALL_FWVERSION" != "$fw_version" ] &&
[ "$SHELLBALL_FWVERSION" != "IGNORE" ]; then
echo "System firmware update available: [$SHELLBALL_FWVERSION]"
echo "Currently installed system firmware: [$fw_version]"
notify_update=1
fi
if [ "$SHELLBALL_ECVERSION" != "$ec_version" ] &&
[ "$SHELLBALL_ECVERSION" != "IGNORE" ]; then
echo "EC firmware update available: [$SHELLBALL_ECVERSION]"
echo "Currently installed EC firmware: [$ec_version]"
notify_update=1
fi
if [ $notify_update -ne 0 ]; then
echo "
Firmware auto updating is disabled for developer mode. If you want to
manually update your firmware, please run the following command from a
root shell:
sudo chromeos-firmwareupdate --mode=recovery
"
fi
# TODO(hungte) add some info here to tell user how to update firmware
exit 0
;;
--mode=autoupdate)
PLATFORM="$(/usr/sbin/mosys platform name 2>/dev/null || true)"
# Mario uses the old updater.
if [ "$PLATFORM" != "Mario" ] &&
[ "$PLATFORM" != "ZGA" ]; then
# This command is inside the stub for quick launch.
fw_version="$(crossystem fwid)"
ec_info="$(mosys -k ec info 2>/dev/null)" || ec_info=""
ec_version="$(eval "$ec_info"; echo "$fw_version")"
notify_update=0
verbose_message "ec_version: $ec_version ; ec_info: $ec_info"
if [ "$SHELLBALL_FWVERSION" != "$fw_version" ] &&
[ "$SHELLBALL_FWVERSION" != "IGNORE" ]; then
echo "System firmware update available: [$SHELLBALL_FWVERSION]"
echo "Currently installed system firmware: [$fw_version]"
notify_update=1
fi
if [ "$SHELLBALL_ECVERSION" != "$ec_version" ] &&
[ "$SHELLBALL_ECVERSION" != "IGNORE" ]; then
echo "EC firmware update available: [$SHELLBALL_ECVERSION]"
echo "Currently installed EC firmware: [$ec_version]"
notify_update=1
fi
if [ $notify_update -eq 0 ]; then
echo "
No firmware auto update is available. Returning gracefully.
"
exit 0
fi
fi
break
;;
--force)
force_flag=1
shift
;;
-h|"-?"|--help)
echo "Shellball -- self-extract and install"
echo ""
echo "Usage: $SELF [options] [-- [inside-script-options]]"
echo ""
echo "options:"
echo " -h show usage help"
echo " -V show version of containing files"
echo " --force force execute and ignore $IGNORE_TAG_FILE"
echo " --sb_check check content integrity"
echo " --sb_extract extract content to temp folder"
echo ""
echo " All other parameters will be passed to the script inside."
echo ""
echo " You can invoke as '$SELF -- -h'"
echo " to see the usage and options of inside-script."
echo ""
exit 1
;;
--debug | --verbose | -v)
# do not shift here because this needs to be passed into the script
IS_VERBOSE=1
;;
--)
shift
;;
esac
# Do nothing if we're debugging BIOS changes, unless forced
if [ -e "$IGNORE_TAG_FILE" ] && [ -z "${force_flag:-}" ]; then
echo "WARNING: $0 is disabled by $IGNORE_TAG_FILE"
echo "To force execution, please add --force to your command:"
echo " sudo $0 --force $ORIGINAL_PARAMS"
exit 0
fi
# Prepare execution environment
make_temp
allow_temp_exec
untar_and_chdir "$SELF"
if [ ! -x $SCRIPT ]; then
error_exit "Cannot execute $SCRIPT"
fi
# Are we running in legacy mode or new flavor?
PATH=".:$PATH"
PLATFORM="$(/usr/sbin/mosys platform name 2>/dev/null || true)"
if [ "$PLATFORM" = "Mario" ] ||
[ "$PLATFORM" = "ZGA" ]; then
SCRIPT=$LEGACY_SCRIPT
# Workaround for chrome-os-partner:1563. If we're supposed to reboot into
# firmware B but haven't, it's likely because the CMOS has lost its state, so
# let's try once more right now.
NEED_FIRMWARE_UPDATE='/mnt/stateful_partition/.need_firmware_update'
NEED_FIRMWARE_TRYB='/mnt/stateful_partition/.need_firmware_tryb'
BINF1='/sys/devices/platform/chromeos_acpi/BINF.1'
# /dev/nvram is required by reboot_mode. chromeos_startup may re-mount devfs
# and caused nvram to disappear for a while. Since we cannot wait for
# delayed-loading, mknod provides a quick solution.
[ -e /dev/nvram ] || mknod /dev/nvram c 10 144
if [ -f "$NEED_FIRMWARE_TRYB" ]; then
# Yes, flag file is present. Make sure we don't do this more than once
rm -f "$NEED_FIRMWARE_TRYB"
if [ -r "$BINF1" ]; then
if [ "$(cat "$BINF1")" = "1" ]; then
# Yes, in firmware A, so we need to try firmware B
reboot_mode --try_firmware_b=1
# When we do, we want to run the shellball again.
touch "$NEED_FIRMWARE_UPDATE"
reboot
# should never get here
sleep 10
error_exit "ERROR: $0 should have rebooted"
fi
fi
fi
fi
verbose_message "Run built-in script ($SCRIPT) ..."
if ! $SCRIPT "$@"; then
error_exit "ERROR: $SCRIPT failed."
fi
exit 0
# Below are uuencoded blob. Don't put code behind exit 0.