summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2011-01-04 16:42:08 -0800
committerRandall Spangler <rspangler@chromium.org>2011-01-04 16:42:08 -0800
commite37ff5d5960c3a94809f54d7e412b387a7c396e5 (patch)
tree73529f01a4ef21a0473a3a779650bbcf0f0be222 /scripts
parentddc06e4be12392d1f9d6b0d6d7c9c16446cb5566 (diff)
downloadvboot-e37ff5d5960c3a94809f54d7e412b387a7c396e5.tar.gz
Check in tofactory script.
Also refactor the other scripts to move more common functions (debug output, etc.) to common.sh. BUG=chrome-os-partner:1903 TEST=manual; ran on a Chrome notebook, verified the right things got copied. Review URL: http://codereview.chromium.org/5878005 Change-Id: Ib7131356ecb6f88eee3d529a518f23b94756d0c0
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/image_signing/common.sh147
-rwxr-xr-xscripts/image_signing/make_dev_firmware.sh18
-rwxr-xr-xscripts/image_signing/make_dev_ssd.sh18
-rwxr-xr-xscripts/image_signing/tofactory.sh185
4 files changed, 279 insertions, 89 deletions
diff --git a/scripts/image_signing/common.sh b/scripts/image_signing/common.sh
index 5465feb8..1566b9d3 100755
--- a/scripts/image_signing/common.sh
+++ b/scripts/image_signing/common.sh
@@ -4,6 +4,9 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+# Globals
+# ----------------------------------------------------------------------------
+
# Determine script directory
SCRIPT_DIR=$(dirname $0)
PROG=$(basename $0)
@@ -94,11 +97,81 @@ load_shflags() {
echo "ERROR: Cannot find the required shflags library."
return 1
fi
+
+ # Add debug option for debug output below
+ DEFINE_boolean debug $FLAGS_FALSE "Provide debug messages" "d"
+}
+
+# Functions for debug output
+# ----------------------------------------------------------------------------
+
+# Reports error message and exit(1)
+# Args: error message
+err_die() {
+ echo "ERROR: $*" 1>&2
+ exit 1
+}
+
+# Returns true if we're running in debug mode.
+#
+# Note that if you don't set up shflags by calling load_shflags(), you
+# must set $FLAGS_debug and $FLAGS_TRUE yourself. The default
+# behavior is that debug will be off if you define neither $FLAGS_TRUE
+# nor $FLAGS_debug.
+is_debug_mode() {
+ [ "${FLAGS_debug:-not$FLAGS_TRUE}" = "$FLAGS_TRUE" ]
+}
+
+# Prints messages (in parameters) in debug mode
+# Args: debug message
+debug_msg() {
+ if is_debug_mode; then
+ echo "DEBUG: $*" 1>&2
+ fi
+}
+
+# Functions for temporary files and directories
+# ----------------------------------------------------------------------------
+
+# Create a new temporary file and return its name.
+# File is automatically cleaned when cleanup_temps_and_mounts() is called.
+make_temp_file() {
+ local tempfile=$(mktemp)
+ echo "$tempfile" >> $TEMP_FILE_LIST
+ echo $tempfile
+}
+
+# Create a new temporary directory and return its name.
+# Directory is automatically deleted and any filesystem mounted on it unmounted
+# when cleanup_temps_and_mounts() is called.
+make_temp_dir() {
+ local tempdir=$(mktemp -d)
+ echo "$tempdir" >> $TEMP_DIR_LIST
+ echo $tempdir
}
-# List of Temporary files and mount points.
-TEMP_FILE_LIST=$(mktemp)
-TEMP_DIR_LIST=$(mktemp)
+cleanup_temps_and_mounts() {
+ for i in $(cat $TEMP_FILE_LIST); do
+ rm -f $i
+ done
+ set +e # umount may fail for unmounted directories
+ for i in $(cat $TEMP_DIR_LIST); do
+ if [ -n "$i" ]; then
+ if has_needs_to_be_resigned_tag "$i"; then
+ echo "Warning: image may be modified. Please resign image."
+ fi
+ sudo umount -d $i 2>/dev/null
+ rm -rf $i
+ fi
+ done
+ set -e
+ rm -rf $TEMP_DIR_LIST $TEMP_FILE_LIST
+}
+
+trap "cleanup_temps_and_mounts" EXIT
+
+# Functions for partition management
+# ----------------------------------------------------------------------------
# Read GPT table to find the starting location of a specific partition.
# Args: DEVICE PARTNUM
@@ -185,54 +258,6 @@ replace_image_partition() {
dd if=$input_file of=$image bs=512 seek=$offset count=$size conv=notrunc
}
-# Create a new temporary file and return its name.
-# File is automatically cleaned when cleanup_temps_and_mounts() is called.
-make_temp_file() {
- local tempfile=$(mktemp)
- echo "$tempfile" >> $TEMP_FILE_LIST
- echo $tempfile
-}
-
-# Create a new temporary directory and return its name.
-# Directory is automatically deleted and any filesystem mounted on it unmounted
-# when cleanup_temps_and_mounts() is called.
-make_temp_dir() {
- local tempdir=$(mktemp -d)
- echo "$tempdir" >> $TEMP_DIR_LIST
- echo $tempdir
-}
-
-cleanup_temps_and_mounts() {
- for i in "$(cat $TEMP_FILE_LIST)"; do
- rm -f $i
- done
- set +e # umount may fail for unmounted directories
- for i in "$(cat $TEMP_DIR_LIST)"; do
- if [ -n "$i" ]; then
- if has_needs_to_be_resigned_tag "$i"; then
- echo "Warning: image may be modified. Please resign image."
- fi
- sudo umount -d $i 2>/dev/null
- rm -rf $i
- fi
- done
- set -e
- rm -rf $TEMP_DIR_LIST $TEMP_FILE_LIST
-}
-
-# Returns true if all files in parameters exist.
-ensure_files_exist() {
- local filename return_value=0
- for filename in "$@"; do
- if [ ! -f "$filename" -a ! -b "$filename" ]; then
- echo "ERROR: Cannot find required file: $filename"
- return_value=1
- fi
- done
-
- return $return_value
-}
-
# For details, see crosutils.git/common.sh
enable_rw_mount() {
local rootfs="$1"
@@ -307,8 +332,25 @@ rw_mount_disabled() {
return 1
}
+# Misc functions
+# ----------------------------------------------------------------------------
+
+# Returns true if all files in parameters exist.
+# Args: List of files
+ensure_files_exist() {
+ local filename return_value=0
+ for filename in "$@"; do
+ if [ ! -f "$filename" -a ! -b "$filename" ]; then
+ echo "ERROR: Cannot find required file: $filename"
+ return_value=1
+ fi
+ done
+
+ return $return_value
+}
+
# Check if the 'chronos' user already has a password
-# ARGS: rootfs
+# Args: rootfs
no_chronos_password() {
local rootfs=$1
sudo grep -q '^chronos:\*:' "$rootfs/etc/shadow"
@@ -317,4 +359,3 @@ no_chronos_password() {
trap "cleanup" INT TERM EXIT
add_cleanup_action "cleanup_temps_and_mounts"
-
diff --git a/scripts/image_signing/make_dev_firmware.sh b/scripts/image_signing/make_dev_firmware.sh
index f4e7d49d..f432c0bd 100755
--- a/scripts/image_signing/make_dev_firmware.sh
+++ b/scripts/image_signing/make_dev_firmware.sh
@@ -26,7 +26,6 @@ DEFINE_boolean force_backup \
$FLAGS_TRUE "Create backup even if source is not live" ""
DEFINE_string backup_dir \
"$DEFAULT_BACKUP_FOLDER" "Path of directory to store firmware backups" ""
-DEFINE_boolean debug $FLAGS_FALSE "Provide debug messages" "d"
# Parse command line
FLAGS "$@" || exit 1
@@ -44,23 +43,6 @@ EXEC_LOG="$(make_temp_file)"
# Functions
# ----------------------------------------------------------------------------
-# Reports error message and exit(1)
-err_die() {
- echo "ERROR: $*" 1>&2
- exit 1
-}
-
-# Returns true if we're running in debug mode
-is_debug_mode() {
- [ "$FLAGS_debug" = $FLAGS_TRUE ]
-}
-
-# Prints messages (in parameters) in debug mode
-debug_msg() {
- if is_debug_mode; then
- echo "DEBUG: $*" 1>&2
- fi
-}
# Reads $IMAGE from $FLAGS_from
read_image() {
diff --git a/scripts/image_signing/make_dev_ssd.sh b/scripts/image_signing/make_dev_ssd.sh
index ee493e7a..67a180e7 100755
--- a/scripts/image_signing/make_dev_ssd.sh
+++ b/scripts/image_signing/make_dev_ssd.sh
@@ -24,7 +24,6 @@ DEFINE_boolean remove_rootfs_verification \
$FLAGS_FALSE "Modify kernel boot config to disable rootfs verification" ""
DEFINE_string backup_dir \
"$DEFAULT_BACKUP_FOLDER" "Path of directory to store kernel backups" ""
-DEFINE_boolean debug $FLAGS_FALSE "Provide debug messages" "d"
DEFINE_string save_config "" \
"Base filename to store kernel configs to, instead of resigning." ""
DEFINE_string set_config "" \
@@ -45,23 +44,6 @@ EXEC_LOG="$(make_temp_file)"
# Functions
# ----------------------------------------------------------------------------
-# Reports error message and exit(1)
-err_die() {
- echo "ERROR: $*" 1>&2
- exit 1
-}
-
-# Returns true if we're running in debug mode
-is_debug_mode() {
- [ "$FLAGS_debug" = $FLAGS_TRUE ]
-}
-
-# Prints messages (in parameters) in debug mode
-debug_msg() {
- if is_debug_mode; then
- echo "DEBUG: $*" 1>&2
- fi
-}
# Removes rootfs verification from kernel boot parameter
remove_rootfs_verification() {
diff --git a/scripts/image_signing/tofactory.sh b/scripts/image_signing/tofactory.sh
new file mode 100755
index 00000000..38a76fdf
--- /dev/null
+++ b/scripts/image_signing/tofactory.sh
@@ -0,0 +1,185 @@
+#!/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.
+#
+# This script converts a Chrome OS device to a pre-factory-install state:
+# * Firmware write protect disabled
+# * H2O BIOS, with RO VPD area copied from the current BIOS
+# * Original EC firmware
+# * Blank SSD (no GPT)
+#
+# Minimal usage:
+# tofactory.sh -b H2OBIOS.bin -e ec_shellball.sh
+
+SCRIPT_BASE="$(dirname "$0")"
+. "$SCRIPT_BASE/common.sh"
+load_shflags || exit 1
+
+# Constants used by DEFINE_*
+VBOOT_BASE='/usr/share/vboot'
+
+# DEFINE_string name default_value description flag
+DEFINE_string bios "" "Path of system firmware (BIOS) binary to write" "b"
+DEFINE_string ec "" "Path of EC shellball to execute" "e"
+DEFINE_string backup_dir "" "Path of directory in whoch to store backups" "k"
+DEFINE_string asset_tag "unspecified_tag" \
+ "Asset tag of device, used to name backups" "a"
+DEFINE_string ssd "/dev/sda" "Path to SSD / target drive" "s"
+DEFINE_boolean wipe_ssd $FLAGS_TRUE "Wipe SSD after firmware updates" ""
+DEFINE_boolean nothing $FLAGS_FALSE \
+ "Print commands but do not modify device" "n"
+
+# Parse command line
+FLAGS "$@" || exit 1
+eval set -- "$FLAGS_ARGV"
+
+# Globals
+# ----------------------------------------------------------------------------
+set -e
+
+# Flashrom commands with device overrides
+FLASHROM_BIOS="flashrom -p internal:bus=spi"
+FLASHROM_EC="flashrom -p internal:bus=lpc"
+
+# A log file to keep the output results of executed command
+EXEC_LOG="$(make_temp_file)"
+
+# Temporary Work directory
+WORK_DIR="$(make_temp_dir)"
+OLD_BIOS="$WORK_DIR/old_bios.bin"
+NEW_BIOS="$WORK_DIR/new_bios.bin"
+
+# Functions
+# ----------------------------------------------------------------------------
+
+# Error message for write protect disable failure, with reminder
+wp_error() {
+ local which_rom=$1
+ shift
+ echo "ERROR: Unable to disable $which_rom write protect: $*" 1>&2
+ echo "Is hardware write protect still enabled?" 1>&2
+ exit 1
+}
+
+# Disable write protect for an EEPROM
+disable_wp() {
+ local which_rom=$1 # EC or BIOS
+ shift
+ local flash_rom="$*" # Flashrom command to use
+
+ debug_msg "Disabling $which_rom write protect"
+ $NOTHING ${flash_rom} --wp-disable || wp_error "$which_rom" "--wp-disable"
+ $NOTHING ${flash_rom} --wp-range 0 0 || wp_error "$which_rom" "--wp-range"
+
+ # WP status bits should report WP: status: 0x00
+ local wp_status="$(${flash_rom} --wp-status | grep "WP: status:")"
+ if [ "$wp_status" != "WP: status: 0x00" ]; then
+ if [ "$FLAGS_nothing" = $FLAGS_FALSE ]; then
+ wp_error "$which_rom" "$wp_status"
+ fi
+ fi
+}
+
+# Back up current firmware and partition table
+make_backups() {
+ debug_msg "Backing up current firmware to $FLAGS_backup_dir"
+ mkdir -p "$FLAGS_backup_dir"
+ cp "$OLD_BIOS" "$FLAGS_backup_dir/$FLAGS_asset_tag.bios.bin"
+ ${FLASHROM_EC} -r "$FLAGS_backup_dir/$FLAGS_asset_tag.ec.bin"
+
+ # Copy the VPD info from RAM, since we can't extract it as text
+ # from the BIOS binary. Failure of this is only a warning, since
+ # the information is still in the old BIOS.
+ mosys vpd print all > "$FLAGS_backup_dir/$FLAGS_asset_tag.vpd.txt" ||
+ echo "WARNING: unable to save VPD as text."
+
+ # Copy the first part of the drive, so we can recreate the partition
+ # table.
+ local gpt_backup="$FLAGS_backup_dir/$FLAGS_asset_tag.gpt.bin"
+ debug_msg "Backing up current GPT table."
+ dd if="$FLAGS_ssd" of="$gpt_backup" bs=512 count=34
+
+ # Add a script to restore the BIOS and GPT
+ local restore_script="$FLAGS_backup_dir/$FLAGS_asset_tag.restore.sh"
+ cat >"$restore_script" <<EOF
+#!/bin/sh
+echo "Restoring BIOS"
+${FLASHROM_BIOS} -w "$FLAGS_asset_tag.bios.bin"
+echo "Restoring EC"
+${FLASHROM_EC} -w "$FLAGS_asset_tag.ec.bin"
+echo "Restoring GPT"
+dd of="$FLAGS_ssd" if="$FLAGS_asset_tag.gpt.bin" conv=notrunc
+EOF
+ echo "To restore original BIOS and SSD:"
+ echo " cd $FLAGS_backup_dir && sh $FLAGS_asset_tag.restore.sh"
+}
+
+# Main
+# ----------------------------------------------------------------------------
+
+main() {
+ # Make sure the files we were passed exist
+ [ -n "$FLAGS_bios" ] || err_die "Please specify a BIOS file (-b bios.bin)"
+ [ -n "$FLAGS_ec" ] || err_die "Please specify an EC updater (-e updater.sh)"
+ ensure_files_exist "$FLAGS_bios" "$FLAGS_ec" || exit 1
+
+ # If --nothing was specified, keep flashrom from writing
+ if [ "$FLAGS_nothing" = $FLAGS_TRUE ]; then
+ NOTHING="echo Not executing: "
+ fi
+
+ # Stop update engine before calling flashrom. Multiple copies of flashrom
+ # interfere with each other.
+ debug_msg "Stopping update engine"
+ initctl stop update-engine
+
+ # Read the current firmware
+ debug_msg "Reading BIOS from EEPROM"
+ ${FLASHROM_BIOS} -r "$OLD_BIOS"
+
+ # Copy current info to the backup dir, if specified
+ if [ -n "$FLAGS_backup_dir" ]; then
+ make_backups
+ fi
+
+ # Find the RO VPD area in the current firmware
+ local t="$(mosys -k eeprom map "$OLD_BIOS" | grep 'RO VPD')"
+ local vpd_offset="$(echo $t | sed 's/.*area_offset="\([^"]*\)" .*/\1/' )"
+ local vpd_size="$(echo $t | sed 's/.*area_size="\([^"]*\)" .*/\1/' )"
+ debug_msg "Found VPD at offset $vpd_offset size $vpd_size"
+ # Convert offset and size to decimal, since dd doesn't grok hex
+ vpd_offset="$(printf "%d" $vpd_offset)"
+ vpd_size="$(printf "%d" $vpd_size)"
+ debug_msg "In decimal, VPD is at offset $vpd_offset size $vpd_size"
+
+ # Copy the RO VPD from the old firmware to the new firmware
+ debug_msg "Copying VPD from old firmware to new firmware"
+ cp "$FLAGS_bios" "$NEW_BIOS"
+ dd bs=1 seek=$vpd_offset skip=$vpd_offset count=$vpd_size conv=notrunc \
+ if="$OLD_BIOS" of="$NEW_BIOS" || err_die "Unable to copy RO VPD"
+
+ # Disable write protect
+ disable_wp "EC" ${FLASHROM_EC}
+ disable_wp "BIOS" ${FLASHROM_BIOS}
+
+ # Write new firmware
+ debug_msg "Writing EC"
+ # TODO: if EC file ends in .bin, use flashrom to write it directly?
+ $NOTHING sh "$FLAGS_ec" --factory || err_die "Unable to write EC"
+ debug_msg "Writing BIOS"
+ $NOTHING ${FLASHROM_BIOS} -w "$NEW_BIOS" || err_die "Unable to write BIOS"
+
+ # Wipe SSD
+ if [ "$FLAGS_wipe_ssd" = $FLAGS_TRUE ]; then
+ debug_msg "Wiping SSD"
+ $NOTHING cgpt create -z "$FLAGS_ssd" || err_die "Unable to wipe SSD"
+ fi
+
+ # Leave the update engine stopped. We've mucked with the firmware
+ # and SSD contents, so we shouldn't be attempting an autoupdate this
+ # boot anyway.
+}
+
+main