Current section

Files

Jump to

fwup.conf

require-fwup-version="1.4.0" # For the GPT support
define(NERVES_FW_PRODUCT, "Nerves Firmware")
define(NERVES_FW_DESCRIPTION, "")
define(NERVES_FW_VERSION, "${NERVES_SDK_VERSION}")
define(NERVES_FW_PLATFORM, "osd32mp1")
define(NERVES_FW_ARCHITECTURE, "arm")
define(NERVES_FW_AUTHOR, "The Nerves Team")
define(EFI_TYPE, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b")
define(LINUX_FILESYSTEM_DATA_TYPE, "0fc63daf-8483-4772-8e79-3d69d8477de4")
define(NERVES_SYSTEM_DISK_UUID, "D55BB8C7-1A91-4FA4-BF38-1F735090DF28")
define(NERVES_SYSTEM_SPL_PART_UUID, "5278721d-0089-4768-85df-b8f1b97e6684")
define(NERVES_SYSETM_UBOOT_PART_UUID, "130e0a2d-b49a-4e1e-a8f9-6af7d5bcfdd6")
define(NERVES_SYSTEM_EFI_PART_UUID, "130e0a2d-b49a-4e1e-a8f9-6af7d5bcfdd7")
define(NERVES_SYSTEM_ROOTFS_PART_UUID, "b1209c26-3b03-4097-adc6-c383fa4e4d2f")
define(NERVES_SYSTEM_APP_PART_UUID, "03c62a5e-bc2e-439a-910d-c41a591a8e98")
define(NERVES_FW_DEVPATH, "/dev/mmcblk0")
define(NERVES_FW_APPLICATION_PART0_DEVPATH, "/dev/mmcblk0p6")
define(NERVES_FW_APPLICATION_PART0_FSTYPE, "f2fs")
define(NERVES_FW_APPLICATION_PART0_TARGET, "/root")
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 GPT and the following layout:
# +----------------------------+
# | Firmware configuration data|
# | (formatted as uboot env) |
# +----------------------------+
# | p0: SPL1 |
# +----------------------------+
# | p1: SPL2 |
# +----------------------------+
# | p2: UBOOT |
# +----------------------------+
# | p3: Boot partition (FAT32) |
# | zImage |
# | osd32mp1-brk.dtb |
# | extlinux.conf |
# +----------------------------+
# | p4: Rootfs A (squashfs) |
# +----------------------------+
# | p5: Rootfs B (squashfs) |
# +----------------------------+
# | p6: Application (f2fs) |
# +----------------------------+
define-eval(UBOOT_ENV_OFFSET, 2048)
define(UBOOT_ENV_COUNT, 256) # 128 KB
define(SPL1_PART_OFFSET, 4096)
define(SPL1_PART_COUNT, 155)
define-eval(SPL2_PART_OFFSET, "${SPL1_PART_OFFSET} + ${SPL1_PART_COUNT}")
define-eval(SPL2_PART_COUNT, "${SPL1_PART_COUNT}")
define-eval(UBOOT_PART_OFFSET, "${SPL2_PART_OFFSET} + ${SPL2_PART_COUNT}")
define(UBOOT_PART_COUNT, 1600)
define-eval(EFI_A_PART_OFFSET, "${UBOOT_PART_OFFSET} + ${UBOOT_PART_COUNT}")
define(EFI_A_PART_COUNT, 204800)
define-eval(EFI_B_PART_OFFSET, "${EFI_A_PART_OFFSET} + ${EFI_A_PART_COUNT}")
define(EFI_B_PART_COUNT, ${EFI_A_PART_COUNT})
# Let the rootfs have room to grow up to 512 MiB
define-eval(ROOTFS_A_PART_OFFSET, "${EFI_B_PART_OFFSET} + ${EFI_B_PART_COUNT}")
define(ROOTFS_A_PART_COUNT, 1048576)
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. 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, 8388608)
# 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 fsbl1 {
host-path = "${NERVES_SYSTEM}/images/u-boot-spl.stm32"
# Error out if the uboot spl binary size exceeds the partition size
assert-size-lte = ${SPL1_PART_COUNT}
}
file-resource fsbl2 {
host-path = "${NERVES_SYSTEM}/images/u-boot-spl.stm32"
# Error out if the uboot spl binary size exceeds the partition size
assert-size-lte = ${SPL1_PART_COUNT}
}
file-resource u-boot.img {
host-path = "${NERVES_SYSTEM}/images/u-boot.img"
# Error out if the uboot binary size exceeds the partition size
assert-size-lte = ${UBOOT_PART_COUNT}
}
file-resource osd32mp1-brk.dtb {
host-path = "${NERVES_SYSTEM}/images/osd32mp1-brk.dtb"
}
file-resource zImage {
host-path = "${NERVES_SYSTEM}/images/zImage"
}
file-resource extlinux.conf {
host-path = "${NERVES_SYSTEM}/images/extlinux.conf"
}
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-a {
guid = ${NERVES_SYSTEM_DISK_UUID}
partition 0 {
block-offset = ${SPL1_PART_OFFSET}
block-count = ${SPL1_PART_COUNT}
guid = ${NERVES_SYSTEM_SPL_PART_UUID}
type = ${LINUX_FILESYSTEM_DATA_TYPE}
name = "fsbl1"
}
partition 1 {
block-offset = ${SPL2_PART_OFFSET}
block-count = ${SPL2_PART_COUNT}
guid = ${NERVES_SYSTEM_SPL_PART_UUID}
type = ${LINUX_FILESYSTEM_DATA_TYPE}
name = "fsbl2"
}
partition 2 {
block-offset = ${UBOOT_PART_OFFSET}
block-count = ${UBOOT_PART_COUNT}
guid = ${NERVES_SYSETM_UBOOT_PART_UUID}
type = ${LINUX_FILESYSTEM_DATA_TYPE}
name = "ssbl"
}
partition 3 {
block-offset = ${EFI_A_PART_OFFSET}
block-count = ${EFI_A_PART_COUNT}
guid = ${NERVES_SYSTEM_EFI_PART_UUID}
type = ${EFI_TYPE}
name = "boot"
}
partition 4 {
block-offset = ${ROOTFS_A_PART_OFFSET}
block-count = ${ROOTFS_A_PART_COUNT}
guid = ${NERVES_SYSTEM_ROOTFS_PART_UUID}
name = "rootfs"
type = ${LINUX_FILESYSTEM_DATA_TYPE}
flags = 0x4
}
partition 5 {
block-offset = ${APP_PART_OFFSET}
block-count = ${APP_PART_COUNT}
guid = ${NERVES_SYSTEM_APP_PART_UUID}
type = ${LINUX_FILESYSTEM_DATA_TYPE}
expand = true
}
}
gpt gpt-b {
guid = ${NERVES_SYSTEM_DISK_UUID}
partition 0 {
block-offset = ${SPL1_PART_OFFSET}
block-count = ${SPL1_PART_COUNT}
guid = ${NERVES_SYSTEM_SPL_PART_UUID}
type = ${LINUX_FILESYSTEM_DATA_TYPE}
name = "fsbl1"
}
partition 1 {
block-offset = ${SPL2_PART_OFFSET}
block-count = ${SPL2_PART_COUNT}
guid = ${NERVES_SYSTEM_SPL_PART_UUID}
type = ${LINUX_FILESYSTEM_DATA_TYPE}
name = "fsbl2"
}
partition 2 {
block-offset = ${UBOOT_PART_OFFSET}
block-count = ${UBOOT_PART_COUNT}
guid = ${NERVES_SYSETM_UBOOT_PART_UUID}
type = ${LINUX_FILESYSTEM_DATA_TYPE}
name = "ssbl"
}
partition 3 {
block-offset = ${EFI_B_PART_OFFSET}
block-count = ${EFI_B_PART_COUNT}
guid = ${NERVES_SYSTEM_EFI_PART_UUID}
type = ${EFI_TYPE}
name = "boot"
}
partition 4 {
block-offset = ${ROOTFS_B_PART_OFFSET}
block-count = ${ROOTFS_B_PART_COUNT}
guid = ${NERVES_SYSTEM_ROOTFS_PART_UUID}
name = "rootfs"
type = ${LINUX_FILESYSTEM_DATA_TYPE}
flags = 0x4
}
partition 5 {
block-offset = ${APP_PART_OFFSET}
block-count = ${APP_PART_COUNT}
guid = ${NERVES_SYSTEM_APP_PART_UUID}
type = ${LINUX_FILESYSTEM_DATA_TYPE}
expand = true
}
}
# 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}
}
# 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-a)
uboot_clearenv(uboot-env)
include("${NERVES_PROVISIONING}")
uboot_setenv(uboot-env, "nerves_fw_active", "a")
uboot_setenv(uboot-env, "nerves_fw_autovalidate", "0")
uboot_setenv(uboot-env, "nerves_fw_validated", "1")
uboot_setenv(uboot-env, "nerves_fw_booted", "0")
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}")
fat_mkfs(${EFI_A_PART_OFFSET}, ${EFI_A_PART_COUNT})
fat_setlabel(${EFI_A_PART_OFFSET}, "BOOT-A")
fat_mkdir(${EFI_A_PART_OFFSET}, "/boot")
fat_mkdir(${EFI_A_PART_OFFSET}, "/boot/extlinux")
}
on-resource fsbl1 { raw_write(${SPL1_PART_OFFSET}) }
on-resource fsbl2 { raw_write(${SPL1_PART_OFFSET}) }
on-resource u-boot.img { raw_write(${UBOOT_PART_OFFSET}) }
on-resource extlinux.conf { fat_write(${EFI_A_PART_OFFSET}, "/boot/extlinux/extlinux.conf") }
on-resource zImage { fat_write(${EFI_A_PART_OFFSET}, "/boot/extlinux/zImage") }
on-resource osd32mp1-brk.dtb { fat_write(${EFI_A_PART_OFFSET}, "/boot/extlinux/osd32mp1-brk.dtb") }
on-resource rootfs.img { 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, so make sure we're running
# on B.
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(${EFI_A_PART_OFFSET}, ${EFI_A_PART_COUNT})
trim(${ROOTFS_A_PART_OFFSET}, ${ROOTFS_A_PART_COUNT})
# Reset the previous contents of the A boot partition
fat_mkfs(${EFI_A_PART_OFFSET}, ${EFI_A_PART_COUNT})
fat_mkdir(${EFI_A_PART_OFFSET}, "/boot")
fat_mkdir(${EFI_A_PART_OFFSET}, "/boot/extlinux")
}
on-resource extlinux.conf { fat_write(${EFI_A_PART_OFFSET}, "/boot/extlinux/extlinux.conf") }
on-resource zImage { fat_write(${EFI_A_PART_OFFSET}, "/boot/extlinux/zImage") }
on-resource osd32mp1-brk.dtb { fat_write(${EFI_A_PART_OFFSET}, "/boot/extlinux/osd32mp1-brk.dtb") }
on-resource rootfs.img { 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")
gpt_write(gpt-a)
}
}
task upgrade.b {
# This task upgrades the B partition, so make sure we're running
# on A.
require-uboot-variable(uboot-env, "nerves_fw_active", "a")
# 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, "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(${EFI_B_PART_OFFSET}, ${EFI_B_PART_COUNT})
trim(${ROOTFS_B_PART_OFFSET}, ${ROOTFS_B_PART_COUNT})
fat_mkfs(${EFI_B_PART_OFFSET}, ${EFI_B_PART_COUNT})
fat_mkdir(${EFI_B_PART_OFFSET}, "/boot")
fat_mkdir(${EFI_B_PART_OFFSET}, "/boot/extlinux")
}
on-resource extlinux.conf { fat_write(${EFI_B_PART_OFFSET}, "/boot/extlinux/extlinux.conf") }
on-resource zImage { fat_write(${EFI_B_PART_OFFSET}, "/boot/extlinux/zImage") }
on-resource osd32mp1-brk.dtb { fat_write(${EFI_B_PART_OFFSET}, "/boot/extlinux/osd32mp1-brk.dtb") }
on-resource rootfs.img { 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")
gpt_write(gpt-b)
}
}
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.wrong {
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}")
}
}