#!/bin/bash
#Author:Terrence.Zhou@ucloud.cn
#Date:9/3/2019
#Update Samung PM883/Intel S4500/Micron 5100/5200 SATA SSD firmware automatically
#Modified in 9/12/2019
#Add Samsung PM863a/Intel S4510 SSD firmware update
#Modified in 4/27/2020
#update Samsumg PM863a SSD FW GXT5404Q_NF
#Modified in 6/9/2020
#Add lsi_hba_card ssd update function
#Add lsi_raid_ssd_erase and pmc_raid_ssd_erase function
#Modified in 6/18/2020
#Delete VD in data disk before ssd erase action
#Move pmc_raid_erase function
#Modified in 7/27/2020
#re-format ssd fw update method which only maitains ssd_upd_list
#Moddified in 9/8/2020
#Update ssd fw update and erase tool with higher hdparm instead of strorcli and arcconf

CPWD=`cd $(dirname $0);pwd`
cd $CPWD
rm -rf *_map
lsi_megaraid_ssd_upd(){
for i in `/opt/MegaRAID/storcli/storcli64 show all |grep -A 10 "Ctl Model" |grep -B 10 "Ctl=Controller Index" |sed -n '/^-/,/-$/p' |grep -v "^-" |awk '{print $1}' |sed '/^\s*$/d'`
do
        /opt/MegaRAID/storcli/storcli64 /c$i/vall delete force >/dev/null 2>&1
        /opt/MegaRAID/storcli/storcli64 /c$i set jbod=on >/dev/null 2>&1
        /opt/MegaRAID/storcli/storcli64 /c$i/eall/sall set jbod >/dev/null 2>&1
done
sleep 5
lsscsi -g |grep ATA > dell_lsi_disk_map
for j in `awk '{print $NF}' dell_lsi_disk_map`
do
        IS_SSD=`smartctl -a $j |grep "Rotation Rate" |awk -F":" '{print $NF}' |sed 's/^\s*//g'`
        Model=`smartctl -a $j |grep "Device Model" |awk -F":" '{print $NF}' |sed 's/\s*//g'`
        FW_Ver=`smartctl -a $j |grep "Firmware Version" |awk -F":" '{print $NF}' |sed 's/\s*//g'`
        for k in `seq 1 $(cat ssd_upd_list |wc -l)`
        do
                match_model=`sed -n "$k"p ssd_upd_list |awk '{print $1}'`
                match_fw_ver=`sed -n "$k"p ssd_upd_list |awk '{print $2}'`
                upd_fw==`sed -n "$k"p ssd_upd_list |awk '{print $3}'`
                if [[ "${IS_SSD}" =~ "Solid State Device" ]];then
                        if [[ "${Model}" =~ "${match_model}" ]] && [[ "${FW_Ver}" != "${match_fw_ver}" ]];then
                                echo -e "\033[31m $j start to update ${Model} sata ssd fw \033[0m"
                                ./hdparm --fwdownload ${upd_fw} --yes-i-know-what-i-am-doing --sanitize-block-erase $j
                                if [[ $? -ne 0 ]];then
                                        continue
                                fi
                                sleep 10
                        fi
                fi
        done
done
}

dell_megaraid_ssd_upd(){
for i in `/opt/MegaRAID/perccli/perccli64 show all |grep -A 10 "Ctl Model" |grep -B 10 "Ctl=Controller Index" |sed -n '/^-/,/-$/p' |grep -v "^-" |awk '{print $1}' |sed '/^\s*$/d'`
do
	/opt/MegaRAID/perccli/perccli64 /c$i/vall delete force >/dev/null 2>&1
        /opt/MegaRAID/perccli/perccli64 /c$i set jbod=on >/dev/null 2>&1
        /opt/MegaRAID/perccli/perccli64 /c$i/eall/sall set jbod > /dev/null 2>&1
done
sleep 5
lsscsi -g |grep ATA > dell_lsi_disk_map
for j in `awk '{print $NF}' dell_lsi_disk_map`
do
        IS_SSD=`smartctl -i $j |grep "Rotation Rate" |awk -F":" '{print $NF}' |sed 's/^\s*//g'`
        Model=`smartctl -i $j |grep "Device Model" |awk -F":" '{print $NF}' |sed 's/\s*//g'`
        FW_Ver=`smartctl -i $j |grep "Firmware Version" |awk -F":" '{print $NF}' |sed 's/\s*//g'`
        for k in `seq 1 $(cat ssd_upd_list |wc -l)`
        do
                match_model=`sed -n "$k"p ssd_upd_list |awk '{print $1}'`
                match_fw_ver=`sed -n "$k"p ssd_upd_list |awk '{print $2}'`
		upd_fw==`sed -n "$k"p ssd_upd_list |awk '{print $3}'`
                if [[ "${IS_SSD}" =~ "Solid State Device" ]];then
                        if [[ "${Model}" =~ "${match_model}" ]] && [[ "${FW_Ver}" != "${match_fw_ver}" ]];then
                                echo -e "\033[31m $j start to update ${Model} sata ssd fw\033[0m"
                                ./hdparm --fwdownload ${upd_fw} --yes-i-know-what-i-am-doing --sanitize-block-erase $j
                                if [[ $? -ne 0 ]];then
                                        continue
                                fi
                                sleep 10
                        fi
                fi
        done
done
}

lsi_mptsas_ssd_upd(){
/opt/op/sas2ircu list  |grep "UNKNOWN" > /dev/null 2>&1
if [[ $? -eq 0 ]];then
	for i in `/opt/op/sas3ircu list |grep SAS |grep -Ev "^SAS|Utility" |awk '{print $1}'`
	do
		/opt/op/sas3ircu $i delete noprompt >/dev/null 2>&1
	done
else
	for i in `/opt/op/sas2ircu list |grep SAS |grep -Ev "^SAS|Utility" |awk '{print $1}'`
	do
		/opt/op/sas2ircu $i delete noprompt >/dev/null 2>&1
	done
fi
lsscsi -g |grep ATA > lsi_hba_ssd_map
for j in `awk '{print $NF}' lsi_hba_ssd_map`;do
	IS_SSD=`smartctl -i $j |grep "Rotation Rate" |awk -F":" '{print $NF}' |sed 's/^\s*//g'`
	Model=`smartctl -i $j |grep "Device Model" |awk -F":" '{print $NF}' |sed 's/\s*//g'`
	FW_Ver=`smartctl -i $j |grep "Firmware Version" |awk -F":" '{print $NF}' |sed 's/\s*//g'`
	if [[ "${IS_SSD}" =~ "Solid State Device" ]];then 
		for k in `seq 1 $(cat ssd_upd_list |wc -l)`
		do
		match_model=`sed -n "$k"p ssd_upd_list |awk '{print $1}'`
        	match_fw_ver=`sed -n "$k"p ssd_upd_list |awk '{print $2}'`
        	upd_fw=`sed -n "$k"p ssd_upd_list |awk '{print $3}'` 
		if [[ "${Model}" =~ "${match_model}" ]] && [[ "${FW_Ver}" != "${match_fw_ver}" ]];then
			echo -e "\033[31m $j ${Model} start to upgrade ${Model} sata ssd firmware \033[0m"
			./hdparm --fwdownload ${upd_fw} --yes-i-know-what-i-am-doing --please-destroy-my-drive $j
			if [[ $? -ne 0 ]];then
				continue
			fi
			sleep 10
		fi
		done
	else
		echo -e "LSI HBA card: $j ${Model} is not an ssd" 
	fi
done
}

pmc_aacraid_ssd_upd(){
for i in `arcconf list |grep "Controllers found" |awk '{print $NF}'`
do
        arcconf delete $i logicaldrive all noprompt >/dev/null 2>&1
        controller_mode=`arcconf list $i |grep -Ew "Controller [0-9]*" |awk -F":" '{print $3}' |awk -F"," '{print $3}' |sed -e 's/(//' -e 's/)//' -e 's/\s*//g'`
        if [[ ${controller_mode} =~ "Hide RAW" ]];then
                arcconf setcontrollermode $i 0 >/dev/null 2>&1
                if [[ $? -ne 0 ]];then
                        echo "Please check the fucking PMC card and driver if any issue"
                        exit 1
                fi
        fi
done
sleep 5
lsscsi -g |grep ATA > pmc_disk_map
for k in `awk '{print $NF}' pmc_disk_map`
do
        IS_SSD=`smartctl -i $k |grep "Rotation Rate" |awk -F":" '{print $NF}' |sed 's/^\s*//g'`
        Model=`smartctl -i $k |grep "Device Model" |awk -F":" '{print $NF}' |sed 's/\s*//g'`
        FW_Ver=`smartctl -i $k |grep "Firmware Version" |awk -F":" '{print $NF}' |sed 's/\s*//g'`
        for m in `seq 1 $(cat ssd_upd_list |wc -l)`
        do
                match_model=`sed -n "$m"p ssd_upd_list |awk '{print $1}'`
                match_fw_ver=`sed -n "$m"p ssd_upd_list |awk '{print $2}'`
		upd_fw=`sed -n "$m"p ssd_upd_list |awk '{print $3}'`
                if [[ "${IS_SSD}" =~ "Solid State Device" ]];then
                        if [[ "${Model}" =~ "${match_model}" ]] && [[ "${FW_Ver}" != "${match_fw_ver}" ]];then
                                echo -e "\033[31m $k start to update ${Model} sata ssd \033[0m"
                                ./hdparm --fwdownload ${upd_fw} --yes-i-know-what-i-am-doing --please-destroy-my-drive $k
                                if [[ $? -ne 0 ]];then
                                        continue
                                fi
                                sleep 10
                        fi
                fi
        done
done
}

pmc_smartpqi_ssd_upd(){
for i in `arcconf list |grep "Controllers found" |awk '{print $NF}'`
do
        arcconf delete $i logicaldrive all noprompt >/dev/null 2>&1
	controller_mode=`arcconf list $i |grep -Ew "Controller [0-9]*" |awk -F":" '{print $3}' |awk -F"," '{print $3}' |sed 's/\s*//g'`
	if [[ ${controller_mode} != "Mixed" ]];then
        	arcconf setcontrollermode $i 5 >/dev/null 2>&1
                if [[ $? -ne 0 ]];then
                        echo "Please check the fucking PMC card and driver if any issue"
                        exit 1
                fi
        fi
done
sleep 5
lsscsi -g |grep ATA > pmc_disk_map
for k in `awk '{print $NF}' pmc_disk_map`
do
        IS_SSD=`smartctl -i $k |grep "Rotation Rate" |awk -F":" '{print $NF}' |sed 's/^\s*//g'`
        Model=`smartctl -i $k |grep "Device Model" |awk -F":" '{print $NF}' |sed 's/\s*//g'`
        FW_Ver=`smartctl -i $k |grep "Firmware Version" |awk -F":" '{print $NF}' |sed 's/\s*//g'`
        for m in `seq 1 $(cat ssd_upd_list |wc -l)`
        do
                match_model=`sed -n "$m"p ssd_upd_list |awk '{print $1}'`
                match_fw_ver=`sed -n "$m"p ssd_upd_list |awk '{print $2}'`
		upd_fw=`sed -n "$m"p ssd_upd_list |awk '{print $3}'`
                if [[ "${IS_SSD}" =~ "Solid State Device" ]];then
                        if [[ "${Model}" =~ "${match_model}" ]] && [[ "${FW_Ver}" != "${match_fw_ver}" ]];then
                                echo -e "\033[31m $k start to update ${Model} sata ssd \033[0m"
                                ./hdparm --fwdownload ${upd_fw} --yes-i-know-what-i-am-doing --please-destroy-my-drive $k
                                if [[ $? -ne 0 ]];then
                                        continue
                                fi
                                sleep 10
                        fi
                fi
        done
done
}

direct_ssd_upd(){
lsscsi -g |grep ATA > direct_disk_map
for i in `awk '{print $NF}' direct_disk_map`;do
        IS_SSD=`smartctl -i $i |grep "Rotation Rate" |awk -F":" '{print $NF}' |sed 's/^\s*//g'`
        Model=`smartctl -i $i |grep "Device Model" |awk -F":" '{print $NF}' |sed 's/\s*//g'`
        FW_Ver=`smartctl -i $i |grep "Firmware Version" |awk -F":" '{print $NF}' |sed 's/\s*//g'`
        if [[ "${IS_SSD}" =~ "Solid State Device" ]];then
		for j in `seq 1 $(cat ssd_upd_list |wc -l)`
		do
		match_model=`sed -n "$j"p ssd_upd_list |awk '{print $1}'`
        	match_fw_ver=`sed -n "$j"p ssd_upd_list |awk '{print $2}'`
        	upd_fw=`sed -n "$j"p ssd_upd_list |awk '{print $3}'`
        	if [[ "${Model}" =~ "${match_model}" ]] && [[ "${FW_Ver}" != "${match_fw_ver}" ]];then
                        echo -e "\033[31m $i start to upgrade ${Model} sata ssd firmware \033[0m"
                        ./hdparm --fwdownload ${upd_fw} --yes-i-know-what-i-am-doing --please-destroy-my-drive $i
                        if [[ $? -ne 0 ]];then
                                continue
                        fi
                        sleep 10
		fi
                done
        else
                echo -e "LSI HBA card: $i ${Model} is not an ssd" 
        fi
done
}

lsi_megaraid_ssd_erase(){
lsscsi -g |grep ATA > lsi_disk_map
for k in `awk '{print $NF}' lsi_disk_map`
do
	IS_SSD=`smartctl -i $k |grep "Rotation Rate" |awk -F":" '{print $NF}' |sed 's/^\s*//g'`	
        Model=`smartctl -i $k |grep "Device Model" |awk -F":" '{print $NF}' |sed 's/\s*//g'`
	FW_Ver=`smartctl -i $k |grep "Firmware Version" |awk -F":" '{print $NF}' |sed 's/\s*//g'`
	for m in `seq 1 $(cat ssd_upd_list |wc -l)`
        do
        	match_model=`sed -n "$m"p ssd_upd_list |awk '{print $1}'`
                match_fw_ver=`sed -n "$m"p ssd_upd_list |awk '{print $2}'`
		if [[ "${IS_SSD}" =~ "Solid State Device" ]];then
        		if [[ "${Model}" =~ "${match_model}" ]] && [[ "${FW_Ver}" == "${match_fw_ver}" ]];then
                		echo -e "\033[31m $k start to erase ${Model} sata ssd \033[0m"
				./hdparm --yes-i-know-what-i-am-doing --sanitize-block-erase $k
				if [[ $? -ne 0 ]];then
					continue
				fi
			fi
		fi
	done
done
sleep 120
for n in `/opt/MegaRAID/storcli/storcli64 show all |grep -A 10 "Ctl Model" |grep -B 10 "Ctl=Controller Index" |sed -n '/^-/,/-$/p' |grep -v "^-" |awk '{print $1}' |sed '/^\s*$/d'`
do
	/opt/MegaRAID/storcli/storcli64 /c$n/eall/sall set good force > /dev/null 2>&1
	/opt/MegaRAID/storcli/storcli64 /c$n set jbod=off
done
}

lsi_mptsas_ssd_erase(){
lsscsi -g |grep ATA > lsi_disk_map
for k in `awk '{print $NF}' lsi_disk_map`
do
        IS_SSD=`smartctl -i $k |grep "Rotation Rate" |awk -F":" '{print $NF}' |sed 's/^\s*//g'`
        Model=`smartctl -i $k |grep "Device Model" |awk -F":" '{print $NF}' |sed 's/\s*//g'`
        FW_Ver=`smartctl -i $k |grep "Firmware Version" |awk -F":" '{print $NF}' |sed 's/\s*//g'`
        for m in `seq 1 $(cat ssd_upd_list |wc -l)`
        do
                match_model=`sed -n "$m"p ssd_upd_list |awk '{print $1}'`
                match_fw_ver=`sed -n "$m"p ssd_upd_list |awk '{print $2}'`
                if [[ "${IS_SSD}" =~ "Solid State Device" ]];then
                        if [[ "${Model}" =~ "${match_model}" ]] && [[ "${FW_Ver}" == "${match_fw_ver}" ]];then
                                echo -e "\033[31m $k start to erase ${Model} sata ssd \033[0m"
                                ./hdparm --yes-i-know-what-i-am-doing --sanitize-block-erase $k
                                if [[ $? -ne 0 ]];then
                                        continue
                                fi
                                sleep 60
				./hdparm --yes-i-know-what-i-am-doing --sanitize-status $k
                        fi
                fi
        done
done
}

dell_megaraid_ssd_erase(){
lsscsi -g |grep ATA > dell_lsi_disk_map
for k in `awk '{print $NF}' dell_lsi_disk_map`
do
        IS_SSD=`smartctl -i $k |grep "Rotation Rate" |awk -F":" '{print $NF}' |sed 's/^\s*//g'`
        Model=`smartctl -i $k |grep "Device Model" |awk -F":" '{print $NF}' |sed 's/\s*//g'`
        FW_Ver=`smartctl -i $k |grep "Firmware Version" |awk -F":" '{print $NF}' |sed 's/\s*//g'`
        for m in `seq 1 $(cat ssd_upd_list |wc -l)`
        do
                match_model=`sed -n "$m"p ssd_upd_list |awk '{print $1}'`
                match_fw_ver=`sed -n "$m"p ssd_upd_list |awk '{print $2}'`
                if [[ "${IS_SSD}" =~ "Solid State Device" ]];then
                        if [[ "${Model}" =~ "${match_model}" ]] && [[ "${FW_Ver}" == "${match_fw_ver}" ]];then
                                echo -e "\033[31m $k start to erase ${Model} sata ssd \033[0m"
                                ./hdparm --yes-i-know-what-i-am-doing --sanitize-block-erase $k
                                if [[ $? -ne 0 ]];then
                                        continue
                                fi
                        fi
                fi
        done
done
sleep 120
for n in `/opt/MegaRAID/perccli/perccli64 show all |grep -A 10 "Ctl Model" |grep -B 10 "Ctl=Controller Index" |sed -n '/^-/,/-$/p' |grep -v "^-" |awk '{print $1}' |sed '/^\s*$/d'`
do
	/opt/MegaRAID/perccli/perccli64 /c$n/eall/sall set good force > /dev/null 2>&1
        /opt/MegaRAID/perccli/perccli64 /c$n set jbod=off
done
}

pmc_aacraid_ssd_erase(){
lsscsi -g |grep ATA > pmc_disk_map
for k in `awk '{print $NF}' pmc_disk_map`
do
        IS_SSD=`smartctl -i $k |grep "Rotation Rate" |awk -F":" '{print $NF}' |sed 's/^\s*//g'`
        Model=`smartctl -i $k |grep "Device Model" |awk -F":" '{print $NF}' |sed 's/\s*//g'`
        FW_Ver=`smartctl -i $k |grep "Firmware Version" |awk -F":" '{print $NF}' |sed 's/\s*//g'`
        for m in `seq 1 $(cat ssd_upd_list |wc -l)`
        do
                match_model=`sed -n "$m"p ssd_upd_list |awk '{print $1}'`
                match_fw_ver=`sed -n "$m"p ssd_upd_list |awk '{print $2}'`
                if [[ "${IS_SSD}" =~ "Solid State Device" ]];then
                        if [[ "${Model}" =~ "${match_model}" ]] && [[ "${FW_Ver}" == "${match_fw_ver}" ]];then
                                echo -e "\033[31m $k start to erase ${Model} sata ssd \033[0m"
                                ./hdparm --yes-i-know-what-i-am-doing --sanitize-block-erase $k
                                if [[ $? -ne 0 ]];then
                                        continue
                                fi
                        fi
                fi
        done
done
sleep 120
}

pmc_smartpqi_ssd_erase(){
rm -rf *_erased_slot_map
for controller_id in `arcconf list |grep "Controllers found" |awk '{print $NF}'`
do
        arcconf getconfig ${controller_id} pd |grep -A10 "Device is a Hard drive" |grep -E "Reported Channel,Device|Model" |awk '{print $NF}' |sed 'N;s/\n/ /' > ${controller_id}_pmc_smartpqi_all_map
        awk -F"(" '{print $1}' ${controller_id}_pmc_smartpqi_all_map > ${controller_id}_all_disk_slot_map
        for j in $(seq 0 `expr $(cat ${controller_id}_all_disk_slot_map |wc -l) - 1`)
        do
        IS_SSD=`smartctl -i -d cciss,$j /dev/sda |grep "Rotation Rate" |awk -F":" '{print $NF}' |sed 's/^\s*//g'`
        Model=`smartctl -i -d cciss,$j /dev/sda |grep "Device Model" |awk -F":" '{print $NF}' |sed 's/\s*//g'`
        FW_Ver=`smartctl -i -d cciss,$j /dev/sda |grep "Firmware Version" |awk -F":" '{print $NF}' |sed 's/\s*//g'`
        New_Channel_ID=$(sed -n "$(($j+1))"p ${controller_id}_all_disk_slot_map |awk -F"," '{print $1}')
        New_Device_ID=$(sed -n "$(($j+1))"p ${controller_id}_all_disk_slot_map |awk -F"," '{print $2}')
                for k in `seq 1 $(cat ssd_upd_list |wc -l)`
                do
                match_model=`sed -n "$k"p ssd_upd_list |awk '{print $1}'`
                match_fw_ver=`sed -n "$k"p ssd_upd_list |awk '{print $2}'`
                        if [[ "${IS_SSD}" =~ "Solid State Device" ]];then
                                if [[ "${Model}" =~ "${match_model}" ]] && [[ "${FW_Ver}" == "${match_fw_ver}" ]];then
                                        echo -e "\033[31m ${New_Channel_ID},${New_Device_ID} start to erase ${Model} sata ssd \033[0m"
                                        #H3C arcconf tool to erase ssd connected in PMC smartpqi RAID/HBA card
                                        arcconf task start ${controller_id} device ${New_Channel_ID} ${New_Device_ID} secureerase pattern 5 noprompt
                                        if [[ $? -ne 0 ]];then
                                                continue
                                        fi
                                        echo -e "${New_Channel_ID} ${New_Device_ID}" >> ${controller_id}_erased_slot_map
                                fi
                        fi
                done
        done
        sleep 120
        for l in $(seq 1 `cat ${controller_id}_erased_slot_map |wc -l`)
        do
                Erased_Channel_ID=`sed -n "$l"p ${controller_id}_erased_slot_map |awk '{print $1}'`
                Erased_Slot_ID=`sed -n "$l"p ${controller_id}_erased_slot_map |awk '{print $2}'`
                #H3C arcconf tool to return original state until erase ssd complete
                arcconf setstate ${controller_id} device ${Erased_Channel_ID} ${Erased_Slot_ID} eed noprompt
        done
done
}

lspci |grep -Ei "lsi|broadcom|pmc|adaptec" |grep -i sas > bdm_pmc_map
if [ -s bdm_pmc_map ];then
	for i in `seq 1 $(cat bdm_pmc_map |wc -l)`
	do
	bus_id=`sed -n "$i"p bdm_pmc_map |awk '{print $1}'`
	sas_description=`echo $(sed -n "$i"p bdm_pmc_map) |tr 'A-Z' 'a-z'`
	if [[ ${sas_description} =~ "adpatec" ]];then
		if [[ "$(arcconf  |grep Version |awk '{print $5}')" !=  "3.02.00" ]];then
                        rpm -Uvh Arcconf-3.02-23597.x86_64.rpm
			echo y |mv /usr/Arcconf/arcconf /usr/sbin/arcconf
                fi
	fi
	driver_type=`lspci -i pci.ids -s ${bus_id} -v |grep "Kernel driver in use" |awk '{print $NF}' |sed 's/\s*//'`
	if [[ "${driver_type}" = "megaraid_sas" ]];then
		Manufacturer=$(dmidecode -s system-manufacturer |tr 'A-Z' 'a-z')
		if [[ "${Manufacturer}" =~ "dell" ]];then
			dell_megaraid_ssd_upd
			dell_megaraid_ssd_erase
		else 
			lsi_megaraid_ssd_upd
			lsi_megaraid_ssd_erase
		fi
	elif [[ "${driver_type}" = "mpt2sas" ]] || [[ "${driver_type}" = "mpt3sas" ]];then
		lsi_mptsas_ssd_upd
		lsi_mptsas_ssd_erase
	elif [[ "${driver_type}" = "aacraid" ]];then 
		pmc_aacraid_ssd_upd
		pmc_aacraid_ssd_erase
	elif [[ "${driver_type}" = "smartpqi" ]];then
		pmc_smartpqi_ssd_upd
                pmc_smartpqi_ssd_erase
	fi
	done
else
	direct_ssd_upd
	direct_ssd_erase
fi	
