# Firmware revert configuration for Khadas VIM3
#
# To use:
# 1. Run `fwup -c -f fwup-revert.conf -o revert.fw` and copy revert.fw to
#    the device. This is done automatically as part of the Nerves system
#    build process. The file is stored in `/usr/share/fwup/revert.fw`.
# 2. On the device, run `fwup -t revert revert.fw -d $NERVES_FW_DEVPATH`. If
#    it succeeds, reboot. If not, then it's possible that there isn't a previous
#    firmware or the metadata about what's stored where is corrupt or out of
#    sync.
#
# It is critical that this is kept in sync with the main fwup.conf.

require-fwup-version="0.19.0"

#
# Firmware metadata
#
define(NERVES_FW_PLATFORM, "vim3")
define(NERVES_FW_ARCHITECTURE, "aarch64")
define(NERVES_FW_AUTHOR, "Dale Anderson | ST8VRT")
define(NERVES_FW_DEVPATH, "/dev/mmcblk0")
define(NERVES_FW_APPLICATION_PART0_DEVPATH, "/dev/mmcblk0p4")
define(NERVES_FW_APPLICATION_PART0_FSTYPE, "f2fs")
define(NERVES_FW_APPLICATION_PART0_TARGET, "/data")

# Default paths if not specified
define(ROOTFS, "${NERVES_SYSTEM}/images/rootfs.squashfs")

# Partition layout - must match fwup.conf
define(BOOT_PART_OFFSET, 17408)
define(BOOT_PART_COUNT, 262144)

define-eval(ROOTFS_A_PART_OFFSET, "${BOOT_PART_OFFSET} + ${BOOT_PART_COUNT}")
define(ROOTFS_A_PART_COUNT, 524288)
define-eval(ROOTFS_B_PART_OFFSET, "${ROOTFS_A_PART_OFFSET} + ${ROOTFS_A_PART_COUNT}")
define(ROOTFS_B_PART_COUNT, ${ROOTFS_A_PART_COUNT})

define-eval(APP_PART_OFFSET, "${ROOTFS_B_PART_OFFSET} + ${ROOTFS_B_PART_COUNT}")
define(APP_PART_COUNT, 1048576)

# Firmware archive metadata
meta-product = "Nerves Firmware"
meta-description = "Khadas VIM3 Revert"
meta-version = ${NERVES_SDK_VERSION}
meta-platform = ${NERVES_FW_PLATFORM}
meta-architecture = ${NERVES_FW_ARCHITECTURE}
meta-author = ${NERVES_FW_AUTHOR}
meta-vcs-identifier = ${NERVES_FW_VCS_IDENTIFIER}
meta-misc = ${NERVES_FW_MISC}

file-resource boot.scr {
    host-path = "${NERVES_SYSTEM}/images/boot.scr"
}

file-resource Image {
    host-path = "${NERVES_SYSTEM}/images/Image"
}

file-resource meson-g12b-a311d-khadas-vim3.dtb {
    host-path = "${NERVES_SYSTEM}/images/meson-g12b-a311d-khadas-vim3.dtb"
}

# Location where installed firmware information is stored
uboot-environment uboot-env {
    block-offset = 16128
    block-count = 256
}

task revert.a {
    # This task reverts to the A partition, so check that we're running on B
    require-uboot-variable(uboot-env, "nerves_fw_active", "b")

    # Verify that partition A has the expected platform/architecture
    require-uboot-variable(uboot-env, "a.nerves_fw_platform", "${NERVES_FW_PLATFORM}")
    require-uboot-variable(uboot-env, "a.nerves_fw_architecture", "${NERVES_FW_ARCHITECTURE}")

    on-resource boot.scr {
        info("Reverting to partition A")

        fat_write(${BOOT_PART_OFFSET}, "boot.scr")
    }
    on-resource Image { fat_write(${BOOT_PART_OFFSET}, "Image") }
    on-resource meson-g12b-a311d-khadas-vim3.dtb {
        fat_write(${BOOT_PART_OFFSET}, "meson-g12b-a311d-khadas-vim3.dtb")
    }

    on-finish {
        # Switch over
        uboot_setenv(uboot-env, "nerves_fw_active", "a")
        uboot_setenv(uboot-env, "nerves_fw_validated", "1")
        uboot_setenv(uboot-env, "bootcmd", "if fatload mmc 1:1 ${scriptaddr} boot.scr; then source ${scriptaddr}; fi")
    }
}

task revert.b {
    # This task reverts to the B partition, so check that we're running on A
    require-uboot-variable(uboot-env, "nerves_fw_active", "a")

    # Verify that partition B has the expected platform/architecture
    require-uboot-variable(uboot-env, "b.nerves_fw_platform", "${NERVES_FW_PLATFORM}")
    require-uboot-variable(uboot-env, "b.nerves_fw_architecture", "${NERVES_FW_ARCHITECTURE}")

    on-resource boot.scr {
        info("Reverting to partition B")

        fat_write(${BOOT_PART_OFFSET}, "boot.scr")
    }
    on-resource Image { fat_write(${BOOT_PART_OFFSET}, "Image") }
    on-resource meson-g12b-a311d-khadas-vim3.dtb {
        fat_write(${BOOT_PART_OFFSET}, "meson-g12b-a311d-khadas-vim3.dtb")
    }

    on-finish {
        # Switch over
        uboot_setenv(uboot-env, "nerves_fw_active", "b")
        uboot_setenv(uboot-env, "nerves_fw_validated", "1")
        uboot_setenv(uboot-env, "bootcmd", "if fatload mmc 1:1 ${scriptaddr} boot.scr; then source ${scriptaddr}; fi")
    }
}

task revert.unexpected.a {
    require-uboot-variable(uboot-env, "a.nerves_fw_platform", "${NERVES_FW_PLATFORM}")
    require-uboot-variable(uboot-env, "a.nerves_fw_architecture", "${NERVES_FW_ARCHITECTURE}")

    on-init {
        # Case where A is good, and the desire is to go to B.
        error("It doesn't look like there's anything to revert to in partition B.")
    }
}

task revert.unexpected.b {
    require-uboot-variable(uboot-env, "b.nerves_fw_platform", "${NERVES_FW_PLATFORM}")
    require-uboot-variable(uboot-env, "b.nerves_fw_architecture", "${NERVES_FW_ARCHITECTURE}")

    on-init {
        # Case where B is good, and the desire is to go to A.
        error("It doesn't look like there's anything to revert to in partition A.")
    }
}

task revert.wrongplatform {
    on-init {
        error("Expecting platform=${NERVES_FW_PLATFORM} and architecture=${NERVES_FW_ARCHITECTURE}")
    }
}
