#!/bin/bash
set -eo pipefail

# Get the root mtd device number (mtdX) from "/dev/ubiblockX_Y on /"
function findrootmtd() {
    rootmatch=" on / "
    m="$(mount | grep "${rootmatch}" | grep "ubiblock")"
    m="${m##*ubiblock}"
    m="${m%_*}"
    if [ -z "${m}" ]; then
        # default to bmc mtd (0)
        m=0
    fi
    echo "mtd${m}"
}

function findrootubi() {
    rootmatch=" on / "
    m="$(mount | grep "${rootmatch}")"
    m="${m##*ubiblock}"
    m="${m% on*}"
    echo "ubi${m}"
}

# Get the mtd device number (mtdX)
function findmtd() {
    m="$(grep -xl "$1" /sys/class/mtd/*/name)"
    m="${m%/name}"
    m="${m##*/}"
    echo "${m}"
}

# Get the mtd device number only (return X of mtdX)
function findmtdnum() {
    m="$(findmtd "$1")"
    m="${m##mtd}"
    echo "${m}"
}

# Get the ubi device number (ubiX_Y)
function findubi() {
    u="$(grep -xl "$1" /sys/class/ubi/ubi?/subsystem/ubi*/name)"
    u="${u%/name}"
    u="${u##*/}"
    echo "${u}"
}

# Get the ubi device number (ubiX_Y) on a specific mtd
function findubi_onmtd() {
    u="$(grep -xl "$1" /sys/class/ubi/ubi"$2"/subsystem/ubi"$2"*/name)"
    u="${u%/name}"
    u="${u##*/}"
    echo "${u}"
}

# Get all ubi device names on a specific mtd that match requested string
function findubiname_onmtd() {
    u="$(grep -h "$1" /sys/class/ubi/ubi"$2"/subsystem/ubi"$2"*/name)"
    u="${u%/name}"
    u="${u##*/}"
    echo "${u}"
}

# Get the name from the requested ubiX_Y volume
function findname() {
    n="$(cat /sys/class/ubi/"$1"/name)"
    echo "${n}"
}

# Set the version path property to the flash location where the image was
# successfully flashed
function set_flashid() {
    busctl set-property xyz.openbmc_project.Software.Manager \
        "/xyz/openbmc_project/software/${version}" \
        xyz.openbmc_project.Common.FilePath \
        Path s "$1" ||
    busctl set-property xyz.openbmc_project.Software.BMC.Updater \
        "/xyz/openbmc_project/software/${version}" \
        xyz.openbmc_project.Common.FilePath \
        Path s "$1"
}

# Set the u-boot envs that perform a side switch on failure to boot
function set_wdt2bite() {
    if ! fw_printenv wdt2bite 2>/dev/null; then
        fw_setenv wdt2bite "mw.l 0x1e785024 0xa 1; mw.b 0x1e78502c 0xb3 1"
        fw_setenv bootalt "run wdt2bite"
        fw_setenv obmc_bootcmd "ubi part obmc-ubi; run do_rwreset; ubi read \
\${loadaddr} \${kernelname}; bootm \${loadaddr} || run bootalt"
    fi
}

# Make space on flash before creating new volumes. This can be enhanced
# determine current flash usage. For now only keep a "keepmax" number of them
function ubi_remove_volumes()
{
    rootubi="$(findrootubi)"
    rootname="$(findname "${rootubi}")"
    rootversion="${rootname##*-}"
    rootkernel="kernel-${rootversion}"

    # Just keep max number of volumes before updating, don't delete the version
    # the BMC is booted from, and when a version is identified to be deleted,
    # delete both the rofs and kernel volumes for that version.
    rmnames="$(findubiname_onmtd "${name%-*}-" "${ro}")"
    mapfile -t array <<< "${rmnames}"
    ubicount="${#array[@]}"
    while [ "${ubicount}" -ge "${keepmax}" ]; do
        # Loop through existing volumes and skip currently active ones
        for (( index=0; index<${#array[@]}; index++ )); do
            rmname="${array[${index}]}"
            rmversion="${rmname##*-}"
            [ "${rmversion}" == "${version}" ] && continue
            rmubi="$(findubi_onmtd "rofs-${rmversion}" "${ro}")"
            if [[ "${rmubi}" != "${rootubi}" ]] && \
                [[ "${rmname}" != "${rootkernel}" ]]; then
                ubi_remove "rofs-${rmversion}" "${ro}"
                ubi_remove "kernel-${rmversion}" "${ro}"
                # Remove priority value
                fw_setenv "${rmversion}"
                break
            fi
        done
        # Decrease count regardless to avoid an infinite loop
        (( ubicount-- ))
    done
}

function ubi_rw() {
    rwmtd="$(findmtd "${reqmtd}")"
    rw="${rwmtd#mtd}"
    ubidev="/dev/ubi${rw}"

    # Update rwfs_size, check imgsize was specified, otherwise it'd clear the var
    if [ -n "$imgsize" ]; then
        rwsize="$(fw_printenv -n rwfs_size 2>/dev/null)" || true
        if [[ "${imgsize}" != "${rwsize}" ]]; then
            fw_setenv rwfs_size "${imgsize}"
        fi
    fi

    vol="$(findubi "${name}")"
    if [ -z "${vol}" ]; then
        ubimkvol "${ubidev}" -N "${name}" -s "${imgsize}"
    fi
}

function ubi_ro() {
    keepmax=2 # Default 2 volumes per mtd
    romtd="$(findmtd "${reqmtd}")"
    romtd2="$(findmtd "${reqmtd2}")"

    if [ ! "${romtd}" == "${romtd2}" ]; then
        # Request to use alternate mtd device, choose the non-root one
        keepmax=1 # 1 volume on each of the requested mtds
        rootmtd="$(findrootmtd)"
        if [ "${rootmtd}" == "${romtd}" ]; then
            romtd="${romtd2}"
        fi
    fi
    ro="${romtd#mtd}"
    ubidev="/dev/ubi${ro}"

    ubi_remove_volumes

    if [ -z "${imgfile}" ]; then
        echo "Unable to create read-only volume. Image file not specified."
        return 1
    fi

    # Create a ubi volume, dynamically sized to fit BMC image if size unspecified
    img="/tmp/images/${version}/${imgfile}"
    imgsize="$(stat -c '%s' "${img}")"

    vol="$(findubi "${name}")"
    if [ -n "${vol}" ]; then
        # Allow a duplicate kernel volume on the alt mtd
        if [[ "${name}" =~ "kernel" ]]; then
            vol="$(findubi_onmtd "${name}" "${ro}")"
        fi
    fi
    if [ -z "${vol}" ]; then
        ubimkvol "${ubidev}" -N "${name}" -s "${imgsize}" --type=static
        vol="$(findubi "${name}")"
    fi

    set_flashid "${version}"
}

# Squashfs images need a ubi block
function ubi_block() {
    vol="$(findubi "${name}")"
    ubidevid="${vol#ubi}"
    block="/dev/ubiblock${ubidevid}"
    if [ ! -e "$block" ]; then
        ubiblock --create "/dev/ubi${ubidevid}"
    fi
}

function ubi_updatevol() {
    vol="$(findubi "${name}")"
    ubidevid="${vol#ubi}"
    img="/tmp/images/${version}/${imgfile}"
    ubiupdatevol "/dev/ubi${ubidevid}" "${img}"
}

function ubi_remove() {
    rmname="$1"
    rmmtd="$2"
    if [ -n "${rmmtd}" ]; then
        vol="$(findubi_onmtd "${rmname}" "${rmmtd}")"
    else
        vol="$(findubi "${rmname}")"
    fi

    if [ -n "$vol" ]; then
        vol="${vol%_*}"

        if grep -q "$rmname" /proc/mounts; then
            mountdir=$(grep "$rmname" /proc/mounts | cut -d " " -f 2)
            umount "$mountdir"
            rm -r "$mountdir"
        fi

        ubirmvol "/dev/${vol}" -N "$rmname"
    fi
}

function ubi_cleanup() {
    # When ubi_cleanup is run, it expects one or no active version.
    activeVersion=$(busctl --list --no-pager tree \
            xyz.openbmc_project.Software.Manager | \
        grep /xyz/openbmc_project/software/ | tail -c 9)

    if [[ -z "$activeVersion" ]]; then
        activeVersion=$(busctl --list --no-pager tree \
                xyz.openbmc_project.Software.BMC.Updater | \
            grep /xyz/openbmc_project/software/ | tail -c 9)
    fi

    if [[ -z "$activeVersion" ]]; then
        vols=$(ubinfo -a | grep "rofs-" | cut -c 14-)
    else
        flashid=$(busctl get-property xyz.openbmc_project.Software.Manager \
                "/xyz/openbmc_project/software/${activeVersion}" \
            xyz.openbmc_project.Common.FilePath Path |  awk '{print $NF;}' | tr -d '"') ||
        flashid=$(busctl get-property xyz.openbmc_project.Software.BMC.Updater \
                "/xyz/openbmc_project/software/${activeVersion}" \
            xyz.openbmc_project.Common.FilePath Path |  awk '{print $NF;}' | tr -d '"')
        vols=$(ubinfo -a | grep "rofs-" | \
            grep -v "$flashid" | cut -c 14-) || true
    fi

    mapfile -t array <<< "${vols}"
    for (( index=0; index<${#array[@]}; index++ )); do
        ubi_remove "${array[index]}"
    done
}

function mount_ubi_alt_rwfs() {
    altNum="$(findmtdnum "alt-bmc")"
    if [ -n "${altNum}" ]; then
        altRwfs=$(ubinfo -a -d "${altNum}" | grep -w "rwfs") || true
        if [ -n "${altRwfs}" ]; then
            altVarMount="/media/alt/var"
            mkdir -p "${altVarMount}"
            if mount ubi"${altNum}":rwfs "${altVarMount}" -t ubifs -o defaults; then
                mkdir -p "${altVarMount}"/persist/etc
            fi
        fi
    fi
}

function remount_ubi() {
    bmcmtd="$(findmtd "bmc")"
    altbmcmtd="$(findmtd "alt-bmc")"
    mtds="${bmcmtd: -1}","${altbmcmtd: -1}"

    rootubi="$(findrootubi)"
    rootname="$(findname "${rootubi}")"

    IFS=',' read -r -a arrayMtds <<< "$mtds"
    for mtd in "${arrayMtds[@]}"; do
        # Get information on all ubi volumes
        ubinfo=$(ubinfo -d "${mtd}")
        presentVolumes=${ubinfo##*:}
        IFS=', ' read -r -a array <<< "$presentVolumes"
        for element in "${array[@]}"; do
            elementProperties=$(ubinfo -d "$mtd" -n "$element")
            # Get ubi volume name by getting rid of additional properties
            name=${elementProperties#*Name:}
            name="${name%Character*}"
            name="$(echo -e "${name}" | tr -d '[:space:]')"

            if [[ ${name} == rofs-* ]]; then
                if [[ "${name}" == "${rootname}" ]]; then
                    mountdir="/media/${name}-functional"
                else
                    mountdir="/media/${name}"
                fi

                if [ ! -d "${mountdir}" ]; then
                    mkdir -p "${mountdir}"
                    # U-Boot will create the ubiblock for the running version, but not
                    # for the version on the other chip
                    if [ ! -e "/dev/ubiblock${mtd}_${element}" ]; then
                        ubiblock --create "/dev/ubi${mtd}_${element}"
                    fi
                    mount -t squashfs -o ro "/dev/ubiblock${mtd}_${element}" "${mountdir}"
                fi
            fi
        done
    done

    set_wdt2bite
}

function mount_static_alt() {
    typ=$1
    altFs=$2
    mountName=$3
    altNum="$(findmtdnum "${altFs}")"
    if [ -n "${altNum}" ]; then
        altFsMount="/run/media/${mountName}"
        mkdir -p "${altFsMount}"
        altFsBlock="/dev/mtdblock${altNum}"
        mount -t "${typ}" "${altFsBlock}" "${altFsMount}"
    fi
}

function umount_static_alt() {
    altFs=$1
    altFsMount="/run/media/${altFs}"
    umount "${altFsMount}"
}

# Read the current env variable and set it on the alternate boot env
function copy_env_var_to_alt() {
    varName=$1
    value="$(fw_printenv -n "${varName}")"
    fw_setenv -c /etc/alt_fw_env.config "${varName}" "${value}"
}

# When the alternate bmc chip boots, u-boot thinks its the primary mtdX.
# Therefore need to swap the chip numbers when copying the ubiblock and root to
# alternate bmc u-boot environment.
function copy_ubiblock_to_alt() {
    value="$(fw_printenv -n ubiblock)"
    bmcNum="$(findmtdnum "bmc")"
    altNum="$(findmtdnum "alt-bmc")"
    replaceAlt="${value/${altNum},/${bmcNum},}"

    if [[ "${value}" == "${replaceAlt}" ]]; then
        replaceBmc="${value/${bmcNum},/${altNum},}"
        value=${replaceBmc}
    else
        value=${replaceAlt}
    fi

    fw_setenv -c /etc/alt_fw_env.config ubiblock "${value}"
}

function copy_root_to_alt() {
    value="$(fw_printenv -n root)"
    bmcNum="$(findmtdnum "bmc")"
    altNum="$(findmtdnum "alt-bmc")"
    replaceAlt="${value/${altNum}_/${bmcNum}_}"

    if [[ "${value}" == "${replaceAlt}" ]]; then
        replaceBmc="${value/${bmcNum}_/${altNum}_}"
        value=${replaceBmc}
    else
        value=${replaceAlt}
    fi

    fw_setenv -c /etc/alt_fw_env.config root "${value}"
}

function ubi_setenv() {
    # The U-Boot environment maintains two banks of environment variables.
    # The banks need to be consistent with each other to ensure that these
    # variables can reliably be read from file. In order to guarantee that the
    # banks are both correct, we need to run fw_setenv twice.
    variable=$1
    if [[ "$variable" == *"="* ]]; then
        varName="${variable%=*}"
        value="${variable##*=}"
        # Write only if var is not set already to the requested value
        currentValue="$(fw_printenv -n "${varName}" 2>/dev/null)" || true
        if [[ "${currentValue}" != "${value}" ]]; then
            fw_setenv "$varName" "$value"
            fw_setenv "$varName" "$value"
        fi
    else
        fw_setenv "$variable"
        fw_setenv "$variable"
    fi
}

function mtd_write() {
    flashmtd="$(findmtd "${reqmtd}")"
    img="/tmp/images/${version}/${imgfile}"
    flashcp -v "${img}" /dev/"${flashmtd}"
}

function backup_env_vars() {
    copy_env_var_to_alt kernelname
    copy_ubiblock_to_alt
    copy_root_to_alt
}

function update_env_vars() {
    vol="$(findubi rofs-"${flashid}")"
    if [ -z "${vol}" ]; then
        return 1
    fi
    ubidevid="${vol#ubi}"
    block="/dev/ubiblock${ubidevid}"
    if [ ! -e "${block}" ]; then
        return 1
    fi
    ubi_setenv "kernelname=kernel-${flashid}"
    ubi_setenv "ubiblock=${ubidevid//_/,}"
    ubi_setenv "root=${block}"
}

#TODO: Replace the implementation with systemd-inhibitors lock
#      once systemd/systemd#949 is resolved
function rebootguardenable() {
    dir="/run/systemd/system/"
    file="reboot-guard.conf"
    units=("reboot" "poweroff" "halt")

    for unit in "${units[@]}"; do
        mkdir -p ${dir}"${unit}".target.d
        echo -e "[Unit]\nRefuseManualStart=yes" >> ${dir}"${unit}".target.d/${file}
    done
}

#TODO: Replace the implementation with systemd-inhibitors lock
#      once systemd/systemd#949 is resolved
function rebootguarddisable() {
    dir="/run/systemd/system/"
    file="reboot-guard.conf"
    units=("reboot" "poweroff" "halt")

    for unit in "${units[@]}"; do
        rm -rf ${dir}"${unit}".target.d/${file}
    done
}

# Create a copy in the alt mtd
function create_vol_in_alt() {
    alt="alt-bmc"
    altmtd="$(findmtd "${alt}")"
    if [ -n "${altmtd}" ]; then
        reqmtd="${alt}"
        reqmtd2="${alt}"
        ubi_ro
        ubi_updatevol
    fi
}

# Copy contents of one MTD device to another
function mtd_copy() {
    in=$1
    out=$2

    # Must erase MTD first to prevent corruption
    flash_eraseall "${out}"
    dd if="${in}" of="${out}"
}

function mirroruboot() {
    bmc="$(findmtd "u-boot")"
    bmcdev="/dev/${bmc}"
    alt="$(findmtd "alt-u-boot")"
    altdev="/dev/${alt}"

    checksum_bmc="$(md5sum "${bmcdev}")"
    checksum_bmc="${checksum_bmc% *}"
    checksum_alt="$(md5sum "${altdev}")"
    checksum_alt="${checksum_alt% *}"

    if [[ "${checksum_bmc}" != "${checksum_alt}" ]]; then
        bmcenv="$(findmtd "u-boot-env")"
        bmcenvdev="/dev/${bmcenv}"
        altenv="$(findmtd "alt-u-boot-env")"
        altenvdev="/dev/${altenv}"

        echo "Mirroring U-boot to alt chip"
        mtd_copy "${bmcdev}" "${altdev}"
        mtd_copy "${bmcenvdev}" "${altenvdev}"

        copy_ubiblock_to_alt
        copy_root_to_alt
    fi
}

# Compare the device where u-boot resides with an image file. Specify the full
# path to the device and image file to use for the compare. Print a value of
# "0" if identical, "1" otherwise.
function cmp_uboot() {
    device="$1"
    image="$2"

    # Since the image file can be smaller than the device, copy the device to a
    # tmp file and write the image file on top, then compare the sum of each.
    # Use cat / redirection since busybox does not have the conv=notrunc option.
    tmpFile="$(mktemp /tmp/ubootdev.XXXXXX)"
    dd if="${device}" of="${tmpFile}"
    devSum="$(sha256sum "${tmpFile}")"
    cat < "${image}" 1<> "${tmpFile}"
    imgSum="$(sha256sum "${tmpFile}")"
    rm -f "${tmpFile}"

    if [ "${imgSum}" == "${devSum}" ]; then
        echo "0";
    else
        echo "1";
    fi
}

# The eMMC partition labels for the kernel and rootfs are boot-a/b and rofs-a/b.
# Return the label (a or b) for the running partition.
function mmc_get_primary_label() {
    # Get root device /dev/mmcblkpX
    rootmatch=" on / "
    root="$(mount | grep "${rootmatch}")"
    # shellcheck disable=SC2295
    root="${root%${rootmatch}*}"

    # Find the device label
    if [[ $(readlink -f /dev/disk/by-partlabel/rofs-a) == "${root}" ]]; then
        echo "a"
    elif [[ $(readlink -f /dev/disk/by-partlabel/rofs-b) == "${root}" ]]; then
        echo "b"
    else
        echo ""
    fi
}

# The eMMC partition labels for the kernel and rootfs are boot-a/b and rofs-a/b.
# Return the label (a or b) for the non-running partition.
function mmc_get_secondary_label() {
    root="$(mmc_get_primary_label)"
    if [[ "${root}" == "a" ]]; then
        echo "b"
    elif [[ "${root}" == "b" ]]; then
        echo "a"
    else
        echo ""
    fi
}

function mmc_mount() {
    primaryId="$(mmc_get_primary_label)"
    secondaryId="$(mmc_get_secondary_label)"

    primaryDir="${mediaDir}/rofs-${primaryId}-functional"
    secondaryDir="${mediaDir}/rofs-${secondaryId}"

    # Check the alternate version, remove it if it's corrupted. This can occur
    # when the BMC is rebooted in the middle of a code update for example.
    if ! fsck.ext4 -p "/dev/disk/by-partlabel/rofs-${secondaryId}"; then
        flashid="${secondaryId}"
        mmc_remove
    fi

    mkdir -p "${primaryDir}"
    mkdir -p "${secondaryDir}"

    mount PARTLABEL=rofs-"${primaryId}" "${primaryDir}" -t ext4 -o ro || rmdir "${primaryDir}"
    mount PARTLABEL=rofs-"${secondaryId}" "${secondaryDir}" -t ext4 -o ro || rmdir "${secondaryDir}"
}

function mmc_update() {
    # Update u-boot if needed
    bootPartition="mmcblk0boot0"
    devUBoot="/dev/${bootPartition}"
    imgUBoot="${imgpath}/${version}/image-u-boot"
    if [ "$(cmp_uboot "${devUBoot}" "${imgUBoot}")" != "0" ]; then
        echo 0 > "/sys/block/${bootPartition}/force_ro"
        dd if="${imgUBoot}" of="${devUBoot}"
        echo 1 > "/sys/block/${bootPartition}/force_ro"
    fi

    # Update the secondary (non-running) boot and rofs partitions.
    label="$(mmc_get_secondary_label)"

    # Update the boot and rootfs partitions, restore their labels after the update
    # by getting the partition number mmcblk0pX from their label.
    zstd -d -c "${imgpath}"/"${version}"/image-kernel | dd of="/dev/disk/by-partlabel/boot-${label}"
    number="$(readlink -f /dev/disk/by-partlabel/boot-"${label}")"
    number="${number##*mmcblk0p}"
    sgdisk --change-name="${number}":boot-"${label}" /dev/mmcblk0 1>/dev/null

    zstd -d -c "${imgpath}"/"${version}"/image-rofs | dd of="/dev/disk/by-partlabel/rofs-${label}"
    number="$(readlink -f /dev/disk/by-partlabel/rofs-"${label}")"
    number="${number##*mmcblk0p}"
    sgdisk --change-name="${number}":rofs-"${label}" /dev/mmcblk0 1>/dev/null

    # Run this after sgdisk for labels to take effect.
    partprobe

    # Update hostfw. The remove function doesn't touch the hostfw image, so
    # need to unmount and delete it prior to updating it.
    if [ -f "${imgpath}"/"${version}"/image-hostfw ]; then
        # Remove patches
        hostfw_alt="hostfw/alternate"
        patchdir="/usr/local/share/${hostfw_alt}"
        if [ -d "${patchdir}" ]; then
            rm -rf "${patchdir:?}"/*
        fi
        if grep -q "${hostfw_alt}" /proc/mounts; then
            hostfw_alt=$(grep "${hostfw_alt}" /proc/mounts | cut -d " " -f 2)
            umount "${hostfw_alt}"
        fi
        hostfwdir=$(grep "hostfw " /proc/mounts | cut -d " " -f 2)
        rm -f "${hostfwdir}/hostfw-${flashid}"
        cp "${imgpath}"/"${version}"/image-hostfw "${hostfwdir}"/hostfw-"${label}"
        mkdir -p "${hostfwdir}"/alternate
        mount "${hostfwdir}"/hostfw-"${label}" "${hostfwdir}"/alternate -o ro
    fi

    set_flashid "${label}"
}

function mmc_remove() {
    # Render the filesystem unbootable by wiping out the first 1MB, this
    # invalidates the filesystem header.
    # Check if the requested id is the one the BMC is running from since dd
    # can still write and corrupt the running partition.
    primaryid="$(mmc_get_primary_label)"
    if [[ "${flashid}" == "${primaryid}" ]]; then
        return 1
    fi
    dd if=/dev/zero of=/dev/disk/by-partlabel/boot-"${flashid}" count=2048
    dd if=/dev/zero of=/dev/disk/by-partlabel/rofs-"${flashid}" count=2048
}

# Set the requested version as primary for the BMC to boot from upon reboot.
function mmc_setprimary() {
    # Point root to the flashid of the requested BMC rootfs.
    fw_setenv bootside "${flashid}"
}

function mmc_mirroruboot() {
    # Get current boot device; 0-primary_bootdev device; 1 - alt_bootdev
    bootdev=$(cat /sys/kernel/debug/aspeed/sbc/abr_image)
    if [[ "${bootdev}" == "0" ]]; then
        bootPartition="mmcblk0boot0"
        alt_bootPartition="mmcblk0boot1"
    else
        bootPartition="mmcblk0boot1"
        alt_bootPartition="mmcblk0boot0"
    fi

    devUBoot="/dev/${bootPartition}"
    alt_devUBoot="/dev/${alt_bootPartition}"

    checksum_UBoot="$(md5sum "${devUBoot}")"
    checksum_UBoot="${checksum_UBoot% *}"
    checksum_alt_UBoot="$(md5sum "${alt_devUBoot}")"
    checksum_alt_UBoot="${checksum_alt% *}"

    if [[ "${checksum_UBoot}" != "${checksum_alt_UBoot}" ]]; then
        echo "Mirroring U-boot to alt chip"
        echo 0 > "/sys/block/${alt_bootPartition}/force_ro"
        dd if="${devUBoot}" of="${alt_devUBoot}"
        echo 1 > "/sys/block/${alt_bootPartition}/force_ro"
    fi
}

case "$1" in
    mtduboot)
        reqmtd="$2"
        version="$3"
        imgfile="image-u-boot"
        mtd_write
        ;;
    ubirw)
        reqmtd="$2"
        name="$3"
        imgsize="$4"
        ubi_rw
        ;;
    ubiro)
        reqmtd="$(echo "$2" | cut -d "+" -f 1)"
        reqmtd2="$(echo "$2" | cut -d "+" -f 2)"
        name="$3"
        version="$4"
        imgfile="image-rofs"
        ubi_ro
        ubi_updatevol
        ubi_block
        ;;
    ubikernel)
        reqmtd="$(echo "$2" | cut -d "+" -f 1)"
        reqmtd2="$(echo "$2" | cut -d "+" -f 2)"
        name="$3"
        version="$4"
        imgfile="image-kernel"
        ubi_ro
        ubi_updatevol
        create_vol_in_alt
        ;;
    ubiremove)
        name="$2"
        ubi_remove "${name}"
        ;;
    ubicleanup)
        ubi_cleanup
        ;;
    ubisetenv)
        ubi_setenv "$2"
        ;;
    ubiremount)
        remount_ubi
        mount_ubi_alt_rwfs
        ;;
    createenvbackup)
        backup_env_vars
        ;;
    updateubootvars)
        flashid="$2"
        update_env_vars
        ;;
    rebootguardenable)
        rebootguardenable
        ;;
    rebootguarddisable)
        rebootguarddisable
        ;;
    mirroruboot)
        mirroruboot
        ;;
    mmc)
        version="$2"
        imgpath="$3"
        mmc_update
        ;;
    mmc-mount)
        mediaDir="$2"
        mmc_mount
        ;;
    mmc-remove)
        flashid="$2"
        mmc_remove
        ;;
    mmc-setprimary)
        flashid="$2"
        mmc_setprimary
        ;;
    mmc-mirroruboot)
        mmc_mirroruboot
        ;;
    static-altfs)
        mount_static_alt "$2" "$3" "$4"
        ;;
    umount-static-altfs)
        umount_static_alt "$2"
        ;;
    *)
        echo "Invalid argument"
        exit 1
        ;;
esac
