blob: bbf9d6abbef016edd62aa50e8cf9583fdfdce024 [file] [log] [blame]
#!/bin/bash
# Copyright 2014 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
SCRIPT="$(readlink -f "$0")"
SCRIPT_DIR="$(dirname "${SCRIPT}")"
EC_DIR="$(readlink -f "${SCRIPT_DIR}/..")"
if [[ "$(basename "${EC_DIR}")" != "ec" ]]; then
EC_DIR=
fi
# Loads script libraries.
# shellcheck source=../../../scripts/lib/shflags/shflags
. "${SHFLAGS:-/usr/share/misc/shflags}" || exit 1
# Redirects tput to stderr, and drop any error messages.
tput2() {
tput "$@" 1>&2 2>/dev/null || true
}
error() {
tput2 bold && tput2 setaf 1
echo "ERROR: $*" >&2
tput2 sgr0
}
info() {
tput2 bold && tput2 setaf 2
echo "INFO: $*" >&2
tput2 sgr0
}
warn() {
tput2 bold && tput2 setaf 3
echo "WARNING: $*" >&2
tput2 sgr0
}
die() {
[ -z "$*" ] || error "$@"
exit 1
}
# Include a board name to the BOARDS_${EC_CHIP} array below ONLY IF servod is
# not aware of its 'ec_chip'. If servod becomes able to answer 'ec_chip'
# for the board, remove it from BOARDS_XXXX array below.
BOARDS_IT83XX=(
adlrvpm_ite
adlrvpp_ite
it83xx_evb
reef_it8320
)
BOARDS_IT83XX_SPI_PROGRAMMING=(
it8xxx2_evb
it8xxx2_pdevb
)
BOARDS_STM32=(
bloonchipper
chell_pd
coffeecake
chocodile_bec
chocodile_vpdmcu
dartmonkey
glados_pd
hatch_fp
jerry
minimuffin
nami_fp
nocturne_fp
oak_pd
pit
strago_pd
zinger
)
BOARDS_STM32_PROG_EN=(
)
BOARDS_STM32_DFU=(
c2d2
dingdong
hoho
twinkie
discovery
servo_v4
servo_v4p1
servo_micro
sweetberry
polyberry
stm32f446e-eval
tigertail
fluffy
)
BOARDS_NPCX_5M5G_JTAG=(
npcx_evb
npcx_evb_arm
)
BOARDS_NPCX_5M6G_JTAG=(
)
BOARDS_NPCX_7M6X_JTAG=(
)
BOARDS_NPCX_7M7X_JTAG=(
npcx7_evb
)
BOARDS_NPCX_SPI=(
buccaneer
helipilot
)
BOARDS_NPCX_INT_SPI=(
adlrvpp_npcx
mtlrvpp_npcx
mtlrvpp_pd
)
BOARDS_SPI_1800MV=(
coral
reef
)
# hold cold_reset:on when using debug header (e.g. servo header)
BOARDS_HOLD_COLD_RESET_DBG_HDR=(
reef
)
BOARDS_RAIDEN=(
coral
eve
fizz
kukui
nami
nautilus
poppy
rammus
reef
soraka
)
BOARDS_MCHP_INT_SPI=(
mtlrvpp_mchp
)
DEFAULT_PORT="${SERVOD_PORT:-9999}"
BITBANG_RATE="57600" # Could be overwritten by a command line option.
# Flags
DEFINE_integer bitbang_rate "${BITBANG_RATE}" \
"UART baud rate to use when bit bang programming, " \
"standard UART rates from 9600 to 57600 are supported."
DEFINE_string board "" \
"The board to run debugger on."
DEFINE_string chip "" \
"The chip to run debugger on."
DEFINE_boolean dry_run "${FLAGS_FALSE}" \
"Print the commands to be run instead of actually running them."
DEFINE_string image "" \
"Full pathname of the EC firmware image to flash."
DEFINE_string mchp_loader "" \
"Full pathname of the Microchip loader firmware image to SRAM."
DEFINE_string logfile "" \
"Stm32 only: pathname of the file to store communications log."
DEFINE_string offset "0" \
"Offset where to program the image from."
DEFINE_integer port "${DEFAULT_PORT}" \
"Port to communicate to servo on."
DEFINE_boolean raiden "${FLAGS_FALSE}" \
"Use raiden_debug_spi programmer"
DEFINE_string read "" "Pathname of the file to store EC firmware image."
DEFINE_boolean ro "${FLAGS_FALSE}" \
"Write only the read-only partition"
DEFINE_boolean servo_micro_uart_rx_rework "${FLAGS_FALSE}" \
"The servo micro for flashing has b/143163043#comment3 rework"
DEFINE_integer timeout 600 \
"Timeout for flashing the EC, measured in seconds."
DEFINE_boolean verbose "${FLAGS_FALSE}" \
"Verbose hw control logging"
DEFINE_boolean verify "${FLAGS_FALSE}" \
"Verify EC firmware image after programming."
DEFINE_boolean zephyr "${FLAGS_FALSE}" \
"Program a Zephyr EC image instead of a CrOS EC image"
DEFINE_boolean no_preserve "${FLAGS_FALSE}" \
"Avoid preserving the sections of firmware image with preserve property"
DEFINE_boolean try_apshutdown "${FLAGS_FALSE}" \
"Shutdown the AP immediately after flashing. It does not guarantee a " \
"successful AP shutdown for all devices or in all situations. You need" \
" to understand the limitations when you build a solution on it. "
DEFINE_integer try_apshutdown_count 16 \
"Number of attempts to shutdown the AP immediately after flashing."
DEFINE_string dut_ip "" \
"DUT IP address"
DEFINE_string token_db "${EC_DIR}/build/tokens.bin" \
"Full pathname of the EC tokenized database to copy to DUT."
# shellcheck disable=SC2034 # Remove someday when autorepair doesn't use it.
DEFINE_boolean use_i2c_pseudo "${FLAGS_FALSE}" \
"Ignored."
# Parse command line
FLAGS_HELP="usage: $0 [flags]"
FLAGS "$@" || exit 1
eval set -- "${FLAGS_ARGV}"
if [[ $# -gt 0 ]]; then
die "invalid arguments: \"$*\""
fi
# Error messages
MSG_PROGRAM_FAIL="Failed to flash EC firmware image"
MSG_READ_FAIL="Failed to read EC firmware image"
MSG_VERIFY_FAIL="Failed to verify EC firmware image."
MSG_CHIP_READ_INVALID="Invalid chip type passed to be read"
set -e
if [[ -n "${BAZEL_DUT_CONTROL}" ]]; then
DUT_CONTROL_CMD=( "${BAZEL_DUT_CONTROL}" )
else
DUT_CONTROL_CMD=( "dut-control" )
fi
DUT_CONTROL_CMD+=( "--port=${FLAGS_port}" )
DUT_CTRL_PREFIX=""
# Run a command which mutates the state of an attached device.
# This is used by the --dry_run flag, when enabled, the command will
# only print. When disabled, the command will run without printing
# any message.
function print_or_run() {
if [ "${FLAGS_dry_run}" = "${FLAGS_TRUE}" ]; then
local arg
local -a quoted_args
# Quote each of the arguments so it can easily be
# copy-pasted into a shell.
for arg in "$@"; do
quoted_args+=("$(printf "%q" "${arg}")")
done
tput2 bold && tput2 setaf 4
echo "DRY RUN:" "${quoted_args[@]}" >&2
tput2 sgr0
else
if [[ "${FLAGS_verbose}" == "${FLAGS_TRUE}" ]]; then
local arg
local -a quoted_args
# Quote each of the arguments so it can easily be
# copy-pasted into a shell.
for arg in "$@"; do
quoted_args+=("$(printf "%q" "${arg}")")
done
echo "${quoted_args[@]}" >&2
fi
"$@"
fi
}
# Helper routine to test if specific control is available.
# This always executes, even with --dry_run so that the control flow
# of the script continues normally.
function dut_has_control() {
local CONTROL=$1
"${DUT_CONTROL_CMD[@]}" -i "${CONTROL}" >/dev/null 2>&1
}
function dut_control() {
local DUT_CTRL_CML=( "${DUT_CONTROL_CMD[@]}" )
for p in "$@" ; do
# Only add the prefix if the arg is a control name.
if [[ ${p} != -* ]] ; then
p="${DUT_CTRL_PREFIX}${p}"
fi
DUT_CTRL_CML+=( "${p}" )
done
print_or_run "${DUT_CTRL_CML[@]}" >/dev/null
}
function dut_control_or_die {
dut_control "$@" || die "command exited $? (non-zero): dut-control $*"
}
function dut_control_get() {
if [ $# -gt 1 ]; then
error "${FUNCNAME[0]} failed: more than one argument: $*"
return 1
fi
local ARGS DUT_GETVAL RETVAL
ARGS=( "${DUT_CONTROL_CMD[@]}" "--value_only" "${DUT_CTRL_PREFIX}$1" )
RETVAL=0
# || statement is attached to avoid an exit if error exit is enabled.
DUT_GETVAL=$( "${ARGS[@]}" ) || RETVAL="$?"
if (( "${RETVAL}" )) ; then
warn "${FUNCNAME[0]} failed: ${ARGS[*]} returned ${RETVAL}."
return "${RETVAL}"
fi
echo "${DUT_GETVAL}"
}
function dut_control_get_or_die {
dut_control_get "$@" || \
die "command exited $? (non-zero): dut-control --value_only $*"
}
: "${BOARD:=${FLAGS_board}}"
in_array() {
local n=$#
local value=${!n}
for (( i=1; i<$#; i++ )) do
if [ "${!i}" == "${value}" ]; then
return 0
fi
done
return 1
}
declare -a SUPPORTED_CHIPS
if in_array "${BOARDS_STM32[@]}" "${BOARD}"; then
SUPPORTED_CHIPS+=("stm32")
fi
if in_array "${BOARDS_STM32_DFU[@]}" "${BOARD}"; then
SUPPORTED_CHIPS+=("stm32_dfu")
fi
if in_array "${BOARDS_NPCX_5M5G_JTAG[@]}" "${BOARD}"; then
SUPPORTED_CHIPS+=("npcx_5m5g_jtag")
fi
if in_array "${BOARDS_NPCX_5M6G_JTAG[@]}" "${BOARD}"; then
SUPPORTED_CHIPS+=("npcx_5m6g_jtag")
fi
if in_array "${BOARDS_NPCX_7M6X_JTAG[@]}" "${BOARD}"; then
SUPPORTED_CHIPS+=("npcx_7m6x_jtag")
fi
if in_array "${BOARDS_NPCX_7M7X_JTAG[@]}" "${BOARD}"; then
SUPPORTED_CHIPS+=("npcx_7m7x_jtag")
fi
if in_array "${BOARDS_NPCX_SPI[@]}" "${BOARD}"; then
SUPPORTED_CHIPS+=("npcx_spi")
fi
if in_array "${BOARDS_NPCX_INT_SPI[@]}" "${BOARD}"; then
SUPPORTED_CHIPS+=("npcx_int_spi")
fi
if in_array "${BOARDS_IT83XX[@]}" "${BOARD}"; then
SUPPORTED_CHIPS+=("it83xx")
fi
if in_array "${BOARDS_IT83XX_SPI_PROGRAMMING[@]}" "${BOARD}"; then
SUPPORTED_CHIPS+=("ite_spi")
fi
if in_array "${BOARDS_MCHP_INT_SPI[@]}" "${BOARD}"; then
SUPPORTED_CHIPS+=("mchp_int_spi")
fi
if [[ ${#SUPPORTED_CHIPS[@]} -eq 0 && -n "${FLAGS_chip}" ]]; then
SUPPORTED_CHIPS+=("${FLAGS_chip}")
fi
if [[ ${#SUPPORTED_CHIPS[@]} -eq 0 ]]; then
SERVO_EC_CHIP="$(dut_control_get ec_chip)"
SERVO_EC_CHIP="${SERVO_EC_CHIP,,}"
if [[ "${SERVO_EC_CHIP}" =~ "unknown" || -z "${SERVO_EC_CHIP}" ]]; then
die "Please check that servod is running or," \
"manually specify either --board or --chip."
fi
SUPPORTED_CHIPS+=("${SERVO_EC_CHIP}")
fi
if [[ ${#SUPPORTED_CHIPS[@]} -eq 0 ]]; then
# This happens if ${FLAGS_board} is not known in this flash_ec yet,
# ${FLAGS_chip} is not given, and servod doesn't know ec_chip.
# In this case, '--chip' should be specified in the command line.
die "board '${BOARD}' not supported." \
"Please check that servod is running, or manually specify --chip."
elif [[ ${#SUPPORTED_CHIPS[@]} -eq 1 ]]; then
CHIP="${SUPPORTED_CHIPS[0]}"
elif [ -n "${FLAGS_chip}" ]; then
if in_array "${SUPPORTED_CHIPS[@]}" "${FLAGS_chip}"; then
CHIP="${FLAGS_chip}"
else
die "board ${BOARD} only supports (${SUPPORTED_CHIPS[*]})," \
"not ${FLAGS_chip}."
fi
else
# Ideally, ec_chip per servo_type should be specified in servo overlay
# file, instead of having multiple board-to-chip mapping info in this
# script. Please refer to crrev.com/c/1496460 for example.
die "board ${BOARD} supports multiple chips" \
"(${SUPPORTED_CHIPS[*]}). Use --chip= to choose one."
fi
if [ -n "${FLAGS_chip}" ] && [ "${CHIP}" != "${FLAGS_chip}" ]; then
die "board ${BOARD} doesn't use chip ${FLAGS_chip}"
fi
if [[ "${CHIP}" = "stm32_dfu" ]]; then
NEED_SERVO="no"
fi
# Servo variables management
case "${BOARD}" in
chocodile_bec ) MCU="usbpd" ;;
oak_pd|strago_pd ) MCU="usbpd" ;;
chell_pd|glados_pd ) MCU="usbpd" ;;
bloonchipper|buccaneer|dartmonkey|hatch_fp|helipilot|nami_fp|nocturne_fp )
MCU="fpmcu"
;;
dingdong|hoho|twinkie ) DUT_CONTROL_CMD=( "true" ); MCU="ec" ;;
*) MCU="ec" ;;
esac
case "${CHIP}" in
"stm32"|"npcx_spi"|"npcx_int_spi"|"it83xx"|"ite_i2c"|"npcx_uut"|"ite_spi"| \
"ite_spi_ccd_i2c"|"it8xxx2"|"mchp_int_spi")
;;
*)
if [[ -n "${FLAGS_read}" ]]; then
die "The flag is not yet supported on ${CHIP}."
fi
# If verification is not supported, then show a warning message.
# Keep it running however.
if [[ "${FLAGS_verify}" == "${FLAGS_TRUE}" ]]; then
warn "Ignoring '--verify'" \
"since read is not supported on ${CHIP}."
fi
;;
esac
SERVO_TYPE="$(dut_control_get servo_type || :)"
if [[ "${SERVO_TYPE}" =~ ^servo_v4(p1)?_with_.*$ ]]; then
ACTIVE_DEVICE="$(dut_control_get active_dut_controller)"
if [[ ${ACTIVE_DEVICE} == neither ]]; then
die "Could not determine servo V4 active device"
fi
else
ACTIVE_DEVICE="${SERVO_TYPE}"
fi
if [[ "${SERVO_TYPE}" =~ ^servo_v4(p1)?_with_.*_and_.*$ ]]; then
# If there are two devices, servo v4 type will show both devices. The
# default device is first. The other device is second.
# servo_type:servo_v4{p1}_with_servo_micro_and_ccd_cr50
SECOND_DEVICE="${SERVO_TYPE#*_and_}"
# servo_v4p1 can shared the same type with servo_v4, since there's no
# difference handling the flash.
SERVO_TYPE="servo_v4_with_${ACTIVE_DEVICE}"
# Controls sent through the default device don't have a prefix. The
# second device controls do. If the default device isn't active, we
# need to use the second device controls to send commands. Use the
# prefix for all dut control commands.
if [[ "${SECOND_DEVICE}" = "${ACTIVE_DEVICE}" ]]; then
DUT_CTRL_PREFIX="${ACTIVE_DEVICE}."
fi
fi
servo_is_ccd() {
[[ "${SERVO_TYPE}" =~ "ccd" ]]
}
servo_has_warm_reset() {
dut_has_control warm_reset
}
servo_has_cold_reset() {
dut_has_control cold_reset
}
servo_has_dut_i2c_mux() {
dut_has_control dut_i2c_mux
}
servo_has_dut_i2c_en() {
dut_has_control dut_i2c_en
}
servo_ec_hard_reset_or_die() {
# Cold reset on C2D2 is H1 reset, which will double reset the EC
if [[ "${SERVO_TYPE}" =~ "c2d2" ]]; then
dut_control_or_die gsc_ec_reset:on
dut_control_or_die gsc_ec_reset:off
elif servo_has_cold_reset; then
dut_control_or_die cold_reset:on
dut_control_or_die cold_reset:off
else
info "Skipping cold reset"
fi
}
servo_ec_hard_reset() {
dut_control cold_reset:on
dut_control cold_reset:off
}
c2d2_ec_hard_reset() {
# This is an H1-level reset (instead of just an EC-level reset)
dut_control cold_reset:on
dut_control cold_reset:off
}
servo_usbpd_hard_reset() {
dut_control usbpd_reset:on sleep:0.5 usbpd_reset:off
}
servo_fpmcu_hard_reset() {
dut_control fpmcu_reset:on sleep:0.5 fpmcu_reset:off
# b/177331210: Workaround for an outstanding issue that prevents
# flashing dartmonkey with a servo_micro. The exact root cause is still
# unknown, but it's been observed that repeating the FPMCU reset
# sequence twice makes the operation succeed.
if [[ "${BOARD}" =~ "dartmonkey" ]] ; then
warn "Workaround for dartmonkey + servo_micro: repeat FPMCU reset sequence"
dut_control fpmcu_reset:on sleep:0.5 fpmcu_reset:off
fi
}
servo_sh_hard_reset() {
dut_control sh_reset:on
dut_control sh_reset:off
}
ec_reset() {
local stype
if [[ "${SERVO_TYPE}" =~ "servo" ]] || servo_is_ccd; then
stype="servo"
else
stype=${SERVO_TYPE}
fi
if [[ -n "${stype}" ]]; then
eval "${stype}_${MCU}_hard_reset"
fi
}
ccd_ec_boot0() {
local on_value="${1}"
local boot_mode="${2}"
info "Using CCD ${boot_mode}."
if [[ "${on_value}" == "on" ]] && [[ "${boot_mode}" == "uut" ]] ; then
# Ti50 requires EC reset to be asserted before UUT mode can be
# enabled, Cr50 should not mind.
dut_control cold_reset:on
fi
dut_control "ccd_ec_boot_mode_${boot_mode}:${on_value}"
}
servo_micro_ec_boot0() {
# Some devices (e.g. hatch) control the RX UART pin via an on-board
# circuit that is controlled by the EC_FLASH_ODL pin. For those boards,
# we want to continue to drive the EC_FLASH_ODL if they do not have the
# servo micro rework listed below.
if [[ "${FLAGS_servo_micro_uart_rx_rework}" == "${FLAGS_TRUE}" ]]; then
info "Servo micro $2 mode: $1 (using rx_rework)"
# Setting the test point allows the EC_TX_SERVO_RX line
# to be driven by the servo for 'on' value. 'off' value
# lets the EC drive the EC_TX_SERVO_RX net.
#
# HW Rework (b/143163043#comment3):
# - Disconnect U45.1 from ground
# - Connected U45.1 to TP1 pad
dut_control "tp1:$1"
dut_control "servo_micro_ec_boot_mode_$2:$1"
else
info "Servo micro $2 mode: $1 (using FW_UP_L)"
dut_control "ec_boot_mode:$1"
fi
}
servo_ec_boot0() {
dut_control "ec_boot_mode:$1"
}
c2d2_ec_boot0() {
dut_control "ec_boot_mode_uut:$1"
}
servo_usbpd_boot0() {
dut_control "usbpd_boot_mode:$1"
}
servo_fpmcu_boot0() {
dut_control "fpmcu_boot_mode:$1"
}
servo_micro_fpmcu_boot0() {
servo_fpmcu_boot0 "$@"
}
servo_micro_usbpd_boot0() {
servo_usbpd_boot0 "$@"
}
servo_sh_boot0() {
dut_control "sh_boot_mode:$1"
}
ec_switch_boot0() {
local on_value=$1
# Enable programming GPIOs
if in_array "${BOARDS_STM32_PROG_EN[@]}" "${BOARD}"; then
servo_save_add "prog_en"
dut_control prog_en:yes
fi
if servo_is_ccd ; then
stype=ccd
elif [[ "${SERVO_TYPE}" =~ "servo_micro" ]] ; then
stype=servo_micro
elif [[ "${SERVO_TYPE}" =~ "servo" ]] ; then
stype=servo
else
stype=${SERVO_TYPE}
fi
eval "${stype}_${MCU}_boot0" "${on_value}" "$2"
}
ec_enable_boot0() {
ec_switch_boot0 "on" "$1"
}
ec_disable_boot0() {
ec_switch_boot0 "off" "$1"
}
# Returns 0 on success (if on beaglebone)
on_servov3() {
grep -qs '^CHROMEOS_RELEASE_BOARD=beaglebone_servo' /etc/lsb-release
}
# Returns 0 on success (if raiden should be used instead of servo)
error_reported= # Avoid double printing the error message.
on_raiden() {
if [[ "${SERVO_TYPE}" =~ "servo_v4" ]] || \
servo_is_ccd || \
[[ "${SERVO_TYPE}" =~ "servo_micro" ]]; then
return 0
fi
if [ -z "${BOARD}" ]; then
[ "${FLAGS_raiden}" = "${FLAGS_TRUE}" ] && return 0 || return 1
fi
if [ "${FLAGS_raiden}" = "${FLAGS_TRUE}" ]; then
if in_array "${BOARDS_RAIDEN[@]}" "${BOARD}"; then
return 0
fi
if [ -z "${error_reported}" ]; then
error_reported="y"
die "raiden mode not supported on ${BOARD}" >&2
fi
fi
return 1
}
declare -a DELETE_LIST # Array of file/dir names to delete at exit
# Put back the servo and the system in a clean state at exit
FROZEN_PIDS=""
cleanup() {
for pid in ${FROZEN_PIDS}; do
info "Sending SIGCONT to process ${pid}!"
kill -CONT "${pid}"
done
# Delete all files or directories in DELETE_LIST.
for item in "${DELETE_LIST[@]}"; do
if [[ -e "${item}" ]]; then
print_or_run rm -rf "${item}" &> /dev/null
fi
done
if [ "${CHIP}" = "it83xx" ]; then
if [ "${SERVO_TYPE}" = "servo_v2" ]; then
info "Reinitializing ftdi_i2c interface"
# Ask servod to close its FTDI I2C interface because it
# could be open or closed at this point. Using
# ftdii2c_cmd:close when it's already closed is okay,
# however ftdii2c_cmd:open when it's already open
# triggers an error.
#
# If there is a simple, reliable way to detect whether
# servod FTDI I2C interface is open or closed, it would
# be preferable to check and only re-initialize if it's
# closed. Patches welcome.
dut_control ftdii2c_cmd:close
dut_control ftdii2c_cmd:init
dut_control ftdii2c_cmd:open
dut_control ftdii2c_cmd:setclock
fi
fi
servo_restore
if [ "${CHIP}" = "stm32" ] || [ "${CHIP}" = "npcx_uut" ]; then
dut_control "${MCU}"_boot_mode:off
fi
if servo_is_ccd; then
dut_control ccd_ec_boot_mode_uut:off
dut_control ccd_ec_boot_mode_bitbang:off
fi
if ! on_raiden || servo_has_cold_reset; then
ec_reset
fi
if [[ "${FLAGS_try_apshutdown}" == "${FLAGS_TRUE}" ]]; then
info "Attempting to shut down the AP..."
dut_control ec_uart_regexp:None
for (( i = 0; i < "${FLAGS_try_apshutdown_count}"; i++ )); do
dut_control ec_uart_cmd:apshutdown
sleep 1
done
fi
}
trap cleanup EXIT
# TODO: the name of the RO images created for zephyr vary based on whether
# the RO image includes a header.
# NPCX images use "build-ro/zephyr/zephyr.npcx.bin"
# ITE images use "build-ro/zephyr/zephyr.bin"
if [ "${FLAGS_ro}" = "${FLAGS_TRUE}" ] && [ "${FLAGS_zephyr}" = "${FLAGS_TRUE}" ]
then
die "The --ro flag is not supported with the --zephyr flag"
fi
# Possible default EC images
if [ "${FLAGS_ro}" = "${FLAGS_TRUE}" ] ; then
EC_FILE=ec.RO.flat
else
EC_FILE=ec.bin
fi
LOCAL_BUILD=
if [[ -n "${EC_DIR}" ]]; then
if [ "${FLAGS_ro}" = "${FLAGS_TRUE}" ] ; then
LOCAL_BUILD="${EC_DIR}/build/${BOARD}/RO/${EC_FILE}"
elif [ "${FLAGS_zephyr}" = "${FLAGS_TRUE}" ] ; then
LOCAL_BUILD="${EC_DIR}/build/zephyr/${BOARD}/output/${EC_FILE}"
else
LOCAL_BUILD="${EC_DIR}/build/${BOARD}/${EC_FILE}"
fi
fi
LOCAL_TOKEN_DB=
if [[ -n "${EC_DIR}" ]]; then
if [ -f "${EC_DIR}/build/tokens.bin" ] ; then
LOCAL_TOKEN_DB="${EC_DIR}/build/tokens.bin"
fi
fi
# Get baseboard from build system if present
BASEBOARD=
# We do not want to exit script if make call fails; we turn -e back on after
# setting BASEBOARD
set +e
if [[ -n "${EC_DIR}" ]]; then
BASEBOARD=$(make --quiet -C "${EC_DIR}" BOARD="${BOARD}" print-baseboard \
2>/dev/null)
elif [[ -d "${HOME}/trunk/src/platform/ec" ]]; then
BASEBOARD=$(make --quiet -C "${HOME}"/trunk/src/platform/ec \
BOARD="${BOARD}" print-baseboard 2>/dev/null)
elif [ -z "${FLAGS_image}" ] ; then
info "Could not find ec build folder to calculate baseboard."
fi
# shellcheck disable=SC2181
if [ $? -ne 0 ] && [ -z "${FLAGS_image}" ]; then
info "EC build system didn't recognize ${BOARD}. Assuming no baseboard."
fi
set -e
if [[ -n "${BASEBOARD}" ]]; then
EMERGE_BUILD=/build/${BASEBOARD}/firmware/${BOARD}/${EC_FILE}
else
EMERGE_BUILD=/build/${BOARD}/firmware/${EC_FILE}
fi
# Find the EC image to use
function ec_image() {
# No image specified on the command line, try default ones
if [[ -n "${FLAGS_image}" ]] ; then
if [ -e "${FLAGS_image}" ] || \
[ "${FLAGS_image}" == "-" ]; then
echo "${FLAGS_image}"
return
fi
die "Invalid image path : ${FLAGS_image}"
else
if [ -f "${LOCAL_BUILD}" ]; then
echo "${LOCAL_BUILD}"
return
fi
if [ -f "${EMERGE_BUILD}" ]; then
echo "${EMERGE_BUILD}"
return
fi
fi
die "no EC image found : build one or specify one."
}
function ec_token_database() {
# No token database specified on command line, try default location
if [[ -n "${FLAGS_token_db}" ]] ; then
if [ -e "${FLAGS_token_db}" ] || \
[ "${FLAGS_token_db}" == "-" ]; then
echo "${FLAGS_token_db}"
return
fi
die "Invalid image path : ${FLAGS_token_db}"
else
if [ -f "${LOCAL_TOKEN_DB}" ]; then
echo "${LOCAL_TOKEN_DB}"
return
fi
fi
die "no token database found : specify one."
}
function load_token_db() {
local TOKEN_DB
local DUT_IP
TOKEN_DB="$(ec_token_database)"
DUT_IP="${FLAGS_dut_ip}"
info "TOKEN_DB=${TOKEN_DB}"
info "DUT_IP=${DUT_IP}"
ssh root@"${DUT_IP}" 'mkdir -p /usr/local/cros_ec/'
scp "${TOKEN_DB}" root@"${DUT_IP}":/usr/local/cros_ec/tokens.bin
return
}
# Find the Loader image to use
function mchp_loader_image() {
# Use the image specified on the command line
if [[ -n "${FLAGS_mchp_loader}" ]] ; then
if [ -e "${FLAGS_mchp_loader}" ] || \
[ "${FLAGS_mchp_loader}" == "-" ]; then
LOADER=${FLAGS_mchp_loader}
fi
# Try default one
else
for dir in \
"$(dirname "${IMG}")" \
"${EC_DIR}/build/${BOARD}/output" \
"${EC_DIR}/build/zephyr/${BOARD}/output" \
"$(dirname "${LOCAL_BUILD}")" \
"$(dirname "${EMERGE_BUILD}")" ;
do
if [ -f "${dir}/second_loader_fw.bin" ] ; then
LOADER="${dir}/second_loader_fw.bin"
break
fi
done
fi
if [ -z "${LOADER}" ] ; then
die "No loader image found: build one or specify correct one"
fi
info "using MCHP loader: ${LOADER}"
echo "${LOADER}"
}
# Get the correct UART for flashing. The resulting string is concatenated with
# the various UART control suffixes, such as "_pty", "_en", "_parity", etc.
function servo_ec_uart_prefix() {
if [[ "${MCU}" == "fpmcu" ]]; then
# The FPMCU has multiple UARTs. Use the platform UART since it's a
# bootloader capable UART on all devices. See
# http://go/cros-fingerprint-reference-designs#uart-console.
echo "fpmcu_platform_uart"
return
fi
echo "${MCU}_uart"
}
# Find the EC UART provided by servo.
function servo_ec_uart() {
SERVOD_FAIL="Cannot communicate with servod. Is servod running?"
local EC_UART_PREFIX
EC_UART_PREFIX="$(servo_ec_uart_prefix)"
PTY=$(dut_control_get "raw_${EC_UART_PREFIX}_pty" ||
dut_control_get "${EC_UART_PREFIX}_pty")
if [[ -z "${PTY}" ]]; then
die "${SERVOD_FAIL}"
fi
echo "${PTY}"
}
declare -a save
#######################################
# Store DUT control value to restore in LIFO order.
# Arguments:
# $1: Control name
# $2: (optional) Value to restore for the name at exit.
#######################################
function servo_save_add() {
local CTRL_RESULT=
case $# in
1) CTRL_RESULT="$( "${DUT_CONTROL_CMD[@]}" \
"${DUT_CTRL_PREFIX}$*" )"
if [[ -n "${CTRL_RESULT}" ]]; then
# Don't save the control with the prefix, because
# dut_control will add the prefix again when we restore
# the settings.
save=( "${CTRL_RESULT#"${DUT_CTRL_PREFIX}"}" "${save[@]}" )
fi
;;
2) save=( "$1:$2" "${save[@]}" )
;;
*) die "${FUNCNAME[0]} failed: arguments error"
;;
esac
}
function servo_save() {
servo_save_add "cold_reset"
if [[ "${SERVO_TYPE}" == "servo_v2" ]]; then
servo_save_add "i2c_mux_en"
servo_save_add "i2c_mux"
dut_control i2c_mux_en:on
dut_control i2c_mux:remote_adc
fi
}
function servo_restore() {
info "Restoring servo settings..."
for ctrl in "${save[@]}"; do
if [[ -n "${ctrl}" ]]; then
dut_control "${ctrl}"
fi
done
}
function claim_pty() {
if grep -q cros_sdk /proc/1/cmdline; then
warn "You might want to run this tool in a chroot that was" \
"entered with 'cros_sdk --no-ns-pid'" \
"(see crbug.com/444931 for details)"
fi
if [[ -z "$1" ]]; then
warn "No parameter passed to claim_pty()"
return
fi
# Disconnect the EC-3PO interpreter from the UART since it will
# interfere with flashing.
servo_save_add "${MCU}_ec3po_interp_connect"
dut_control "${MCU}_ec3po_interp_connect:off" || \
warn "hdctools cannot disconnect the EC-3PO interpreter from" \
"the UART."
pids=$(lsof -FR 2>/dev/null -- "$1" | grep -v '^f' | tr -d 'pR')
FROZEN_PIDS=""
# reverse order to SIGSTOP parents before children
for pid in $(echo "${pids}" | tac -s " "); do
# shellcheck disable=SC2009
if ps -o cmd= "${pid}" | grep -qE "(servod|/sbin/init)"; then
info "Skip stopping servod or init: process ${pid}."
else
info "Sending SIGSTOP to process ${pid}!"
FROZEN_PIDS+=" ${pid}"
sleep 0.02
kill -STOP "${pid}"
fi
done
}
# Returns if get_serial used CCD.
function get_serial_is_ccd() {
if [[ "${SERVO_TYPE}" =~ ^servo_v4(p1)?_with_servo_micro ]]; then
false
elif [[ "${SERVO_TYPE}" =~ ^servo_v4(p1)?_with_c2d2 ]]; then
false
elif [[ "${SERVO_TYPE}" =~ "_with_ccd" ]] ; then
true
else
false
fi
}
# Returns the serialnumber of the specified servo.
function get_serial() {
if [[ "${SERVO_TYPE}" =~ ^servo_v4(p1)?_with_servo_micro ]]; then
if [[ -z "${BOARD}" ]]; then
sn_ctl="servo_micro_"
elif [[ "$(dut_control_get "servo_micro_for_${BOARD}_serialname")" =~ \
"unknown" ]] ; then
# Fall back to servo_micro_ if S/N is uknown.
sn_ctl="servo_micro_"
else
sn_ctl="servo_micro_for_${BOARD}_"
fi
elif [[ "${SERVO_TYPE}" =~ ^servo_v4(p1)?_with_c2d2 ]]; then
if [[ -z "${BOARD}" ]]; then
sn_ctl="c2d2_"
elif [[ "$(dut_control_get "c2d2_for_${BOARD}_serialname")" =~ \
"unknown" ]] ; then
# Fall back to c2d2_ if S/N is uknown.
sn_ctl="c2d2_"
else
sn_ctl="c2d2_for_${BOARD}_"
fi
elif [[ "${SERVO_TYPE}" =~ "_with_ccd" ]] ; then
sn_ctl="ccd_"
else
# If it's none of the above, the main serialname will do.
sn_ctl=""
fi
dut_control_get "${sn_ctl}serialname"
}
function c2d2_wait_for_h1_power_on_or_reset() {
# Ensure we have the latest c2d2 fw and hdctools. This could
# be removed eventually (estimate removal 2020/06/01)
dut_control h1_vref_present || die "Need to kill servod and run:
repo sync && sudo emerge hdctools servo-firmware && sudo servo_updater -b c2d2"
# Handle the case when flash_ec starts before DUT power is
# applied. Otherwise just use h1-level reset.
if [[ "$(dut_control_get h1_vref_present)" = "off" ]] ; then
info "Please attach C2D2 to DUT and power DUT now!"
# Waits ~40 seconds for Vref presence before timeout
local LOOP_COUNTER=100
while [[ "$(dut_control_get h1_vref_present)" = "off" \
&& "${LOOP_COUNTER}" -gt 1 ]] ; do
sleep 0.1
(( LOOP_COUNTER=LOOP_COUNTER-1 ))
done
# If we ran out of time, then just die now
if [[ "${LOOP_COUNTER}" -eq 1 ]] ; then
die "H1 Vref not present after waiting"
fi
else
# Ensure DUT is in clean state with H1 Reset
dut_control cold_reset:on
dut_control cold_reset:off
fi
}
# Board specific flashing scripts
# helper function for using servo v2/3 with openocd
function flash_openocd() {
OCD_CFG="servo.cfg"
if [[ -z "${EC_DIR}" ]]; then
# check if we're on beaglebone
if [[ -e "/usr/share/ec-devutils" ]]; then
OCD_PATH="/usr/share/ec-devutils"
else
die "Cannot locate openocd configs"
fi
else
OCD_PATH="${EC_DIR}/util/openocd"
fi
servo_save_add "jtag_buf_on_flex_en"
servo_save_add "jtag_buf_en"
dut_control jtag_buf_on_flex_en:on
dut_control jtag_buf_en:on
print_or_run sudo timeout -k 10 -s 9 "${FLAGS_timeout}" \
openocd -s "${OCD_PATH}" -f "${OCD_CFG}" -f "${OCD_CHIP_CFG}" \
-c "${OCD_CMDS}" || \
die "Failed to program ${IMG}"
}
# helper function for using servo with flashrom
function flash_flashrom() {
TOOL_PATH="${EC_DIR}/build/${BOARD}/util:${PATH}:/usr/sbin"
FLASHROM=$(PATH="${TOOL_PATH}" which flashrom)
local TEMP_DIR
TEMP_DIR="$(mktemp -d --suffix="${TEMP_SUFFIX}")"
DELETE_LIST+=("${TEMP_DIR}")
if on_servov3; then
FLASHROM_ARGS="--programmer=linux_spi"
elif on_raiden; then
if [[ "${SERVO_TYPE}" =~ "servo_micro" ]]; then
# Servo micro doesn't use the "target" parameter.
FLASHROM_ARGS="--programmer=raiden_debug_spi:"
else
FLASHROM_ARGS="--programmer=raiden_debug_spi:target=EC,"
fi
else
FLASHROM_ARGS="--programmer=ft2232_spi:type=google-servo-v2,port=B,"
fi
if [ ! -x "${FLASHROM}" ]; then
die "no flashrom util found."
fi
if ! on_servov3; then
SERIALNAME=$(get_serial)
if [[ "${SERIALNAME}" != "" ]] ; then
FLASHROM_ARGS+="serial=${SERIALNAME}"
fi
fi
# Eventually remove ite_spi_ccd_i2c once all references are removed
if ! on_raiden || [[ "${SERVO_TYPE}" =~ "servo_micro" ]] ; then
if in_array "${BOARDS_SPI_1800MV[@]}" "${BOARD}"; then
SPI_VOLTAGE="pp1800"
elif [[ "${CHIP}" == "ite_spi" ||
"${CHIP}" == "ite_spi_ccd_i2c" ||
"${CHIP}" == "it8xxx2" ]]; then
SPI_VOLTAGE="pp1800"
else
SPI_VOLTAGE="pp3300"
fi
dut_control cold_reset:on
# If spi flash is in npcx's ec, enable gang programer mode
if [[ "${CHIP}" == "npcx_int_spi" ]]; then
servo_save_add "fw_up" "off"
# Set GP_SEL# as low then start ec
dut_control fw_up:on
sleep 0.2
if ! in_array "${BOARDS_HOLD_COLD_RESET_DBG_HDR[@]}" "${BOARD}"; then
dut_control cold_reset:off
fi
# Gang programmer mode for npcx_spi requires using dev_mode
# rather than fw_up
elif [[ "${CHIP}" == "npcx_spi" ]]; then
servo_save_add "dev_mode" "off"
dut_control dev_mode:on
sleep 0.2
if ! in_array "${BOARDS_HOLD_COLD_RESET_DBG_HDR[@]}" "${BOARD}"; then
dut_control cold_reset:off
fi
fi
# Enable SPI programming mode.
if [[ "${CHIP}" == "ite_spi" ||
"${CHIP}" == "ite_spi_ccd_i2c" ||
"${CHIP}" == "it8xxx2" ]]; then
# Set hardware strap pin (GPG6) of SPI
# programming as low then start ec
dut_control fw_up:on
sleep 0.1
dut_control cold_reset:off
sleep 0.2
# We have to release the HW strap pin
# because it also SPI clock pin.
dut_control fw_up:off
fi
servo_save_add "spi1_vref" "off"
servo_save_add "spi1_buf_en" "off"
# Turn on SPI1 interface on servo for SPI Flash Chip
dut_control "spi1_vref:${SPI_VOLTAGE}" spi1_buf_en:on
if [[ ! "${SERVO_TYPE}" =~ "servo_micro" ]]; then
# Servo micro doesn't support this control.
servo_save_add "spi1_buf_on_flex_en" "off"
dut_control spi1_buf_on_flex_en:on
fi
else
if [[ "${CHIP}" == "npcx_int_spi" ]]; then
servo_save_add "fw_up" "off"
# Set GP_SEL# as low then start ec
dut_control cold_reset:on
dut_control fw_up:on
sleep 0.2
dut_control cold_reset:off
else
# Assert EC reset.
dut_control cold_reset:on
fi
# Temp layout
L=/tmp/flash_spi_layout_$$
DELETE_LIST+=( "${L}" )
[[ -z "${FLAGS_read}" ]] && dump_fmap -F "${IMG}" > "${L}"
FLASHROM_OPTIONS=(-i EC_RW -i WP_RO -l "${L}" --noverify-all)
fi
# Generate the correct flashrom command base.
# shellcheck disable=SC2206
FLASHROM_CMDLINE=("${FLASHROM}" ${FLASHROM_ARGS})
if [[ -z "${FLAGS_read}" ]]; then
# Program EC image.
# flashrom should report the image size at the end of the output.
local FLASHROM_GETSIZE=(sudo "${FLASHROM_CMDLINE[@]}" --flash-size)
if [[ "${FLAGS_verbose}" == "${FLAGS_TRUE}" ]]; then
info "Running flashrom:" 1>&2
echo " ${FLASHROM_GETSIZE[*]}" 1>&2
fi
SPI_SIZE=$("${FLASHROM_GETSIZE[@]}" | grep -oe '[0-9]\+$' |
tail -n1) || die "Failed to determine chip size!"
[[ ${SPI_SIZE} -eq 0 ]] && die "Chip size is 0!"
PATCH_SIZE=$(( SPI_SIZE - IMG_SIZE ))
# Temp image
T=/tmp/flash_spi_$$
DELETE_LIST+=( "${T}" )
if [[ "${CHIP}" =~ ^npcx(|_int)_spi$ ]] || \
[[ "${CHIP}" =~ "ite_spi_ccd_i2c" ]] ||
[[ "${CHIP}" =~ "it8xxx2" ]] ||
[[ "${CHIP}" =~ "ite_spi" ]] ; then
{ # Patch temp image up to SPI_SIZE
cat "${IMG}"
if [[ ${IMG_SIZE} -lt ${SPI_SIZE} ]] ; then
dd if=/dev/zero bs="${PATCH_SIZE}" count=1 | \
tr '\0' '\377'
fi
} > "${T}"
else
{ # Patch temp image up to SPI_SIZE
if [[ ${IMG_SIZE} -lt ${SPI_SIZE} ]] ; then
dd if=/dev/zero bs="${PATCH_SIZE}" count=1 | \
tr '\0' '\377'
fi
cat "${IMG}"
} > "${T}"
fi
if [[ "${FLAGS_no_preserve}" == "${FLAGS_FALSE}" ]]; then
local IMG_CPY
IMG_CPY="${TEMP_DIR}/ec.new.cpy.bin"
cat "${T}" > "${IMG_CPY}"
T="${IMG_CPY}"
preserve_sections "spi" "${T}" "${TEMP_DIR}" \
"${FLASHROM}" "${FLASHROM_ARGS}" || die "${MSG_PROGRAM_FAIL}"
fi
info "Programming EC firmware image."
local FLASHROM_WRITE=("${FLASHROM_CMDLINE[@]}" "${FLASHROM_OPTIONS[@]}")
if [[ "${FLAGS_verbose}" == "${FLAGS_TRUE}" ]]; then
info "Running flashrom:" 1>&2
fi
print_or_run sudo timeout -k 10 -s 9 "${FLAGS_timeout}" \
"${FLASHROM_WRITE[@]}" -w "${T}" \
|| die "${MSG_PROGRAM_FAIL}"
else
# Read EC image.
info "Reading EC firmware image."
if [[ "${FLAGS_verbose}" == "${FLAGS_TRUE}" ]]; then
info "Running flashrom:" 1>&2
fi
print_or_run sudo timeout -k 10 -s 9 "${FLAGS_timeout}" \
"${FLASHROM_CMDLINE[@]}" -r "${FLAGS_read}" \
|| die "${MSG_READ_FAIL}"
fi
}
function flash_stm32() {
local STM32MON
local STM32MON_OPT=()
if ! servo_has_cold_reset; then
die "Cold reset must be available for STM32 programming"
fi
TOOL_PATH="${EC_DIR}/build/${BOARD}/util:${PATH}"
STM32MON=$(PATH="${TOOL_PATH}" which stm32mon)
EC_UART="$(servo_ec_uart)"
EC_UART_PREFIX="$(servo_ec_uart_prefix)"
if [ ! -x "${STM32MON}" ]; then
die "no stm32mon util found."
fi
info "Using serial flasher : ${STM32MON}"
info "${MCU} UART pty : ${EC_UART}"
claim_pty "${EC_UART}"
STM32MON_OPT+=(-d "${EC_UART}")
# Make sure EC reboots in serial monitor mode.
ec_enable_boot0 "bitbang"
# Pulse EC reset.
ec_reset
if ! on_raiden && [[ "${SERVO_TYPE}" =~ "servo" ]] ; then
servo_save_add "${EC_UART_PREFIX}_en"
dut_control "${EC_UART_PREFIX}_en:on"
fi
servo_save_add "${EC_UART_PREFIX}_parity"
dut_control "${EC_UART_PREFIX}_parity:even"
if servo_is_ccd ; then
case "${FLAGS_bitbang_rate}" in
(9600|19200|38400|57600) : ;;
(*)
die "${FLAGS_bitbang_rate} is not a valid" \
"bit bang rate"
;;
esac
info "Programming at ${FLAGS_bitbang_rate} baud"
servo_save_add "${EC_UART_PREFIX}_baudrate"
servo_save_add "${EC_UART_PREFIX}_bitbang_en"
dut_control "${EC_UART_PREFIX}_baudrate:${FLAGS_bitbang_rate}"
dut_control "${EC_UART_PREFIX}_bitbang_en:on"
else
servo_save_add "${EC_UART_PREFIX}_baudrate"
dut_control "${EC_UART_PREFIX}_baudrate:115200"
fi
# Add a delay long enough for cr50 to update the ccdstate. Cr50 updates
# ccdstate once a second, so a 2 second delay should be safe.
if servo_is_ccd ; then
sleep 2
STM32MON_OPT+=(-c)
fi
if [ -n "${FLAGS_logfile}" ]; then
info "Saving log in ${FLAGS_logfile}"
STM32MON_OPT+=(-L "${FLAGS_logfile}")
fi
local IMG_READ="${FLAGS_read}"
# Program EC image.
if [[ -z "${IMG_READ}" ]]; then
info "Programming EC firmware image."
# Unprotect flash, erase, and write
local STM32MON_COMMAND=("${STM32MON}" "${STM32MON_OPT[@]}" -U -u -e -w)
print_or_run timeout -k 10 -s 9 "${FLAGS_timeout}" \
"${STM32MON_COMMAND[@]}" "${IMG}" \
|| die "${MSG_PROGRAM_FAIL}"
# If it is a program-verify request, then make a temporary
# directory to store the image
if [[ "${FLAGS_verify}" == "${FLAGS_TRUE}" ]]; then
local TEMP_SUFFIX
local TEMP_DIR
TEMP_SUFFIX=".$(basename "${SCRIPT}").${CHIP}"
TEMP_DIR="$(mktemp -d --suffix="${TEMP_SUFFIX}")"
IMG_READ="${TEMP_DIR}/ec.read.bin"
DELETE_LIST+=( "${TEMP_DIR}" )
fi
fi
# Read EC image.
if [[ -n "${IMG_READ}" ]]; then
info "Reading EC firmware image."
local STM32MON_READ_CMD=("${STM32MON}" "${STM32MON_OPT[@]}" -U -r)
print_or_run timeout -k 10 -s 9 "${FLAGS_timeout}" \
"${STM32MON_READ_CMD[@]}" "${IMG_READ}" \
|| die "${MSG_READ_FAIL}"
fi
# Verify the flash by comparing the source image to the read image,
# only if it was a flash write request.
if [[ -z "${FLAGS_read}" && "${FLAGS_verify}" == "${FLAGS_TRUE}" ]]; then
info "Verifying EC firmware image."
if [[ "${FLAGS_verbose}" == "${FLAGS_TRUE}" ]]; then
echo "cmp -n ${IMG_SIZE} ${IMG} ${IMG_READ}"
fi
cmp -s -n "${IMG_SIZE}" "${IMG}" "${IMG_READ}" \
|| die "${MSG_VERIFY_FAIL}"
fi
# Remove the Application processor reset
# TODO(crosbug.com/p/30738): we cannot rely on servo_VARS to restore it
if servo_has_warm_reset; then
dut_control warm_reset:off
fi
}
function flash_stm32_dfu() {
DFU_DEVICE=0483:df11
ADDR=0x08000000
DFU_UTIL='dfu-util'
which "${DFU_UTIL}" &> /dev/null || die \
"no dfu-util util found. Did you 'sudo emerge dfu-util'"
info "Using dfu flasher : ${DFU_UTIL}"
dev_cnt=$(lsusb -d "${DFU_DEVICE}" | wc -l)
if [ "${dev_cnt}" -eq 0 ] ; then
die "unable to locate dfu device at ${DFU_DEVICE}"
elif [ "${dev_cnt}" -ne 1 ] ; then
die "too many dfu devices (${dev_cnt}). Disconnect all but one."
fi
SIZE=$(wc -c "${IMG}" | cut -d' ' -f1)
# Remove read protection
print_or_run sudo timeout -k 10 -s 9 "${FLAGS_timeout}" "${DFU_UTIL}" -a 0 \
-d "${DFU_DEVICE}" -s "${ADDR}:${SIZE}:force:unprotect" -D "${IMG}"
# Wait for mass-erase and reboot after unprotection
print_or_run sleep 1
# Actual image flashing
print_or_run sudo timeout -k 10 -s 9 "${FLAGS_timeout}" "${DFU_UTIL}" -a 0 \
-d "${DFU_DEVICE}" -s "${ADDR}:${SIZE}" -D "${IMG}"
}
function ite_dfu_mode() {
# Send the special waveform to the ITE EC.
if [[ "${SERVO_TYPE}" =~ "servo_micro" || \
"${SERVO_TYPE}" =~ "c2d2" ]] ; then
info "Asking servo to send the dbgr special waveform to ${CHIP}"
sleep 3
dut_control_or_die enable_ite_dfu
elif servo_is_ccd; then
local CCD_I2C_CAP
CCD_I2C_CAP="$(dut_control_get ccd_i2c_en)"
if [[ "${CCD_I2C_CAP,,}" != "always" ]]; then
die "CCD I2C capability is not set as 'Always'" \
": ${CCD_I2C_CAP}"
fi
info "Asking CR50 to send the dbgr special waveform to ${CHIP}"
sleep 2
dut_control_or_die cr50_i2c_ctrl:ite_debugger_mode
sleep 3
elif [[ "${SERVO_TYPE}" == "servo_v2" ]]; then
info "Closing servod connection to ftdi_i2c interface"
dut_control_or_die ftdii2c_cmd:close
else
die "This servo type is not yet supported: ${SERVO_TYPE}"
fi
}
function flash_it83xx() {
local TOOL_PATH="${EC_DIR}/build/host/util:${PATH}"
local ITEFLASH_BIN
local TEMP_DIR
ITEFLASH_BIN=$(PATH="${TOOL_PATH}" which iteflash)
TEMP_DIR="$(mktemp -d --suffix="${TEMP_SUFFIX}")"
DELETE_LIST+=("${TEMP_DIR}")
if [[ ! -x "${ITEFLASH_BIN}" ]]; then
die "no iteflash util found."
fi
# We need to ensure that c2d2 and dut-side path are set up for i2c
if [[ "${SERVO_TYPE}" =~ "c2d2" ]]; then
c2d2_wait_for_h1_power_on_or_reset
# Don't let the EC come out of reset after H1 reset
dut_control gsc_ec_reset:on
# Enable i2c bus on C2D2 at 400kbps
servo_save_add "i2c_ec_bus_speed"
dut_control_or_die i2c_ec_bus_speed:400
# We need to swing the DUT-side muxes to I2C instead of UART.
# This is done by convention with EC_FLASH_SELECT pin of the
# GSC. Also make sure that the setting is restored after
# completion.
servo_save_add "ec_flash_select" "off"
dut_control_or_die ec_flash_select:on
fi
# Now the we have enabled the I2C mux on the servo to talk to the dut,
# we need to switch the I2C mux on the dut to allow ec programing (if
# there is a mux on the dut)
if servo_has_dut_i2c_mux; then
info "Switching DUT I2C Mux to ${CHIP}"
servo_save_add "dut_i2c_mux"
dut_control dut_i2c_mux:ec_prog
fi
# The board overlay defines "dut_i2c_en" if there is a signal that
# must be asserted to access the I2C programming pins on the dut.
if servo_has_dut_i2c_en; then
info "Enabling I2C programming to ${CHIP}"
servo_save_add "dut_i2c_en"
dut_control dut_i2c_en:on
fi
# We need to send the special waveform very soon after the EC powers on
if [[ "${SERVO_TYPE}" =~ "c2d2" ]]; then
# The EC was held in reset above
dut_control gsc_ec_reset:off
else
servo_ec_hard_reset_or_die
fi
ite_dfu_mode
# Build the iteflash command line.
local ITEFLASH_ARGS=( "${ITEFLASH_BIN}" )
if [[ "${SERVO_TYPE}" == "servo_v2" ]]; then
ITEFLASH_ARGS+=( "--send-waveform=1" "--i2c-interface=ftdi" )
else
ITEFLASH_ARGS+=( "--send-waveform=0" "--i2c-interface=usb" \
"-s" "$(get_serial)" )
if get_serial_is_ccd; then
ITEFLASH_ARGS+=( "--block-write-size=256" )
fi
fi
if [[ "${FLAGS_no_preserve}" == "${FLAGS_FALSE}" && \
-z "${FLAGS_read}" ]]; then
local IMG_CPY
IMG_CPY="${TEMP_DIR}/ec.new.cpy.bin"
cat "${IMG}" > "${IMG_CPY}"
IMG="${IMG_CPY}"
preserve_sections "ite_i2c" "${IMG}" "${TEMP_DIR}" \
"${ITEFLASH_ARGS[@]}" || die "${MSG_PROGRAM_FAIL}"
fi
local ERROR_MSG
if [[ -n "${FLAGS_read}" ]]; then
ITEFLASH_ARGS+=( "--read=${FLAGS_read}" )
info "Reading EC firmware image using iteflash..."
ERROR_MSG="${MSG_READ_FAIL}"
else
ITEFLASH_ARGS+=( "--erase" "--write=${IMG}" )
info "Programming EC firmware image using iteflash..."
ERROR_MSG="${MSG_PROGRAM_FAIL}"
fi
if [[ "${FLAGS_verify}" == "${FLAGS_FALSE}" ]]; then
ITEFLASH_ARGS+=( "--noverify" )
fi
if [[ "${FLAGS_verbose}" == "${FLAGS_TRUE}" ]]; then
ITEFLASH_ARGS+=( "--debug" )
fi
# Ensure the CR50 doesn't go into low power while flashing
# otherwise the DUT side muxes will get cut. Note this also needs to
# happen once the CR50 hooks have settled and H1 realizes that the
# "AP [is] Off", since that over writes the idle action with sleep.
if [[ "${SERVO_TYPE}" =~ "c2d2" ]]; then
dut_control cr50_idle_level:active
fi
print_or_run "${ITEFLASH_ARGS[@]}" || die "${ERROR_MSG}"
}
# Alias for flashing ITE chips over I2C from all servo types.
function flash_ite_i2c() {
flash_it83xx
}
# Alias for flashing ITE chips over SPI from all servo types.
function flash_ite_spi() {
flash_flashrom
}
# Flash ITE chips over SPI when using the servod debug connector
# and over I2C whn using CCD.
function flash_ite_spi_ccd_i2c() {
if [[ "${SERVO_TYPE}" =~ "servo_micro" || \
"${SERVO_TYPE}" =~ "servo_v2" ]] ; then
flash_flashrom
else
flash_it83xx
fi
}
# Flash ITE chips over SPI when using the servod debug connector
# and over I2C whn using CCD.
function flash_it8xxx2() {
flash_ite_spi_ccd_i2c
}
function flash_npcx_jtag() {
IMG_PATH="${EC_DIR}/build/${BOARD}"
OCD_CHIP_CFG="npcx_chip.cfg"
if [ "${FLAGS_ro}" = "${FLAGS_TRUE}" ] ; then
# Program RO region only
OCD_CMDS="init; flash_npcx_ro ${CHIP} ${IMG_PATH} ${FLAGS_offset}; shutdown;"
else
# Program all EC regions
OCD_CMDS="init; flash_npcx_all ${CHIP} ${IMG_PATH} ${FLAGS_offset}; shutdown;"
fi
# Reset the EC
ec_reset
flash_openocd
}
function flash_npcx_uut() {
local NPCX_UUT
local EC_UART
local TEMP_SUFFIX
local TEMP_DIR
local TOOL_PATH="${EC_DIR}/build/${BOARD}/util:${PATH}"
set +e
NPCX_UUT=$(PATH="${TOOL_PATH}" which uartupdatetool)
set -e
EC_UART="$(servo_ec_uart)"
TEMP_SUFFIX=".$(basename "${SCRIPT}").${CHIP}.$$"
TEMP_DIR="$(mktemp -d --suffix="${TEMP_SUFFIX}")"
DELETE_LIST+=("${TEMP_DIR}")
# Look for npcx_monitor.bin in multiple directories, starting with
# the same path as the EC binary.
local MON=""
for dir in \
"$(dirname "${IMG}")/chip/npcx/spiflashfw" \
"$(dirname "${IMG}")" \
"${EC_DIR}/build/${BOARD}/chip/npcx/spiflashfw" \
"${EC_DIR}/build/zephyr/${BOARD}/output" \
"$(dirname "${LOCAL_BUILD}")" \
"$(dirname "${EMERGE_BUILD}")" ;
do
if [ -f "${dir}/npcx_monitor.bin" ] ; then
MON="${dir}/npcx_monitor.bin"
break
fi
done
if [ -z "${MON}" ] ; then
echo "Failed to find npcx_monitor.bin"
exit 1
fi
info "Using NPCX image : ${MON}"
# The start address to restore monitor firmware binary
local MON_ADDR="0x200C3020"
if [ ! -x "${NPCX_UUT}" ]; then
die "no NPCX UART Update Tool found."
fi
info "Using: NPCX UART Update Tool"
info "${MCU} UART pty : ${EC_UART}"
claim_pty "${EC_UART}"
if [[ "${SERVO_TYPE}" =~ "ccd_cr50" ]] ; then
# Ti50 does not yet support ccd_keepalive option which
# requires ccdstate command on the GSC console.
# TODO(b/161483597) remove the check when Ti50 CCD is on par.
servo_save_add ccd_keepalive_en
dut_control ccd_keepalive_en:on
fi
# C2D2 does not use waits and has to ensure that the EC does not come
# out of reset after using a H1-level reset
if [[ "${SERVO_TYPE}" =~ "c2d2" ]] ; then
c2d2_wait_for_h1_power_on_or_reset
# Don't let the EC come out of reset after H1 reset
dut_control gsc_ec_reset:on
# Force the EC to boot in UART update mode coming out of reset
ec_enable_boot0 "uut"
dut_control gsc_ec_reset:off
# Ensure normal UART operation
ec_disable_boot0 "uut"
else
# Force the EC to boot in UART update mode
ec_enable_boot0 "uut"
ec_reset
# Have to wait a bit for EC boot-up
print_or_run sleep 0.1
# Ensure normal UART operation
ec_disable_boot0 "uut"
print_or_run sleep 0.1
fi
# Remove the prefix "/dev/" because uartupdatetool will add it.
local UUT_ARGS=( "--port=${EC_UART#/dev/}" " --baudrate=115200" )
local IMG_READ="${FLAGS_read}"
# Program EC image.
if [[ -z "${IMG_READ}" ]]; then
info "Loading monitor binary."
local UUT_MON=( "${NPCX_UUT}" "${UUT_ARGS[@]}" \
"--opr=wr" "--addr=${MON_ADDR}" \
"--file=${MON}" )
# Load monitor binary to address 0x200C3020
local monitor_res=0
print_or_run timeout -k 10 -s 9 "${FLAGS_timeout}" \
"${UUT_MON[@]}" || monitor_res=$?
if [[ ${monitor_res} != 0 ]]; then
# Try to determine if WP is enabled
local dut_res=0
local wp_state
wp_state=$(dut-control fw_wp_state) || dut_res=$?
if [[ ${dut_res} = 0 ]]; then
if echo "${wp_state}" | grep "on"; then
die "Failed to load monitor binary, WP is enabled"
fi
fi
die "Failed to load monitor binary."
fi
if [[ "${FLAGS_no_preserve}" == "${FLAGS_FALSE}" ]]; then
local IMG_CPY
IMG_CPY="${TEMP_DIR}/ec.new.cpy.bin"
cat "${IMG}" > "${IMG_CPY}"
IMG="${IMG_CPY}"
preserve_sections "${CHIP}" "${IMG}" "${TEMP_DIR}" \
"${NPCX_UUT}" "${UUT_ARGS[@]}" || die "${MSG_PROGRAM_FAIL}"
fi
info "Programming EC firmware image."
local UUT_WR=( "${NPCX_UUT}" "${UUT_ARGS[@]}" \
"--auto" "--offset=${FLAGS_offset}" \
"--file=${IMG}" )
print_or_run timeout -k 10 -s 9 "${FLAGS_timeout}" \
"${UUT_WR[@]}" || die "${MSG_PROGRAM_FAIL}"
# If it is a program-verify request, then make a temporary
# directory to store the image.
if [[ "${FLAGS_verify}" == "${FLAGS_TRUE}" ]]; then
IMG_READ="${TEMP_DIR}/ec.read.bin"
fi
fi
# Read EC image.
if [[ -n "${IMG_READ}" ]]; then
info "Reading EC firmware image."
local UUT_RD=( "${NPCX_UUT}" "${UUT_ARGS[@]}" \
"--read-flash" "--file=${IMG_READ}" )
print_or_run timeout -k 10 -s 9 "${FLAGS_timeout}" \
"${UUT_RD[@]}" || die "${MSG_READ_FAIL}"
fi
# Verify the flash by comparing the source image to the read image,
# only if it was a flash write request.
if [[ -z "${FLAGS_read}" && "${FLAGS_verify}" == "${FLAGS_TRUE}" ]]; then
info "Verifying EC firmware image."
print_or_run cmp -s -n "${IMG_SIZE}" "${IMG}" "${IMG_READ}" \
|| die "${MSG_VERIFY_FAIL}"
fi
}
function flash_npcx_5m5g_jtag() {
flash_npcx_jtag
}
function flash_npcx_5m6g_jtag() {
flash_npcx_jtag
}
function flash_npcx_7m6x_jtag() {
flash_npcx_jtag
}
function flash_npcx_7m7x_jtag() {
flash_npcx_jtag
}
function flash_npcx_spi() {
flash_flashrom
}
function flash_npcx_int_spi() {
flash_flashrom
}
function flash_mchp_int_spi() {
EC_UART="$(servo_ec_uart)"
EC_UART_PREFIX="$(servo_ec_uart_prefix)"
MCHP_DIR="${EC_DIR}/util/mchp"
# Gather the image information before changing the UART settings
MCHP_LOADER=$(mchp_loader_image)
EC_IMAGE=$(ec_image)
# Store the EC UART interpreter status
ec_ec3po_interp="$(dut_control_get ec_ec3po_interp_connect)"
servo_save_add "ec_ec3po_interp_connect" "${ec_ec3po_interp}"
# Disable the EC UART interpreter
dut_control ec_ec3po_interp_connect:off
# Use of --value_only argument helps to get only baudrate value.
current_baudrate="$(dut_control_get "${EC_UART_PREFIX}"_baudrate)"
# On script exit, serial port will be configured back with saved
# baudrate by servo_restore thru cleanup method
servo_save_add "${EC_UART_PREFIX}_baudrate" "${current_baudrate}"
# Reset chip in firmware update mode
dut_control cold_reset:on fw_up:on cold_reset:off
# Set 9600 baudrate to program Second loader image
sec_load_baudrate=9600
if [ "${current_baudrate}" != "${sec_load_baudrate}" ] ; then
dut_control "${EC_UART_PREFIX}"_baudrate:"${sec_load_baudrate}"
fi
# Load Second loader image into SRAM
"${MCHP_DIR}"/crisis_rcvry_util.py -s "${MCHP_LOADER}" -p "${EC_UART}"
# Set 57600 baudrate to program EC image
image_load_baudrate=57600
dut_control "${EC_UART_PREFIX}"_baudrate:"${image_load_baudrate}"
# Flash EC image into the internal flash
"${MCHP_DIR}"/crisis_rcvry_util.py -e "${EC_IMAGE}" -p "${EC_UART}"
# Reset chip in firmware execution mode
dut_control cold_reset:on fw_up:off cold_reset:off
# Restore the EC UART interpreter back
dut_control ec_ec3po_interp_connect:"${ec_ec3po_interp}"
}
info "Using ${SERVO_TYPE}."
# Only if it is a flash program request, call ec_image.
if [[ -z "${FLAGS_read}" ]]; then
IMG="$(ec_image)"
info "Using ${MCU} image : ${IMG}"
IMG_SIZE=$(stat -c%s "${IMG}")
fi
if [ "${NEED_SERVO}" != "no" ] ; then
servo_save
fi
function preserve_sections() {
local CHIP_TYPE
local NEW_IMG
local TEMP_DIR
local CHIP_CMD_PREFIX
CHIP_TYPE=${1:?"missing arg 1: Chip type"}
shift
NEW_IMG=${1:?"missing arg 2: New EC image path"}
NEW_IMG=$(readlink -f "${NEW_IMG}")
shift
TEMP_DIR=${1:?"missing arg 3: Temp directory path"}
shift
CHIP_CMD_PREFIX=("$@")
(
cd "${TEMP_DIR}"
local NEW_FMAP
local NEW_FMAP_OFFSET
local NEW_FMAP_SIZE
local CUR_FMAP_IMG
local CUR_IMG
local CUR_FMAP_HEADER
NEW_FMAP=$(dump_fmap "${NEW_IMG}" -e FMAP)
NEW_FMAP_NFIELD=$(echo "${NEW_FMAP}" | awk '{print NF}')
if [ "${NEW_FMAP_NFIELD}" -ne 4 ]; then
die "The output of dump_fmap is not expected; try update_chroot"
fi
NEW_FMAP_OFFSET=$(echo "${NEW_FMAP}" | awk '{print $2}')
NEW_FMAP_SIZE=$(echo "${NEW_FMAP}" | awk '{print $3}')
CUR_FMAP_IMG="${TEMP_DIR}/ec.cur.fmap.bin"
CUR_IMG="${TEMP_DIR}/ec.cur.bin"
info "Reading FMAP section from EC chip"
read_chip_partially "${CHIP_TYPE}" "${NEW_FMAP_OFFSET}" \
"${NEW_FMAP_SIZE}" "${CUR_FMAP_IMG}" "FMAP" \
"${CHIP_CMD_PREFIX[@]}"
# Verify the partial file starts with the correct FMAP header.
# If the FMAP has moved between the current image and new
# image, this should catch this.
# bash can't store NUL characters into variables so strip
# any read from the file.
CUR_FMAP_HEADER=$(head -c 8 "${CUR_FMAP_IMG}" | tr -d '\0')
if [[ "${CUR_FMAP_HEADER}" != "__FMAP__" ]]; then
info "FMAP section read failed, reading complete image"
read_chip "${CHIP_TYPE}" "${CUR_IMG}" "${CHIP_CMD_PREFIX[@]}"
check_preserve_sections_not_present "${CUR_IMG}" \
"${NEW_IMG}" "${TEMP_DIR}" || die
preserve_sections_with_cur_image "${CUR_IMG}" "${NEW_IMG}" "${TEMP_DIR}"
else
info "FMAP read is successful from EC flash"
check_preserve_sections_not_present "${CUR_FMAP_IMG}" \
"${NEW_IMG}" "${TEMP_DIR}" || die
preserve_sections_with_fmap_image "${CUR_FMAP_IMG}" \
"${NEW_IMG}" "${TEMP_DIR}" "${CHIP_TYPE}" \
"${CHIP_CMD_PREFIX[@]}"
fi
)
}
function check_preserve_sections_not_present() {
local CUR_IMG
local NEW_IMG
local TEMP_DIR
CUR_IMG=${1:?"missing arg 1: Cur EC image path"}
NEW_IMG=${2:?"missing arg 2: New EC image path"}
TEMP_DIR=${3:?"missing arg 3: Temp directory path"}
if ! dump_fmap "${CUR_IMG}" -e | grep -q ' preserve'; then
info "No sections are being preserved"
else
check_preserve_sections_presence "${CUR_IMG}" "${NEW_IMG}" "${TEMP_DIR}"
fi
}
function preserve_sections_with_fmap_image() {
local CUR_FMAP_IMG
local NEW_IMG
local TEMP_DIR
local CHIP_TYPE
local CHIP_CMD_PREFIX
CUR_FMAP_IMG=${1:?"missing arg 1: Cur EC FMAP image path"}
shift
NEW_IMG=${1:?"missing arg 2: New EC image path"}
shift
TEMP_DIR=${1:?"missing arg 3: Temp directory path"}
shift
CHIP_TYPE=${1:?"missing arg 4: Chip type"}
shift
CHIP_CMD_PREFIX=("$@")
(
cd "${TEMP_DIR}"
dump_fmap "${CUR_FMAP_IMG}" -e | grep ' preserve' | cut \
-f1 -d' ' |
while read -r line
do
local SEC_IMG
local SEC_FMAP_DUMP
local SEC_OFFSET
local SEC_SIZE
SEC_IMG="${TEMP_DIR}/ec.cur.${line}.bin"
SEC_FMAP_DUMP=$(dump_fmap "${CUR_FMAP_IMG}" -e "${line}")
SEC_OFFSET=$(echo "${SEC_FMAP_DUMP}" | awk '{print $2}')
SEC_SIZE=$(echo "${SEC_FMAP_DUMP}" | awk '{print $3}')
info "Reading ${line} section from EC chip"
read_chip_partially "${CHIP_TYPE}" \
"${SEC_OFFSET}" "${SEC_SIZE}" "${SEC_IMG}" "${line}" "${CHIP_CMD_PREFIX[@]}"
info "Preserving ${line} section in new image"
futility load_fmap "${NEW_IMG}" "${line}:${SEC_IMG}"
done
)
}
function preserve_sections_with_cur_image() {
local CUR_IMG
local NEW_IMG
local TEMP_DIR
CUR_IMG=${1:?"missing arg 1: Cur EC image path"}
NEW_IMG=${2:?"missing arg 2: New EC image path"}
TEMP_DIR=${3:?"missing arg 3: Temp directory path"}
(
cd "${TEMP_DIR}"
dump_fmap "${CUR_IMG}" -e | grep ' preserve' | cut \
-f1 -d' ' |
while read -r line
do
local SEC_IMG
info "Preserving ${line} section on EC chip"
SEC_IMG="${TEMP_DIR}/ec.cur.${line}.bin"
futility dump_fmap -x "${CUR_IMG}" "${line}"
mv "${line}" "${SEC_IMG}"
futility load_fmap "${NEW_IMG}" "${line}:${SEC_IMG}"
done
)
}
function read_chip_partially() {
local CHIP_TYPE
local OFFSET
local SIZE
local FILE_PATH
local SECTION
local CHIP_CMD_PREFIX
CHIP_TYPE=${1:?"missing arg 1: Chip type"}
shift
OFFSET=${1:?"missing arg 2: Offset"}
shift
SIZE=${1:?"missing arg 3: Size"}
shift
FILE_PATH=${1:?"missing arg 4: Image storage path"}
shift
SECTION=${1:?"missing arg 5: Section name"}
shift
CHIP_CMD_PREFIX=("$@")
if [ "${CHIP_TYPE}" = "npcx_uut" ]; then
local NPCX_BASE_ADDR
NPCX_BASE_ADDR=0x64000000
OFFSET=$(("${NPCX_BASE_ADDR}" + "${OFFSET}"))
UUT_CUR_FMAP_RD=( "${CHIP_CMD_PREFIX[@]}" "--opr=rd" \
"--addr=${OFFSET}" "--size=${SIZE}" \
"--file=${FILE_PATH}" )
print_or_run timeout -k 10 -s 9 "${FLAGS_timeout}" \
"${UUT_CUR_FMAP_RD[@]}" || die "${MSG_READ_FAIL}"
elif [ "${CHIP_TYPE}" == "ite_i2c" ]; then
local UUT_CUR_FMAP_RD
local ALIGNED_START SKIP_BYTES ALIGNED_SIZE RANGE ALIGNED_FILE
# ITE flash tool can start reads on a 256 byte page boundary
info "ITE partial read: offset ${OFFSET} size ${SIZE}"
ALIGNED_START=$((OFFSET & 0xFFFFFF00))
SKIP_BYTES=$((OFFSET - ALIGNED_START))
ALIGNED_SIZE=$((SIZE + SKIP_BYTES))
ALIGNED_FILE="${FILE_PATH}.aligned"
# --range requires hex representation
RANGE=$(printf '0x%x:0x%x' "${ALIGNED_START}" "${ALIGNED_SIZE}" )
info "ITE partial read range ${RANGE}"
UUT_CUR_FMAP_RD=( "${CHIP_CMD_PREFIX[@]}" \
"--read=${ALIGNED_FILE}" "--range=${RANGE}")
print_or_run timeout -k 10 -s 9 "${FLAGS_timeout}" \
"${UUT_CUR_FMAP_RD[@]}" || die "${MSG_READ_FAIL}"
if [[ "${ALIGNED_START}" != "${OFFSET}" ]]; then
local DD_CMD
# We had to read extra data from the DUT. Use dd
# to extract just the portion needed.
info "Extract ${SIZE} bytes from temp file"
DD_CMD=( "dd" "if=${ALIGNED_FILE}" "of=${FILE_PATH}" \
"skip=${SKIP_BYTES}" "count=${SIZE}" "bs=1" )
print_or_run "${DD_CMD[@]}"
else
# Extracted file has what we need
print_or_run mv "${ALIGNED_FILE}" "${FILE_PATH}"
fi
# Reset EC before setting DFU mode
servo_ec_hard_reset_or_die
# ITE DFU mode must be re-enabled after each operation
ite_dfu_mode
elif [ "${CHIP_TYPE}" == "spi" ]; then
local FLASHROM_FMAP_RD
FLASHROM_FMAP_RD=( "sudo" "${CHIP_CMD_PREFIX[@]}" \
"--extract" "--include=${SECTION}:${FILE_PATH}")
print_or_run timeout -k 10 -s 9 "${FLAGS_timeout}" \
"${FLASHROM_FMAP_RD[@]}" || die "${MSG_READ_FAIL}"
else
die "${MSG_CHIP_READ_INVALID}"
fi
}
function read_chip() {
local CHIP_TYPE
local FILE_PATH
local UUT_CUR_RD
local FLASHROM_RD
local CHIP_CMD_PREFIX
CHIP_TYPE=${1:?"missing arg 1: Chip type"}
shift
FILE_PATH=${1:?"missing arg 2: Image storage path"}
shift
CHIP_CMD_PREFIX=("$@")
if [ "${CHIP_TYPE}" = "npcx_uut" ]; then
UUT_CUR_RD=( "${CHIP_CMD_PREFIX[@]}" "--read-flash" "--file=${FILE_PATH}" )
print_or_run timeout -k 10 -s 9 "${FLAGS_timeout}" \
"${UUT_CUR_RD[@]}" || die "${MSG_READ_FAIL}"
elif [ "${CHIP_TYPE}" == "ite_i2c" ]; then
UUT_CUR_RD=( "${CHIP_CMD_PREFIX[@]}" "--read=${FILE_PATH}" )
print_or_run timeout -k 10 -s 9 "${FLAGS_timeout}" \
"${UUT_CUR_RD[@]}" || die "${MSG_READ_FAIL}"
# Reset EC before setting DFU mode
servo_ec_hard_reset_or_die
# ITE DFU mode must be re-enabled after each operation
ite_dfu_mode
elif [ "${CHIP_TYPE}" == "spi" ]; then
FLASHROM_RD=( "sudo" "${CHIP_CMD_PREFIX[@]}" "--read=${FILE_PATH}" )
print_or_run timeout -k 10 -s 9 "${FLAGS_timeout}" \
"${FLASHROM_RD[@]}" || die "${MSG_READ_FAIL}"
else
die "${MSG_CHIP_READ_INVALID}"
fi
}
function check_preserve_sections_presence() {
local CUR_IMG
local NEW_IMG
local TEMP_DIR
CUR_IMG=${1:?"missing arg 1: Cur EC image path"}
NEW_IMG=${2:?"missing arg 2: New EC image path"}
TEMP_DIR=${3:?"missing arg 3: Temp directory path"}
(
cd "${TEMP_DIR}"
dump_fmap "${CUR_IMG}" -e | grep ' preserve' | cut \
-f1 -d' ' |
while read -r line
do
if [[ -z "$(dump_fmap "${NEW_IMG}" -e "${line}")" ]]; then
die "New image don't contain the ${line} section"
fi
done
)
}
if [[ -n "${FLAGS_dut_ip}" ]] ; then
info "Updating token database"
load_token_db
fi
info "Flashing chip ${CHIP}."
flash_"${CHIP}"
info "Flashing done."