[mellanox] Extend Mellanox FW utils with CPLD update (#3723)

* [mellanox] Extend Mellanox FW utils with CPLD update
* [mellanox] Fix FW utils review comments
This commit is contained in:
Nazarii Hnydyn 2019-11-15 20:43:17 +02:00 committed by Qi Luo
parent 45f5270399
commit e546c64c76

View File

@ -4,39 +4,62 @@ declare -r SCRIPT_NAME="$(basename "$0")"
declare -r SCRIPT_PATH="$(readlink -f "$0")" declare -r SCRIPT_PATH="$(readlink -f "$0")"
declare -r SCRIPT_DIR="$(dirname "$SCRIPT_PATH")" declare -r SCRIPT_DIR="$(dirname "$SCRIPT_PATH")"
declare -r VERBOSE_ERROR="1"
declare -r VERBOSE_WARNING="2"
declare -r VERBOSE_NOTICE="3"
declare -r VERBOSE_INFO="4"
declare -r VERBOSE_MAX="${VERBOSE_INFO}"
declare -r VERBOSE_MIN="${VERBOSE_ERROR}"
declare -r YES_PARAM="yes"
declare -r NO_PARAM="no"
declare -r EXIT_SUCCESS="0" declare -r EXIT_SUCCESS="0"
declare -r EXIT_ERROR="1" declare -r EXIT_FAILURE="1"
declare -r QUERY_CMD="mlxfwmanager --query" declare -r QUERY_CMD="mlxfwmanager --query"
declare -r BURN_CMD="mlxfwmanager -u -f -y" declare -r BURN_CMD="mlxfwmanager -u -f -y"
declare -r FW_FILE="/etc/mlnx/fw-SPC.mfa" declare -r FW_FILE="/etc/mlnx/fw-SPC.mfa"
declare -r QUERY_FILE="/tmp/mlnxfwmanager-query.txt" declare -r QUERY_FILE="/tmp/mlxfwmanager-query.txt"
declare -r FW_REQUIRED="{{ MLNX_FW_VERSION }}" declare -r FW_REQUIRED="{{ MLNX_FW_VERSION }}"
IMAGE_UPGRADE="no" IMAGE_UPGRADE="${NO_PARAM}"
CPLD_UPGRADE="${NO_PARAM}"
VERBOSE_LEVEL="${VERBOSE_MIN}"
function PrintHelp() { function PrintHelp() {
echo echo
echo "Usage: ./${SCRIPT_NAME} [OPTIONS]" echo "Usage: ./${SCRIPT_NAME} [OPTIONS]"
echo echo
echo "OPTIONS:" echo "OPTIONS:"
echo " -u, --upgrade Upgrade MLNX ASIC firmware using next boot image (useful after SONiC-To-SONiC update)" echo " -u, --upgrade Upgrade firmware using next boot image (useful after SONiC-To-SONiC update)"
echo " -c, --cpld Upgrade CPLD firmware (requires -u|--upgrade)"
echo " -v, --verbose Verbose mode"
echo " -h, --help Print help" echo " -h, --help Print help"
echo echo
echo "Examples:" echo "Examples:"
echo " ./${SCRIPT_NAME}" echo " ./${SCRIPT_NAME}"
echo " ./${SCRIPT_NAME} --upgrade" echo " ./${SCRIPT_NAME} --upgrade --cpld --verbose"
echo " ./${SCRIPT_NAME} --upgrade --verbose"
echo " ./${SCRIPT_NAME} --help" echo " ./${SCRIPT_NAME} --help"
echo echo
} }
function ParseArguments() { function ParseArguments() {
while [ $# -ge 1 ]; do while [[ $# -ge 1 ]]; do
case "$1" in case "$1" in
-u|--upgrade) -u|--upgrade)
IMAGE_UPGRADE="yes" IMAGE_UPGRADE="${YES_PARAM}"
VERBOSE_LEVEL="${VERBOSE_MAX}"
;;
-c|--cpld)
CPLD_UPGRADE="${YES_PARAM}"
;;
-v|--verbose)
VERBOSE_LEVEL="${VERBOSE_MAX}"
;; ;;
-h|--help) -h|--help)
PrintHelp PrintHelp
@ -47,43 +70,121 @@ function ParseArguments() {
done done
} }
function LogError() {
if [[ "${VERBOSE_LEVEL}" -ge "${VERBOSE_ERROR}" ]]; then
echo "ERROR: $*"
fi
}
function LogWarning() {
if [[ "${VERBOSE_LEVEL}" -ge "${VERBOSE_WARNING}" ]]; then
echo "WARNING: $*"
fi
}
function LogNotice() {
if [[ "${VERBOSE_LEVEL}" -ge "${VERBOSE_NOTICE}" ]]; then
echo "NOTICE: $*"
fi
}
function LogInfo() {
if [[ "${VERBOSE_LEVEL}" -ge "${VERBOSE_INFO}" ]]; then
echo "INFO: $*"
fi
}
function ExitFailure() {
if [[ "${VERBOSE_LEVEL}" -ge "${VERBOSE_ERROR}" ]]; then
echo
LogError "$@"
echo
fi
exit "${EXIT_FAILURE}"
}
function ExitSuccess() {
if [[ "${VERBOSE_LEVEL}" -ge "${VERBOSE_INFO}" ]]; then
echo
LogInfo "$@"
echo
fi
exit "${EXIT_SUCCESS}"
}
function ParseMachineConf() {
ONIE_MACHINE="$(cat /host/machine.conf | grep 'onie_machine=' | cut -f2 -d'=')"
ONIE_PLATFORM="$(cat /host/machine.conf | grep 'onie_platform=' | cut -f2 -d'=')"
}
function ShowProgressBar() {
local -rA SPIN=(
[0]="-"
[1]="\\"
[2]="|"
[3]="/"
)
if [[ "${VERBOSE_LEVEL}" -lt "${VERBOSE_INFO}" ]]; then
sleep 2s
return "${EXIT_SUCCESS}"
fi
# Print progress bar: use carriage return to overwrite command line content
for i in "${SPIN[@]}"; do
echo -ne "\r[${i}] ${1}"
sleep 0.5s
done
# Clear command line content + carriage return
echo -ne "\033[1K\r"
}
function WaitForDevice() { function WaitForDevice() {
local -i QUERY_RETRY_COUNT_MAX="10" local -i QUERY_RETRY_COUNT_MAX="10"
local -i QUERY_RETRY_COUNT="0" local -i QUERY_RETRY_COUNT="0"
${QUERY_CMD} > /dev/null ${QUERY_CMD} &> /dev/null
while [[ ("${QUERY_RETRY_COUNT}" -lt "${QUERY_RETRY_COUNT_MAX}") && ("$?" -ne "0") ]]; do while [[ ("${QUERY_RETRY_COUNT}" -lt "${QUERY_RETRY_COUNT_MAX}") && ("$?" -ne "0") ]]; do
sleep 1s sleep 1s
((QUERY_RETRY_COUNT++)) ((QUERY_RETRY_COUNT++))
${QUERY_CMD} > /dev/null ${QUERY_CMD} &> /dev/null
done done
} }
function RunCmd() { function RunCmd() {
$1 local _EXIT_CODE="${EXIT_SUCCESS}"
if [[ $? != 0 ]]; then
echo "Command failed: cmd=$1, errno=$?" if [[ "${VERBOSE_LEVEL}" -eq "${VERBOSE_MAX}" ]]; then
exit "${EXIT_ERROR}" eval "$@"
else
eval "$@" &>/dev/null
fi
_EXIT_CODE="$?"
if [[ "${_EXIT_CODE}" != "${EXIT_SUCCESS}" ]]; then
ExitFailure "command failed: $@"
fi fi
} }
function UpgradeFW() { function UpgradeASICFW() {
local _FW_FILE="$1" local _FW_FILE="$1"
if [ ! -z "${_FW_FILE}" ]; then if [[ ! -z "${_FW_FILE}" ]]; then
if [ ! -f "${_FW_FILE}" ]; then if [[ ! -f "${_FW_FILE}" ]]; then
echo "No such file: ${_FW_FILE}" ExitFailure "no such file: ${_FW_FILE}"
exit "${EXIT_ERROR}"
fi fi
RunCmd "${QUERY_CMD} -i ${_FW_FILE}" > "${QUERY_FILE}" RunCmd "${QUERY_CMD} -i ${_FW_FILE} > ${QUERY_FILE}"
local -r _FW_INFO="$(grep FW ${QUERY_FILE})" local -r _FW_INFO="$(grep FW ${QUERY_FILE})"
local -r _FW_CURRENT="$(echo ${_FW_INFO} | cut -f2 -d' ')" local -r _FW_CURRENT="$(echo ${_FW_INFO} | cut -f2 -d' ')"
local -r _FW_AVAILABLE="$(echo ${_FW_INFO} | cut -f3 -d' ')" local -r _FW_AVAILABLE="$(echo ${_FW_INFO} | cut -f3 -d' ')"
else else
RunCmd "${QUERY_CMD}" > "${QUERY_FILE}" RunCmd "${QUERY_CMD} > ${QUERY_FILE}"
local -r _FW_INFO="$(grep FW ${QUERY_FILE})" local -r _FW_INFO="$(grep FW ${QUERY_FILE})"
local -r _FW_CURRENT="$(echo ${_FW_INFO} | cut -f2 -d' ')" local -r _FW_CURRENT="$(echo ${_FW_INFO} | cut -f2 -d' ')"
@ -93,51 +194,148 @@ function UpgradeFW() {
fi fi
if [[ -z "${_FW_CURRENT}" ]]; then if [[ -z "${_FW_CURRENT}" ]]; then
echo "Could not retreive current FW version" ExitFailure "could not retrieve current ASIC firmware version"
exit "${EXIT_ERROR}"
fi fi
if [[ -z "${_FW_AVAILABLE}" ]]; then if [[ -z "${_FW_AVAILABLE}" ]]; then
echo "Could not retreive available FW version" ExitFailure "could not retrieve available ASIC firmware version"
exit "${EXIT_ERROR}"
fi fi
if [[ "${_FW_CURRENT}" == "${_FW_AVAILABLE}" ]]; then if [[ "${_FW_CURRENT}" = "${_FW_AVAILABLE}" ]]; then
echo "Mellanox firmware is up to date" LogInfo "ASIC firmware is up to date"
else return "${EXIT_SUCCESS}"
echo "Mellanox firmware upgrade is required. Installing compatible version..."
RunCmd "${BURN_CMD} -i ${_FW_FILE}"
fi fi
LogNotice "ASIC firmware upgrade is required. Installing compatible version..."
LogInfo "current ASIC firmware version: ${_FW_CURRENT}"
LogInfo "target ASIC firmware version: ${_FW_AVAILABLE}"
LogInfo "ASIC firmware file: ${_FW_FILE}"
RunCmd "${BURN_CMD} -i ${_FW_FILE}"
}
function UpgradeCPLDFW_Worker() {
local -r _CPLD_BURN_FILE="${1}"
local -r _CPLD_REFRESH_FILE="${2}"
local -r _ASIC_DEV="$(find /dev/mst -iname '*_pciconf0')"
if [[ -f /tmp/cpld_fw_updated ]]; then
RunCmd "cpldupdate --dev ${_ASIC_DEV} ${_CPLD_REFRESH_FILE}"
return "${EXIT_SUCCESS}"
fi
RunCmd "cpldupdate --dev ${_ASIC_DEV} ${_CPLD_BURN_FILE}"
RunCmd "cpldupdate --dev ${_ASIC_DEV} ${_CPLD_REFRESH_FILE}"
}
function UpgradeCPLDFW() {
local -r _CPLD_ARCHIVE="$1"
if [[ -f /tmp/cpld_fw_updated ]]; then
LogWarning "forced CPLD refresh was requested for ${ONIE_PLATFORM}"
CPLD_UPGRADE="${YES_PARAM}"
fi
if [[ "${CPLD_UPGRADE}" != "${YES_PARAM}" ]]; then
LogNotice "CPLD upgrade was not requested for ${ONIE_PLATFORM}"
return "${EXIT_SUCCESS}"
fi
if [[ ! -f "${_CPLD_ARCHIVE}" ]]; then
LogNotice "CPLD update $(basename ${_CPLD_ARCHIVE}) was not provided for ${ONIE_PLATFORM}"
return "${EXIT_SUCCESS}"
fi
CPLD_DIR="$(mktemp -d)"
RunCmd "tar xzf ${_CPLD_ARCHIVE} -C ${CPLD_DIR}"
local -r _CPLD_BURN_FILE="${CPLD_DIR}/$(cat ${CPLD_DIR}/bundle.txt | grep 'burn=' | cut -f2 -d'=')"
local -r _CPLD_REFRESH_FILE="${CPLD_DIR}/$(cat ${CPLD_DIR}/bundle.txt | grep 'refresh=' | cut -f2 -d'=')"
local -r _CPLD_VERSION="$(cat ${CPLD_DIR}/bundle.txt | grep 'version=' | cut -f2 -d'=')"
local _CURRENT_CPLD_VERSION="${_CPLD_VERSION}"
local _TARGET_CPLD_VERSION="${_CPLD_VERSION}"
if [[ -f /bsp/cpld/cpld_mgmt_version ]]; then
_CURRENT_CPLD_VERSION="$(cat /bsp/cpld/cpld_mgmt_version)"
elif [[ -f /var/run/hw-management/system/cpld1_version ]]; then
_CURRENT_CPLD_VERSION="$(cat /var/run/hw-management/system/cpld1_version)"
else
ExitFailure "could not retrieve current CPLD firmware version"
fi
if [[ "${_CURRENT_CPLD_VERSION}" = "${_TARGET_CPLD_VERSION}" ]]; then
LogInfo "CPLD firmware is up to date"
return "${EXIT_SUCCESS}"
fi
LogNotice "CPLD firmware upgrade is required. Installing compatible version..."
LogInfo "current CPLD firmware version: ${_CURRENT_CPLD_VERSION}"
LogInfo "target CPLD firmware version: ${_TARGET_CPLD_VERSION}"
LogInfo "CPLD burn firmware file: ${_CPLD_BURN_FILE}"
LogInfo "CPLD refresh firmware file: ${_CPLD_REFRESH_FILE}"
UpgradeCPLDFW_Worker "${_CPLD_BURN_FILE}" "${_CPLD_REFRESH_FILE}" &
local -r _PID="$!"
while $(ps -e -o pid | grep -E "^[[:blank:]]*${_PID}$" &> /dev/null); do
ShowProgressBar "CPLD update..."
done
RunCmd "wait ${_PID}"
} }
function UpgradeFWFromImage() { function UpgradeFWFromImage() {
local -r _NEXT_SONIC_IMAGE="$(sonic_installer list | grep "Next: " | cut -f2 -d' ')" local -r _NEXT_SONIC_IMAGE="$(sonic_installer list | grep 'Next: ' | cut -f2 -d' ')"
local -r _CURRENT_SONIC_IMAGE="$(sonic_installer list | grep "Current: " | cut -f2 -d' ')" local -r _CURRENT_SONIC_IMAGE="$(sonic_installer list | grep 'Current: ' | cut -f2 -d' ')"
local -r _FS_PATH="/host/image-${_NEXT_SONIC_IMAGE#SONiC-OS-}/fs.squashfs" if [[ "${_CURRENT_SONIC_IMAGE}" = "${_NEXT_SONIC_IMAGE}" ]]; then
local -r _FS_MOUNTPOINT="/tmp/image-${_NEXT_SONIC_IMAGE#SONiC-OS-}-fs" ExitSuccess "firmware is up to date"
fi
if [[ "${_CURRENT_SONIC_IMAGE}" == "${_NEXT_SONIC_IMAGE}" ]]; then FS_PATH="/host/image-${_NEXT_SONIC_IMAGE#SONiC-OS-}/fs.squashfs"
echo "Mellanox firmware is up to date" FS_MOUNTPOINT="/tmp/image-${_NEXT_SONIC_IMAGE#SONiC-OS-}-fs"
else
mkdir -p "${_FS_MOUNTPOINT}"
mount -t squashfs "${_FS_PATH}" "${_FS_MOUNTPOINT}"
UpgradeFW "${_FS_MOUNTPOINT}/etc/mlnx/fw-SPC.mfa" RunCmd "mkdir -p ${FS_MOUNTPOINT}"
RunCmd "mount -t squashfs ${FS_PATH} ${FS_MOUNTPOINT}"
umount -rf "${_FS_MOUNTPOINT}" UpgradeASICFW "${FS_MOUNTPOINT}${FW_FILE}"
rm -rf "${_FS_MOUNTPOINT}" UpgradeCPLDFW "${FS_MOUNTPOINT}/etc/mlnx/cpld/${ONIE_MACHINE#mlnx_}_cpld.tar.gz"
}
function Cleanup() {
if [[ -d "${FS_MOUNTPOINT}" ]]; then
umount -rf "${FS_MOUNTPOINT}"
rm -rf "${FS_MOUNTPOINT}"
fi
if [[ -d "${CPLD_DIR}" ]]; then
rm -rf "${CPLD_DIR}"
fi fi
} }
trap Cleanup EXIT
ParseMachineConf
ParseArguments "$@" ParseArguments "$@"
WaitForDevice WaitForDevice
if [ "${IMAGE_UPGRADE}" != "yes" ]; then if [[ "${CPLD_UPGRADE}" = "${YES_PARAM}" ]]; then
UpgradeFW if [[ "${IMAGE_UPGRADE}" = "${NO_PARAM}" ]]; then
else ExitFailure "mandatory parameter was not provided: -u|--upgrade"
UpgradeFWFromImage fi
fi fi
exit "${EXIT_SUCCESS}" if [[ "${IMAGE_UPGRADE}" = "${YES_PARAM}" ]]; then
UpgradeFWFromImage
else
UpgradeASICFW
fi
ExitSuccess "firmware upgrade is completed"