| #!/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. |