Current section

Files

Jump to
nerves_system_vultr fwup-ops.conf
Raw

fwup-ops.conf

# Post-installation firmware operations for a Vultr Server Image
#
# To use:
#
# 1. Run `fwup -c -f fwup-ops.conf -o ops.fw` and copy ops.fw to
# the device. This is done automatically as part of the Nerves system
# build process. The file is stored in `/usr/share/fwup/ops.fw`.
# 2. On the device, run `fwup -t <task> -d /dev/rootdisk0 --enable-trim /usr/share/fwup/ops.fw`.
# 3. Reboot after running `revert` or `factory-reset`.
#
# It is critical that this is kept in sync with the main fwup.conf.
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 Vultr Image")
define(NERVES_FW_DESCRIPTION, "")
define(NERVES_FW_VERSION, "${NERVES_SDK_VERSION}")
define(NERVES_FW_PLATFORM, "vultr")
define(NERVES_FW_ARCHITECTURE, "x86_64")
define(NERVES_FW_AUTHOR, "The Nerves Team")
# This configuration file will create an image that
# has an MBR and the following layout:
#
# +----------------------------+
# | MBR w/ Grub boot code |
# +----------------------------+
# | grub.img (<256K) |
# +----------------------------+
# | Firmware configuration data|
# | (formatted as uboot env) |
# +----------------------------+
# | Boot partition (FAT32) |
# | /boot/grub/grub.cfg |
# | /boot/grub/grubenv |
# +----------------------------+
# | p2: Rootfs A (squashfs) |
# +----------------------------+
# | p3: Rootfs B (squashfs) |
# +----------------------------+
# | p4: Application (ext4) |
# +----------------------------+
define(UBOOT_ENV_OFFSET, 2048)
define(UBOOT_ENV_COUNT, 16) # 8 KB
# The boot partition contains the bootloader configuration
# 16 MB should be plenty for now.
define(BOOT_PART_OFFSET, 4096)
define(BOOT_PART_COUNT, 31232)
# Let the rootfs have room to grow up to 256 MiB
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})
# Application data partition (10 GiB). This can be enlarged
# to fill the entire volume.
define-eval(APP_PART_OFFSET, "${ROOTFS_B_PART_OFFSET} + ${ROOTFS_B_PART_COUNT}")
define(APP_PART_COUNT, 20971520)
# 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-resource grubenv_a {
host-path = "${NERVES_SYSTEM}/images/grubenv_a"
}
file-resource grubenv_b {
host-path = "${NERVES_SYSTEM}/images/grubenv_b"
}
# Location where installed firmware information is stored.
# While this is called "u-boot", u-boot isn't involved in this
# setup. It just provides a convenient key/value store format.
uboot-environment uboot-env {
block-offset = ${UBOOT_ENV_OFFSET}
block-count = ${UBOOT_ENV_COUNT}
}
##
# factory-reset
##
task factory-reset {
on-init {
info("Erasing all writable data")
# This requires --enable-trim
trim(${APP_PART_OFFSET}, ${APP_PART_COUNT})
raw_memset(${APP_PART_OFFSET}, 256, 0xff)
}
}
##
# prevent-revert
#
# Pass `--enable-trim` to also clear out the partition that no longer should be used.
##
task prevent-revert.a {
# Check that we're running on B
require-uboot-variable(uboot-env, "nerves_fw_active", "b")
on-init {
info("Preventing reverts to partition A")
# Remove U-Boot variables that fwup uses to allow reverting images
uboot_unsetenv(uboot-env, "a.nerves_fw_platform")
uboot_unsetenv(uboot-env, "a.nerves_fw_architecture")
# Clear out the old image using TRIM. This requires --enable-trim
trim(${ROOTFS_A_PART_OFFSET}, ${ROOTFS_A_PART_COUNT})
}
}
task prevent-revert.b {
# Check that we're running on A
require-uboot-variable(uboot-env, "nerves_fw_active", "a")
on-init {
info("Preventing reverts to partition B")
# Remove U-Boot variables that fwup uses to allow reverting images
uboot_unsetenv(uboot-env, "b.nerves_fw_platform")
uboot_unsetenv(uboot-env, "b.nerves_fw_architecture")
# Clear out the old image using TRIM. This requires --enable-trim
trim(${ROOTFS_B_PART_OFFSET}, ${ROOTFS_B_PART_COUNT})
}
}
task prevent-revert.fail {
on-init {
error("Error detecting active partition")
}
}
##
# revert
##
task revert.a {
# This task reverts to the A partition, so check that we're running on B
require-path-on-device("/", "/dev/vda3")
# 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 grubenv_a {
info("Reverting to partition A")
# Switch over
uboot_setenv(uboot-env, "nerves_fw_active", "a")
fat_write(${BOOT_PART_OFFSET}, "/boot/grub/grubenv")
}
}
task revert.b {
# This task reverts to the B partition, so check that we're running on A
require-path-on-device("/", "/dev/vda2")
# 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 grubenv_b {
info("Reverting to partition B")
# Switch over
uboot_setenv(uboot-env, "nerves_fw_active", "b")
fat_write(${BOOT_PART_OFFSET}, "/boot/grub/grubenv")
}
}
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}")
}
}
##
# status
#
# Run "fwup /usr/share/fwup/ops.fw -t status -d /dev/vda -q -U" to check the status.
task status.aa {
require-path-on-device("/", "/dev/vda2")
require-uboot-variable(uboot-env, "nerves_fw_active", "a")
on-init { info("a") }
}
task status.ab {
require-path-on-device("/", "/dev/vda2")
require-uboot-variable(uboot-env, "nerves_fw_active", "b")
on-init { info("a->b") }
}
task status.bb {
require-path-on-device("/", "/dev/vda3")
require-uboot-variable(uboot-env, "nerves_fw_active", "b")
on-init { info("b") }
}
task status.ba {
require-path-on-device("/", "/dev/vda3")
require-uboot-variable(uboot-env, "nerves_fw_active", "a")
on-init { info("b->a") }
}
task status.fail {
on-init { error("fail") }
}