#!/bin/bash
############################################################################
#说明：这个脚本用于PMC 8224/8222卡的固件升级.
#功能：
#1. 支持多张卡更新.
#2. 支持不同固件类型更新
#3. 支持标卡、OEM卡的型号识别和固件更新。
#作者：Sky.Zhang
#脚本名：update.sh
#版本：1.0
#发布时间：2021/12/03
##############################################################################
#版本：1.1
#发布时间：2021/12/07
#作者：sky.zhang
#更新列表：
#1. 修复因固件包名中有特殊符号导致异常问题。
#2. 增加日志删除功能。
#3. 增加管理工具版本检测功能，并指定工具版本：3.07.00 (23971)
#4. 调整过滤条件为关键字,因PMC卡架构不同芯片使用不通。
#5. 合并支持PMC8222和PMC8204卡固件升级包。
###############################################################################
#版本：1.1
#发布时间：2022/04/26
#作者：sky.zhang
#更新列表：
#1. 修复方法fw_check_update中获取存储控制器数量逻辑。
#2. 增加通过设备的PCI地址判断功能逻辑，避免slot判断逻辑异常导致无法正常执行。
##############################################################################
CURRENT_DIR="`cd $(dirname $0);pwd`"
cd ${CURRENT_DIR}
source "${CURRENT_DIR}/fw_update.conf"
TEMP_FILE=PMC82xx.temp
PCI_ADDRESS_TEMP=pci_address.temp
FW_FILE=""
FW_VERSION=""
NVRAM_FILE=""

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

}


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

	cd ${CURRENT_DIR}
       
	if [ ! -f "${FW_FLASH_TOOL}" ]; then
    		yum install Arcconf -y
		FW_FLASH_TOOL="/usr/sbin/arcconf"
	elif [ "`${FW_FLASH_TOOL} | grep "3.07.00 (23971)"`" == "" ];then
    		yum update Arcconf -y
		FW_FLASH_TOOL="/usr/sbin/arcconf"
	fi

        #再次判断是否DELL存储控制器工具是否安装，没有代表上一步安装失败，退出固件升级进程
        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 "P460-M2"`" != "" ];then
		FW_FILE="${H3C_PMC8204_FW_FILE}"
		FW_VERSION="${H3C_PMC8204_FW_VERSION}"
		NVRAM_FILE="${H3C_PMC8204_NVRAM_FILE}"
	elif [ "`grep -i "${1}" ${CURRENT_DIR}/${SSID_LIB_FILE} | grep -i "H460-M1"`" != "" ];then
		FW_FILE="${H3C_PMC8222_FW_FILE}"
		FW_VERSION="${H3C_PMC8222_FW_VERSION}"
		NVRAM_FILE="${H3C_PMC8222_NVRAM_FILE}"
	elif [ "`grep -i "${1}" ${CURRENT_DIR}/${SSID_LIB_FILE} | grep -i "H460-B1"`" != "" ];then
                FW_FILE="${H3C_PMC8222_FW_FILE}"
                FW_VERSION="${H3C_PMC8222_FW_VERSION}"
                NVRAM_FILE="${H3C_PMC8222_NVRAM_FILE}"
	elif [ "`grep -i "${1}" ${CURRENT_DIR}/${SSID_LIB_FILE} | grep -i "INSPUR" | grep "PM8222-SHBA"`" != "" ];then
		FW_FILE="${INSPUR_PMC8222_FW_FILE}"
		FW_VERSION="${INSPUR_PMC8222_FW_VERSION}"
	else 
		echo -e "存储控制器${CTRL_ID}和固件类型不匹配,停止更新。"
		exit 0x02
	fi
}


function fw_check_update() {
	cd ${CURRENT_DIR}

	#查询控制器数量	
	CONTROLLER_COUNT=`${FW_FLASH_TOOL} list | grep "Controllers found:" | awk '{print $NF}'`
		
	for((CTRL_ID=1;CTRL_ID<=${CONTROLLER_COUNT};CTRL_ID++))
	do
		CTRL_PCI_ADDRESS="`${FW_FLASH_TOOL} getconfig ${CTRL_ID} ad | grep "PCI Address" | awk '{print $NF}' | cut -d ':' -f 2-10`"
		PCI_ADDRESS="`echo ${1} | sed -e 's/:00/:0/g' -e 's/\./:/g'`"
		CTRL_SLOT_ID="`${FW_FLASH_TOOL} list ${CTRL_ID} | grep "Controller ${CTRL_ID}:" | cut -d ',' -f 2| awk '{print $NF}'`"
		SLOT_ID=`lspci -v -s ${1} | grep "Physical Slot" | awk '{print $NF}'`
		
		#判断当前控制器的插槽位置和要执行固件升级的设备的位置是否一致，一致执行固件升级，不一致，退出固件升级。
		if [ "${CTRL_PCI_ADDRESS}" != "" -a "${CTRL_PCI_ADDRESS}" == "${PCI_ADDRESS}" ] || [ "${CTRL_SLOT_ID}" -eq ${SLOT_ID} ];then
			echo -e "固件和存储器${CTRL_ID}型号匹配，可继续更新固件。"	
			CURRENT_FW_VERSION="`${FW_FLASH_TOOL} getversion ${CTRL_ID} | grep "^Firmware" | cut -d ':' -f 2 | sed -e 's/^ //g' -e 's/\[.\]//g' `"
			if [ "${CURRENT_FW_VERSION}" != "${FW_VERSION}" ]; then
				${FW_FLASH_TOOL} romupdate ${CTRL_ID} "${CURRENT_DIR}/${FW_FILE}" force noprompt
				sleep 5s
				echo -e "存储控制器固件版本已完成升级，重启生效。"
			else
				echo -e "存储控制器${CTRL_ID}当前固件版本已为标准版本:${CURRENT_FW_VERSION}，不需要再更新。"
			fi
			
			${CURRENT_DIR}/${H3C_NVRAM_TOOL}  --ctrl slot=${SLOT_ID} --flash-nvram ${CURRENT_DIR}/${NVRAM_FILE} --preserve
			LD_COUNT=`${FW_FLASH_TOOL} getconfig ${CTRL_ID} ld | grep 'Logical Device number' -c`
			for ((j=0;j<${LD_COUNT};j++))
			do
				${FW_FLASH_TOOL} setarrayparam ${CTRL_ID} ${j} ssdiobypass disable
			done
			sleep 3s
			${FW_FLASH_TOOL} setcache ${CTRL_ID} logicaldrive all con
			sleep 3s
			${FW_FLASH_TOOL} setcontrollermode ${CTRL_ID} 5
			sleep 3s
			${FW_FLASH_TOOL} CONSISTENCYCHECK ${CTRL_ID} on 3
			sleep 3s
			${FW_FLASH_TOOL} consistencycheck ${CTRL_ID} parallelcount 1
			sleep 3s
			${FW_FLASH_TOOL} setcache ${CTRL_ID} DRIVEWRITECACHEPOLICY Configured 0 Unconfigured 0 hba 0	
			break
		else
			echo -e "固件和存储控制器${CTRL_ID}型号不匹配。"
			#exit 0x03
		fi	
	done
}


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

	while read PCI_ADDRESS
	do
		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

		fw_info_check "${SSID_PREFIX}:${SSID_STUFFIX}"
			
		fw_check_update "${PCI_ADDRESS}"
		
	done < "${CURRENT_DIR}/${PCI_ADDRESS_TEMP}"
	clear_logs
}


main
