#!/bin/sh

export BD="/mnt/ramdisk/bundle"
export CFG="/mnt/cfg"

source /usr/bin/fcns.shinc
source /usr/bin/utils.sh

# =====================================================================
# $1 - Name of the ini file with mtd-to-file properties
# $2 - Name of the folder where all files will we saved
# =====================================================================
createMcMtdFiles()
{
    local iniFile="$1"
    local outFolder="$2"

    mkdir -p "$outFolder"

    # depends on info in fcns.shinc to tell which partitions
    getExtractableMtds mtdNames

    for name in $mtdNames; do
        apiActive $actComp "Install $name."
        # See if we need to save meta-data about the partition to its tail
        local map=mtd_mc_$name
        eval local outFile="\$$map"
        local partnbr=mtdnbr_$name
        eval local partition="/dev/mtd\$$partnbr"

        local nbrBytes=$(inicntrl "$iniFile" "${outFile//\./_}" size)
        if [ -n "$nbrBytes" ]; then
            dd if=$partition of=$outFolder/$outFile \
               bs=$nbrBytes count=1

            md5Orig=$(calcmd5 $partition 0 $nbrBytes)
            md5New=$(calcmd5 $outFolder/$outFile)
            local md5Expected=$(inicntrl "$iniFile" "${outFile//\./_}" md5sum)

            if [ "$md5Orig" == "$md5New" ]; then
                if [ "$md5New" == "$md5Expected" ]; then
                    apiActive $actComp "Verified - Extracted file $name from mtd partition"
                else
                    apiError $actComp 2006 "ERROR - md5sum from version.txt does not match mtd file $outFile"
                    local badBundle=$(inicntrl "$iniFile" system_bundle version)
                    apiError $actComp 2006 "ERROR - bad version.txt has system_bundle.version=$badBundle"
                    return 1
                fi
            else
                apiError $actComp 2006 "ERROR - md5sum error while extracting mtd file $outFile"
                return 1
            fi
        fi
    done

    return 0

}

# =====================================================================
# $1 - returns:  variable name to place true/false status
# =====================================================================
checkPrepI2c()
{
    # workaround:  some systems seem to not communicate at first.
    # Run a couple of commands to prime the pump.
    local rc=0
    for i1 in $(seq 0 4); do
        results=$(i2c-codeload --target cpld --currinfo 2>&1)
        rc=$?
        if [ "$rc" -eq 0 ]; then
            break
        else
            echo "$i1 currinfo failed"
            echo "$results"
        fi

        sleep 0.8
    done

    local isWorking
    [ "$rc" -eq 0 ] && isWorking=true || isWorking=false
    eval "$1=$isWorking"
}

echo "buildbundle: $@"

doCFG=false
doFW=false

for var in "$@"
do
    case "$var" in
    "cfg")
    doCFG=true
    ;;
    "fw")
    doFW=true
    ;;
    *)
    echo "arg $var specified."
    ;;
    esac
done

echo "cfg=$doCFG, fw=$doFW"

### first the common stuff
actComp="/"
apiActive $actComp "Building PFU bundle."

# start fresh
if [ -d ${BD} ]
then
    rm -rf ${BD}
fi

# make the directory structure
mkdir ${BD}
cd ${BD}
# the rest of the script runs within the bundle directory

for name in mc ec sc cpld cfg; do
    echo "making $name/components"
    mkdir -p $name/components
done

# add scripts
tar xvf /usr/local/bundlepatchpfu.tar

if ! $doFW; then
    # only keep cfg
    rm ec/update.sh sc/update.sh cpld/update.sh mc/update.sh
fi

# add bundle additions
/usr/bin/bundleadditions.sh "/" "${BD}"

# touch any general files
touch is.spiboot
touch is.pfu
touch do.reboot

# copy any additional files manually
if [ -f /app/relinfo/release.xml ]
then
    cp /app/relinfo/release.xml mc
fi

# mix in any CFG specific stuff
if $doCFG; then
    actComp="/bundle/cfg"
    apiActive $actComp "adding Configuration."

    touch is.cfg

    if [ -d "${CFG}/brand" ]
    then
        mkdir cfg/components/brand
        cp -R ${CFG}/brand/* cfg/components/brand
    fi
    mkdir cfg/components/etc
    if [ -d "${CFG}/etc/autopool" ]
    then
        mkdir cfg/components/etc/autopool
        cp -R ${CFG}/etc/autopool/* cfg/components/etc/autopool
    fi
    if [ -d "${CFG}/etc/health" ]
    then
        mkdir cfg/components/etc/health
        cp -R ${CFG}/etc/health/* cfg/components/etc/health
    fi
    mkdir cfg/components/etc/config
    cp ${CFG}/etc/config/snmpd.conf cfg/components/etc/config

    for name in opt roles rs scheds sfcb ssl sysinfo tasks users; do
        echo "$PWD"
        echo "making cfg/components/$name"
        mkdir -p cfg/components/$name
        echo "copying from ${CFG}/$name/ to cfg/components/$name"
        cp -R ${CFG}/$name/* cfg/components/$name
    done

    mkdir cfg/components/ssh
    cp ${CFG}/ssh/sshd_config cfg/components/ssh/sshd_config

    apiOK $actComp

fi

if $doFW; then
    actComp="/bundle/fw"
    apiActive $actComp "adding Firmware."

    ## MC

    ### this version of the MC supports clean pfu, so indicate as such
    touch do.cleanpfu

    genAllMtdPropVariables "$(cat /proc/moose/mtd)"
    # we're going to be extracting the flash images given a manifest definition for sizes
    # the best would be /cfg/version.txt
    # next best would be /app/mc_system_version.txt
    VERSFILE=""
    if [ -f ${CFG}/version.txt ]
    then
        VERSFILE="${CFG}/version.txt"
    else
        if [ -f /app/mc_system_version.txt ]
        then
            VERSFILE="/app/mc_system_version.txt"
        fi
    fi
    mkdir -p system
    cp $VERSFILE system
    cp $VERSFILE mc
    createMcMtdFiles  ${VERSFILE} mc/components
    rc=$?

    if [ -d ${CFG}/ecfw ]; then
        mkdir -p ec/components
        cp ${CFG}/ecfw/* ec/components
        rm -f ec/components/midplane
    fi

    ## CPLD
    checkPrepI2c i2cIsWorking
    if ! $i2cIsWorking; then
        echo "Failure when attempting cpld flash"
        echo "Could not communicate to i2c connection."
        apiError $actComp 1403 "Unrecoverable CPLD flash error."
        exit $LOAD_STATUS_FAILED
    fi

    mkdir -p cpld/components
    for i in $( seq 1 3 ); do
        i2c-codeload --target cpld --read cpld/components/CPLD_PFU.bit
        cpldRC=$?
        if [ $cpldRC -eq 0 ]; then
            i2c-codeload --checkfile cpld/components/CPLD_PFU.bit --target cpld
            cpldRC=$?
            if [ $cpldRC -eq 0 ]; then
                i2c-codeload --target cpld --verify cpld/components/CPLD_PFU.bit
                cpldRC=$?
                [ $cpldRC -eq 0 ] && break
            fi
        fi
    done

    ### when we implement centralized MC PFU, we will add the other components here

    if [ "$rc" -eq "0" -a "$cpldRC" -eq "0" ]
    then
        apiOK $actComp
    else
        rm -rf ${BD}
        # if we messed up, we really do not want to flash the partner. We're going to clear this out and fail the PFU.
        apiError $actComp 2006 "Bundle build failure."
        exit 1
    fi

fi

actComp="/"
apiOK $actComp
exit 0
