13bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin#!/bin/sh
23bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin#
3af44dce1e80ebd818770b906a328423762389753Hung-Te Lin# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
43bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin# Use of this source code is governed by a BSD-style license that can be
53bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin# found in the LICENSE file.
63bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin#
73bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin# This script can change key (usually developer keys) in a firmware binary
8af44dce1e80ebd818770b906a328423762389753Hung-Te Lin# image or system live firmware (EEPROM), and assign proper HWID, FLAGS as well.
93bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
103bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te LinSCRIPT_BASE="$(dirname "$0")"
11605500b88cd99097d482ddcefee4ba04898781aeGaurav Shah. "$SCRIPT_BASE/common_minimal.sh"
1220525b91644a786e966c9486ac9afdf3d7c5447fHung-Te Linload_shflags || exit 1
133bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
143bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin# Constants used by DEFINE_*
1520525b91644a786e966c9486ac9afdf3d7c5447fHung-Te LinVBOOT_BASE='/usr/share/vboot'
1620525b91644a786e966c9486ac9afdf3d7c5447fHung-Te LinDEFAULT_KEYS_FOLDER="$VBOOT_BASE/devkeys"
173bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te LinDEFAULT_BACKUP_FOLDER='/mnt/stateful_partition/backups'
183bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
193bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin# DEFINE_string name default_value description flag
203bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te LinDEFINE_string from "" "Path of input file (empty for system live firmware)" "f"
213bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te LinDEFINE_string to "" "Path of output file (empty for system live firmware)" "t"
2220525b91644a786e966c9486ac9afdf3d7c5447fHung-Te LinDEFINE_string keys "$DEFAULT_KEYS_FOLDER" "Path to folder of dev keys" "k"
23af44dce1e80ebd818770b906a328423762389753Hung-Te LinDEFINE_string preamble_flags "" "Override preamble flags value. Known values:
24af44dce1e80ebd818770b906a328423762389753Hung-Te Lin                        0: None. (Using RW to boot in normal. aka, two-stop)
25af44dce1e80ebd818770b906a328423762389753Hung-Te Lin                        1: VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL (one-stop)" "p"
26af44dce1e80ebd818770b906a328423762389753Hung-Te LinDEFINE_boolean mod_gbb_flags \
27af44dce1e80ebd818770b906a328423762389753Hung-Te Lin  $FLAGS_TRUE "Modify GBB flags to enable developer friendly features" ""
283bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te LinDEFINE_boolean force_backup \
293bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  $FLAGS_TRUE "Create backup even if source is not live" ""
303bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te LinDEFINE_string backup_dir \
313bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  "$DEFAULT_BACKUP_FOLDER" "Path of directory to store firmware backups" ""
323bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
333bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin# Parse command line
343bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te LinFLAGS "$@" || exit 1
353bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lineval set -- "$FLAGS_ARGV"
363bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
373bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin# Globals
383bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin# ----------------------------------------------------------------------------
393bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Linset -e
403bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
413bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin# the image we are (temporary) working with
4220525b91644a786e966c9486ac9afdf3d7c5447fHung-Te LinIMAGE="$(make_temp_file)"
43010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te LinIMAGE="$(readlink -f "$IMAGE")"
443bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
453bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin# a log file to keep the output results of executed command
4620525b91644a786e966c9486ac9afdf3d7c5447fHung-Te LinEXEC_LOG="$(make_temp_file)"
473bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
483bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin# Functions
493bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin# ----------------------------------------------------------------------------
503bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
5138d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lin# Disables write protection status registers
5238d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lindisable_write_protection() {
5338d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lin  # No need to change WP status in file mode
5438d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lin  if [ -n "$FLAGS_to" ]; then
5538d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lin    return $FLAGS_TRUE
5638d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lin  fi
5738d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lin
5838d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lin  # --wp-disable command may return success even if WP is still enabled,
5938d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lin  # so we should use --wp-status to verify the results.
6038d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lin  echo "Disabling system software write protection status..."
6138d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lin  (flashrom --wp-disable && flashrom --wp-status) 2>&1 |
6238d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lin    tee "$EXEC_LOG" |
6338d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lin    grep -q '^WP: .* is disabled\.$'
6438d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lin}
6538d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lin
663bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin# Reads $IMAGE from $FLAGS_from
673bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Linread_image() {
683bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  if [ -z "$FLAGS_from" ]; then
693bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    echo "Reading system live firmware..."
703bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    if is_debug_mode; then
713bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin      flashrom -V -r "$IMAGE"
723bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    else
733bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin      flashrom -r "$IMAGE" >"$EXEC_LOG" 2>&1
743bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    fi
753bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  else
763bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    debug_msg "reading from file: $FLAGS_from"
773bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    cp -f "$FLAGS_from" "$IMAGE"
783bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  fi
793bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin}
803bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
813bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin# Writes $IMAGE to $FLAGS_to
823bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Linwrite_image() {
833bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  if [ -z "$FLAGS_to" ]; then
843bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    echo "Writing system live firmware..."
8520525b91644a786e966c9486ac9afdf3d7c5447fHung-Te Lin    # TODO(hungte) we can enable partial write to make this faster
863bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    if is_debug_mode; then
873bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin      flashrom -V -w "$IMAGE"
883bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    else
893bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin      flashrom -w "$IMAGE" >"$EXEC_LOG" 2>&1
903bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    fi
913bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  else
923bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    debug_msg "writing to file: $FLAGS_to"
933bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    cp -f "$IMAGE" "$FLAGS_to"
943bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    chmod a+r "$FLAGS_to"
953bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  fi
963bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin}
973bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
983bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin# Converts HWID from $1 to proper format with "DEV" extension
993bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Linecho_dev_hwid() {
1003bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  local hwid="$1"
1013bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  local hwid_no_dev="${hwid% DEV}"
1023bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
1033bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  # NOTE: Some DEV firmware image files may put GUID in HWID.
1043bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  # These are not officially supported and they will see "{GUID} DEV".
1053bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
1063bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  if [ "$hwid" != "$hwid_no_dev" ]; then
1073bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    hwid="$hwid_no_dev"
1083bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  fi
1093bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  local hwid_dev="$hwid DEV"
1103bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  debug_msg "echo_dev_hwid: [$1] -> [$hwid_dev]"
1113bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  echo "$hwid_dev"
1123bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin}
1133bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
1143bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin# Main
1153bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin# ----------------------------------------------------------------------------
1163bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Linmain() {
1173bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  # Check parameters
1183bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  local root_pubkey="$FLAGS_keys/root_key.vbpubk"
1193bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  local recovery_pubkey="$FLAGS_keys/recovery_key.vbpubk"
1203bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  local firmware_keyblock="$FLAGS_keys/firmware.keyblock"
1213bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  local firmware_prvkey="$FLAGS_keys/firmware_data_key.vbprivk"
1222c7213d4dc5cef71b5cf76c44a12ff14e15dfeb4Hung-Te Lin  local dev_firmware_keyblock="$FLAGS_keys/dev_firmware.keyblock"
1232c7213d4dc5cef71b5cf76c44a12ff14e15dfeb4Hung-Te Lin  local dev_firmware_prvkey="$FLAGS_keys/dev_firmware_data_key.vbprivk"
1243bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  local kernel_sub_pubkey="$FLAGS_keys/kernel_subkey.vbpubk"
1253bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  local is_from_live=0
1263bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  local backup_image=
1273bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
12820525b91644a786e966c9486ac9afdf3d7c5447fHung-Te Lin  debug_msg "Prerequisite check"
12920525b91644a786e966c9486ac9afdf3d7c5447fHung-Te Lin  ensure_files_exist \
1303bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    "$root_pubkey" \
1313bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    "$recovery_pubkey" \
1323bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    "$firmware_keyblock" \
1333bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    "$firmware_prvkey" \
134f82f4ae92048f0af8ec4e1934fe58f438301c4e9Hung-Te Lin    "$kernel_sub_pubkey" ||
13520525b91644a786e966c9486ac9afdf3d7c5447fHung-Te Lin    exit 1
1363bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
1373bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  if [ -z "$FLAGS_from" ]; then
1383bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    is_from_live=1
1393bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  else
140f82f4ae92048f0af8ec4e1934fe58f438301c4e9Hung-Te Lin    ensure_files_exist "$FLAGS_from" || exit 1
1413bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  fi
1423bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
14338d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lin  debug_msg "Checking software write protection status"
14438d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lin  disable_write_protection ||
14538d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lin    if is_debug_mode; then
14638d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lin      err_die "Failed to disable WP. Diagnose Message: $(cat "$EXEC_LOG")"
14738d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lin    else
14838d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lin      err_die "Write protection is still enabled. " \
14938d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lin              "Please verify that hardware write protection is disabled."
15038d3ef763179db8e00eb09131e6521e9d6be14c0Hung-Te Lin    fi
1513bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
1523bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  debug_msg "Pulling image to $IMAGE"
1533bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  (read_image && [ -s "$IMAGE" ]) ||
1543bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    err_die "Failed to read image. Error message: $(cat "$EXEC_LOG")"
1553bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
1563bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  debug_msg "Prepare to backup the file"
1573bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  if [ -n "$is_from_live" -o $FLAGS_force_backup = $FLAGS_TRUE ]; then
15820525b91644a786e966c9486ac9afdf3d7c5447fHung-Te Lin    backup_image="$(make_temp_file)"
1593bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    debug_msg "Creating backup file to $backup_image..."
1603bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    cp -f "$IMAGE" "$backup_image"
1613bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  fi
1623bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
163010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin  debug_msg "Detecting developer firmware keyblock"
164010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin  local expanded_firmware_dir="$(make_temp_dir)"
165010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin  local use_devfw_keyblock="$FLAGS_FALSE"
166010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin  (cd "$expanded_firmware_dir"; dump_fmap -x "$IMAGE" >/dev/null 2>&1) ||
167010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin    err_die "Failed to extract firmware image."
168010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin  if [ -f "$expanded_firmware_dir/VBLOCK_A" ]; then
169010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin    local has_dev=$FLAGS_TRUE has_norm=$FLAGS_TRUE
170010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin    # In output of vbutil_keyblock, "!DEV" means "bootable on normal mode" and
171010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin    # "DEV" means "bootable on developer mode". Here we try to match the pattern
172010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin    # in output of vbutil_block, and disable the flags (has_dev, has_norm) if
173010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin    # the pattern was not found.
174010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin    vbutil_keyblock --unpack "$expanded_firmware_dir/VBLOCK_A" |
175010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin      grep -qw '!DEV' || has_norm=$FLAGS_FALSE
176010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin    vbutil_keyblock --unpack "$expanded_firmware_dir/VBLOCK_A" |
177010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin      grep -qw '[^!]DEV' || has_dev=$FLAGS_FALSE
178010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin    if [ "$has_norm" = "$FLAGS_FALSE" -a "$has_dev" = "$FLAGS_TRUE" ]; then
179010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin      use_devfw_keyblock=$FLAGS_TRUE
180010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin    fi
181010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin  fi
182010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin
183010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin  if [ "$use_devfw_keyblock" = "$FLAGS_TRUE" ]; then
184010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin    echo "Using keyblocks (developer, normal)..."
185010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin  else
186010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin    echo "Using keyblocks (normal, normal)..."
187010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin    dev_firmware_prvkey="$firmware_prvkey"
188010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin    dev_firmware_keyblock="$firmware_keyblock"
189010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin  fi
190010630f18c8880b80e564fc6a0bcf8e5eb7f9de6Hung-Te Lin
1913bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  # TODO(hungte) We can use vbutil_firmware to check if the current firmware is
19220525b91644a786e966c9486ac9afdf3d7c5447fHung-Te Lin  # valid so that we know keys and vbutil_firmware are all working fine.
1933bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
1943bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  echo "Preparing new firmware image..."
1959fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin
1969fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin  debug_msg "Resign the firmware code (A/B) with new keys"
1979fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin  # Note resign_firmwarefd.sh needs the original rootkey to determine firmware
1989fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin  # body size, so we must resign image before changing GBB rootkey.
1999fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin
2009fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin  local unsigned_image="$(make_temp_file)"
2019fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin  local optional_opts=""
2029fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin  if [ -n "$FLAGS_preamble_flags" ]; then
2039fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin    # optional_opts: VERSION FLAGS
2049fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin    debug_msg "Setting new VERSION=1, FLAGS=$FLAGS_preamble_flags"
2059fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin    optional_opts="1 $FLAGS_preamble_flags"
2069fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin  fi
2079fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin  cp -f "$IMAGE" "$unsigned_image"
2089fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin  "$SCRIPT_BASE/resign_firmwarefd.sh" \
2099fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin    "$unsigned_image" \
2109fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin    "$IMAGE" \
2119fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin    "$firmware_prvkey" \
2129fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin    "$firmware_keyblock" \
2139fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin    "$dev_firmware_prvkey" \
2149fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin    "$dev_firmware_keyblock" \
2159fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin    "$kernel_sub_pubkey" \
2169fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin    $optional_opts >"$EXEC_LOG" 2>&1 ||
2179fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin    err_die "Failed to re-sign firmware. (message: $(cat "$EXEC_LOG"))"
2189fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin    if is_debug_mode; then
2199fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin      cat "$EXEC_LOG"
2209fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin    fi
2219fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin
2229fc41a02f5106a318c2e0d02be39b51e45337e77Hung-Te Lin  debug_msg "Extract current HWID"
2233bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  local old_hwid
22420525b91644a786e966c9486ac9afdf3d7c5447fHung-Te Lin  old_hwid="$(gbb_utility --get --hwid "$IMAGE" 2>"$EXEC_LOG" |
225af44dce1e80ebd818770b906a328423762389753Hung-Te Lin              sed -rne 's/^hardware_id: (.*)$/\1/p')"
2263bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
2273bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  debug_msg "Decide new HWID"
228af44dce1e80ebd818770b906a328423762389753Hung-Te Lin  [ -z "$old_hwid" ] &&
2293bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    err_die "Cannot find current HWID. (message: $(cat "$EXEC_LOG"))"
23020525b91644a786e966c9486ac9afdf3d7c5447fHung-Te Lin  local new_hwid="$(echo_dev_hwid "$old_hwid")"
2313bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
232af44dce1e80ebd818770b906a328423762389753Hung-Te Lin  local old_gbb_flags
233af44dce1e80ebd818770b906a328423762389753Hung-Te Lin  old_gbb_flags="$(gbb_utility --get --flags "$IMAGE" 2>"$EXEC_LOG" |
234af44dce1e80ebd818770b906a328423762389753Hung-Te Lin                   sed -rne 's/^flags: (.*)$/\1/p')"
235af44dce1e80ebd818770b906a328423762389753Hung-Te Lin  debug_msg "Decide new GBB flags from: $old_gbb_flags"
236af44dce1e80ebd818770b906a328423762389753Hung-Te Lin  [ -z "$old_gbb_flags" ] &&
237af44dce1e80ebd818770b906a328423762389753Hung-Te Lin    err_die "Cannot find GBB flags. (message: $(cat "$EXEC_LOG"))"
238af44dce1e80ebd818770b906a328423762389753Hung-Te Lin  # 0x30: GBB_FLAG_FORCE_DEV_BOOT_USB | GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK
239af44dce1e80ebd818770b906a328423762389753Hung-Te Lin  local new_gbb_flags="$((old_gbb_flags | 0x30))"
240af44dce1e80ebd818770b906a328423762389753Hung-Te Lin
2413bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  debug_msg "Replace GBB parts (gbb_utility allows changing on-the-fly)"
2423bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  gbb_utility --set \
2433bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    --hwid="$new_hwid" \
2443bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    --rootkey="$root_pubkey" \
2453bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    --recoverykey="$recovery_pubkey" \
2463bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    "$IMAGE" >"$EXEC_LOG" 2>&1 ||
2473bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    err_die "Failed to change GBB Data. (message: $(cat "$EXEC_LOG"))"
2483bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
249af44dce1e80ebd818770b906a328423762389753Hung-Te Lin  # Old firmware does not support GBB flags, so let's make it an exception.
250af44dce1e80ebd818770b906a328423762389753Hung-Te Lin  if [ "$FLAGS_mod_gbb_flags" = "$FLAGS_TRUE" ]; then
251af44dce1e80ebd818770b906a328423762389753Hung-Te Lin    debug_msg "Changing GBB flags from $old_gbb_flags to $new_gbb_flags"
252af44dce1e80ebd818770b906a328423762389753Hung-Te Lin    gbb_utility --set \
253af44dce1e80ebd818770b906a328423762389753Hung-Te Lin      --flags="$new_gbb_flags" \
254af44dce1e80ebd818770b906a328423762389753Hung-Te Lin      "$IMAGE" >"$EXEC_LOG" 2>&1 ||
255af44dce1e80ebd818770b906a328423762389753Hung-Te Lin      echo "Warning: GBB flags ($old_gbb_flags -> $new_gbb_flags) can't be set."
256af44dce1e80ebd818770b906a328423762389753Hung-Te Lin  fi
257af44dce1e80ebd818770b906a328423762389753Hung-Te Lin
2583bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  # TODO(hungte) compare if the image really needs to be changed.
2593bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
26020525b91644a786e966c9486ac9afdf3d7c5447fHung-Te Lin  debug_msg "Check if we need to make backup file(s)"
2613bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  if [ -n "$backup_image" ]; then
26220525b91644a786e966c9486ac9afdf3d7c5447fHung-Te Lin    local backup_hwid_name="$(echo "$old_hwid" | sed 's/ /_/g')"
26320525b91644a786e966c9486ac9afdf3d7c5447fHung-Te Lin    local backup_date_time="$(date +'%Y%m%d_%H%M%S')"
2643bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    local backup_file_name="firmware_${backup_hwid_name}_${backup_date_time}.fd"
2653bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    local backup_file_path="$FLAGS_backup_dir/$backup_file_name"
2663bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    if mkdir -p "$FLAGS_backup_dir" &&
2673bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin       cp -f "$backup_image" "$backup_file_path"; then
268eb868eeb1d2eb15d99eaa0625521c418472e8baaHung-Te Lin      true
269eb868eeb1d2eb15d99eaa0625521c418472e8baaHung-Te Lin    elif cp -f "$backup_image" "/tmp/$backup_file_name"; then
270eb868eeb1d2eb15d99eaa0625521c418472e8baaHung-Te Lin      backup_file_path="/tmp/$backup_file_name"
271eb868eeb1d2eb15d99eaa0625521c418472e8baaHung-Te Lin    else
272eb868eeb1d2eb15d99eaa0625521c418472e8baaHung-Te Lin      backup_file_path=''
273eb868eeb1d2eb15d99eaa0625521c418472e8baaHung-Te Lin    fi
274eb868eeb1d2eb15d99eaa0625521c418472e8baaHung-Te Lin    if [ -n "$backup_file_path" -a -s "$backup_file_path" ]; then
275eb868eeb1d2eb15d99eaa0625521c418472e8baaHung-Te Lin      # TODO(hungte) maybe we can wrap the flashrom by 'make_dev_firmware.sh -r'
276eb868eeb1d2eb15d99eaa0625521c418472e8baaHung-Te Lin      # so that the only command to remember would be make_dev_firmware.sh.
277eb868eeb1d2eb15d99eaa0625521c418472e8baaHung-Te Lin      echo "
278eb868eeb1d2eb15d99eaa0625521c418472e8baaHung-Te Lin      Backup of current firmware image is stored in:
279eb868eeb1d2eb15d99eaa0625521c418472e8baaHung-Te Lin        $backup_file_path
280eb868eeb1d2eb15d99eaa0625521c418472e8baaHung-Te Lin      Please copy the backup file to a safe place ASAP.
281eb868eeb1d2eb15d99eaa0625521c418472e8baaHung-Te Lin
282eb868eeb1d2eb15d99eaa0625521c418472e8baaHung-Te Lin      To stop using devkeys and restore original firmware, execute command:
283eb868eeb1d2eb15d99eaa0625521c418472e8baaHung-Te Lin        flashrom -w [PATH_TO_BACKUP_IMAGE]
284eb868eeb1d2eb15d99eaa0625521c418472e8baaHung-Te Lin      Ex: flashrom -w $backup_file_path
285eb868eeb1d2eb15d99eaa0625521c418472e8baaHung-Te Lin      "
2863bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    else
28720525b91644a786e966c9486ac9afdf3d7c5447fHung-Te Lin      echo "WARNING: Cannot create file in $FLAGS_backup_dir... Ignore backups."
2883bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    fi
2893bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  fi
2903bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
2913bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  # TODO(hungte) use vbutil_firmware to check if the new firmware is valid.
29220525b91644a786e966c9486ac9afdf3d7c5447fHung-Te Lin  # Or, do verification in resign_firmwarefd.sh and trust it.
2933bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
2943bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  debug_msg "Write the image"
2953bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  write_image ||
2963bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    err_die "Failed to write image. Error message: $(cat "$EXEC_LOG")"
2973bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
2983bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  debug_msg "Complete."
2993bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  if [ -z "$FLAGS_to" ]; then
3003bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin    echo "Successfully changed firmware to Developer Keys. New HWID: $new_hwid"
3013bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  else
30220525b91644a786e966c9486ac9afdf3d7c5447fHung-Te Lin    echo "Firmware '$FLAGS_to' now uses Developer Keys. New HWID: $new_hwid"
3033bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin  fi
3043bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin}
3053bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Lin
3063bdfc4601ebc2f637c7afb629ec6ce5a929f9e67Hung-Te Linmain
307