coreboot-libre-fam15h-rdimm/3rdparty/chromeec/util/flash_fp_mcu

292 lines
8.7 KiB
Bash

#!/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'
# Both flash read and write protection are removed by default, but you
# can optionally enable them (for testing purposes).
DEFINE_boolean 'remove_flash_read_protect' "${FLAGS_TRUE}" \
'Remove flash read protection while performing command' 'U'
DEFINE_boolean 'remove_flash_write_protect' "${FLAGS_TRUE}" \
'Remove flash write protection while performing command' 'u'
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=" -p -s ${spidev} -r"
local STM32MON_WRITE_FLAGS="-p -s ${spidev} -e -w"
local stm32mon_flags=""
if [[ "${FLAGS_remove_flash_write_protect}" -eq "${FLAGS_TRUE}" ]]; then
STM32MON_READ_FLAGS=" -u ${STM32MON_READ_FLAGS}"
STM32MON_WRITE_FLAGS="-u ${STM32MON_WRITE_FLAGS}"
fi
if [[ "${FLAGS_remove_flash_read_protect}" -eq "${FLAGS_TRUE}" ]]; then
STM32MON_READ_FLAGS=" -U ${STM32MON_READ_FLAGS}"
STM32MON_WRITE_FLAGS="-U ${STM32MON_WRITE_FLAGS}"
fi
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"
# Print out the actual underlying command we're running and run it
local cmd="stm32mon ${stm32mon_flags} ${file}"
echo "${cmd}"
${cmd}
local cmd_exit_status=$?
# 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
if [[ "${cmd_exit_status}" -ne 0 ]]; then
exit 1
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}"