#!/bin/sh
#
# Copyright (c) 2015-2016, 2018-2022 by Cisco Systems, Inc.
# All rights reserved.
#
# This script runs on host and Calvados
# On Host it creates a ubifs type volume and device
# On Calvados it simply mounts this volume on /mnt/plog for obfl to use
#
# Check the onboard flashes.
# There are two MTD flashes
# 1. Bootflash 128MB on FC and SC 
# 2. OBFL 64MB on all the cards
# We use UBIFS on them. 
# Check if they have been formatted already. 
# If not, format them accordingly.
#
# mtdparts from /proc/cmdline
# FOR Fretta RP 
#mtdparts=physmap-flash.0:256k(SM_LOG),256k(RR_LOG),256k(KLOG),18m(PLOG),512k(mtdoops)
# FOR Pizza Box RPs and Fretta LC
#mtdparts=physmap-flash.0:256k(SM_LOG),256k(RR_LOG),256k(KLOG),18m(PLOG),512k(mtdoops),4m(shmoo)
# FOR SC AND FC
# mtdparts=physmap-flash.0:64m(bootflash);physmap-flash.1:256k(SM_LOG),256k(RR_LOG),18m(PLOG),256k(KLOG),1m(mtdoops),16m(KTRACES)
# /dev/mtd3 represents the OBFL PLOG
# /dev/mtd5 represents SHMOO 
#
# NOTE:!!!!
# Please check the cmdline param definition in the imaging file for the
# definition of mtdparts. This cmdline param will dictate the number of mtd
# devices we see and the sizes of it in kernel.
#
# After UBI formatting, 
# /dev/ubi3_0 will be /mnt/plog
# /dev/ubi5_0 will be /mnt/shmoo 
#
# Thinxr 'check-flash' changes merged with this script.
# Changes include:
# Arguments to work for Fixed, RP, FC and LC instead of static
# mounts in the main().
# A few additional checks and some changes in the flow.
# The mtd_num is derived from mtd_name,
# mtd_num is subsequently used for all functions.

function am_i_thinxr()
{
    [[ -e "/opt/cisco/thinxr/am_i_thinxr" ]]
}

if am_i_thinxr; then
    CHECKFLASH="/var/log/check_flash_$2.log"
else
    # import helpers
    source /etc/init.d/spirit_pd.sh
    CHECKFLASH=/var/log/check-flash.log
fi

PLOG_MTD_NUM=3
SHMOO_MTD_NUM=5
BOOTFLASH_MTD_NUM=0
HDD_PART_NUM=5
EXT2_FS_MAGIC_NUMBER=0xEF53

#CHECKFLASH=/dev/null
CHECK_OBFL_FLASH=/var/run/check_obfl_flash
fs_sb_output=/tmp/fs_sb_output

check_mtd() {

    if am_i_thinxr; then
        local mtdname=$1
        local mtdnum
        mtdnum=$(ls /sys/class/mtd/mtd*/name | xargs grep "^${mtdname}$" | \
                  cut -d'/' -f5 | grep -o "[0-9]*")
        if [ -z "$mtdnum" ]; then
            echo "$(date): mtd:${mtdname} not found." >> $CHECKFLASH
            echo -1
            return
        fi
        echo $mtdnum
    else
        local mtdnum=$1
        local mtdname=$2
        local my_mtdname

        local mtddev="mtd${mtdnum}"

        if [ ! -e /sys/class/mtd/${mtddev} ]; then
            echo "$(date): /dev/${mtddev} not found." >> $CHECKFLASH
            exit -1
        fi

        my_mtdname=$(cat /sys/class/mtd/${mtddev}/name | tr '[:upper:]' '[:lower:]')

        if [ "$my_mtdname" != "$mtdname" ]; then
            echo "$(date): /dev/${mtddev} $mtdname not found." >> $CHECKFLASH
            exit -1
        fi
   fi
}

check_block() {

    local partnum=$1
    local partname=$2
    local my_partname

    if [ ! -e /sys/class/block/${partname} ]; then
        echo "$(date): /dev/sda${partnum} not found." >> $CHECKFLASH
        exit -1
    fi

    my_partname=$(cat /sys/class/block/${partname}/uevent | grep DEVNAME= | sed 's/^.*DEVNAME=//')

    if [ "$my_partname" != "$partname" ]; then
        echo "$(date): /dev/sda${partnum} not found." >> $CHECKFLASH
        exit -1
    fi
}

check_bad_files() {
    local mount_dir=$1

    # Check you can list the files.
    ls -R $mount_dir/ > /dev/null 2>> $CHECKFLASH
    if [ $? -ne 0 ]; then
        echo "$(date): Cannot ls directory. The filesystem looks bad" >> $CHECKFLASH
        echo -1
        return
    fi

    # Check you can read all files.
    if [ -n "$(ls $mount_dir/)" ]; then
        for file in `ls $mount_dir`
        do
            if [ ! -f $mount_dir/$file ]; then
                continue
            fi
            if am_i_thinxr; then
                md5sum $mount_dir/$file >/dev/null 2>> $CHECKFLASH
            else
                cksum $mount_dir/$file > /dev/null
            fi
            if [ $? -ne 0 ]; then
                echo "$(date): Can not read file, The filesystem looks bad" >> $CHECKFLASH
                echo -1
                return
            fi
        done
    fi

    # Check you can write a file
    touch $mount_dir/test_sanity
    echo "BADBEEF" > $mount_dir/test_sanity
    if [ $? -ne 0 ]; then
        echo "$(date): Can not write a file, The filesystem looks bad" >> $CHECKFLASH
        echo -1
        return
    fi
    rm -rf $mount_dir/test_sanity > /dev/null 2>> $CHECKFLASH

    if am_i_thinxr; then
        local ubi_part=$2
        local magic_errors
        local node_errors
        local crc_errors

        # we may have missed some crc errors which have not been propaged to
        # userspace (crc corruption of inodes)
        magic_errors=$(cat /sys/fs/ubifs/$ubi_part/errors_magic)
        node_errors=$(cat /sys/fs/ubifs/$ubi_part/errors_node)
        crc_errors=$(cat /sys/fs/ubifs/$ubi_part/errors_crc)
        if [ $(($magic_errors + $node_errors + $crc_errors)) -gt 0 ]; then
            echo "$(date): Found $magic_errors magic error(s), $node_errors node error(s) and $crc_errors crc error(s) not deteced by userspace" >> $CHECKFLASH
	    echo -1
	    return
        fi

        echo "$(date): Filesystem working correctly." >> $CHECKFLASH
        echo 0
    fi
}

check_mount() {
    local mtd_num=$1
    local mount_dir=$2
    local mtd_name=$3
    local mounted_fs
    local ubi_part
    echo "$(date): Check if ${mount_dir} mounted." >> $CHECKFLASH

    mounted_fs=$(grep $mount_dir /proc/mounts | grep "ubi${mtd_num}" | cut -d' ' -f3)
    # check if not mounted
    if [ -z "${mounted_fs}" ]; then
        echo "$(date): Directory ${mount_dir} not mounted." >> $CHECKFLASH
        echo -1
        return
    fi

    # check if mounted with other filesystem
    if [ "$mounted_fs" != "ubifs" ]; then
        echo "$(date): Mounted but not with ubifs mounted, so umount." >> $CHECKFLASH
        umount $mount_dir &>> $CHECKFLASH
        echo -1
        return
    fi

    ubi_part=$(basename $(grep $mount_dir /proc/mounts | grep "ubi${mtd_num}" | cut -d' ' -f1))
    echo "$(date): Mounted with ubifs, check if correctly mounted." >> $CHECKFLASH
    # check if read write works fine
    if [ $(check_bad_files $mount_dir $ubi_part) -ne 0 ]; then
        echo "$(date): File operations on ${mount_dir} failed. Not mounted correctly" >> $CHECKFLASH
        umount $mount_dir &>> $CHECKFLASH
        echo -1
        return
    fi

    echo "$(date): Directory $mount_dir mounted correctly." >> $CHECKFLASH
    if [ -e /mnt/${mtd_name} ]; then
        rm /mnt/${mtd_name}
    fi
    ln -s ${mount_dir} /mnt/${mtd_name}
    echo 0
}

# Mount UBIFS on mtd partition
mount_ubifs_on_thinxr() {
    local ret
    local mtd_num=$1
    local mount_dir=$2
    local mtd_name=$3
    local ubi_part="ubi${mtd_num}_0"
    local current_name

    if [ ! -c "/dev/${ubi_part}" ]; then
        echo "$(date): Partition ${ubi_part} does not exist. Bailing out of function mount_ubifs." >> $CHECKFLASH
        echo -1
        return
    fi

    current_mtd_name=$(ubinfo "/dev/${ubi_part}" 2>> CHECKFLASH | grep ^Name | cut -b 14-)
    if [ ""${mtd_name} != ""${current_mtd_name} ]; then
        echo "$(date): Remote CPUless card was moved from one slot to another. Renaming partition ${current_mtd_name} to ${mtd_name}." >> $CHECKFLASH
        ubirename "/dev/ubi${mtd_num}" $current_mtd_name $mtd_name &>> CHECKFLASH

        local err=$?
        if [ $err -ne 0 ]; then
            echo "$(date): Renaming partition ${current_mtd_name} to ${mtd_name} failed with $err" >> $CHECKFLASH
            echo -1
            return
        fi
    fi

    echo "$(date): Mounting ubifs on ${mount_dir}." >> $CHECKFLASH

    # example: mount -o chk_data_crc -t ubifs ubi0_0 /mnt/obfl
    mount -o chk_data_crc -t ubifs "/dev/${ubi_part}" ${mount_dir} &>> $CHECKFLASH

    local err=$?
    if [ $err -ne 0 ]; then
        echo "$(date): Mounting ${mount_dir} failed with $err" >> $CHECKFLASH
        echo -1
        return
    fi

    # restore content context
    # only happens on selinux enabled platforms when current label doesnot
    # match expectation
    # example outputs of ls -lZd and matchpathcon:
    # drwxr-xr-x. 2 root root system_u:object_r:iosxr_var_t:s0 6632 Nov  3 23:14 /mnt/mtd0/
    # /mnt/mtd0       system_u:object_r:iosxr_var_t:s0
    local slx_enforced=$(grep -cw slx_enforce /proc/cmdline)
    if [ $slx_enforced -eq 1 ]; then
        echo $(date): Selinux: System is selinux enabled >> $CHECKFLASH
        local current_label=$(ls -lZd ${mount_dir})
        local expected_label=$(matchpathcon ${mount_dir})
        local current_type=$(echo $current_label | cut -d ":" -f 3)
        local expected_type=$(echo $expected_label | cut -d ":" -f 3)
        if [ $current_type == $expected_type ]; then
            echo "$(date): Selinux: No need to restore context for ${mount_dir}" >> $CHECKFLASH
        else
            echo "$(date): Selinux: Restoring context for ${mount_dir}" >> $CHECKFLASH
            restorecon -RF ${mount_dir}
        fi
    else
        echo $(date): Selinux: System is NOT selinux enabled >> $CHECKFLASH
    fi

    # check if mount went through
    if [ $(check_mount ${mtd_num} ${mount_dir} ${mtd_name}) -ne 0 ]; then
        echo "$(date): Mounting ubifs on ${mount_dir} failed." >> $CHECKFLASH
        echo -1
        return
    fi
    echo 0
}

format_ubi_on_mtd() {

    local mtd_num=$1
    local vol_name=$2
    local mount_dir=$3
    local dev_mtd="/dev/mtd${mtd_num}"
    local dev_ubi="/dev/ubi${mtd_num}"
    local ret
    # STEPS:
    # 1. ubidetach
    # 2. ubiformat
    # 3. ubiattach
    # 4. ubimkvol
    # 5. mount (on non vm platform)

    echo "$(date): Doing ubidetach on ${dev_mtd}." >> $CHECKFLASH
    ubidetach -m ${mtd_num} &>> $CHECKFLASH
    if ! am_i_thinxr; then
        # punch the watchdog
        pd_punch_watchdog

        # Send post code to indicate MTD device format has started
        pd_notify_host_mtd_format_started
    fi

    echo "$(date): Doing ubiformat on ${dev_mtd}." >> $CHECKFLASH
    ubiformat ${dev_mtd} -y &>> $CHECKFLASH
    ret=$?
    if [ $ret -ne 0 ]; then
        echo "$(date): UBI Formating of ${dev_mtd} failed with $ret. ${dev_ubi}" >> $CHECKFLASH
        if ! am_i_thinxr; then
            # Send post code to indicate MTD device format has failed
            pd_notify_host_mtd_format_failed
            exit -1
        fi
        echo -1
        return
    fi

    echo "$(date): Doing ubiattach on ${dev_mtd}." >> $CHECKFLASH
    ubiattach -m ${mtd_num} -d ${mtd_num} &>> $CHECKFLASH

    echo "$(date): Doing ubimkvol on ${dev_mtd}." >> $CHECKFLASH
    # -m for use maximum size of the mtd for the volume
    ubimkvol ${dev_ubi} -N ${vol_name} -m &>> $CHECKFLASH
    ret=$?
    if [ $ret -ne 0 ]; then
        echo "$(date): UBI Volume [${vol_name}] creation on ${dev_ubi} failed with $ret." >> $CHECKFLASH
        if ! am_i_thinxr; then
            # Send post code to indicate MTD device volume creation has failed
            pd_notify_host_mtd_mkvol_failed
            exit -1
        fi
        echo -1
        return
    fi

    if ! am_i_thinxr; then
        # Send post code to indicate MTD device format and volume creation
        #  has ended
        pd_notify_host_mtd_format_ended
    else
        # check if mount with ubifs fails even after format
        if [ $(mount_ubifs_on_thinxr $mtd_num $mount_dir $vol_name) -ne 0 ]; then
            echo -1
            return
        fi
        echo 0
    fi
}

mount_ubifs() {

    local ret
    local UBI_PART=$1
    local MOUNT_DIR=$2

    # The mouting takes time if chk_fs is enabled
    # punch the watchdog
    pd_punch_watchdog

    mount /dev/${UBI_PART} ${MOUNT_DIR} -o chk_data_crc -t ubifs

    ret=$?

    return $ret
}

mount_ext4() {

    local ret
    local HDD_PART=$1
    local MOUNT_DIR=$2

    # The mouting takes time if chk_fs is enabled
    # punch the watchdog
    pd_punch_watchdog

    mount /dev/${HDD_PART} ${MOUNT_DIR} -t ext4 -o offset=1048576

    ret=$?
    return $ret
}

check_flash() {

    local MTD_NUM=$1
    local MTD_NAME=$2
    local MOUNT_DIR=$3
    local UBI_PART="ubi${MTD_NUM}_0"
    local FORCE_FORMAT=$4

    check_mtd $MTD_NUM $MTD_NAME

    if [ -n "$FORCE_FORMAT" ]; then
        umount $MOUNT_DIR
        format_ubi_on_mtd ${MTD_NUM} ${MTD_NAME}
    fi

    ubiattach -m ${MTD_NUM} -d ${MTD_NUM}

    #ubi attach failed
    if [ ! -e /sys/class/ubi/${UBI_PART} ]; then
        format_ubi_on_mtd ${MTD_NUM} ${MTD_NAME}
    fi

    [ -e ${MOUNT_DIR} ] || mkdir ${MOUNT_DIR}
    mount_ubifs ${UBI_PART} ${MOUNT_DIR}

    # mount fails
    if [ $? -ne 0 ]; then
        # try format
        format_ubi_on_mtd ${MTD_NUM} ${MTD_NAME}

        #try mounting again
        mount_ubifs ${UBI_PART} ${MOUNT_DIR}
        if [ $? -ne 0 ]; then
            echo "$(date): Mounting ${MOUNT_DIR} failed." >> $CHECKFLASH
            echo "$(date): Mounting ${MOUNT_DIR} failed." >> $CHECK_OBFL_FLASH
            exit -1
        fi
    fi
}

function check_fs_sb {
    local return_code=0
    local fs_mn=0
    local part=${1}

    local loop=$(get_loop_device ${part})
    if [ -n $loop ]; then
        dumpe2fs -h ${loop}  > $fs_sb_output 2>&1
        if (( $? == 1 )); then
            return_code=1
        else
            fs_mn=$(grep "magic number" $fs_sb_output | awk '{print $4}')
            if (( $fs_mn != $EXT2_FS_MAGIC_NUMBER )); then 
                return_code=2
            fi
        fi

        losetup -d ${loop}
    fi

    return $return_code
}

function format_partition {
    local dev_name=${1} label=${2}


    # During bake time, obfl partition (/dev/sda5) file system is created
    # at sector offset 2048. Hence we have to loop mount the obfl partition 
    # to access the file system. 
    local loop=$(get_loop_device ${dev_name})
    if [ -n $loop ]; then
        
        # Reformat partition with an ext4 file system
        #we disable huge_file feature beacuse,
        #we need huge file support when files are bigger than 2TB.
        /sbin/mkfs.ext4 -L ${label} -b 4096 -O ^huge_file -O ^64bit -vv ${loop} >> $CHECKFLASH 2>&1
    
        if [ $? -ne 0 ]; then
            # Send post code to indicate hard disk partition format has failed
            pd_notify_host_disk_partition_format_failed 
        fi
    
        /sbin/tune2fs -c 0 -i 0 ${loop} >> $CHECKFLASH 2>&1

        if [ $? -ne 0 ]; then
            # Send post code to indicate hard disk partition format has failed
            pd_notify_host_disk_partition_format_failed 
        fi

        losetup -d ${loop}
    fi

    sync
    if [ $? -ne 0 ]; then
        # Send post code to indicate disk partition's data synchronization to memory failed 
        pd_notify_host_disk_partition_sync_failed
    fi
}

function check_fs_partition {
    local dev_name=${1} label=${2}

    # Send post code to indicate hard disk partition format has started
    pd_notify_host_disk_partition_format_started

    check_fs_sb ${dev_name}
    # Even though super block is EXT4, redo mkfs.
    # The Partition label may have changed
    format_partition ${dev_name} ${label}

    # Send post code to indicate hard disk partition format has completed
    pd_notify_host_disk_partition_format_ended
}

check_hdd_partition() {

    local PART_NUM=$1
    local HDD_PART=$2
    local MOUNT_DIR=$3
    local FORCE_FORMAT=$4

    check_block $PART_NUM sda5
    
    if [ -n "$FORCE_FORMAT" ]; then
        umount $MOUNT_DIR
        check_fs_partition /dev/${HDD_PART} "obfl"         
    fi

    [ -e ${MOUNT_DIR} ] || mkdir ${MOUNT_DIR}    
    mount_ext4 ${HDD_PART} ${MOUNT_DIR}

    # mount fails
    if [ $? -ne 0 ]; then
        # try format
        check_fs_partition /dev/${HDD_PART} "obfl" 

        #try mounting again
        mount_ext4 ${HDD_PART} ${MOUNT_DIR}
        if [ $? -ne 0 ]; then
            echo "$(date): Mounting ${MOUNT_DIR} failed." >> $CHECKFLASH
            echo "$(date): Mounting ${MOUNT_DIR} failed." >> $CHECK_OBFL_FLASH
            exit -1
        fi
    fi
}

check_partition() {

    local name=$1
    
    local mtd_num=$2

    local force_format=$3

    check_flash $mtd_num $name /mnt/${name} $force_format
        
    if [ -n "$(check_bad_files /mnt/${name})" ]; then
        echo "$(date): check_flash /mnt/${name} failed, force_format" >> $CHECKFLASH
        check_flash ${mtd_num} $name /mnt/${name} "force_format" 
    else
        echo "$(date): Partition /mnt/${name} looks good." >> $CHECKFLASH
    fi
}

unmount_partition() {

    local name=$1

    mountpoint -q /mnt/${name}

    if [ $? == 0 ]; then
        umount /mnt/${name}
    fi
}

check_bootflash() {

    local force_format=$1

    check_flash ${BOOTFLASH_MTD_NUM} "bootflash" /mnt/bootflash $force_format
}


unprotect_flash() {
    local reg_val
    local reg_off=0x308

    echo "$(date): Unprotect_flash, start from here" >> $CHECKFLASH

    # MISC_CNTL_REG (0x0000_0308) bit 4, OBFL flash WP (write protect)
    # 1 = Enable
    # 0 = Disable
    reg_val=$(iofpga_reg_read_common 0 ${reg_off})

    echo "$(date): Unprotecting flash get reg_val from read_common, $reg_val" >> $CHECKFLASH
    reg_val=$((reg_val&0xffffffef))
    reg_val=$(printf "0x%x" $reg_val)

    boot_debug "Unprotecting flash reg_off ${reg_off}, reg_val $reg_val"
    echo "$(date): Unprotecting flash reg_off ${reg_off}, reg_val $reg_val" >> $CHECKFLASH
    iofpga_reg_write_common 0 ${reg_off} $reg_val
}

enable_ubifs_fs_check() {
    echo 1 > /sys/kernel/debug/ubifs/chk_fs
}

get_loop_device() {

    local dev=$1
    local offset=$(get_fs_offset "${dev}" "p1")
    local sizelimit=$(get_fs_sizelimit "${dev}" "p1")

    loop=$(losetup -f --show ${dev} -o ${offset} --sizelimit ${sizelimit})
    if [ $? != 0 ]; then
        echo "Failed to create loop device for $dev" >> $CHECKFLASH
    else
        echo "Successfully created loop device $loop" >> $CHECKFLASH
    fi 
    echo $loop
}

main() {

    # mtd formatting takes sometime.
    # inform to SUP via SC One-Wire about our status,
    # to extend any normal boot timeouts.
    #send_ow_err_code ${CHECK_FLASH_BEGIN}

    echo "$(date): Unprotecting flashes .." >> $CHECKFLASH
    unprotect_flash

    # Enable ubifs fs check
    enable_ubifs_fs_check

    echo "$(date): Check_flash for plog partition in host " >> $CHECKFLASH
    check_flash $PLOG_MTD_NUM plog /mnt/plog
    unmount_partition plog

    pd_is_shmoo_partition_needed
    shmoo_needed=$? 

    if [ $shmoo_needed -eq 1 ];then
        echo "$(date): Check_flash for shmoo partition in host" >> $CHECKFLASH
        check_flash $SHMOO_MTD_NUM shmoo /mnt/shmoo 
        unmount_partition shmoo
    fi

     #Enable bootflash when needed on FC and SC
     #boot_debug "Checking bootflash ..."
     #check_bootflash
    
     #Unmount /mnt/bootflash on host os    
     #mountpoint -q /mnt/bootflash
     #if [ $? == 0 ]; then
     #   umount /mnt/bootflash
     #fi

     #send_ow_err_code ${CHECK_FLASH_OK}

}

check_flash_on_thinxr() {
    local mtd_name=$1

    # check if mtd exists and get mtd num
    local mtd_num="$(check_mtd $mtd_name)"
    if [ $mtd_num -lt 0 ]; then
        echo "$(date): Partition ${mtd_name} doesn't look good." >> $CHECKFLASH
        exit 19
    fi
    local mount_dir="/mnt/mtd${mtd_num}"

    # check if already mounted with ubifs
    if [ $(check_mount $mtd_num $mount_dir ${mtd_name}) -eq 0 ]; then
        echo 0
        return
    fi

    mkdir -p ${mount_dir}

    ubiattach -m ${mtd_num} -d ${mtd_num} &>> $CHECKFLASH
    if [ $(mount_ubifs_on_thinxr $mtd_num $mount_dir $mtd_name) -eq 0 ]; then
        echo 0
        return
    fi
    # if all else fails format
    if [ $(format_ubi_on_mtd $mtd_num $mtd_name $mount_dir) -eq 0 ]; then
        echo 0
        return
    fi
    echo "$(date): Partition ${mtd_name} doesn't look good." >> $CHECKFLASH
    exit 1
}

stop() {
    # checks are made to accomodate multiple calls to stops
    # check-flash stop can be called when:
    # 1. both mountpoint and ubi device exist
    # 2. mountpoint doesn't exist but ubi device does

    local mtd_name=$1
    echo "$(date): Removing ${mtd_name} partition." >> $CHECKFLASH

    # get mtd_num from symlink
    local mtd_num=$(readlink /mnt/$mtd_name | \
                    sed s#'/mnt/mtd'#''# 2>> $CHECKFLASH)
    local re='^[0-9]+$'
    if ! [[ $mtd_num =~ $re ]];then
        echo "$(date): Partition ${mtd_name} not found." >> $CHECKFLASH
        exit 19
    fi

    # umount ubifs if mountpoint exists
    # if umounting fails return error
    echo "$(date): Unmounting ${mtd_name}." >> $CHECKFLASH
    local mount_dir="/mnt/mtd${mtd_num}"
    if [ -z "$(cat /proc/mounts | grep mtd${mtd_num})" ];then
        echo "$(date): Mountpoint for /mnt/mtd${mtd_num} ${mtd_name} not found." >> $CHECKFLASH
    else
        umount $mount_dir &>> $CHECKFLASH
        if [ $? -ne 0 ];then
            echo "$(date): Unmounting ${mtd_name} failed." >> $CHECKFLASH
            exit 1
        fi
        sleep 1
    fi

    # ubidetach if ubi device exists
    # if ubidetach fails return error
    echo "$(date): Ubi detaching -m ${mtd_num}." >> $CHECKFLASH
    if [ -z "$(ubinfo 2>> $CHECKFLASH | grep ubi${mtd_num})" ];then
        echo "$(date): No such device ubi${mtd_num}." >> $CHECKFLASH
    else
        ubidetach -m ${mtd_num} &>> $CHECKFLASH
        if [ $? -ne 0 ];then
            echo "$(date): Ubi detaching -m ${mtd_num} failed." >> $CHECKFLASH
            exit 1
        fi
    fi

    # remove the symlink and mountdir
    rm /mnt/${mtd_name} &>> $CHECKFLASH
    rmdir $mount_dir &>> $CHECKFLASH
}

case "$1" in
    start)
        if am_i_thinxr; then
           # to be called by OBFL_manager for mounting and
           # checking filesystems on OBFL flashes on RP, LC
           # and FCs
           # RP/LC: check-flash start obfl
           # FC:    check-flash start obfl_fc_18
           #        where 18 is the slot_id
           echo "$(date): Setting up a partition for $2." >> $CHECKFLASH
           check_flash_on_thinxr $2 > /dev/null
           echo "$(date): Partition $2 looks good." >> $CHECKFLASH
           exit 0
        fi

        # Populate BOARDTYPE variable
        get_board_type

        VMTYPE=`cat /proc/cmdline | grep vmtype=`
        CARDINDEX=`cat /proc/cmdline | grep card_index=`

        declare -F pd_wait_for_klm_loading &> /dev/null
        if  [ $? -eq 0 ]; then
            pd_wait_for_klm_loading
        fi

        if [ -n "$VMTYPE" ]; then
            VMTYPE=`cat /proc/cmdline | sed 's/^.*vmtype=//' | cut -d" " -f1`
        fi

        if [ -n "$CARDINDEX" ]; then
            CARDINDEX=`cat /proc/cmdline | sed 's/^.*card_index=//' | cut -d" " -f1`
        else
            echo "$(date): Card_index is not available." >> $CHECKFLASH
        fi

        if [ "$VMTYPE" == "hostos" ]; then
            echo "$(date): in hostos !!!!!!!!! " 

            declare -F pd_is_hdd_partition_needed &> /dev/null && pd_is_hdd_partition_needed
            if  [ $? -eq 0 ]; then
                echo "$(date): Check_hdd_partition for harddisk partition in host" >> $CHECKFLASH
                dev=/dev/sda5

                # Run fsck on the obfl partition created on SSD.
                # As it is vulnerable to file system corruption
                loop=$(get_loop_device $dev)
                if [ -n $loop ]; then
                    fsck -fy $loop >> $CHECKFLASH
                    status=$?
                    if [ $status -eq 1 ]; then
                        echo "Filesystem error detected and repaired on obfl partition $dev" >> $CHECKFLASH
                    elif [ $status -gt 1 ]; then
                        echo "Filesystem errors detected on obfl partition $dev" >> $CHECKFLASH
                    fi
                    losetup -d ${loop}
                fi

                check_hdd_partition ${HDD_PART_NUM} sda5 /mnt/plog 
                unmount_partition plog
            else
                if [ ! -e /sys/kernel/debug/ubifs ]; then
                    modprobe ubifs
                fi
                main
            fi

        elif [ "$VMTYPE" == "sysadmin-vm" ];then
            if [ -f $CHECK_OBFL_FLASH ]; then
                echo "$(date): sysadmin : OBFL is bad ? check and mount it here" >> $CHECKFLASH 
                mkdir -p /mnt/plog
                if [ "$CARDINDEX" == "27037" -o "$CARDINDEX" == "27042" ]; then
                    # check bad file in sysadmin, after sysadmin come up
                    if [ -n "$(check_bad_files /mnt/plog)" ]; then
                        echo "$(date): check_hdd_partition /mnt/plog and force_format in sysadmin-vm ." >> $CHECKFLASH
                        check_hdd_partition ${HDD_PART_NUM} vdf /mnt/plog "force_format"
                    else
                        echo "$(date): Partition /mnt/plog looks good in sysadmin-vm ." >> $CHECKFLASH
                    fi

                    echo "$(date): sysadmin-vm, mount_ubifs, ubi${PLOG_MTD_NUM}_0" >> $CHECKFLASH
                    mount_ext4 "vdf" /mnt/plog
                else
                    # check bad file in sysadmin, after sysadmin come up
                    if [ -n "$(check_bad_files /mnt/plog)" ]; then
                        echo "$(date): check_flash /mnt/plog and force_format in sysadmin-vm ." >> $CHECKFLASH
                        check_flash ${PLOG_MTD_NUM} plog /mnt/plog "force_format"
                    else
                        echo "$(date): Partition /mnt/plog looks good in sysadmin-vm ." >> $CHECKFLASH
                    fi

                    echo "$(date): sysadmin-vm, mount_ubifs, ubi${PLOG_MTD_NUM}_0" >> $CHECKFLASH
                    mount_ubifs "ubi${PLOG_MTD_NUM}_0" /mnt/plog                  
                fi
                rm $CHECK_OBFL_FLASH
            else
                echo "$(date): in sysadmin-vm, don't do anything here" >> $CHECKFLASH 
            fi
        elif [ "$VMTYPE" == "xr-vm" ] && [ "$BOARDTYPE" == "LC" ];then
            echo "$(date): XR : check OBFL flash here" >> $CHECKFLASH
            mkdir -p /mnt/shmoo
            if [ -n "$(check_bad_files /mnt/shmoo)" ]; then
                echo "$(date): check_flash /mnt/shmoo and force_format in xr-vm ." >> $CHECKFLASH
                check_flash ${SHMOO_MTD_NUM} plog /mnt/shmoo "force_format"
            else
                echo "$(date): Partition /mnt/shmoo looks good in xr-vm ." >> $CHECKFLASH
            fi

            echo "$(date): in xr-vm, LC, mount_ubifs, ubi${SHMOO_MTD_NUM}_0" >> $CHECKFLASH
            mount_ubifs "ubi${SHMOO_MTD_NUM}_0" /mnt/shmoo
        fi
        ;;

    obfl)
        if am_i_thinxr; then
            echo "Usage: $0 {start|stop} <obfl_name>" >&2
            exit 1
        fi

        if [ "$VMTYPE" == "sysadmin-vm" ];then
            CARDINDEX=`cat /proc/cmdline | grep card_index=`

            if [ -n "$CARDINDEX" ]; then
                CARDINDEX=`cat /proc/cmdline | sed 's/^.*card_index=//' | cut -d" " -f1`
            else
                echo "$(date): Card_index is not available." >> $CHECKFLASH
            fi

            echo "$(date): OBFL : from sysadmin-vm obfl process" >> $CHECKFLASH 
            if [ -f $CHECK_OBFL_FLASH ]; then
                echo "$(date): OBFL : FLASH is bad, skip both OBFL flash check and mount " >> $CHECKFLASH 
                exit 1
            fi

            mkdir -p /mnt/plog

            if [ "$CARDINDEX" == "27037" -o "$CARDINDEX" == "27042" ]; then
                # check bad file in sysadmin, after sysadmin come up
                if [ -n "$(check_bad_files /mnt/plog)" ]; then
                    echo "$(date): OBFL : check_hdd_partition /mnt/plog and force_format in obfl ." >> $CHECKFLASH
                    check_hdd_partition ${HDD_PART_NUM} vdf /mnt/plog "force_format"
                else
                    echo "$(date): OBFL : Partition /mnt/plog looks good, mount ext4 ." >> $CHECKFLASH
                fi

                echo "$(date): OBFL : sysadmin-vm, mount_ext4" >> $CHECKFLASH
                mount_ext4 "vdf" /mnt/plog
            else
                # check bad file in sysadmin, after sysadmin come up
                if [ -n "$(check_bad_files /mnt/plog)" ]; then
                    echo "$(date): OBFL : check_flash /mnt/plog and force_format in obfl ." >> $CHECKFLASH
                    check_flash ${PLOG_MTD_NUM} plog /mnt/plog "force_format"
                else
                    echo "$(date): OBFL : Partition /mnt/plog looks good, mount ubifs ." >> $CHECKFLASH
                fi

                echo "$(date): OBFL : sysadmin-vm, mount_ubifs, ubi${PLOG_MTD_NUM}_0" >> $CHECKFLASH
                mount_ubifs "ubi${PLOG_MTD_NUM}_0" /mnt/plog                  
            fi
        fi
        ;;

    stop)
	if am_i_thinxr; then
           # to be called when FC is ejected
           # example: check-flash stop obfl_fc_18
           #          where 18 is the slot_id
           stop $2
	fi
        ;;

    restart | reload | force-reload | status | condrestart | try-restart)
        ;;

    *)
        NAME=/etc/init.d/check-flash
        if am_i_thinxr; then
            echo "Usage: $0 {start|stop} <obfl_name>" >&2
            exit 1
        fi
        echo "Usage: $NAME {start}" >&2
        exit 1
        ;;
esac

exit 0
