#!/bin/bash
################################################################
#说明：这个脚本用于SAS3416卡的固件升级.
#功能：
#1. 支持多张卡更新.
#2. 支持不同固件类型更新
#3. 支持标卡、OEM卡的型号识别和固件更新。
#4. 支持标卡CPLD更新。
#作者：Sky.Zhang
#脚本名：update.sh
#版本：1.0
#发布时间：2021/12/01
##############################################################
#版本：1.1
#发布时间：2021/12/02
#作者：sky.zhang
#变更列表：
#1.删除固件升级中resetnow参数（由于SAS HBA不支持在线固件升级固件）。
###################################################################
#版本：1.2
#发布时间：2021/12/07
#变更列表：
#1. 修复主函数main过滤关键词错误bug。
#2. 修复主函数main传参参数错误bug。
#3. 修复因文件命名有特殊符号导致的异常报错。
#4. 增加日志删除功能。
#5. 修复临时日志命名错误。
#5. 调整过滤条件为关键字。
##################################################################


CURRENT_DIR="`cd $(dirname $0);pwd`"
cd ${CURRENT_DIR}
source "${CURRENT_DIR}/fw_update.conf"
TEMP_FILE=SAS3416.temp
PCI_ADDRESS_TEMP=pci_address.temp
FW_FILE=""
FW_VERSION=""

function clear_logs() {
	rm -rf "${CURRENT_DIR}/${TEMP_FILE}" "${CURRENT_DIR}/${PCI_ADDRESS_TEMP}"
}


##判断存储控制器工具类型、是否安装，没有安装，则yum安装
function flash_tools_check() {

        cd ${CURRENT_DIR}

        if [ "`grep -i "${1}" ${SSID_LIB_FILE} | grep -i dell`" != "" ]; then
                FW_FLASH_TOOL="/opt/MegaRAID/perccli/perccli64"
                if [ ! -f "${FW_FLASH_TOOL}" ]; then
                        yum install perccli -y
                        FW_FLASH_TOOL="/opt/MegaRAID/perccli/perccli64"
                fi
        else
                if [ ! -f "${FW_FLASH_TOOL}" ]; then
                        yum install storcli -y
                        FW_FLASH_TOOL="/opt/MegaRAID/storcli/storcli64"
                fi
        fi

        #再次判断存储控制器工具是否安装，没有代表上一步安装失败，退出固件升级进程
        if [ ! -f "${FW_FLASH_TOOL}" ]; then
                echo -e "缺少控制器固件升级工具，停止固件升级。"
                exit 0x01
        fi
}


function fw_info_check() {
	#符合标准的厂商/设备的主/子ID的设备，方可以执行固件升级，否则反馈设备和固件类型不匹配。
	if [ "`grep -i "${1}" ${CURRENT_DIR}/${SSID_LIB_FILE} | grep -i "dell" | grep -i 1f3c`" != "" ];then
		FW_FILE="${DELL_SAS3416_1F3C_FW_FILE}"
		FW_VERSION="${DELL_SAS3416_FW_VERSION}"
	elif [ "`grep -i "${1}" ${CURRENT_DIR}/${SSID_LIB_FILE} | grep -i "dell" | grep -i 1f3d`" != "" ];then
		FW_FILE="${DELL_SAS3416_1F3D_FW_FILE}"
		FW_VERSION="${DELL_SAS3416_FW_VERSION}"
	else 
		echo -e "存储控制器${CTRL_ID}和固件类型不匹配,停止更新。"
		exit 0x02
	fi
}


function fw_check_update() {
	cd ${CURRENT_DIR}
	#查询控制器数量	
	CONTROLLER_COUNT=`${FW_FLASH_TOOL} show ctrlcount | grep "Controller Count" | awk '{print $NF}'`
		
	for((CTRL_ID=0;CTRL_ID<${CONTROLLER_COUNT};CTRL_ID++))
	do
		#判断当前控制器的PCI 地址和要执行固件升级的设备的地址是否一致，一致执行固件升级，不一致，退出固件升级。
		PCI_ADDRESS="`echo ${1} | sed 's/\(.*\)\.\(.*\)/\1:\2/'`"
		if [ "`${FW_FLASH_TOOL} /c${CTRL_ID} show all | grep "${PCI_ADDRESS}"`" != "" ];then	
			CURRENT_FW_VERSION="`${FW_FLASH_TOOL} /c${CTRL_ID} show | grep -i "FW Version" | awk '{print $NF}'`"
			if [ "${CURRENT_FW_VERSION}" != "${FW_VERSION}" ]; then
				${FW_FLASH_TOOL} /c${CTRL_ID} download file="${CURRENT_DIR}/${FW_FILE}" noverchk
				sleep 5s
				echo -e "存储控制器固件版本已完成升级,重启生效。"
			else
				echo -e "存储控制器${CTRL_ID}当前固件版本已为标准版本:${CURRENT_FW_VERSION}，不需要再更新。"
			fi
		else
			echo -e "固件和存储控制器${CTRL_ID}型号不匹配。"
			exit 0x03
		fi
		
		rm -rf ${CURRENT_DIR}/${TEMP_FILE}
	done
}


function main() {
	clear_logs
	#获取控制器数量
	lspci | grep "${KEYWORD}" | awk '{print $1}' > ${PCI_ADDRESS_TEMP}	

	while read PCI_ADDRESS
	do
		if [ "`lspci -k -s ${PCI_ADDRESS} | grep "Kernel driver in use:"| awk '{print $NF}'`" == "megaraid_sas" ]; then	
			SSID_PREFIX="`lspci -n -s ${PCI_ADDRESS} | awk '{print $(NF-2)}'`"
			SSID_STUFFIX="`lspci -vn -s ${PCI_ADDRESS} | grep 'Subsystem:' | awk '{print $NF}'`"
			flash_tools_check "${SSID_PREFIX}:${SSID_STUFFIX}"

			fw_info_check "${SSID_PREFIX}:${SSID_STUFFIX}"
			
			fw_check_update "${PCI_ADDRESS}"
		else
			echo -e "存储控制器${PCI_ADDRESS}的固件不是IMR类型，暂不支持更新。"
			continue	
		fi
	done < ${PCI_ADDRESS_TEMP}
	clear_logs
}

main
