#!/bin/bash
# 前置参数
. ${PWD}/defs
RV_OK=0
RV_FAIL=1
ACTIVE_TOOL=""
ACTIVE_TARGS=""
JQTOOL="${PWD}/jq_linux_amd64"
LOGDIR="${PWD}/sistlogs"
mode=""
ROM_TYPE=""
# G40 G50机型 默认是G50 开启CID功能
ModelGeneration="G50" 
chmod +x *

################Funtion Here##############
get_bmc_ipaddr()
{
  local output=""
  local ret=0
  ipmitool lan print 1 >${IPMILOG} 2>&1
  output=$(awk '{if(match($0, "IP Address")){ if($3 != "Source"){print $NF;exit;}}}' ${IPMILOG})
  ret=$?
  echo "${output}"
  return ${RV_OK}
}

get_log_file()
{
local logs=""
logs=$(ls -t ${LOGDIR})
if [ x"${logs}" = "x" ]; then
  return ${RV_FAIL}
fi
for log in ${logs}; do
  echo "${LOGDIR}/${log}"
  break
done
return ${RV_OK}
}

is_update_success()
{
  local logfile="$*"
  local ret=0
  grep -iE "Upgrade ActiveBMC successfully|Upgrade BothBMC successfully|percent 100%"  ${logfile} 
  ret=$?
  if [ ${ret} -eq 0 ]; then
    return ${RV_OK}
  fi
  return ${RV_FAIL}
}

is_authorization_error()
{
  local logfile="$*"
  local ret=0
  grep "Invalid username or password" ${logfile} > /dev/null 2>&1
  ret=$?
  if [ ${ret} -ne 0 ]; then
    return ${RV_OK}
  fi
  return ${RV_FAIL}
}

get_host_sn()
{
  local sn=""
  sn=$(awk -f sn.awk /appmodules/sugon_auto_tests.conf)
  echo "${sn}"
  return ${RV_OK}
}


get_login_data()
{
  local sn="$*"
  local url="http://adm.sims.com:6080/client/v2/getBmcInfo?host=${sn}"
  local bmcjson="${PWD}/bmc.info.json"
  local username=""
  local password=""
  local ret=0
  local output=()
  
  curl -s --location --request GET ${url} -o ${bmcjson}
  username=$(${JQTOOL} .data.bmcUserName -r ${bmcjson})
  ret=$?
  if [ ${ret} -ne 0 ]; then
    return ${RV_FAIL}
  fi

  password=$(${JQTOOL} .data.bmcPassword -r ${bmcjson})
  ret=$?
  if [ ${ret} -ne 0 ]; then
    return ${RV_FAIL}
  fi

  output[0]=${username}
  output[1]=${password}
  echo "${output[@]}"
  return ${RV_OK}
}


function convert_ascii()
{
    ret_ascii=""
    string=$1
    for (( i=0; i<${#string}; i++ ))
    do
        char=${string:i:1}
        ascii_val=$(printf "%x" "'$char")
        ret_ascii="$ret_ascii 0x$ascii_val"
    done
    echo "${ret_ascii#?}"
}

# CID功能
function write_cid()
{
    chmod +x sims_api jq_linux_amd64
    sn=$(get_host_sn)
    if [[ -z $customerId ]]; then
        ./sims_api -I api -T order -O order.json -S $sn
        api_rs=`./jq_linux_amd64 -r .result order.json |grep -ic "NO ERROR"`
        if [[ $api_rs -gt 0 ]]; then
            vendor=`./jq_linux_amd64 -r .data.wgpp order.json`
            customerId=`./jq_linux_amd64 -r .data.customerId order.json`
        else
            echo "[ERROR]Cannot get order info"
            echo "$(cat order.json)"
            exit 1
        fi
    fi
    if [ -z $customerId ]; then
        if [[ $vendor == "NO" ]]; then
            cid="S04"
        elif [[ $vendor == "KKA" ]]; then
            cid="C05"
        elif [[ $vendor == "SGA" ]]; then
            cid="000"
        fi
    else
        cid=$customerId
    fi
    cid_ascii=$(convert_ascii $cid)
    echo "enable eeprom write protect"
    # 沧海G40/G50
    ipmitool raw 0x3a 0x30 0xdc 0x00 0x01 
    [[ $? -eq 0 ]] && echo "沧海G40/G50 enable eeprom write protect"
    #S版G50 
    ipmitool raw 0x3a 0x30 0xc2 0x00 0x01 > /dev/null 2>&1
    ipmitool raw 0x3a 0x30 0xc2 0x01 0x00 
    [[ $? -eq 0 ]] && echo "S版G50  enable eeprom write protect"
    #淮河项目（天翼云）
    ipmitool raw 0x3e 0x30 0xc2 0x00 0x01 > /dev/null 2>&1
    ipmitool raw 0x3e 0x30 0xc2 0x01 0x00 
    [[ $? -eq 0 ]] && echo "淮河项目（天翼云）  enable eeprom write protect"

    echo "write cid"
	# 旧写入CID指令
    ipmitool raw 0x06 0x52 0x51 0xa0 0x00 0x0f 0x20 ${cid_ascii} 0x0 0x0 0x0 0x0 0x0 > /dev/null 2>&1
    ipmitool raw 0x06 0x52 0x0b 0xa0 0x00 0x0f 0x20 ${cid_ascii} 0x0 0x0 0x0 0x0 0x0 > /dev/null 2>&1
    # 新写入CID指令
    ipmitool raw 0x3c 0xff 0x05 ${cid_ascii} 0x0 0x0 0x0 0x0 0x0 > /dev/null 2>&1
    sleep 5s
    cid_ascii=`echo $cid_ascii |sed 's/0x//g'`
    echo "check cid $cid_ascii"
    cid_check=`ipmitool raw 0x06 0x52 0x51 0xa0 0x0f 0x0f 0x20` 
    if [[ -z $cid_check ]];then
        cid_check=`ipmitool raw 0x06 0x52 0x0b 0xa0 0x0f 0x0f 0x20`
		# 新检查CID指令
		 if [[ -z $cid_check ]];then
			cid_check=`ipmitool raw 0x3c 0xff 0x04`
		 fi
    fi
    if [[ ${cid_check} =~ $cid_ascii ]];then
        echo "[PASS] successfully write CID: $cid"
        echo $cid_check
    else
        echo "[ERROR] Fail write CID: $cid"
        echo $cid_check
        exit 1
    fi
}


# 刷新工具选择
function refresh_tool()
{
    echo "刷新工具选择"
    
    # 提取文件名进行判断
    FILENAME=$(basename "$ROM")
    
    # 通过文件后缀进行判断使用的镜像文件
    if [[ "$FILENAME" =~ \.tar$ ]]; then
        echo "检测到TAR格式ROM文件(后缀匹配): $ROM"
        ROM_TYPE="tar"
    else
        echo "非TAR格式的ROM文件格式: $ROM"
    fi
    
    # 刷新工具选择
    if [[ "$ROM_TYPE" == "tar" ]]; then
        ACTIVE_TOOL="${TOOL}"
    else
        echo "FILENAME : ${FILENAME}"
         # 提取型号是否匹配
        if [[ "$FILENAME" =~ (^|_)R6(2|4)(0|4) ]] ; then
            echo "匹配到 R620/R624/R640/R644"
            ACTIVE_TOOL="${tool}"
            ACTIVE_TARGS="${G40A_targs}"
            ModelGeneration="G40A"
        elif [[ "$FILENAME" =~ (^|_)X7(3|4|8)40 ]]; then
            echo "匹配到 X7340/X7440/X7840"
            ACTIVE_TOOL="${tool}"
            ACTIVE_TARGS="${G40A_targs}"
            ModelGeneration="G40A"
        elif [[ "$FILENAME" =~ (^|_)6215 ]]; then
            echo "匹配到 6215 机型"
            ACTIVE_TOOL="${tool}"
            ACTIVE_TARGS="${G40A_targs}"
            ModelGeneration="G40A"
        elif  [[ "$FILENAME" =~ (^|_)R(3|5)240 ]] ; then
            echo "匹配到 R3240/R5240 单镜像版本"
            ACTIVE_TOOL="${tool}"
            ACTIVE_TARGS="${G40S_targs}"
            ModelGeneration="G40S"
        else
            echo "G50机型非TAR文件"
            ACTIVE_TOOL="${tool}"
            ACTIVE_TARGS="${G50targs}"
            ModelGeneration="G50"
        fi

    fi

    ROM="${PWD}/${ROM}"
    ACTIVE_TOOL="${PWD}/${ACTIVE_TOOL}"
    return $RV_OK

}

# 等待BMC重新启动 20分钟
function wait_bmc_up(){
    cnt=1
	sleep 20s
    while true;do
        timeout 2 ipmitool raw 6 1 >/dev/null 2>&1
        if [[ $? -ne 0 ]];then
            sleep 20s
        else
            VER=`ipmitool mc info|grep -i "Firmware Revision"|awk '{print $NF}'`
            echo "BMC is startup now...Current version is $VER"
            return $RV_OK
        fi
        ((cnt++))
        if (( $cnt >= 60 ));then
            echo "## BMC starting up fail ##"
            exit 1
        fi
    done
}

# 执行BMC刷新操作
# sistool工具刷新逻辑
function update_bmc_sistool(){
    LOGDATE=$(date +%Y%m%d%H%M%S)
    IPMILOG=ipmi_lan_${LOGDATE}.log
    sn=$(get_host_sn)

    if [ -f "${JQTOOL}" ]; then
        chmod a+x ${JQTOOL}
    else
        echo "[ERROR]: cannot access ${JQTOOL}  jq工具不存在！"
        exit ${RV_FAIL}
    fi

    curl -X GET "http://adm.sims.com:6080/client/v2/getBmcInfo?host=${sn}" >bmc_info.json
    DEFUSERNAME=`${JQTOOL} -r ".data.bmcUserName" bmc_info.json`
    DEFPASSWORD=`${JQTOOL} -r ".data.bmcPassword" bmc_info.json`

    if [[ -z $DEFPASSWORD || $DEFPASSWORD == null ]]; then
        DEFUSERNAME="Admin"
        DEFPASSWORD="Admin@8000"
    fi

    IPADDR=$(get_bmc_ipaddr)
    # 增加对默认密码的试验
    ipmitool -H ${IPADDR} -U Admin -P Admin@8000 mc info 
    if [[ $? -eq 0 ]]; then
        DEFUSERNAME="Admin"
        DEFPASSWORD="Admin@8000"
    fi
    # 防止密码包含特殊字符
    echo "$DEFPASSWORD" > passwd.txt
    echo "BMC PASSWORD: $DEFPASSWORD"

    if [ -f "${ACTIVE_TOOL}" ]; then
        chmod a+x ${ACTIVE_TOOL}
    else
        echo "[ERROR]: cannot access ${ACTIVE_TOOL}  刷新工具不存在刷新包！"
        exit ${RV_FAIL}
    fi

    
    if [ ! -f "${ROM}" ]; then
        echo "[ERROR]: cannot access ${ROM}  刷新镜像不存在刷新包中！"
        exit ${RV_FAIL}
    fi

    if [ -d "${LOGDIR}" ]; then
        rm -rf ${LOGDIR}
    fi

    IPADDR=$(get_bmc_ipaddr)
    if [ x"${IPADDR}" = "x" ]; then
        echo "[ERROR]: get bmc dedicate lan ipaddr fail  请检查BMC IP是否存在！"
        exit ${RV_FAIL}
    fi

    echo "执行刷新命令: ${ACTIVE_TOOL} update ${ACTIVE_TARGS} -H ${IPADDR} -U ${DEFUSERNAME} -f passwd.txt -I ${ROM}"
    ${ACTIVE_TOOL} update ${ACTIVE_TARGS} -H ${IPADDR} -U ${DEFUSERNAME} -f passwd.txt -I ${ROM}

    LOGFILE=$(get_log_file)
    if [ x"${LOGFILE}" = "x" ]; then
        echo "[ERROR]: sistlogs directory is empty  刷新日志不存在！"
        exit ${RV_FAIL}
    fi  


    is_update_success "${LOGFILE}"
    RET=$?
    if [ ${RET} -eq ${RV_OK} ]; then
        echo "Waitting for BMC  to bootup in moment...  等待BMC重启中..."
        wait_bmc_up
        RET=$?
        if [ ${RET} -eq ${RV_OK} ]; then
            echo "[INFO]: BMC firmware upgrade success  刷新成功！" 
            return ${RV_OK}
        fi
    else
        echo "[INFO]: BMC firmware upgrade fail  刷新失败！"
        #is_authorization_error "${LOGFILE}"
        #RET=$?
        #if [ ${RET} -ne ${RV_OK} ]; then
        echo "[ERROR]: BMC firmware upgrade fail"
        echo "[LOG]: ================================ START ======================================="
        tail -n 30 ${LOGFILE}
        echo "[LOG]: ================================  END  ======================================="
        exit ${RV_FAIL}
        #fi
    fi


}

# 执行BMC刷新操作
# socflash工具刷新逻辑
function update_bmc_socflash(){
    LOGDATE=$(date +%Y%m%d%H%M%S)
    LOGFILE=45_bmc_upgrade_${LOGDATE}.log
    echo "update $1 time: $LOGDATE"
    ipmitool mc info |grep -i "firmware" &>/dev/null
    [[ $? -ne 0 ]] && systemctl restart ipmi.service
    ipmitool mc info |grep -i "firmware" &>/dev/null
    [[ $? -ne 0 ]] && echo "check ipmi service fail" && ipmitool mc info && exit 1
    
    #unlock BMC G40没有锁
    if [[ ! "${ModelGeneration}" =~ "G40" ]]; then
        # A/S版G50 unlock bmc命令
        ipmitool raw 0x3a 0x1a 0x01
        if [ $? -eq 0 ]; then
            echo "Succeeded to unlock write Protect using 0x3a..."
        else
            #淮河项目（天翼云）
            ipmitool raw 0x3e 0x1a 0x01
            if [ $? -eq 0 ]; then
                echo "Succeeded to unlock write Protect using 0x3e..."
            else
                echo "Failed to unlock write Protect with both methods"
                exit 1
            fi
        fi

        echo "Succeeded to unlock write Protect ..."
        sleep 2
    fi
    
    chmod +x ${ACTIVE_TOOL}
    echo "${ACTIVE_TOOL} ${ACTIVE_TARGS} if=${ROM} cs=$1 "
    echo y | ${ACTIVE_TOOL} ${ACTIVE_TARGS} if=${ROM} cs=$1 >> $LOGFILE
    sleep 5 
    grep -i "Update Flash Chip O.K" ${LOGFILE} &>/dev/null
    RET=$?
    cat ${LOGFILE}
    if [ ${RET} -ne 0 ]; then
        echo "##################################"
        echo "## 2. Upgrade BMC Failed.       ##"
        echo "##################################"
        exit ${RV_FAIL}
    fi
    echo "##################################"
    echo "## 2. Upgrade BMC Successfully. ##"
    echo "##################################"
    echo "Waitting for BMC $1 to bootup in moment..."

    wait_bmc_up

}

# select BMC
function select_bmc()
{
    
   
   
    # 判断BMC的主备镜像  区分G40 G50平台
    mode=`ipmitool raw 0x32 0x008f 0x07|tr -d [:space:]`
    if [[ -z ${mode} ]];then
        mode=`ipmitool raw 0x3c 0x008f 0x07  |tr -d [:space:]`
        if [[ -z ${mode} ]];then
            mode=`ipmitool raw 0x3c 0x008f 0x07 0x00 |tr -d [:space:]`
        fi
    fi

    echo "mode: ${mode}"
# 01: 正在使用主镜像，备镜像闲置
# 02：正在使用备镜像，主镜像闲置
# 09：正在使用主镜像，备镜像不在位或者故障
# 06：正在使用备镜像
# 0a：正在使用备镜像，主镜像不在位或故障
    case ${mode} in 
        01)
            if [[ "$ACTIVE_TOOL" =~ sistool  ]]; then
                ACTIVE_TARGS='bothbmc -N'
                update_bmc_sistool
            else
                CS=2
                update_bmc_socflash 1
                update_bmc_socflash 0 
            fi
			
			# 写CID
			if [[ "${ModelGeneration}" =~ "G50" ]] || [[ "${ROM_TYPE}" =~ "tar" ]] || [[ "x${customerId}" != "x" ]] ; then
				echo "开始写入CID"
				write_cid
			fi
			
			ipmitool mc reset cold
			wait_bmc_up
            ;;
        09)
            if [[ "$ACTIVE_TOOL" =~ sistool  ]]; then
                ACTIVE_TARGS='bmc -N'
                update_bmc_sistool
            else
                CS=0
                update_bmc_socflash 0 
            fi
			
			# 写CID
			if [[ "${ModelGeneration}" =~ "G50" ]] || [[ "${ROM_TYPE}" =~ "tar" ]] || [[ "x${customerId}" != "x" ]] ; then
				echo "开始写入CID"
				write_cid
			fi
			ipmitool mc reset cold
			wait_bmc_up
            ;;
        *)
            echo "Please check BMC chip  请检查BMC 镜像状态是否正常"
            echo "02：正在使用备镜像，主镜像闲置"
            echo "06：正在使用备镜像"
            echo "0a：正在使用备镜像，主镜像不在位或故障"
            echo "当前BMC镜像状态:${mode} "
        exit 2
    esac
	
	
    
}

#############Start Here##################
modprobe -r ipmi_si
modprobe ipmi_si

refresh_tool

if [[ "$ACTIVE_TOOL" =~ socflash_x64  ]]; then

    # 如果是G40S版本 直接套用旧规则，直接开刷
    if [[ "${ModelGeneration}" =~ "G40S" ]]; then
        LOGDATE=$(date +%Y%m%d%H%M%S)
        LOGFILE=45_bmc_upgrade_${LOGDATE}.log
        echo "##############################"
        echo "## 1. Start Upgrade BMC ... ##"
        echo "##############################"
        chmod +x ${ACTIVE_TOOL}
        ${ACTIVE_TOOL} ${ACTIVE_TARGS} if=${ROM} |tee -a ${LOGFILE}

        grep -i "Update Flash Chip O.K" ${LOGFILE} &>/dev/null
        RET=$?
        cat ${LOGFILE}
        if [ ${RET} -ne 0 ]; then
            echo "##################################"
            echo "## 2. Upgrade BMC Failed.       ##"
            echo "##################################"
            exit ${RV_FAIL}
        fi
            echo "##################################"
            echo "## 2. Upgrade BMC Successfully. ##"
            echo "##################################"
            # 等待BMC被激活
            wait_bmc_up

            exit ${RV_OK}
        
    fi

    echo "Begin at: $(date)"
    echo "##############################"
    echo "## 1. Start Upgrade BMC ... ##"
    echo "##############################"
    echo $sn

    ipmitool fru >ipmitool.log 2>&1
    echo "$(cat ipmitool.log)"

    timeout 2 ipmitool raw 6 1 &>/dev/null
    if [[ $? -eq 0 ]]; then
        select_bmc
    else
        update_bmc_socflash 0
        select_bmc
    fi
    echo "End at: $(date)"
else
    select_bmc
fi

exit ${RV_OK}



