Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/bin/sh | |
| 2 # | |
| 3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | |
| 4 # Use of this source code is governed by a BSD-style license that can be | |
| 5 # found in the LICENSE file. | |
| 6 # | |
| 7 # This script converts a Chrome OS device to a pre-factory-install state: | |
| 8 # * Firmware write protect disabled | |
| 9 # * H2O BIOS, with RO VPD area copied from the current BIOS | |
| 10 # * Original EC firmware | |
| 11 # * Blank SSD (no GPT) | |
| 12 # | |
| 13 # Minimal usage: | |
| 14 # tofactory.sh -b H2OBIOS.bin -e ec_shellball.sh | |
| 15 | |
| 16 SCRIPT_BASE="$(dirname "$0")" | |
| 17 . "$SCRIPT_BASE/common.sh" | |
| 18 load_shflags || exit 1 | |
| 19 | |
| 20 # Constants used by DEFINE_* | |
| 21 VBOOT_BASE='/usr/share/vboot' | |
| 22 | |
| 23 # DEFINE_string name default_value description flag | |
| 24 DEFINE_string bios "" "Path of system firmware (BIOS) binary to write" "b" | |
| 25 DEFINE_string ec "" "Path of EC shellball to execute" "e" | |
| 26 DEFINE_string backup_dir "" "Path of directory in whoch to store backups" "k" | |
| 27 DEFINE_string asset_tag "unspecified_tag" \ | |
| 28 "Asset tag of device, used to name backups" "a" | |
| 29 DEFINE_string ssd "/dev/sda" "Path to SSD / target drive" "s" | |
| 30 DEFINE_boolean wipe_ssd $FLAGS_TRUE "Wipe SSD after firmware updates" "" | |
| 31 DEFINE_boolean nothing $FLAGS_FALSE \ | |
| 32 "Print commands but do not modify device" "n" | |
| 33 | |
| 34 # Parse command line | |
| 35 FLAGS "$@" || exit 1 | |
| 36 eval set -- "$FLAGS_ARGV" | |
| 37 | |
| 38 # Globals | |
| 39 # ---------------------------------------------------------------------------- | |
| 40 set -e | |
| 41 | |
| 42 # Flashrom commands with device overrides | |
| 43 FLASHROM_BIOS="flashrom -p internal:bus=spi" | |
| 44 FLASHROM_EC="flashrom -p internal:bus=lpc" | |
| 45 | |
| 46 # A log file to keep the output results of executed command | |
| 47 EXEC_LOG="$(make_temp_file)" | |
| 48 | |
| 49 # Temporary Work directory | |
| 50 WORK_DIR="$(make_temp_dir)" | |
| 51 OLD_BIOS="$WORK_DIR/old_bios.bin" | |
| 52 NEW_BIOS="$WORK_DIR/new_bios.bin" | |
| 53 | |
| 54 # Functions | |
| 55 # ---------------------------------------------------------------------------- | |
| 56 | |
| 57 # Error message for write protect disable failure, with reminder | |
| 58 wp_error() { | |
| 59 local which_rom=$1 | |
| 60 shift | |
| 61 echo "ERROR: Unable to disable $which_rom write protect: $*" 1>&2 | |
| 62 echo "Is hardware write protect still enabled?" 1>&2 | |
| 63 exit 1 | |
| 64 } | |
| 65 | |
| 66 # Disable write protect for an EEPROM | |
| 67 disable_wp() { | |
| 68 local which_rom=$1 # EC or BIOS | |
| 69 shift | |
| 70 local flash_rom="$*" # Flashrom command to use | |
| 71 | |
| 72 debug_msg "Disabling $which_rom write protect" | |
| 73 $NOTHING ${flash_rom} --wp-disable || wp_error "$which_rom" "--wp-disable" | |
| 74 $NOTHING ${flash_rom} --wp-range 0 0 || wp_error "$which_rom" "--wp-range" | |
| 75 | |
| 76 # WP status bits should report WP: status: 0x00 | |
| 77 local wp_status="$(${flash_rom} --wp-status | grep "WP: status:")" | |
| 78 if [ "$wp_status" != "WP: status: 0x00" ]; then | |
| 79 if [ "$FLAGS_nothing" = $FLAGS_FALSE ]; then | |
| 80 wp_error "$which_rom" "$wp_status" | |
| 81 fi | |
| 82 fi | |
| 83 } | |
| 84 | |
| 85 # Back up current firmware and partition table | |
| 86 make_backups() { | |
| 87 debug_msg "Backing up current firmware to $FLAGS_backup_dir" | |
| 88 mkdir -p "$FLAGS_backup_dir" | |
| 89 cp "$OLD_BIOS" "$FLAGS_backup_dir/$FLAGS_asset_tag.bios.bin" | |
| 90 ${FLASHROM_EC} -r "$FLAGS_backup_dir/$FLAGS_asset_tag.ec.bin" | |
| 91 | |
| 92 # Copy the VPD info from RAM, since we can't extract it as text | |
| 93 # from the BIOS binary. Failure of this is only a warning, since | |
| 94 # the information is still in the old BIOS. | |
| 95 mosys vpd print all > "$FLAGS_backup_dir/$FLAGS_asset_tag.vpd.txt" || | |
| 96 echo "WARNING: unable to save VPD as text." | |
| 97 | |
| 98 # Copy the first part of the drive, so we can recreate the partition | |
| 99 # table. | |
| 100 local gpt_backup="$FLAGS_backup_dir/$FLAGS_asset_tag.gpt.bin" | |
| 101 debug_msg "Backing up current GPT table." | |
| 102 dd if="$FLAGS_ssd" of="$gpt_backup" bs=512 count=34 | |
| 103 | |
| 104 # Add a script to restore the BIOS and GPT | |
| 105 local restore_script="$FLAGS_backup_dir/$FLAGS_asset_tag.restore.sh" | |
| 106 cat >"$restore_script" <<EOF | |
| 107 #!/bin/sh | |
| 108 echo "Restoring BIOS" | |
| 109 ${FLASHROM_BIOS} -w "$FLAGS_asset_tag.bios.bin" | |
| 110 echo "Restoring EC" | |
| 111 ${FLASHROM_EC} -w "$FLAGS_asset_tag.ec.bin" | |
| 112 echo "Restoring GPT" | |
| 113 dd of="$FLAGS_ssd" if="$FLAGS_asset_tag.gpt.bin" conv=notrunc | |
| 114 EOF | |
| 115 echo "To restore original BIOS and SSD:" | |
| 116 echo " cd $FLAGS_backup_dir && sh $FLAGS_asset_tag.restore.sh" | |
| 117 } | |
| 118 | |
| 119 | |
| 120 # Main | |
| 121 # ---------------------------------------------------------------------------- | |
| 122 | |
| 123 main() { | |
| 124 # Make sure the files we were passed exist | |
| 125 [ -n "$FLAGS_bios" ] || err_die "Please specify a BIOS file (-b bios.bin)" | |
| 126 [ -n "$FLAGS_ec" ] || err_die "Please specify an EC updater (-e updater.sh)" | |
| 127 ensure_files_exist "$FLAGS_bios" "$FLAGS_ec" || exit 1 | |
| 128 | |
| 129 # If --nothing was specified, keep flashrom from writing | |
| 130 if [ "$FLAGS_nothing" = $FLAGS_TRUE ]; then | |
| 131 NOTHING="echo Not executing: " | |
| 132 fi | |
| 133 | |
| 134 # Stop update engine before calling flashrom. Multiple copies of flashrom | |
| 135 # interfere with each other. | |
| 136 debug_msg "Stopping update engine" | |
| 137 initctl stop update-engine | |
| 138 trap "initctl start update-engine" EXIT | |
|
Bill Richardson
2010/12/17 01:10:53
You've already set a trap on EXIT in common.sh. Do
| |
| 139 | |
| 140 # Read the current firmware | |
| 141 debug_msg "Reading BIOS from EEPROM" | |
| 142 ${FLASHROM_BIOS} -r "$OLD_BIOS" | |
| 143 | |
| 144 # Copy current info to the backup dir, if specified | |
| 145 if [ -n "$FLAGS_backup_dir" ]; then | |
| 146 make_backups | |
| 147 fi | |
| 148 | |
| 149 # Find the RO VPD area in the current firmware | |
| 150 local t="$(mosys -k eeprom map "$OLD_BIOS" | grep 'RO VPD')" | |
| 151 local vpd_offset="$(echo $t | sed 's/.*area_offset="\([^"]*\)" .*/\1/' )" | |
| 152 local vpd_size="$(echo $t | sed 's/.*area_size="\([^"]*\)" .*/\1/' )" | |
| 153 debug_msg "Found VPD at offset $vpd_offset size $vpd_size" | |
| 154 # Convert offset and size to decimal, since dd doesn't grok hex | |
| 155 vpd_offset="$(printf "%d" $vpd_offset)" | |
| 156 vpd_size="$(printf "%d" $vpd_size)" | |
| 157 debug_msg "In decimal, VPD is at offset $vpd_offset size $vpd_size" | |
| 158 | |
| 159 # Copy the RO VPD from the old firmware to the new firmware | |
| 160 debug_msg "Copying VPD from old firmware to new firmware" | |
| 161 cp "$FLAGS_bios" "$NEW_BIOS" | |
| 162 dd bs=1 seek=$vpd_offset skip=$vpd_offset count=$vpd_size conv=notrunc \ | |
| 163 if="$OLD_BIOS" of="$NEW_BIOS" || err_die "Unable to copy RO VPD" | |
| 164 | |
| 165 # Disable write protect | |
| 166 disable_wp "EC" ${FLASHROM_EC} | |
| 167 disable_wp "BIOS" ${FLASHROM_BIOS} | |
| 168 | |
| 169 # Write new firmware | |
| 170 debug_msg "Writing EC" | |
| 171 # TODO: if EC file ends in .bin, use flashrom to write it directly? | |
| 172 $NOTHING sh "$FLAGS_ec" --factory || err_die "Unable to write EC" | |
| 173 debug_msg "Writing BIOS" | |
| 174 $NOTHING ${FLASHROM_BIOS} -w "$NEW_BIOS" || err_die "Unable to write BIOS" | |
| 175 | |
| 176 # Wipe SSD | |
| 177 if [ "$FLAGS_wipe_ssd" = $FLAGS_TRUE ]; then | |
| 178 debug_msg "Wiping SSD" | |
| 179 $NOTHING cgpt create -z "$FLAGS_ssd" || err_die "Unable to wipe SSD" | |
| 180 fi | |
| 181 } | |
| 182 | |
| 183 main | |
| OLD | NEW |