How to go from MBR to GPT in fwup

I have little experience using GPT. How would I know if this migration is correct? Here is the file with MBR and the other with GPT. Thanks for your help in advance.

I needed to create one more partition and MBR cannot be done.

Whit MBR:

# Firmware configuration file for the 
require-fwup-version="1.0.0"
#
# Firmware metadata
#
# All of these can be overriden using environment variables of the same name.
#
#  Run 'fwup -m' to query values in a .fw file.
#  Use 'fw_printenv' to query values on the target.
#
# These are used by Nerves libraries to introspect.
define(NERVES_FW_PRODUCT, "Nerves Firmware")
define(NERVES_FW_DESCRIPTION, "")
define(NERVES_FW_VERSION, "${NERVES_SDK_VERSION}")
define(NERVES_FW_PLATFORM, "rcm3")
define(NERVES_FW_ARCHITECTURE, "arm")
define(NERVES_FW_AUTHOR, "The Nerves Team")
define(NERVES_FW_DEVPATH, "/dev/mmcblk0")
define(NERVES_FW_APPLICATION_PART0_DEVPATH, "/dev/mmcblk0p4") # Linux part number is 1-based
define(NERVES_FW_APPLICATION_PART0_FSTYPE, "f2fs")
define(NERVES_FW_APPLICATION_PART0_TARGET, "/root")
define(NERVES_FW_APPLICATION_PART1_DEVPATH, "/dev/mmcblk0p5") # Linux part number is 1-based
define(NERVES_FW_APPLICATION_PART1_FSTYPE, "f2fs")
define(NERVES_FW_APPLICATION_PART1_TARGET, "/home/ggc_user")
define(NERVES_PROVISIONING, "${NERVES_SYSTEM}/images/fwup_include/provisioning.conf")
# Default paths if not specified via the commandline
define(ROOTFS, "${NERVES_SYSTEM}/images/rootfs.squashfs")
# This configuration file will create an image that
# has an MBR and the following layout:
#
# +----------------------------+
# | MBR                        |
# +----------------------------+
# | Firmware configuration data|
# | (formatted as uboot env)   |
# +----------------------------+
# | p0: Boot partition (FAT32) |
# | Dummy partition            |
# | All boot files are loaded  |
# | from the rootfs partition  |
# +----------------------------+
# | p1: Rootfs A (squashfs)    |
# +----------------------------+
# | p2: Rootfs B (squashfs)    |
# +----------------------------+
# | p3: Application (f2fs)     |
# +----------------------------+
# The U-Boot environment is written directly to the SDCard/eMMC. It is not
# in any partition
define(UBOOT_ENV_OFFSET, 24576) # 12 MB
define(UBOOT_ENV_COUNT, 256)  # 128 KB
# The loader partition contains the proprietary bootcode and the first- and second-stage bootloaders (Uboot)
define(LOADER_PART_OFFSET, 64) # 32 KB
define(LOADER_PART_COUNT, 23552) # 11.5 MB
# Dummy boot partition to avoid having having to adapt all references to the partition numbers
define(BOOT_PART_OFFSET, 36864) # 18 MB
define(BOOT_PART_COUNT, 2048) # 1 MB
# Let the rootfs have room to grow up to 140 MiB and align it to the nearest 1
# MB boundary
define(ROOTFS_A_PART_OFFSET, 40960) # 20 MB
define(ROOTFS_A_PART_COUNT, 286720) # 140 MB
define-eval(ROOTFS_B_PART_OFFSET, "${ROOTFS_A_PART_OFFSET} + ${ROOTFS_A_PART_COUNT}")
define(ROOTFS_B_PART_COUNT, ${ROOTFS_A_PART_COUNT})
# Application partition. This partition can occupy all of the remaining space.
# Size it to fit the destination.
define-eval(APP_PART_OFFSET, "${ROOTFS_B_PART_OFFSET} + ${ROOTFS_B_PART_COUNT}")
define(APP_PART_COUNT, 1048576) # 512 MB
# Firmware archive metadata
meta-product = ${NERVES_FW_PRODUCT}
meta-description = ${NERVES_FW_DESCRIPTION}
meta-version = ${NERVES_FW_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 resources are listed in the order that they are included in the .fw file
# This is important, since this is the order that they're written on a firmware
# update due to the event driven nature of the update system.
file-resource u-boot-rockchip.bin {
    host-path = "${NERVES_SYSTEM}/images/u-boot-rockchip.bin"
    assert-size-lte = ${LOADER_PART_COUNT}
}
file-resource uboot-env.bin {
    host-path = "${NERVES_SYSTEM}/images/uboot-env.bin"
    assert-size-lte = ${UBOOT_ENV_COUNT}
}
file-resource rootfs.img {
    host-path = ${ROOTFS}
    # Error out if the rootfs size exceeds the partition size
    assert-size-lte = ${ROOTFS_A_PART_COUNT}
}
mbr mbr {
    partition 0 {
        block-offset = ${BOOT_PART_OFFSET}
        block-count = ${BOOT_PART_COUNT}
        type = 0xc # FAT32
        boot = true
    }
    partition 1 {
        block-offset = ${ROOTFS_A_PART_OFFSET}
        block-count = ${ROOTFS_A_PART_COUNT}
        type = 0x83 # Linux
    }
    partition 2 {
        block-offset = ${ROOTFS_B_PART_OFFSET}
        block-count = ${ROOTFS_B_PART_COUNT}
        type = 0x83 # Linux
    }
    partition 3 {
        block-offset = ${APP_PART_OFFSET}
        block-count = ${APP_PART_COUNT}
        type = 0x83 # Linux
        expand = true
    }
}
# Location where installed firmware information is stored.
uboot-environment uboot-env {
    block-offset = ${UBOOT_ENV_OFFSET}
    block-count = ${UBOOT_ENV_COUNT}
}
# This firmware task writes everything to the destination media.
# This should only be run at the factory to initialize a board!
task complete {
    # Only match if not mounted
    require-unmounted-destination = true
    on-init {
        mbr_write(mbr)
        fat_mkfs(${BOOT_PART_OFFSET}, ${BOOT_PART_COUNT})
        fat_setlabel(${BOOT_PART_OFFSET}, "BOOT")
    }
    
    on-resource u-boot-rockchip.bin { raw_write(${LOADER_PART_OFFSET}) }
    on-resource uboot-env.bin {
        # Boot to the A partition first and don't fail back.
        # If this fails, we bricked the board with no recovery.
        raw_write(${UBOOT_ENV_OFFSET})
        # Include provisioning instructions
        include("${NERVES_PROVISIONING}")
        # Add in the generic Nerves metadata variables.
        uboot_setenv(uboot-env, "nerves_fw_active", "a")
        uboot_setenv(uboot-env, "nerves_fw_devpath", ${NERVES_FW_DEVPATH})
        uboot_setenv(uboot-env, "a.nerves_fw_application_part0_devpath", ${NERVES_FW_APPLICATION_PART0_DEVPATH})
        uboot_setenv(uboot-env, "a.nerves_fw_application_part0_fstype", ${NERVES_FW_APPLICATION_PART0_FSTYPE})
        uboot_setenv(uboot-env, "a.nerves_fw_application_part0_target", ${NERVES_FW_APPLICATION_PART0_TARGET})
        uboot_setenv(uboot-env, "a.nerves_fw_product", ${NERVES_FW_PRODUCT})
        uboot_setenv(uboot-env, "a.nerves_fw_description", ${NERVES_FW_DESCRIPTION})
        uboot_setenv(uboot-env, "a.nerves_fw_version", ${NERVES_FW_VERSION})
        uboot_setenv(uboot-env, "a.nerves_fw_platform", ${NERVES_FW_PLATFORM})
        uboot_setenv(uboot-env, "a.nerves_fw_architecture", ${NERVES_FW_ARCHITECTURE})
        uboot_setenv(uboot-env, "a.nerves_fw_author", ${NERVES_FW_AUTHOR})
        uboot_setenv(uboot-env, "a.nerves_fw_vcs_identifier", ${NERVES_FW_VCS_IDENTIFIER})
        uboot_setenv(uboot-env, "a.nerves_fw_misc", ${NERVES_FW_MISC})
        uboot_setenv(uboot-env, "a.nerves_fw_uuid", "\${FWUP_META_UUID}")
    }
    
    on-resource rootfs.img {
        # write to the first rootfs partition
        raw_write(${ROOTFS_A_PART_OFFSET})
    }
    on-finish {
        # Clear out any old data in the B partition that might be mistaken for
        # a file system. This is mostly to avoid confusion in humans when
        # reprogramming SDCards with unknown contents.
        raw_memset(${ROOTFS_B_PART_OFFSET}, 256, 0xff)
        # Invalidate the application data partition so that it is guaranteed to
        # trigger the corrupt filesystem detection code on first boot and get
        # formatted. If this isn't done and an old SDCard is reused, the
        # application data could be in a weird state.
        raw_memset(${APP_PART_OFFSET}, 256, 0xff)
    }
}
task upgrade.a {
    # This task upgrades the A partition
    require-uboot-variable(uboot-env, "nerves_fw_active", "b")
    # Require that the running version of firmware has been validated.
    # If it has not, then failing back is not guaranteed to work.
    require-uboot-variable(uboot-env, "nerves_fw_validated", "1")
    # Verify 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-init {
        info("Upgrading partition A")
        # Clear some firmware information just in case this update gets
        # interrupted midway. If this partition was bootable, it's not going to
        # be soon.
        uboot_unsetenv(uboot-env, "a.nerves_fw_version")
        uboot_unsetenv(uboot-env, "a.nerves_fw_platform")
        uboot_unsetenv(uboot-env, "a.nerves_fw_architecture")
        uboot_unsetenv(uboot-env, "a.nerves_fw_uuid")
        # Indicate that the entire partition can be cleared
        trim(${ROOTFS_A_PART_OFFSET}, ${ROOTFS_A_PART_COUNT})
    }
    # Write the new firmware and Linux images, but don't
    # commit them. That way if the user aborts midway, we
    # still are using the original firmware.
    on-resource rootfs.img {
        delta-source-raw-offset=${ROOTFS_B_PART_OFFSET}
        delta-source-raw-count=${ROOTFS_B_PART_COUNT}
        raw_write(${ROOTFS_A_PART_OFFSET})
    }
    on-finish {
        # Update firmware metadata
        uboot_setenv(uboot-env, "a.nerves_fw_application_part0_devpath", ${NERVES_FW_APPLICATION_PART0_DEVPATH})
        uboot_setenv(uboot-env, "a.nerves_fw_application_part0_fstype", ${NERVES_FW_APPLICATION_PART0_FSTYPE})
        uboot_setenv(uboot-env, "a.nerves_fw_application_part0_target", ${NERVES_FW_APPLICATION_PART0_TARGET})
        uboot_setenv(uboot-env, "a.nerves_fw_product", ${NERVES_FW_PRODUCT})
        uboot_setenv(uboot-env, "a.nerves_fw_description", ${NERVES_FW_DESCRIPTION})
        uboot_setenv(uboot-env, "a.nerves_fw_version", ${NERVES_FW_VERSION})
        uboot_setenv(uboot-env, "a.nerves_fw_platform", ${NERVES_FW_PLATFORM})
        uboot_setenv(uboot-env, "a.nerves_fw_architecture", ${NERVES_FW_ARCHITECTURE})
        uboot_setenv(uboot-env, "a.nerves_fw_author", ${NERVES_FW_AUTHOR})
        uboot_setenv(uboot-env, "a.nerves_fw_vcs_identifier", ${NERVES_FW_VCS_IDENTIFIER})
        uboot_setenv(uboot-env, "a.nerves_fw_misc", ${NERVES_FW_MISC})
        uboot_setenv(uboot-env, "a.nerves_fw_uuid", "\${FWUP_META_UUID}")
        # Reset the validation status and boot to A
        # next time.
        uboot_setenv(uboot-env, "nerves_fw_active", "a")
        uboot_setenv(uboot-env, "nerves_fw_validated", "0")
        uboot_setenv(uboot-env, "nerves_fw_booted", "0")
    }
    on-error {
    }
}
task upgrade.b {
    # This task upgrades the B partition
    require-uboot-variable(uboot-env, "nerves_fw_active", "a")
    require-uboot-variable(uboot-env, "nerves_fw_validated", "1")
    # Verify 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-init {
        info("Upgrading partition B")
        # Clear some firmware information just in case this update gets
        # interrupted midway.
        uboot_unsetenv(uboot-env, "b.nerves_fw_version")
        uboot_unsetenv(uboot-env, "b.nerves_fw_platform")
        uboot_unsetenv(uboot-env, "b.nerves_fw_architecture")
        uboot_unsetenv(uboot-env, "b.nerves_fw_uuid")
        trim(${ROOTFS_B_PART_OFFSET}, ${ROOTFS_B_PART_COUNT})
    }
    on-resource rootfs.img {
        delta-source-raw-offset=${ROOTFS_A_PART_OFFSET}
        delta-source-raw-count=${ROOTFS_A_PART_COUNT}
        raw_write(${ROOTFS_B_PART_OFFSET})
    }
    on-finish {
        # Update firmware metadata
        uboot_setenv(uboot-env, "b.nerves_fw_application_part0_devpath", ${NERVES_FW_APPLICATION_PART0_DEVPATH})
        uboot_setenv(uboot-env, "b.nerves_fw_application_part0_fstype", ${NERVES_FW_APPLICATION_PART0_FSTYPE})
        uboot_setenv(uboot-env, "b.nerves_fw_application_part0_target", ${NERVES_FW_APPLICATION_PART0_TARGET})
        uboot_setenv(uboot-env, "b.nerves_fw_product", ${NERVES_FW_PRODUCT})
        uboot_setenv(uboot-env, "b.nerves_fw_description", ${NERVES_FW_DESCRIPTION})
        uboot_setenv(uboot-env, "b.nerves_fw_version", ${NERVES_FW_VERSION})
        uboot_setenv(uboot-env, "b.nerves_fw_platform", ${NERVES_FW_PLATFORM})
        uboot_setenv(uboot-env, "b.nerves_fw_architecture", ${NERVES_FW_ARCHITECTURE})
        uboot_setenv(uboot-env, "b.nerves_fw_author", ${NERVES_FW_AUTHOR})
        uboot_setenv(uboot-env, "b.nerves_fw_vcs_identifier", ${NERVES_FW_VCS_IDENTIFIER})
        uboot_setenv(uboot-env, "b.nerves_fw_misc", ${NERVES_FW_MISC})
        uboot_setenv(uboot-env, "b.nerves_fw_uuid", "\${FWUP_META_UUID}")
        # Reset the validation status and boot to B next time.
        uboot_setenv(uboot-env, "nerves_fw_active", "b")
        uboot_setenv(uboot-env, "nerves_fw_validated", "0")
        uboot_setenv(uboot-env, "nerves_fw_booted", "0")
    }
    on-error {
    }
}
task upgrade.unvalidated {
    require-uboot-variable(uboot-env, "nerves_fw_validated", "0")
    on-init {
        error("Please validate the running firmware before upgrading it again.")
    }
}
task upgrade.unexpected {
    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 {
        error("Please check the media being upgraded. It doesn't look like either the A or B partitions are active.")
    }
}
task upgrade.wrongplatform {
    on-init {
        error("Expecting platform=${NERVES_FW_PLATFORM} and architecture=${NERVES_FW_ARCHITECTURE}")
    }
}
task provision {
    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 {
        include("${NERVES_PROVISIONING}")
    }
}
task provision.wrongplatform {
    on-init {
        error("Expecting platform=${NERVES_FW_PLATFORM} and architecture=${NERVES_FW_ARCHITECTURE}")
    }
}

with GPT:

# Firmware configuration file for the 
require-fwup-version="1.4.0"  # For the GPT support
#
# Firmware metadata
#
# All of these can be overriden using environment variables of the same name.
#
#  Run 'fwup -m' to query values in a .fw file.
#  Use 'fw_printenv' to query values on the target.
#
# These are used by Nerves libraries to introspect.
define(NERVES_FW_PRODUCT, "Intuitivo Firmware")
define(NERVES_FW_DESCRIPTION, "")
define(NERVES_FW_VERSION, "${NERVES_SDK_VERSION}")
define(NERVES_FW_PLATFORM, "opcm4")
define(NERVES_FW_ARCHITECTURE, "arm")
define(NERVES_FW_AUTHOR, "The Intuitivo Team")
define(NERVES_FW_DEVPATH, "/dev/mmcblk0")
define(NERVES_FW_APPLICATION_PART0_DEVPATH, "/dev/mmcblk0p4") # Linux part number is 1-based
define(NERVES_FW_APPLICATION_PART0_FSTYPE, "f2fs")
define(NERVES_FW_APPLICATION_PART0_TARGET, "/root")
define(NERVES_FW_APPLICATION_PART1_DEVPATH, "/dev/mmcblk0p5") # Linux part number is 1-based
define(NERVES_FW_APPLICATION_PART1_FSTYPE, "f2fs")
define(NERVES_FW_APPLICATION_PART1_TARGET, "/home/ggc_user")
define(NERVES_PROVISIONING, "${NERVES_SYSTEM}/images/fwup_include/provisioning.conf")
# Default paths if not specified via the commandline
define(ROOTFS, "${NERVES_SYSTEM}/images/rootfs.squashfs")
# This configuration file will create an image that
# has an GPT and the following layout:
#
# +----------------------------+
# | GPT                        |
# +----------------------------+
# | Firmware configuration data|
# | (formatted as uboot env)   |
# +----------------------------+
# | p0: Boot partition (FAT32) |
# | Dummy partition            |
# | All boot files are loaded  |
# | from the rootfs partition  |
# +----------------------------+
# | p1: Rootfs A (squashfs)    |
# +----------------------------+
# | p2: Rootfs B (squashfs)    |
# +----------------------------+
# | p3: Application (f2fs)     |
# +----------------------------+
# | p4: Application2 (f2fs)    |
# +----------------------------+
define(LINUX_BOOT_TYPE, "bc13c2ff-59e6-4262-a352-b275fd6f7172")
define(LINUX_FILESYSTEM_DATA_TYPE, "0fc63daf-8483-4772-8e79-3d69d8477de4")
define(NERVES_SYSTEM_DISK_UUID, "D55BB8C7-1A91-4FA4-BF38-1F735090DF28")
define(NERVES_SYSTEM_BOOT_PART_UUID, "338efbad-8508-4f3c-bf56-477ba4bee991")
define(NERVES_SYSTEM_ROOTFS_PART_UUID, "b1209c26-3b03-4097-adc6-c383fa4e4d2f")
define(NERVES_SYSTEM_APP_PART_UUID, "03c62a5e-bc2e-439a-910d-c41a591a8e98")
define(NERVES_SYSTEM_APP2_PART_UUID, "5db81cc9-3b32-4916-b559-a98943bc2b8b")
# The U-Boot environment is written directly to the SDCard/eMMC. It is not
# in any partition
define(UBOOT_ENV_OFFSET, 24576) # 12 MB
define(UBOOT_ENV_COUNT, 256)  # 128 KB
# The loader partition contains the proprietary bootcode and the first- and second-stage bootloaders (Uboot)
define(LOADER_PART_OFFSET, 64) # 32 KB
define(LOADER_PART_COUNT, 23552) # 11.5 MB
# Dummy boot partition to avoid having having to adapt all references to the partition numbers
define(BOOT_PART_OFFSET, 36864) # 18 MB
define(BOOT_PART_COUNT, 2048) # 1 MB
# Let the rootfs have room to grow up to 140 MiB and align it to the nearest 1
# MB boundary
define(ROOTFS_A_PART_OFFSET, 40960) # 20 MB
define(ROOTFS_A_PART_COUNT, 286720) # 140 MB
define-eval(ROOTFS_B_PART_OFFSET, "${ROOTFS_A_PART_OFFSET} + ${ROOTFS_A_PART_COUNT}")
define(ROOTFS_B_PART_COUNT, ${ROOTFS_A_PART_COUNT})
# Application partition. This partition can occupy all of the remaining space.
# Size it to fit the destination.
define-eval(APP_PART_OFFSET, "${ROOTFS_B_PART_OFFSET} + ${ROOTFS_B_PART_COUNT}")
define(APP_PART_COUNT, 8388608) # 4 GB
define-eval(APP_PART1_OFFSET, "${APP_PART_OFFSET} + ${APP_PART_COUNT}")
define(APP_PART1_COUNT, 4194304) # 2GB
# Firmware archive metadata
meta-product = ${NERVES_FW_PRODUCT}
meta-description = ${NERVES_FW_DESCRIPTION}
meta-version = ${NERVES_FW_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 resources are listed in the order that they are included in the .fw file
# This is important, since this is the order that they're written on a firmware
# update due to the event driven nature of the update system.
file-resource u-boot-rockchip.bin {
    host-path = "${NERVES_SYSTEM}/images/u-boot-rockchip.bin"
    assert-size-lte = ${LOADER_PART_COUNT}
}
file-resource uboot-env.bin {
    host-path = "${NERVES_SYSTEM}/images/uboot-env.bin"
    assert-size-lte = ${UBOOT_ENV_COUNT}
}
file-resource rootfs.img {
    host-path = ${ROOTFS}
    # Error out if the rootfs size exceeds the partition size
    assert-size-lte = ${ROOTFS_A_PART_COUNT}
}
gpt gpt {
    guid = ${NERVES_SYSTEM_DISK_UUID}
    partition 0 {
        block-offset = ${BOOT_PART_OFFSET}
        block-count = ${BOOT_PART_COUNT}
        guid = ${NERVES_SYSTEM_BOOT_PART_UUID}
        type = ${LINUX_BOOT_TYPE}
        name = "boot"
    }
    partition 1 {
        block-offset = ${ROOTFS_A_PART_OFFSET}
        block-count = ${ROOTFS_A_PART_COUNT}
        guid = ${NERVES_SYSTEM_ROOTFS_PART_UUID}
        name = "rootfsa"
        type = ${LINUX_FILESYSTEM_DATA_TYPE}
        flags = 0x4
    }
    partition 2 {
        block-offset = ${ROOTFS_B_PART_OFFSET}
        block-count = ${ROOTFS_B_PART_COUNT}
        guid = ${NERVES_SYSTEM_ROOTFS_PART_UUID}
        name = "rootfsb"
        type = ${LINUX_FILESYSTEM_DATA_TYPE}
        flags = 0x4
    }
    partition 3 {
        block-offset = ${APP_PART_OFFSET}
        block-count = ${APP_PART_COUNT}
        guid = ${NERVES_SYSTEM_APP_PART_UUID}
        type = ${LINUX_FILESYSTEM_DATA_TYPE}
    }
    partition 4 {
        block-offset = ${APP_PART1_OFFSET}
        block-count = ${APP_PART1_COUNT}
        guid = ${NERVES_SYSTEM_APP2_PART_UUID}
        type = ${LINUX_FILESYSTEM_DATA_TYPE}
    }
}
# Location where installed firmware information is stored.
uboot-environment uboot-env {
    block-offset = ${UBOOT_ENV_OFFSET}
    block-count = ${UBOOT_ENV_COUNT}
}
# This firmware task writes everything to the destination media.
# This should only be run at the factory to initialize a board!
task complete {
    # Only match if not mounted
    require-unmounted-destination = true
    on-init {
        gpt_write(gpt)
        fat_mkfs(${BOOT_PART_OFFSET}, ${BOOT_PART_COUNT})
        fat_setlabel(${BOOT_PART_OFFSET}, "BOOT")
    }
    
    on-resource u-boot-rockchip.bin { raw_write(${LOADER_PART_OFFSET}) }
    on-resource uboot-env.bin {
        # Boot to the A partition first and don't fail back.
        # If this fails, we bricked the board with no recovery.
        raw_write(${UBOOT_ENV_OFFSET})
        # Include provisioning instructions
        include("${NERVES_PROVISIONING}")
        # Add in the generic Nerves metadata variables.
        uboot_setenv(uboot-env, "nerves_fw_active", "a")
        uboot_setenv(uboot-env, "nerves_fw_devpath", ${NERVES_FW_DEVPATH})
        uboot_setenv(uboot-env, "a.nerves_fw_application_part0_devpath", ${NERVES_FW_APPLICATION_PART0_DEVPATH})
        uboot_setenv(uboot-env, "a.nerves_fw_application_part0_fstype", ${NERVES_FW_APPLICATION_PART0_FSTYPE})
        uboot_setenv(uboot-env, "a.nerves_fw_application_part0_target", ${NERVES_FW_APPLICATION_PART0_TARGET})
        uboot_setenv(uboot-env, "a.nerves_fw_product", ${NERVES_FW_PRODUCT})
        uboot_setenv(uboot-env, "a.nerves_fw_description", ${NERVES_FW_DESCRIPTION})
        uboot_setenv(uboot-env, "a.nerves_fw_version", ${NERVES_FW_VERSION})
        uboot_setenv(uboot-env, "a.nerves_fw_platform", ${NERVES_FW_PLATFORM})
        uboot_setenv(uboot-env, "a.nerves_fw_architecture", ${NERVES_FW_ARCHITECTURE})
        uboot_setenv(uboot-env, "a.nerves_fw_author", ${NERVES_FW_AUTHOR})
        uboot_setenv(uboot-env, "a.nerves_fw_vcs_identifier", ${NERVES_FW_VCS_IDENTIFIER})
        uboot_setenv(uboot-env, "a.nerves_fw_misc", ${NERVES_FW_MISC})
        uboot_setenv(uboot-env, "a.nerves_fw_uuid", "\${FWUP_META_UUID}")
    }
    
    on-resource rootfs.img {
        # write to the first rootfs partition
        raw_write(${ROOTFS_A_PART_OFFSET})
    }
    on-finish {
        # Clear out any old data in the B partition that might be mistaken for
        # a file system. This is mostly to avoid confusion in humans when
        # reprogramming SDCards with unknown contents.
        raw_memset(${ROOTFS_B_PART_OFFSET}, 256, 0xff)
        # Invalidate the application data partition so that it is guaranteed to
        # trigger the corrupt filesystem detection code on first boot and get
        # formatted. If this isn't done and an old SDCard is reused, the
        # application data could be in a weird state.
        raw_memset(${APP_PART_OFFSET}, 256, 0xff)
    }
}
task upgrade.a {
    # This task upgrades the A partition
    require-uboot-variable(uboot-env, "nerves_fw_active", "b")
    # Require that the running version of firmware has been validated.
    # If it has not, then failing back is not guaranteed to work.
    require-uboot-variable(uboot-env, "nerves_fw_validated", "1")
    # Verify 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-init {
        info("Upgrading partition A")
        # Clear some firmware information just in case this update gets
        # interrupted midway. If this partition was bootable, it's not going to
        # be soon.
        uboot_unsetenv(uboot-env, "a.nerves_fw_version")
        uboot_unsetenv(uboot-env, "a.nerves_fw_platform")
        uboot_unsetenv(uboot-env, "a.nerves_fw_architecture")
        uboot_unsetenv(uboot-env, "a.nerves_fw_uuid")
        # Indicate that the entire partition can be cleared
        trim(${ROOTFS_A_PART_OFFSET}, ${ROOTFS_A_PART_COUNT})
    }
    # Write the new firmware and Linux images, but don't
    # commit them. That way if the user aborts midway, we
    # still are using the original firmware.
    on-resource rootfs.img {
        delta-source-raw-offset=${ROOTFS_B_PART_OFFSET}
        delta-source-raw-count=${ROOTFS_B_PART_COUNT}
        raw_write(${ROOTFS_A_PART_OFFSET})
    }
    on-finish {
        # Update firmware metadata
        uboot_setenv(uboot-env, "a.nerves_fw_application_part0_devpath", ${NERVES_FW_APPLICATION_PART0_DEVPATH})
        uboot_setenv(uboot-env, "a.nerves_fw_application_part0_fstype", ${NERVES_FW_APPLICATION_PART0_FSTYPE})
        uboot_setenv(uboot-env, "a.nerves_fw_application_part0_target", ${NERVES_FW_APPLICATION_PART0_TARGET})
        uboot_setenv(uboot-env, "a.nerves_fw_application_part1_devpath", ${NERVES_FW_APPLICATION_PART1_DEVPATH})
        uboot_setenv(uboot-env, "a.nerves_fw_application_part1_fstype", ${NERVES_FW_APPLICATION_PART1_FSTYPE})
        uboot_setenv(uboot-env, "a.nerves_fw_application_part1_target", ${NERVES_FW_APPLICATION_PART1_TARGET})
        uboot_setenv(uboot-env, "a.nerves_fw_product", ${NERVES_FW_PRODUCT})
        uboot_setenv(uboot-env, "a.nerves_fw_description", ${NERVES_FW_DESCRIPTION})
        uboot_setenv(uboot-env, "a.nerves_fw_version", ${NERVES_FW_VERSION})
        uboot_setenv(uboot-env, "a.nerves_fw_platform", ${NERVES_FW_PLATFORM})
        uboot_setenv(uboot-env, "a.nerves_fw_architecture", ${NERVES_FW_ARCHITECTURE})
        uboot_setenv(uboot-env, "a.nerves_fw_author", ${NERVES_FW_AUTHOR})
        uboot_setenv(uboot-env, "a.nerves_fw_vcs_identifier", ${NERVES_FW_VCS_IDENTIFIER})
        uboot_setenv(uboot-env, "a.nerves_fw_misc", ${NERVES_FW_MISC})
        uboot_setenv(uboot-env, "a.nerves_fw_uuid", "\${FWUP_META_UUID}")
        # Reset the validation status and boot to A
        # next time.
        uboot_setenv(uboot-env, "nerves_fw_active", "a")
        uboot_setenv(uboot-env, "nerves_fw_validated", "0")
        uboot_setenv(uboot-env, "nerves_fw_booted", "0")
    }
    on-error {
    }
}
task upgrade.b {
    # This task upgrades the B partition
    require-uboot-variable(uboot-env, "nerves_fw_active", "a")
    require-uboot-variable(uboot-env, "nerves_fw_validated", "1")
    # Verify 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-init {
        info("Upgrading partition B")
        # Clear some firmware information just in case this update gets
        # interrupted midway.
        uboot_unsetenv(uboot-env, "b.nerves_fw_version")
        uboot_unsetenv(uboot-env, "b.nerves_fw_platform")
        uboot_unsetenv(uboot-env, "b.nerves_fw_architecture")
        uboot_unsetenv(uboot-env, "b.nerves_fw_uuid")
        trim(${ROOTFS_B_PART_OFFSET}, ${ROOTFS_B_PART_COUNT})
    }
    on-resource rootfs.img {
        delta-source-raw-offset=${ROOTFS_A_PART_OFFSET}
        delta-source-raw-count=${ROOTFS_A_PART_COUNT}
        raw_write(${ROOTFS_B_PART_OFFSET})
    }
    on-finish {
        # Update firmware metadata
        uboot_setenv(uboot-env, "b.nerves_fw_application_part0_devpath", ${NERVES_FW_APPLICATION_PART0_DEVPATH})
        uboot_setenv(uboot-env, "b.nerves_fw_application_part0_fstype", ${NERVES_FW_APPLICATION_PART0_FSTYPE})
        uboot_setenv(uboot-env, "b.nerves_fw_application_part0_target", ${NERVES_FW_APPLICATION_PART0_TARGET})
        uboot_setenv(uboot-env, "b.nerves_fw_application_part1_devpath", ${NERVES_FW_APPLICATION_PART1_DEVPATH})
        uboot_setenv(uboot-env, "b.nerves_fw_application_part1_fstype", ${NERVES_FW_APPLICATION_PART1_FSTYPE})
        uboot_setenv(uboot-env, "b.nerves_fw_application_part1_target", ${NERVES_FW_APPLICATION_PART1_TARGET})
        uboot_setenv(uboot-env, "b.nerves_fw_product", ${NERVES_FW_PRODUCT})
        uboot_setenv(uboot-env, "b.nerves_fw_description", ${NERVES_FW_DESCRIPTION})
        uboot_setenv(uboot-env, "b.nerves_fw_version", ${NERVES_FW_VERSION})
        uboot_setenv(uboot-env, "b.nerves_fw_platform", ${NERVES_FW_PLATFORM})
        uboot_setenv(uboot-env, "b.nerves_fw_architecture", ${NERVES_FW_ARCHITECTURE})
        uboot_setenv(uboot-env, "b.nerves_fw_author", ${NERVES_FW_AUTHOR})
        uboot_setenv(uboot-env, "b.nerves_fw_vcs_identifier", ${NERVES_FW_VCS_IDENTIFIER})
        uboot_setenv(uboot-env, "b.nerves_fw_misc", ${NERVES_FW_MISC})
        uboot_setenv(uboot-env, "b.nerves_fw_uuid", "\${FWUP_META_UUID}")
        # Reset the validation status and boot to B next time.
        uboot_setenv(uboot-env, "nerves_fw_active", "b")
        uboot_setenv(uboot-env, "nerves_fw_validated", "0")
        uboot_setenv(uboot-env, "nerves_fw_booted", "0")
    }
    on-error {
    }
}
task upgrade.unvalidated {
    require-uboot-variable(uboot-env, "nerves_fw_validated", "0")
    on-init {
        error("Please validate the running firmware before upgrading it again.")
    }
}
task upgrade.unexpected {
    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 {
        error("Please check the media being upgraded. It doesn't look like either the A or B partitions are active.")
    }
}
task upgrade.wrongplatform {
    on-init {
        error("Expecting platform=${NERVES_FW_PLATFORM} and architecture=${NERVES_FW_ARCHITECTURE}")
    }
}
task provision {
    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 {
        include("${NERVES_PROVISIONING}")
    }
}
task provision.wrongplatform {
    on-init {
        error("Expecting platform=${NERVES_FW_PLATFORM} and architecture=${NERVES_FW_ARCHITECTURE}")
    }
}

What I did was split MBR into two parts. I’m about to try it, I hope it works.

# Firmware configuration file for the 
require-fwup-version="1.0.0"

#
# Firmware metadata
#

# All of these can be overriden using environment variables of the same name.
#
#  Run 'fwup -m' to query values in a .fw file.
#  Use 'fw_printenv' to query values on the target.
#
# These are used by Nerves libraries to introspect.
define(NERVES_FW_PRODUCT, "Intuitivo Firmware")
define(NERVES_FW_DESCRIPTION, "")
define(NERVES_FW_VERSION, "${NERVES_SDK_VERSION}")
define(NERVES_FW_PLATFORM, "opcm4")
define(NERVES_FW_ARCHITECTURE, "arm")
define(NERVES_FW_AUTHOR, "The Intuitivo Team")

define(NERVES_FW_DEVPATH, "/dev/mmcblk0")
define(NERVES_FW_APPLICATION_PART0_DEVPATH, "/dev/mmcblk0p3") # Linux part number is 1-based
define(NERVES_FW_APPLICATION_PART0_FSTYPE, "f2fs")
define(NERVES_FW_APPLICATION_PART0_TARGET, "/root")
define(NERVES_FW_APPLICATION_PART1_DEVPATH, "/dev/mmcblk0p4") # Linux part number is 1-based
define(NERVES_FW_APPLICATION_PART1_FSTYPE, "f2fs")
define(NERVES_FW_APPLICATION_PART1_TARGET, "/home/ggc_user")
define(NERVES_PROVISIONING, "${NERVES_SYSTEM}/images/fwup_include/provisioning.conf")

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

# This configuration file will create an image that
# has an MBR and the following layout:
#
# +----------------------------+
# | MBR                        |
# +----------------------------+
# | Firmware configuration data|
# | (formatted as uboot env)   |
# +----------------------------+
# | p0: Boot partition (FAT32) |
# | Dummy partition            |
# | All boot files are loaded  |
# | from the rootfs partition  |
# +----------------------------+
# | p1: Rootfs A (squashfs)    |
# +----------------------------+
# | p2: Rootfs B (squashfs)    |
# +----------------------------+
# | p3: Application (f2fs)     |
# +----------------------------+
# | p4: Application2 (f2fs)    |
# +----------------------------+

# The U-Boot environment is written directly to the SDCard/eMMC. It is not
# in any partition
define(UBOOT_ENV_OFFSET, 24576) # 12 MB
define(UBOOT_ENV_COUNT, 256)  # 128 KB

# The loader partition contains the proprietary bootcode and the first- and second-stage bootloaders (Uboot)
define(LOADER_PART_OFFSET, 64) # 32 KB
define(LOADER_PART_COUNT, 23552) # 11.5 MB

# Dummy boot partition to avoid having having to adapt all references to the partition numbers
define(BOOT_PART_OFFSET, 36864) # 18 MB
define(BOOT_PART_COUNT, 2048) # 1 MB

# Let the rootfs have room to grow up to 140 MiB and align it to the nearest 1
# MB boundary
define(ROOTFS_A_PART_OFFSET, 40960) # 20 MB
define(ROOTFS_A_PART_COUNT, 286720) # 140 MB
define-eval(ROOTFS_B_PART_OFFSET, "${ROOTFS_A_PART_OFFSET} + ${ROOTFS_A_PART_COUNT}")
define(ROOTFS_B_PART_COUNT, ${ROOTFS_A_PART_COUNT})

# Application partition. This partition can occupy all of the remaining space.
# Size it to fit the destination.
define-eval(APP_PART_OFFSET, "${ROOTFS_B_PART_OFFSET} + ${ROOTFS_B_PART_COUNT}")
define(APP_PART_COUNT, 8388608) # 4 GB

define-eval(APP_PART1_OFFSET, "${APP_PART_OFFSET} + ${APP_PART_COUNT}")
define(APP_PART1_COUNT, 4194304) # 2GB

# Firmware archive metadata
meta-product = ${NERVES_FW_PRODUCT}
meta-description = ${NERVES_FW_DESCRIPTION}
meta-version = ${NERVES_FW_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 resources are listed in the order that they are included in the .fw file
# This is important, since this is the order that they're written on a firmware
# update due to the event driven nature of the update system.
file-resource u-boot-rockchip.bin {
    host-path = "${NERVES_SYSTEM}/images/u-boot-rockchip.bin"
    assert-size-lte = ${LOADER_PART_COUNT}
}
file-resource uboot-env.bin {
    host-path = "${NERVES_SYSTEM}/images/uboot-env.bin"
    assert-size-lte = ${UBOOT_ENV_COUNT}
}
file-resource rootfs.img {
    host-path = ${ROOTFS}

    # Error out if the rootfs size exceeds the partition size
    assert-size-lte = ${ROOTFS_A_PART_COUNT}
}

mbr mbr-a {
    partition 0 {
        block-offset = ${BOOT_PART_OFFSET}
        block-count = ${BOOT_PART_COUNT}
        type = 0xc # FAT32
        boot = true
    }
    partition 1 {
        block-offset = ${ROOTFS_A_PART_OFFSET}
        block-count = ${ROOTFS_A_PART_COUNT}
        type = 0x83 # Linux
    }
    partition 2 {
        block-offset = ${APP_PART_OFFSET}
        block-count = ${APP_PART_COUNT}
        type = 0x83 # Linux
    }
    partition 3 {
        block-offset = ${APP_PART1_OFFSET}
        block-count = ${APP_PART1_COUNT}
        type = 0x83 # Linux
    }
}

mbr mbr-b {
    partition 0 {
        block-offset = ${BOOT_PART_OFFSET}
        block-count = ${BOOT_PART_COUNT}
        type = 0xc # FAT32
        boot = true
    }
    partition 1 {
        block-offset = ${ROOTFS_B_PART_OFFSET}
        block-count = ${ROOTFS_B_PART_COUNT}
        type = 0x83 # Linux
    }
    partition 2 {
        block-offset = ${APP_PART_OFFSET}
        block-count = ${APP_PART_COUNT}
        type = 0x83 # Linux
    }
    partition 3 {
        block-offset = ${APP_PART1_OFFSET}
        block-count = ${APP_PART1_COUNT}
        type = 0x83 # Linux
    }
}

# Location where installed firmware information is stored.
uboot-environment uboot-env {
    block-offset = ${UBOOT_ENV_OFFSET}
    block-count = ${UBOOT_ENV_COUNT}
}

# This firmware task writes everything to the destination media.
# This should only be run at the factory to initialize a board!
task complete {
    # Only match if not mounted
    require-unmounted-destination = true

    on-init {
        mbr_write(mbr-a)

        fat_mkfs(${BOOT_PART_OFFSET}, ${BOOT_PART_COUNT})
        fat_setlabel(${BOOT_PART_OFFSET}, "BOOT")
    }
    
    on-resource u-boot-rockchip.bin { raw_write(${LOADER_PART_OFFSET}) }

    on-resource uboot-env.bin {
        # Boot to the A partition first and don't fail back.
        # If this fails, we bricked the board with no recovery.
        raw_write(${UBOOT_ENV_OFFSET})

        # Include provisioning instructions
        include("${NERVES_PROVISIONING}")

        # Add in the generic Nerves metadata variables.
        uboot_setenv(uboot-env, "nerves_fw_active", "a")
        uboot_setenv(uboot-env, "nerves_fw_devpath", ${NERVES_FW_DEVPATH})
        uboot_setenv(uboot-env, "a.nerves_fw_application_part0_devpath", ${NERVES_FW_APPLICATION_PART0_DEVPATH})
        uboot_setenv(uboot-env, "a.nerves_fw_application_part0_fstype", ${NERVES_FW_APPLICATION_PART0_FSTYPE})
        uboot_setenv(uboot-env, "a.nerves_fw_application_part0_target", ${NERVES_FW_APPLICATION_PART0_TARGET})
        uboot_setenv(uboot-env, "a.nerves_fw_product", ${NERVES_FW_PRODUCT})
        uboot_setenv(uboot-env, "a.nerves_fw_description", ${NERVES_FW_DESCRIPTION})
        uboot_setenv(uboot-env, "a.nerves_fw_version", ${NERVES_FW_VERSION})
        uboot_setenv(uboot-env, "a.nerves_fw_platform", ${NERVES_FW_PLATFORM})
        uboot_setenv(uboot-env, "a.nerves_fw_architecture", ${NERVES_FW_ARCHITECTURE})
        uboot_setenv(uboot-env, "a.nerves_fw_author", ${NERVES_FW_AUTHOR})
        uboot_setenv(uboot-env, "a.nerves_fw_vcs_identifier", ${NERVES_FW_VCS_IDENTIFIER})
        uboot_setenv(uboot-env, "a.nerves_fw_misc", ${NERVES_FW_MISC})
        uboot_setenv(uboot-env, "a.nerves_fw_uuid", "\${FWUP_META_UUID}")
    }
    
    on-resource rootfs.img {
        # write to the first rootfs partition
        raw_write(${ROOTFS_A_PART_OFFSET})
    }

    on-finish {
        # Clear out any old data in the B partition that might be mistaken for
        # a file system. This is mostly to avoid confusion in humans when
        # reprogramming SDCards with unknown contents.
        raw_memset(${ROOTFS_B_PART_OFFSET}, 256, 0xff)

        # Invalidate the application data partition so that it is guaranteed to
        # trigger the corrupt filesystem detection code on first boot and get
        # formatted. If this isn't done and an old SDCard is reused, the
        # application data could be in a weird state.
        raw_memset(${APP_PART_OFFSET}, 256, 0xff)
        raw_memset(${APP_PART1_OFFSET}, 256, 0xff)
    }
}

task upgrade.a {
    # This task upgrades the A partition
    require-uboot-variable(uboot-env, "nerves_fw_active", "b")

    # Require that the running version of firmware has been validated.
    # If it has not, then failing back is not guaranteed to work.
    require-uboot-variable(uboot-env, "nerves_fw_validated", "1")

    # Verify 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-init {
        info("Upgrading partition A")

        # Clear some firmware information just in case this update gets
        # interrupted midway. If this partition was bootable, it's not going to
        # be soon.
        uboot_unsetenv(uboot-env, "a.nerves_fw_version")
        uboot_unsetenv(uboot-env, "a.nerves_fw_platform")
        uboot_unsetenv(uboot-env, "a.nerves_fw_architecture")
        uboot_unsetenv(uboot-env, "a.nerves_fw_uuid")

        # Indicate that the entire partition can be cleared
        trim(${ROOTFS_A_PART_OFFSET}, ${ROOTFS_A_PART_COUNT})
    }

    # Write the new firmware and Linux images, but don't
    # commit them. That way if the user aborts midway, we
    # still are using the original firmware.
    on-resource rootfs.img {
        delta-source-raw-offset=${ROOTFS_B_PART_OFFSET}
        delta-source-raw-count=${ROOTFS_B_PART_COUNT}
        raw_write(${ROOTFS_A_PART_OFFSET})
    }

    on-finish {
        # Update firmware metadata
        uboot_setenv(uboot-env, "a.nerves_fw_application_part0_devpath", ${NERVES_FW_APPLICATION_PART0_DEVPATH})
        uboot_setenv(uboot-env, "a.nerves_fw_application_part0_fstype", ${NERVES_FW_APPLICATION_PART0_FSTYPE})
        uboot_setenv(uboot-env, "a.nerves_fw_application_part0_target", ${NERVES_FW_APPLICATION_PART0_TARGET})
        uboot_setenv(uboot-env, "a.nerves_fw_application_part1_devpath", ${NERVES_FW_APPLICATION_PART1_DEVPATH})
        uboot_setenv(uboot-env, "a.nerves_fw_application_part1_fstype", ${NERVES_FW_APPLICATION_PART1_FSTYPE})
        uboot_setenv(uboot-env, "a.nerves_fw_application_part1_target", ${NERVES_FW_APPLICATION_PART1_TARGET})
        uboot_setenv(uboot-env, "a.nerves_fw_product", ${NERVES_FW_PRODUCT})
        uboot_setenv(uboot-env, "a.nerves_fw_description", ${NERVES_FW_DESCRIPTION})
        uboot_setenv(uboot-env, "a.nerves_fw_version", ${NERVES_FW_VERSION})
        uboot_setenv(uboot-env, "a.nerves_fw_platform", ${NERVES_FW_PLATFORM})
        uboot_setenv(uboot-env, "a.nerves_fw_architecture", ${NERVES_FW_ARCHITECTURE})
        uboot_setenv(uboot-env, "a.nerves_fw_author", ${NERVES_FW_AUTHOR})
        uboot_setenv(uboot-env, "a.nerves_fw_vcs_identifier", ${NERVES_FW_VCS_IDENTIFIER})
        uboot_setenv(uboot-env, "a.nerves_fw_misc", ${NERVES_FW_MISC})
        uboot_setenv(uboot-env, "a.nerves_fw_uuid", "\${FWUP_META_UUID}")

        # Reset the validation status and boot to A
        # next time.
        uboot_setenv(uboot-env, "nerves_fw_active", "a")
        uboot_setenv(uboot-env, "nerves_fw_validated", "0")
        uboot_setenv(uboot-env, "nerves_fw_booted", "0")

        mbr_write(mbr-a)
    }

    on-error {
    }
}

task upgrade.b {
    # This task upgrades the B partition
    require-uboot-variable(uboot-env, "nerves_fw_active", "a")
    require-uboot-variable(uboot-env, "nerves_fw_validated", "1")

    # Verify 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-init {
        info("Upgrading partition B")

        # Clear some firmware information just in case this update gets
        # interrupted midway.
        uboot_unsetenv(uboot-env, "b.nerves_fw_version")
        uboot_unsetenv(uboot-env, "b.nerves_fw_platform")
        uboot_unsetenv(uboot-env, "b.nerves_fw_architecture")
        uboot_unsetenv(uboot-env, "b.nerves_fw_uuid")

        trim(${ROOTFS_B_PART_OFFSET}, ${ROOTFS_B_PART_COUNT})
    }

    on-resource rootfs.img {
        delta-source-raw-offset=${ROOTFS_A_PART_OFFSET}
        delta-source-raw-count=${ROOTFS_A_PART_COUNT}
        raw_write(${ROOTFS_B_PART_OFFSET})
    }

    on-finish {
        # Update firmware metadata
        uboot_setenv(uboot-env, "b.nerves_fw_application_part0_devpath", ${NERVES_FW_APPLICATION_PART0_DEVPATH})
        uboot_setenv(uboot-env, "b.nerves_fw_application_part0_fstype", ${NERVES_FW_APPLICATION_PART0_FSTYPE})
        uboot_setenv(uboot-env, "b.nerves_fw_application_part0_target", ${NERVES_FW_APPLICATION_PART0_TARGET})
        uboot_setenv(uboot-env, "b.nerves_fw_application_part1_devpath", ${NERVES_FW_APPLICATION_PART1_DEVPATH})
        uboot_setenv(uboot-env, "b.nerves_fw_application_part1_fstype", ${NERVES_FW_APPLICATION_PART1_FSTYPE})
        uboot_setenv(uboot-env, "b.nerves_fw_application_part1_target", ${NERVES_FW_APPLICATION_PART1_TARGET})
        uboot_setenv(uboot-env, "b.nerves_fw_product", ${NERVES_FW_PRODUCT})
        uboot_setenv(uboot-env, "b.nerves_fw_description", ${NERVES_FW_DESCRIPTION})
        uboot_setenv(uboot-env, "b.nerves_fw_version", ${NERVES_FW_VERSION})
        uboot_setenv(uboot-env, "b.nerves_fw_platform", ${NERVES_FW_PLATFORM})
        uboot_setenv(uboot-env, "b.nerves_fw_architecture", ${NERVES_FW_ARCHITECTURE})
        uboot_setenv(uboot-env, "b.nerves_fw_author", ${NERVES_FW_AUTHOR})
        uboot_setenv(uboot-env, "b.nerves_fw_vcs_identifier", ${NERVES_FW_VCS_IDENTIFIER})
        uboot_setenv(uboot-env, "b.nerves_fw_misc", ${NERVES_FW_MISC})
        uboot_setenv(uboot-env, "b.nerves_fw_uuid", "\${FWUP_META_UUID}")

        # Reset the validation status and boot to B next time.
        uboot_setenv(uboot-env, "nerves_fw_active", "b")
        uboot_setenv(uboot-env, "nerves_fw_validated", "0")
        uboot_setenv(uboot-env, "nerves_fw_booted", "0")

        mbr_write(mbr-b)
    }

    on-error {
    }
}

task upgrade.unvalidated {
    require-uboot-variable(uboot-env, "nerves_fw_validated", "0")

    on-init {
        error("Please validate the running firmware before upgrading it again.")
    }
}

task upgrade.unexpected {
    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 {
        error("Please check the media being upgraded. It doesn't look like either the A or B partitions are active.")
    }
}

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

task provision {
    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 {
        include("${NERVES_PROVISIONING}")
    }
}
task provision.wrongplatform {
    on-init {
        error("Expecting platform=${NERVES_FW_PLATFORM} and architecture=${NERVES_FW_ARCHITECTURE}")
    }
}

You can look at public nerves systems on github. Iirc none of the nerves team maintained ones use GPT, but some public 3rd party ones did.