summaryrefslogtreecommitdiff
path: root/util/flash_fp_mcu
diff options
context:
space:
mode:
Diffstat (limited to 'util/flash_fp_mcu')
-rw-r--r--util/flash_fp_mcu265
1 files changed, 265 insertions, 0 deletions
diff --git a/util/flash_fp_mcu b/util/flash_fp_mcu
new file mode 100644
index 0000000000..6a23aa691c
--- /dev/null
+++ b/util/flash_fp_mcu
@@ -0,0 +1,265 @@
+#!/bin/bash
+# Copyright 2019 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.
+
+. /usr/share/misc/shflags
+
+DEFINE_boolean 'read' "${FLAGS_FALSE}" 'Read instead of write' 'r'
+FLAGS_HELP="Usage: ${0} [flags] ec.bin"
+
+# Process commandline flags
+FLAGS "${@}" || exit 1
+eval set -- "${FLAGS_ARGV}"
+
+if [[ "$#" -eq 0 ]]; then
+ echo "Missing filename"
+ flags_help
+ exit 1
+fi
+
+# print out canonical path to differentiate between /usr/local/bin and
+# /usr/bin installs
+echo "$(readlink -f "$0")"
+
+readonly CROS_EC_SPI_MODALIAS_STR="of:NcrfpTCgoogle,cros-ec-spi"
+
+check_hardware_write_protect_disabled() {
+ local hardware_write_protect_state="$(crossystem wpsw_cur)"
+ if [[ "${hardware_write_protect_state}" != "0" ]]; then
+ echo "Please make sure hardware write protect is disabled."
+ echo "See https://www.chromium.org/chromium-os/firmware-porting-guide/firmware-ec-write-protection"
+ exit 1
+ fi
+}
+
+# Get the spiid for the fingerprint sensor based on the modalias
+# string: https://crbug.com/955117
+get_spiid() {
+ for dev in /sys/bus/spi/devices/*; do
+ if [[ "$(cat "${dev}/modalias")" == "${CROS_EC_SPI_MODALIAS_STR}" ]]; then
+ echo "$(basename "${dev}")"
+ exit 0
+ fi
+ done
+
+ exit 1
+}
+
+# Taken verbatim from
+# https://chromium.googlesource.com/chromiumos/docs/+/master/lsb-release.md#shell
+# This should not be used by anything except get_platform_name.
+# See https://crbug.com/98462.
+lsbval() {
+ local key="$1"
+ local lsbfile="${2:-/etc/lsb-release}"
+
+ if ! echo "${key}" | grep -Eq '^[a-zA-Z0-9_]+$'; then
+ return 1
+ fi
+
+ sed -E -n -e \
+ "/^[[:space:]]*${key}[[:space:]]*=/{
+ s:^[^=]+=[[:space:]]*::
+ s:[[:space:]]+$::
+ p
+ }" "${lsbfile}"
+}
+
+# Get the underlying board (reference design) that we're running on (not the
+# FPMCU or sensor).
+get_platform_name() {
+ # "-l" converts to lowercase
+ local -l platform_name="$(cros_config /identity platform-name)"
+
+ # If we don't get any result from cros_config, then we have to possible cases:
+ #
+ # 1) We're running on a non-unibuild device (the only one with FP is nocturne)
+ # 2) We're running on a proto device during bringup and the cros_config
+ # settings haven't yet been setup.
+ #
+ # In either case we can fall back to /etc/lsb-release. It's not recommended
+ # to do this, but we don't have any other options in this case.
+ #
+ # TODO(https://crbug.com/984629): cros_config should handle reading
+ # /etc/lsb-release as backup for us.
+ if [[ -z "${platform_name}" ]]; then
+ echo "Getting platform name from cros_config failed." \
+ "Falling back to /etc/lsb-release." 1>&2
+ platform_name="$(lsbval "CHROMEOS_RELEASE_BOARD")"
+ if [[ -z "${platform_name}" ]]; then
+ exit 1
+ fi
+ fi
+
+ echo "${platform_name}"
+}
+
+check_gpio_chip_exists() {
+ local gpiochip="$1"
+ if [[ ! -e "/sys/class/gpio/${gpiochip}" ]]; then
+ echo "Cannot find GPIO chip: ${gpiochip}"
+ exit 1
+ fi
+}
+
+flash_fp_mcu_stm32() {
+ local spidev="${1}"
+ local gpio_nrst="${2}"
+ local gpio_boot0="${3}"
+ local gpio_pwren="${4}"
+ local file="${5}"
+ local spiid
+
+ local STM32MON_READ_FLAGS=" -U -u -p -s ${spidev} -r"
+ local STM32MON_WRITE_FLAGS="-U -u -p -s ${spidev} -e -w"
+ local stm32mon_flags=""
+
+ if [[ "${FLAGS_read}" -eq "${FLAGS_TRUE}" ]]; then
+ if [[ -e "${file}" ]]; then
+ echo "Output file already exists: ${file}"
+ exit 1
+ fi
+ stm32mon_flags="${STM32MON_READ_FLAGS}"
+ else
+ if [[ ! -f "${file}" ]]; then
+ echo "Invalid image file: ${file}"
+ exit 1
+ fi
+ stm32mon_flags="${STM32MON_WRITE_FLAGS}"
+ fi
+
+ check_hardware_write_protect_disabled
+
+ spiid="$(get_spiid)"
+ if [[ $? -ne 0 ]]; then
+ echo "Unable to find FP sensor SPI device: ${CROS_EC_SPI_MODALIAS_STR}"
+ exit 1
+ fi
+
+ echo "Flashing SPI device ID: ${spiid}"
+
+ # Ensure the ACPI is not cutting power when unloading cros-ec-spi
+ if [[ -n "${gpio_pwren}" ]]; then
+ echo "${gpio_pwren}" > /sys/class/gpio/export
+ echo "out" > "/sys/class/gpio/gpio${gpio_pwren}/direction"
+ echo 1 > "/sys/class/gpio/gpio${gpio_pwren}/value"
+ fi
+
+ # Remove cros_fp if present
+ echo "${spiid}" > /sys/bus/spi/drivers/cros-ec-spi/unbind
+
+ # Configure the MCU Boot0 and NRST GPIOs
+ echo "${gpio_boot0}" > /sys/class/gpio/export
+ echo "out" > "/sys/class/gpio/gpio${gpio_boot0}/direction"
+ echo "${gpio_nrst}" > /sys/class/gpio/export
+ echo "out" > "/sys/class/gpio/gpio${gpio_nrst}/direction"
+
+ # Reset sequence to enter bootloader mode
+ echo 1 > "/sys/class/gpio/gpio${gpio_boot0}/value"
+ echo 0 > "/sys/class/gpio/gpio${gpio_nrst}/value"
+ sleep 0.001
+
+ # load spidev (fail on cros-ec-spi first to change modalias)
+ echo "${spiid}" > /sys/bus/spi/drivers/cros-ec-spi/bind 2>/dev/null
+ echo "${spiid}" > /sys/bus/spi/drivers/spidev/bind
+
+ # Release reset as the SPI bus is now ready
+ echo 1 > "/sys/class/gpio/gpio${gpio_nrst}/value"
+ echo "in" > "/sys/class/gpio/gpio${gpio_nrst}/direction"
+
+ stm32mon ${stm32mon_flags} "${file}"
+
+ # unload spidev
+ echo "${spiid}" > /sys/bus/spi/drivers/spidev/unbind
+
+ # Go back to normal mode
+ echo "out" > "/sys/class/gpio/gpio${gpio_nrst}/direction"
+ echo 0 > "/sys/class/gpio/gpio${gpio_boot0}/value"
+ echo 0 > "/sys/class/gpio/gpio${gpio_nrst}/value"
+ echo 1 > "/sys/class/gpio/gpio${gpio_nrst}/value"
+
+ # Give up GPIO control
+ echo "in" > "/sys/class/gpio/gpio${gpio_boot0}/direction"
+ echo "in" > "/sys/class/gpio/gpio${gpio_nrst}/direction"
+ echo "${gpio_boot0}" > /sys/class/gpio/unexport
+ echo "${gpio_nrst}" > /sys/class/gpio/unexport
+
+ # wait for FP MCU to come back up (including RWSIG delay)
+ sleep 2
+ # Put back cros_fp driver
+ echo "${spiid}" > /sys/bus/spi/drivers/cros-ec-spi/bind
+ # Kernel driver is back, we are no longer controlling power
+ if [[ -n "${gpio_pwren}" ]]; then
+ echo "${gpio_pwren}" > /sys/class/gpio/unexport
+ fi
+ # Test it
+ ectool --name=cros_fp version
+}
+
+config_hatch() {
+ check_gpio_chip_exists "gpiochip200"
+
+ readonly SPIDEV="/dev/spidev1.1"
+ # FPMCU RST_ODL is on GPP_A12 = 200 + 12 = 212
+ readonly GPIO_NRST=212
+ # FPMCU BOOT0 is on GPP_A22 = 200 + 22 = 222
+ readonly GPIO_BOOT0=222
+ # No PWREN GPIO on Hatch, FPMCU is always on
+ readonly GPIO_PWREN=""
+}
+
+config_nami() {
+ check_gpio_chip_exists "gpiochip360"
+
+ readonly SPIDEV="/dev/spidev32765.0"
+ # FPMCU RST_ODL is on GPP_C9 = 360 + 57 = 417
+ readonly GPIO_NRST=417
+ # FPMCU BOOT0 is on GPP_D5 = 360 + 77 = 437
+ readonly GPIO_BOOT0=437
+ # FP_PWR_EN is on GPP_B11 = 360 + 35 = 395
+ readonly GPIO_PWREN=395
+}
+
+config_nocturne() {
+ check_gpio_chip_exists "gpiochip360"
+
+ readonly SPIDEV="/dev/spidev32765.0"
+ # FPMCU RST_ODL is on GPP_C10 = 360 + 58 = 418
+ readonly GPIO_NRST=418
+ # FPMCU BOOT0 is on GPP_C8 = 360 + 56 = 416
+ readonly GPIO_BOOT0=416
+ # FP_PWR_EN is on GPP_A11 = 360 + 11 = 371
+ readonly GPIO_PWREN=371
+}
+
+# The "platform name" corresponds to the underlying board (reference design)
+# that we're running on (not the FPMCU or sensor). At the moment all of the
+# reference designs use the same GPIOs. If for some reason a design differs in
+# the future, we will want to add a nested check in the config_<platform_name>
+# function. Doing it in this manner allows us to reduce the number of
+# configurations that we have to maintain (and reduces the amount of testing
+# if we're only updating a specific config_<platform_name>).
+readonly PLATFORM_NAME="$(get_platform_name)"
+
+echo "Using config for ${PLATFORM_NAME}"
+
+# Check that the config function exists
+if [[ "$(type -t "config_${PLATFORM_NAME}")" != "function" ]]; then
+ echo "No config for platform ${PLATFORM_NAME}"
+ exit 1
+fi
+
+config_${PLATFORM_NAME}
+
+if [[ $? -ne 0 ]]; then
+ echo "Configuration failed for platform ${PLATFORM_NAME}"
+ exit 1
+fi
+
+flash_fp_mcu_stm32 \
+ "${SPIDEV}" \
+ "${GPIO_NRST}" \
+ "${GPIO_BOOT0}" \
+ "${GPIO_PWREN}" \
+ "${1}"