#!/bin/bash
# =============================================================================
#  raid_fw_update.sh -- RAID Controller Firmware Updater
#  Detects all controllers and updates any that are outdated
# =============================================================================

if ! command -v storcli &>/dev/null; then
    echo "ERROR: storcli not found"
    exit 1
fi

# Supported controllers: key=match_string, value="LATEST|ROM|URL|IS_ZIP"
declare -A CTRL_LATEST=(
    ["9361"]="24.21.0-0159"
    ["3108"]="24.21.0-0151"
    ["3908"]="52.33.0-6171"
    ["3916"]="52.33.0-6171"
)

declare -A CTRL_ROM=(
    ["9361"]="24.21.0-0159_SAS_MR_FW_IMAGE_APP_4.680.00-8577.zip"
    ["3108"]="smc3108.rom"
    ["3908"]="S3908L_52.33.0-6171.rom"
    ["3916"]="S3916L_52.33.0-6171.rom"
)

declare -A CTRL_URL=(
    ["9361"]="http://184.154.112.130/raid/lsi/9361/24.21.0-0159_SAS_MR_FW_IMAGE_APP_4.680.00-8577.zip"
    ["3108"]="http://184.154.112.130/raid/lsi/3108/4.680.00-8561/smc3108.rom"
    ["3908"]="http://216.104.40.250/raid/lsi/AOC-S3908L/S3908L_52.33.0-6171.rom"
    ["3916"]="http://216.104.40.250/raid/lsi/AOC-S3916L/S3916L_52.33.0-6171.rom"
)

declare -A CTRL_IS_ZIP=(
    ["9361"]=1 ["3108"]=0 ["3908"]=0 ["3916"]=0
)

# Get all controller indices
CTRL_COUNT=$(storcli show 2>/dev/null | grep -oE 'Number of Controllers = [0-9]+' | grep -oE '[0-9]+$')
[ -z "$CTRL_COUNT" ] && CTRL_COUNT=1

OVERALL_EXIT=0

for ci in $(seq 0 $(( CTRL_COUNT - 1 ))); do
    echo "========================================"
    echo "Controller /c${ci}"
    echo "========================================"

    CTRL_OUTPUT=$(storcli /c${ci} show 2>/dev/null)
    if [ -z "$CTRL_OUTPUT" ]; then
        echo "ERROR: Cannot read /c${ci}"
        continue
    fi

    PRODUCT=$(echo "$CTRL_OUTPUT" | grep "Product Name" | awk -F= '{print $2}' | xargs)
    FW_PKG=$(echo "$CTRL_OUTPUT"  | grep "FW Package Build" | awk -F= '{print $2}' | xargs)

    echo "Controller detected: $PRODUCT"
    echo "Current FW:          $FW_PKG"

    # Match controller type
    CTRL_KEY=""
    if   echo "$PRODUCT" | grep -qi "9361"; then CTRL_KEY="9361"
    elif echo "$PRODUCT" | grep -qi "3108"; then CTRL_KEY="3108"
    elif echo "$PRODUCT" | grep -qi "3908"; then CTRL_KEY="3908"
    elif echo "$PRODUCT" | grep -qi "3916"; then CTRL_KEY="3916"
    else
        echo "ERROR: Controller '$PRODUCT' is not supported (EOL or unknown)"
        OVERALL_EXIT=1
        continue
    fi

    LATEST="${CTRL_LATEST[$CTRL_KEY]}"
    ROM="${CTRL_ROM[$CTRL_KEY]}"
    URL="${CTRL_URL[$CTRL_KEY]}"
    IS_ZIP="${CTRL_IS_ZIP[$CTRL_KEY]}"

    echo "Controller type:     $CTRL_KEY"
    echo "Latest FW:           $LATEST"

    if echo "$FW_PKG" | grep -q "$LATEST"; then
        echo "RAID FW IS AT LATEST VERSION ($FW_PKG) -- NO UPDATE NEEDED"
        continue
    fi

    echo "UPDATE NEEDED: $FW_PKG -> $LATEST"
    echo "Downloading firmware..."

    WORKDIR=$(mktemp -d /tmp/fw_${CTRL_KEY}.XXXXXX)
    cd "$WORKDIR"

    if [ "$IS_ZIP" -eq 1 ]; then
        if ! wget -q "$URL" -O "$ROM"; then
            echo "ERROR: Failed to download $URL"
            rm -rf "$WORKDIR"; OVERALL_EXIT=1; continue
        fi
        echo "Extracting firmware..."
        if ! unzip -q "$ROM"; then
            echo "ERROR: Failed to extract $ROM"
            rm -rf "$WORKDIR"; OVERALL_EXIT=1; continue
        fi
        ROM_FILE=$(find . -name "*.rom" | head -1)
        if [ -z "$ROM_FILE" ]; then
            echo "ERROR: No .rom file found in zip"
            rm -rf "$WORKDIR"; OVERALL_EXIT=1; continue
        fi
        ROM_FILE=$(basename "$ROM_FILE")
    else
        if ! wget -q "$URL" -O "$ROM"; then
            echo "ERROR: Failed to download $URL"
            rm -rf "$WORKDIR"; OVERALL_EXIT=1; continue
        fi
        ROM_FILE="$ROM"
    fi

    echo "Firmware downloaded: $ROM_FILE"
    echo "Flashing /c${ci} -- controller will reset after update..."
    echo "WARNING: Do not interrupt this process!"

    storcli /c${ci} download file="$ROM_FILE" ResetNow
    FDT=$?

    cd /tmp
    rm -rf "$WORKDIR"

    if [ $FDT -eq 0 ]; then
        echo "RAID FIRMWARE UPDATE COMPLETE on /c${ci} -- Controller is resetting"
        echo "Wait 2-3 minutes before running QA Summary"
    else
        echo "ERROR: Firmware update failed on /c${ci} (exit code $FDT)"
        OVERALL_EXIT=1
    fi
done

exit $OVERALL_EXIT