#!/bin/bash # Copyright (c) 2014 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. 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. . "/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 } BOARDS_IT83XX=( bip dragonegg glkrvp_ite it83xx_evb reef_it8320 ) BOARDS_LM4=( samus ) BOARDS_STM32=( big blaze chell_pd coffeecake elm glados_pd hammer jerry kitty kukui meowth_fp minimuffin nocturne_fp oak oak_pd pit plankton rainier samus_pd scarlet staff strago_pd wand whiskers zinger ) BOARDS_STM32_PROG_EN=( plankton ) BOARDS_STM32_DFU=( dingdong hoho twinkie discovery servo_v4 servo_micro sweetberry polyberry stm32f446e-eval tigertail ) 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=( coral eve fizz glkrvp lux nami nautilus poppy reef soraka ) BOARDS_NPCX_INT_SPI=( atlas bobba fleex grunt meep meowth nocturne phaser yorp zoombini ) BOARDS_NPCX_UUT=( cheza grunt ) BOARDS_NRF51=( hadoken ) BOARDS_MEC1322=( chell glados strago ) BOARDS_SPI_1800MV=( coral reef ) BOARDS_RAIDEN=( coral eve fizz kukui nami nautilus poppy reef scarlet soraka ) # A map of supported board + chip + servo permutations. # The value is a regex that will be checked against $SERVO_TYPE. # i.e., If a board needs to use one CHIP when connected via a Suzy-Q and another # chip when connected via a Servo. declare -A VALID_CHIP_COMBO VALID_CHIP_COMBO["grunt.npcx_uut"]="ccd_cr50" VALID_CHIP_COMBO["grunt.npcx_spi"]="servo" DEFAULT_PORT="${SERVOD_PORT:-9999}" BITBANG_RATE="9600" # 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 "${DEFAULT_BOARD}" \ "The board to run debugger on." DEFINE_string chip "" \ "The chip to run debugger on." DEFINE_string image "" \ "Full pathname of the EC firmware image to flash." 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_boolean ro "${FLAGS_FALSE}" \ "Write only the read-only partition" DEFINE_integer timeout 600 \ "Timeout for flashing the EC, measured in seconds." DEFINE_boolean verbose "${FLAGS_FALSE}" \ "Verbose hw control logging" # Parse command line FLAGS_HELP="usage: $0 [flags]" FLAGS "$@" || exit 1 eval set -- "${FLAGS_ARGV}" if [[ $# -gt 0 ]]; then die "invalid arguments: \"$*\"" fi set -e if [ -z "${FLAGS_board}" -a -z "${FLAGS_chip}" ]; then die "should specify a board or a chip." fi DUT_CONTROL_CMD="dut-control --port=${FLAGS_port}" function dut_control() { if [ "${FLAGS_verbose}" = ${FLAGS_TRUE} ]; then echo "$DUT_CONTROL_CMD $@" 1>&2 fi $DUT_CONTROL_CMD "$@" >/dev/null } function get_servo_type() { if dut_control "servo_type" ; then $DUT_CONTROL_CMD servo_type | sed -e s/servo_type:// fi } 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_LM4[@]}" "${BOARD}"); then SUPPORTED_CHIPS+=("lm4") fi 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_spi") fi if $(in_array "${BOARDS_NPCX_UUT[@]}" "${BOARD}"); then SUPPORTED_CHIPS+=("npcx_uut") fi if $(in_array "${BOARDS_NRF51[@]}" "${BOARD}"); then SUPPORTED_CHIPS+=("nrf51") fi if $(in_array "${BOARDS_MEC1322[@]}" "${BOARD}"); then SUPPORTED_CHIPS+=("mec1322") fi if $(in_array "${BOARDS_IT83XX[@]}" "${BOARD}"); then SUPPORTED_CHIPS+=("it83xx") fi if [[ ${#SUPPORTED_CHIPS[@]} -eq 0 && -n "${FLAGS_chip}" ]]; then SUPPORTED_CHIPS+="${FLAGS_chip}" fi SERVO_TYPE="$(get_servo_type)" if [[ ${#SUPPORTED_CHIPS[@]} -eq 0 ]]; then die "board '${BOARD}' not supported. Please 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 declare -a FILTERED_CHIPS for i in "${SUPPORTED_CHIPS[@]}"; do SUPPORTED_SERVO="${VALID_CHIP_COMBO["${BOARD}.${i}"]}" if [[ -z "$SUPPORTED_SERVO" || \ "$SERVO_TYPE" =~ "$SUPPORTED_SERVO" ]]; then FILTERED_CHIPS+=("$i") fi done if [[ ${#FILTERED_CHIPS[@]} -eq 0 ]]; then die "servo ${SERVO_TYPE} is unsupported for board ${BOARD}." elif [[ ${#FILTERED_CHIPS[@]} -eq 1 ]]; then CHIP="${FILTERED_CHIPS[0]}" else die "board ${BOARD} supports multiple chips" \ "(${FILTERED_CHIPS[@]}). Use --chip= to choose one." fi fi if [ -n "${FLAGS_chip}" -a "${CHIP}" != "${FLAGS_chip}" ]; then die "board ${BOARD} doesn't use chip ${FLAGS_chip}" fi if [ "${CHIP}" = "stm32_dfu" -o "${CHIP}" = "it83xx" ]; then NEED_SERVO="no" fi servo_has_warm_reset() { dut_control -i warm_reset >/dev/null 2>&1 } servo_has_cold_reset() { dut_control -i cold_reset >/dev/null 2>&1 } servo_has_dut_i2c_mux() { dut_control -i dut_i2c_mux >/dev/null 2>&1 } # reset the EC toad_ec_hard_reset() { if dut_control cold_reset 2>/dev/null ; then dut_control cold_reset:on dut_control cold_reset:off else info "you probably need to hard-reset your EC manually" fi } servo_ec_hard_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_sh_hard_reset() { dut_control sh_reset:on dut_control sh_reset:off } ccd_cr50_ec_hard_reset() { servo_ec_hard_reset } ec_reset() { stype=${SERVO_TYPE} if [[ "${SERVO_TYPE}" =~ "servo" ]] ; then stype=servo fi if [[ ! -z "${stype}" ]]; then eval ${stype}_${MCU}_hard_reset fi } # force the EC to boot in serial monitor mode toad_ec_boot0() { dut_control boot_mode:$1 } ccd_ec_boot0() { info "Using CCD $2." dut_control ccd_ec_boot_mode_$2:$1 } servo_ec_boot0() { dut_control ec_boot_mode:$1 } servo_usbpd_boot0() { dut_control usbpd_boot_mode:$1 } servo_sh_boot0() { dut_control sh_boot_mode:$1 } ec_switch_boot0() { on_value=$1 # Enable programming GPIOs if $(in_array "${BOARDS_STM32_PROG_EN[@]}" "${BOARD}"); then dut_control prog_en:yes fi if [[ "${SERVO_TYPE}" =~ "ccd_cr50" ]] ; then stype=ccd elif [[ "${SERVO_TYPE}" =~ "servo" ]] ; then stype=servo else stype=${SERVO_TYPE} if [[ "${SERVO_TYPE}" =~ "toad" ]] ; then if [[ "${on_value}" == "on" ]] ; then on_value="yes" else on_value="no" fi fi 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_TYPE}" =~ "ccd_cr50" ]] || \ [[ "${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 } # Put back the servo and the system in a clean state at exit FROZEN_PIDS="" cleanup() { if [ -n "${save}" ]; then info "Restoring servo settings..." servo_restore "$save" fi for pid in ${FROZEN_PIDS}; do info "Sending SIGCONT to process ${pid}!" kill -CONT ${pid} done if [ "${CHIP}" == "it83xx" ] ; then info "Reinitialize ftdi_i2c interface" dut_control ftdii2c_cmd:init dut_control ftdii2c_cmd:open dut_control ftdii2c_cmd:setclock # Reset the dut mux if it exists if $(servo_has_dut_i2c_mux); then # Ensure servo i2c mux is on so we can talk to dut dut_control i2c_mux_en:on dut_control i2c_mux:remote_adc # Turn off dut i2c mux dut_control dut_i2c_mux:none # Turn off servo i2c mux dut_control i2c_mux_en:off fi fi if [ "${CHIP}" == "stm32" -o "${CHIP}" == "npcx_uut" ] ; then # Reconnect the EC-3PO interpreter to the UART. dut_control ${MCU}_ec3po_interp_connect:on || \ warn "hdctools cannot reconnect the EC-3PO interpreter to" \ "the UART." dut_control ${MCU}_boot_mode:off fi if [[ "${SERVO_TYPE}" =~ "ccd_cr50" ]] ; then dut_control ccd_ec_boot_mode_uut:off dut_control ccd_ec_boot_mode_bitbang:off dut_control ${MCU}_uart_bitbang_en:off fi if ! on_raiden || $(servo_has_cold_reset); then ec_reset fi } trap cleanup EXIT # 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}" else LOCAL_BUILD="${EC_DIR}/build/${BOARD}/${EC_FILE}" fi fi # Get baseboard from build system if present BASEBOARD= if [[ -n "${EC_DIR}" ]]; then BASEBOARD=$(make --quiet -C ${EC_DIR} BOARD=${BOARD} print-baseboard) elif [[ -d "${HOME}/trunk/src/platform/ec" ]]; then BASEBOARD=$(make --quiet -C ${HOME}/trunk/src/platform/ec \ BOARD=${BOARD} print-baseboard) else info "Could not find ec build folder to calculate baseboard." fi 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 [ -f "${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." } # Find the EC UART provided by servo. function servo_ec_uart() { SERVOD_FAIL="Cannot communicate with servod. Is servod running?" PTY=$(($DUT_CONTROL_CMD raw_${MCU}_uart_pty || $DUT_CONTROL_CMD ${MCU}_uart_pty) | cut -d: -f2) if [[ -z "${PTY}" ]]; then die "${SERVOD_FAIL}" fi echo $PTY } # Servo variables management case "${BOARD}" in oak_pd|samus_pd|strago_pd ) MCU="usbpd" ;; chell_pd|glados_pd ) MCU="usbpd" ;; meowth_fp|nocturne_fp ) MCU="usbpd" ;; dingdong|hoho|twinkie ) DUT_CONTROL_CMD="true" ; MCU="ec" ;; *) MCU="ec" ;; esac # Not every control is supported on every servo type. Therefore, define which # controls are supported by each servo type. servo_v2_VARS="jtag_buf_on_flex_en jtag_buf_en cold_reset spi1_vref" servo_micro_VARS="cold_reset spi1_vref" servo_v4_with_ccd_cr50_VARS="cold_reset" # Flashing an STM32 over the UART requires modifying the UART properties along # with the boot mode pin. if [ "${CHIP}" = "stm32" ] ; then common_stm32_VARS=" ${MCU}_uart_parity" common_stm32_VARS+=" ${MCU}_uart_baudrate" servo_v2_VARS+=$common_stm32_VARS servo_v2_VARS+=" ${MCU}_uart_en" servo_micro_VARS+=$common_stm32_VARS servo_micro_VARS+=" ${MCU}_uart_en" servo_v4_with_ccd_cr50_VARS+=$common_stm32_VARS fi if $(in_array "${BOARDS_STM32_PROG_EN[@]}" "${BOARD}"); then servo_v2_VARS+=" prog_en" fi if [ "${CHIP}" = "npcx_uut" ] ; then servo_v4_with_ccd_cr50_VARS+=" ccd_keepalive_en" fi toad_VARS="${MCU}_uart_parity ${MCU}_uart_baudrate boot_mode" if $(in_array "${BOARDS_NPCX_INT_SPI[@]}" "${BOARD}"); then servo_v2_VARS+=" fw_up" fi # Some servo boards use the same controls. servo_v3_VARS="${servo_v2_VARS}" servo_v4_with_servo_micro_VARS="${servo_micro_VARS}" function servo_save() { SERVO_VARS_NAME=${SERVO_TYPE}_VARS if [[ -n "${!SERVO_VARS_NAME}" ]]; then $DUT_CONTROL_CMD ${!SERVO_VARS_NAME} fi } function servo_restore() { echo "$1" | while read line do dut_control "$line" done } function claim_pty() { if grep -q cros_sdk /proc/1/cmdline; then die "You must 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. 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 | tr -d 'pR') FROZEN_PIDS="" # reverse order to SIGSTOP parents before children for pid in $(echo ${pids} | tac -s " "); do 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 } function get_serial() { if [[ "${SERVO_TYPE}" =~ "servo_v4_with_servo_micro" ]]; then if [[ -z "${BOARD}" ]]; then sn_ctl="servo_micro_" else sn_ctl="servo_micro_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 SERIALNAME=$(${DUT_CONTROL_CMD} "${sn_ctl}serialname" | cut -d: -f2) echo $SERIALNAME } # 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/bin/lib" ]]; then OCD_PATH="/usr/bin/lib" else die "Cannot locate openocd configs" fi else OCD_PATH="${EC_DIR}/util/openocd" fi dut_control jtag_buf_on_flex_en:on dut_control jtag_buf_en:on 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:/usr/sbin/:$PATH" FLASHROM=$(PATH="${TOOL_PATH}" which flashrom) if on_servov3; then FLASHROM_PARAM="-p linux_spi" elif on_raiden; then if [[ "${SERVO_TYPE}" =~ "servo_micro" ]]; then # Servo micro doesn't use the "target" parameter. FLASHROM_PARAM="-p raiden_debug_spi:" else FLASHROM_PARAM="-p raiden_debug_spi:target=EC," fi else FLASHROM_PARAM="-p ft2232_spi:type=servo-v2,port=B," fi if [ ! -x "$FLASHROM" ]; then die "no flashrom util found." fi # Check whether the SPI flash is internal to the NPCX's EC. # # If the in_array function return non-zero, the script will exit. # Therefore, temporarily ignore errors so we can capture the return # value. set +e local board_is_npcx_internal_spi $(in_array "${BOARDS_NPCX_INT_SPI[@]}" "${BOARD}") board_is_npcx_internal_spi=$? set -e # Okay, don't ignore errors anymore. if ! on_servov3; then SERIALNAME=$(get_serial) if [[ "$SERIALNAME" != "" ]] ; then FLASHROM_PARAM+="serial=${SERIALNAME}" fi fi if ! on_raiden || [[ "${SERVO_TYPE}" =~ "servo_micro" ]] ; then if $(in_array "${BOARDS_SPI_1800MV[@]}" "${BOARD}"); 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 [ $board_is_npcx_internal_spi -eq 0 ]; then # Set GP_SEL# as low then start ec dut_control fw_up:on sleep 0.1 dut_control cold_reset:off fi # 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. dut_control spi1_buf_on_flex_en:on fi # b/65694390: Zoombini and Meowth take enough power that when # flashing without power, the SPI Vref voltage dips for a little # bit. Therefore, wait 1 second to let the voltage stabilize. if [[ "${BOARD}" == "zoombini" || \ "${BOARD}" == "meowth" ]]; then sleep 1 fi else if [ $board_is_npcx_internal_spi -eq 0 ]; then # Set GP_SEL# as low then start ec dut_control cold_reset:on dut_control fw_up:on # sleep 0.1 dut_control cold_reset:off else # Assert EC reset. dut_control cold_reset:on fi # Temp layout L=/tmp/flash_spi_layout_$$ dump_fmap -F "${IMG}" > "${L}" FLASHROM_OPTIONS="-i EC_RW -i WP_RO -l "${L}" --ignore-fmap \ --fast-verify" fi # flashrom should report the image size at the end of the output. FLASHROM_CMDLINE="sudo ${FLASHROM} ${FLASHROM_PARAM} --get-size" if [ "${FLAGS_verbose}" = ${FLAGS_TRUE} ]; then echo "Running flashrom:" 1>&2 echo " ${FLASHROM_CMDLINE}" 1>&2 fi SPI_SIZE=$(${FLASHROM_CMDLINE} 2>/dev/null |\ grep -oe '[0-9]\+$') || \ die "Failed to determine chip size!" (( SPI_SIZE == 0 )) && die "Chip size is 0!" IMG_SIZE=$(stat -c%s "$IMG") PATCH_SIZE=$((${SPI_SIZE} - ${IMG_SIZE})) # Temp image T=/tmp/flash_spi_$$ if [ "${CHIP}" = "npcx_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 # Generate the correct flashrom command to write the ec. FLASHROM_CMDLINE="${FLASHROM} ${FLASHROM_PARAM}" FLASHROM_CMDLINE+=" ${FLASHROM_OPTIONS} -w ${T}" if [ "${FLAGS_verbose}" = ${FLAGS_TRUE} ]; then echo "Running flashrom:" 1>&2 echo " ${FLASHROM_CMDLINE}" 1>&2 fi sudo timeout -k 10 -s 9 "${FLAGS_timeout}" \ ${FLASHROM_CMDLINE} rm $T # Set GP_SEL# as default to disable GP mode when ec reboots if [ $board_is_npcx_internal_spi -eq 0 ]; then dut_control fw_up:off fi if ! on_raiden || [[ "${SERVO_TYPE}" =~ "servo_micro" ]] ; then # Turn off SPI1 interface on servo dut_control spi1_vref:off spi1_buf_en:off if [[ ! "${SERVO_TYPE}" =~ "servo_micro" ]] ; then dut_control spi1_buf_on_flex_en:off fi else rm $L fi # Do not save/restore servo settings save= } function flash_stm32() { local log_option local STM32MON 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)" 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} # Make sure EC reboots in serial monitor mode. ec_enable_boot0 "bitbang" # Pulse EC reset. ec_reset if ! on_raiden && [[ "${SERVO_TYPE}" =~ "servo" ]] ; then dut_control ${MCU}_uart_en:on fi dut_control ${MCU}_uart_parity:even if [[ "${SERVO_TYPE}" =~ "ccd_cr50" ]] ; 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" dut_control ${MCU}_uart_baudrate:"${FLAGS_bitbang_rate}" dut_control ${MCU}_uart_bitbang_en:on else dut_control ${MCU}_uart_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_TYPE}" =~ "ccd_cr50" ]] ; then sleep 2 fi if [ -n "${FLAGS_logfile}" ]; then log_option="-L ${FLAGS_logfile}" info "Saving log in ${FLAGS_logfile}" fi # Unprotect flash, erase, and write STM32MON_COMMAND="${STM32MON} -d ${EC_UART} ${log_option} -U -u -e -w" if [ "${FLAGS_verbose}" = ${FLAGS_TRUE} ]; then echo "${STM32MON_COMMAND}" "${IMG}" fi timeout -k 10 -s 9 "${FLAGS_timeout}" \ ${STM32MON_COMMAND} "${IMG}" # 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 sudo timeout -k 10 -s 9 "${FLAGS_timeout}" \ $DFU_UTIL -a 0 -s ${ADDR}:${SIZE}:force:unprotect -D "${IMG}" # Wait for mass-erase and reboot after unprotection sleep 1 # Actual image flashing sudo timeout -k 10 -s 9 "${FLAGS_timeout}" \ $DFU_UTIL -a 0 -s ${ADDR}:${SIZE} -D "${IMG}" } function flash_it83xx() { TOOL_PATH="${EC_DIR}/build/${BOARD}/util:$PATH" ITEFLASH=$(PATH="${TOOL_PATH}" which iteflash) if [ ! -x "$ITEFLASH" ]; then die "no iteflash util found." fi dut_control i2c_mux_en:on dut_control i2c_mux:remote_adc # 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 dut_control dut_i2c_mux:ec_prog fi # Ensure that the AP is off while we are flashing the EC servo_ec_hard_reset info "Close connection to ftdi_i2c interface" dut_control ftdii2c_cmd:close info "Run iteflash..." sudo ${ITEFLASH} -w ${IMG} } function flash_lm4() { OCD_CHIP_CFG="lm4_chip.cfg" OCD_CMDS="init; flash_lm4 ${IMG} ${FLAGS_offset}; shutdown;" flash_openocd } function flash_nrf51() { OCD_CHIP_CFG="nrf51_chip.cfg" OCD_CMDS="init; flash_nrf51 ${IMG} ${FLAGS_offset}; exit_debug_mode_nrf51; shutdown;" flash_openocd # waiting 100us for the reset pulse is not necessary, it takes ~2.5ms dut_control swd_reset:on swd_reset:off } 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() { TOOL_PATH="${EC_DIR}/build/${BOARD}/util:$PATH" NPCX_UUT=$(PATH="${TOOL_PATH}" which uartupdatetool) EC_UART="$(servo_ec_uart)" BUILD_PATH="${EC_DIR}/build/${BOARD}" MONITOR_PATH="${BUILD_PATH}/chip/npcx/spiflashfw" MON="${MONITOR_PATH}/npcx_monitor.bin" if [[ ! -f "$MON" ]]; then MON="$(dirname "$IMG")/npcx_monitor.bin" fi if [[ ! -f "$MON" ]]; then echo "Failed to find npcx_monitor.bin" exit 1 fi # The start address to restore monitor firmware binary 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 dut_control ccd_keepalive_en:on fi # Force the EC to boot in UART update mode ec_enable_boot0 "uut" ec_reset # Have to wait a bit for EC boot-up sleep 0.1 # For CCD, disable the trigger pin for normal UART operation ec_disable_boot0 "uut" sleep 0.1 # Remove the prefix "/dev/" because uartupdatetool will add it. EC_UART=${EC_UART#/dev/} UUT_PARAMS="--port ${EC_UART} --baudrate 115200" # Load monitor binary to address 0x200C3020 ${NPCX_UUT} ${UUT_PARAMS} --opr wr --addr ${MON_ADDR} --file ${MON} ${NPCX_UUT} ${UUT_PARAMS} --auto --offset ${FLAGS_offset} --file ${IMG} } 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_mec1322() { flash_flashrom } if dut_control boot_mode 2>/dev/null ; then if [[ "${MCU}" != "ec" ]] ; then die "Toad cable can't support non-ec UARTs" fi SERVO_TYPE=toad info "Using a dedicated debug cable" fi info "Using ${SERVO_TYPE}." IMG="$(ec_image)" info "Using ${MCU} image : ${IMG}" if [ "${NEED_SERVO}" != "no" ] ; then save="$(servo_save)" fi info "Flashing chip ${CHIP}." flash_${CHIP} info "Flashing done."