Giter Club home page Giter Club logo

fwup's Introduction

The fwup pup

Overview

CircleCI Coverage Status Coverity Scan Build Status

fwup is a configurable image-based software update utility for embedded Linux-based systems. It primarily supports software upgrade strategies that update entire root filesystem images at once. This includes strategies like swapping back and forth between A and B partitions, recovery partitions, and various trial update/failback scenarios. All software update information is combined into a ZIP archive that may optionally be cryptographically signed. fwup has minimal dependencies and runtime requirements. Scripts are intentionally limited to make failure scenarios easier to reason about. Distribution of software update archives is not a feature. Users can call out to fwup to run upgrades from external media, stream them from the network, or script them using a tool like Ansible if so desired.

Here's a list of features:

  1. Uses standard ZIP archives to make debugging and transmission simple.

  2. Simple, but flexible configuration language to enable firmware updates on various platforms and firmware update policies.

  3. Streaming firmware update processing to simplify target storage requirements.

  4. Multiple firmware update task options per archive so that one archive can upgrade varying target configurations

  5. Basic disk partitioning (GPT and MBR) and FAT filesystem manipulation

  6. Human and machine readable progress.

  7. Initialize or update SDCards on your development system whether you're running Linux, OSX, BSD, or Windows. MMC and SDCards are automatically detected and unmounted. No need to scan logs or manually unmount.

  8. Firmware archive digital signature creation and verification

  9. Delta update support using VCDIFF. See delta update section for details (BETA FEATURE).

  10. Sparse file support to reduce number of bytes that need to be written when initializing large file systems (see section on sparse files)

  11. Permissive license (Apache 2.0 License - see end of doc for details)

  12. Extensively regression tested! Tests also provide examples of functionality.

Internally, fwup has many optimizations to speed up low level disk writes over what can easily be achieved with dd(1). It orders, Flash erase block aligns, and can skip writing large unused sections to minimize write time. It also verifies writes to catch corruption before the device reboots to the new firmware. The goal is to make updates fast enough for code development and reliable enough for production use.

Installing

The simplest way to install fwup is via a package manager or installer.

On OSX, fwup is in homebrew:

brew install fwup

On Linux, download and install the appropriate package for your platform:

On Windows, fwup can be installed from chocolatey

choco install fwup

Alternatively, download the fwup executable and place it in your path.

If you're using another platform or prefer to build it yourself, download the latest source code release or clone this repository. Then read one of the following files:

When building from source, please verify that the regression test pass on your system (run make check) before using fwup in production. While the tests usually pass, they have found minor issues in third party libraries in the past that really should be fixed.

NOTE: For space-constrained target devices, use ./configure --enable-minimal-build to trim functionality that's rarely used.

Invoking

If you were given a .fw file and just want to install its contents on an SDCard, here's an example run on Linux:

$ sudo fwup example.fw
Use 14.92 GiB memory card found at /dev/sdc? [y/N] y
100%
Elapsed time: 2.736s

If you're on OSX or Windows, leave off the call to sudo.

IMPORTANT: If you're using an older version of fwup, you'll have to specify more arguments. Run: fwup -a -i example.fw -t complete

Here's a list of other options:

Usage: fwup [OPTION]...

Options:
  -a, --apply   Apply the firmware update
  -c, --create  Create the firmware update
  -d <file> Device file for the memory card
  -D, --detect List attached SDCards or MMC devices and their sizes
  -E, --eject Eject removable media after successfully writing firmware.
  --no-eject Do not eject media after writing firmware
  --enable-trim Enable use of the hardware TRIM command
  --exit-handshake Send a Ctrl+Z on exit and wait for stdin to close (Erlang)
  -f <fwup.conf> Specify the firmware update configuration file
  -F, --framing Apply framing on stdin/stdout
  -g, --gen-keys Generate firmware signing keys (fwup-key.pub and fwup-key.priv)
  -i <input.fw> Specify the input firmware update file (Use - for stdin)
  -l, --list   List the available tasks in a firmware update
  -m, --metadata   Print metadata in the firmware update
  --metadata-key <key> Only output the specified key's value when printing metadata
  --minimize-writes Skip write if contents match destination
  --no-minimize-writes Don't try to minimize writes when applying firmware updates (default)
  -n   Report numeric progress
  -o <output.fw> Specify the output file when creating an update (Use - for stdout)
  -p, --public-key-file <keyfile> A public key file for verifying firmware updates
  --private-key <key> A private key for signing firmware updates
  --progress-low <number> When displaying progress, this is the lowest number (normally 0 for 0%)
  --progress-high <number> When displaying progress, this is the highest number (normally 100 for 100%)
  --public-key <key> A public key for verifying firmware updates
  -q, --quiet   Quiet
  -s, --private-key-file <keyfile> A private key file for signing firmware updates
  -S, --sign Sign an existing firmware file (specify -i and -o)
  --sparse-check <path> Check if the OS and file system supports sparse files at path
  --sparse-check-size <bytes> Hole size to check for --sparse-check
  -t, --task <task> Task to apply within the firmware update
  -u, --unmount Unmount all partitions on device first
  -U, --no-unmount Do not try to unmount partitions on device
  --unsafe Allow unsafe commands (consider applying only signed archives)
  -v, --verbose   Verbose
  -V, --verify  Verify an existing firmware file (specify -i)
  --verify-writes Verify writes when applying firmware updates to detect corruption (default for writing to device files)
  --no-verify-writes Do not verify writes when applying firmware updates (default for regular files)
  --version Print out the version
  -y   Accept automatically found memory card when applying a firmware update
  -z   Print the memory card that would be automatically detected and exit
  -1   Fast compression (for create)
  -9   Best compression (default)

Examples:

Create a firmware update archive:

  $ fwup -c -f fwup.conf -o myfirmware.fw

Apply the firmware to an attached SDCard. This would normally be run on the host
where it would auto-detect an SDCard and initialize it using the 'complete' task:

  $ fwup -a -i myfirmware.fw -t complete

Apply the firmware update to /dev/sdc and specify the 'upgrade' task:

  $ fwup -a -d /dev/sdc -i myfirmware.fw -t upgrade

Create an image file from a .fw file for use with dd(1):

  $ fwup -a -d myimage.img -i myfirmware.fw -t complete

Generate a public/private key pair:

  $ fwup -g

Store fwup-key.priv in a safe place and fwup-key.pub on the target. To sign
an existing archive run:

  $ fwup -S -s fwup-key.priv -i myfirmware.fw -o signedfirmware.fw

Example usage

The regression tests contain short examples for usage of various script elements and are likely the most helpful to read due to their small size.

Other examples can be found in the bbb-buildroot-fwup for project for the BeagleBone Black and Raspberry Pi. The Nerves Project has more examples and is better maintained.

My real world use of fwup involves writing the new firmware to a place on the Flash that's not in current use and then 'flipping' over to it at the very end. The examples tend to reflect that. fwup can also be used to overwrite an installation in place assuming you're using an initramfs, but that doesn't give protection against someone pulling power at a bad time. Also, fwup's one pass over the archive feature means that firmware validation is mostly done on the fly, so you'll want to verify the archive first (see the -V option).

Helper scripts

While not the original use of fwup, it can be convenient to convert other files to .fw files. fwup comes with the following shell script helper:

  • img2fwup - convert a raw image file to a .fw file

A use case for the img2fwup script is to convert a large SDCard image file to one that is compressed and checksummed by fwup for distribution.

Versioning

fwup uses semver for versioning. For example, if you are using 1.0.0, that means no breaking changes until 2.0.0 or new features until 1.1.0. I highly recommend a conservative approach to upgrading fwup once you have devices in the field. For example, if you have 1.0.0 devices in the field, it's ok to update to 1.1.0, but be very careful about using 1.1.0 features in your fwup.conf files. They will be ignored by 1.0.0 devices and that may or may not be what you want.

Configuration file format

fwup uses the Unix configuration library, libconfuse, so its configuration has some similarities to other programs. The configuration file is used to create firmware archives. During creation, fwup embeds a processed version of the configuration file into the archive that has been stripped of comments, has had all variables resolved, and has some additional useful metadata added. Configuration files are organized into scoped blocks and options are set using a key = value syntax. Additionally, configuration files may include configuration fragments and other files by calling include("filename").

Environment variables

For integration into build systems and other scripts, fwup performs variable substitution inside of the configuration files. Keep in mind that environment variables are resolved on the host during firmware update file creation. Generated firmware files do not contain

Environment variables are referenced as follows:

key = ${ANY_ENVIRONMENT_VARIABLE}

It is possible to provide default values for environment variables using the :- symbol:

key = ${ANY_ENVIRONMENT_VARIABLE:-adefault}

Inside configuration files, it can be useful to define constants that are used throughout the file. Constants are referenced identically to environment variables. Here is an example:

define(MY_CONSTANT, 5)

By default, repeated definitions of the same constant do not change that constant's value. In other words, the first definition wins. Note that the first definition could come from a similarly named environment variable. This makes it possible to override a constant in a build script.

In some cases, having the last definition win is preferable for constants that never ever should be overridden by the environment or by earlier calls to define. For this behavior, use define!:

define!(MY_CONSTANT, "Can't override this")

Simple math calculations may also be performed using define-eval() and define-eval!(). For example:

define-eval(AN_OFFSET, "${PREVIOUS_OFFSET} + ${PREVIOUS_COUNT}")

These two functions were added in release 0.10.0, but since they are evaluated at firmware creation time, .fw files created using them are compatible with older versions of fwup.

Finally, file-resource will define a variable named FWUP_SIZE_<resource_name> with the size of the resource. For example the following will create a variable named FWUP_SIZE_zImage:

file-resource zImage {
        host-path = "output/images/zImage"
}

execute("echo zImage size is ${FWUP_SIZE_zImage} bytes")

Global scope

At the global scope, the following options are available:

Key Description
require-fwup-version Require a minimum version of fwup to apply this update
meta-product Product name
meta-description Description of product or firmware update
meta-version Firmware version
meta-author Author or company behind the update
meta-platform Platform that this update runs on (e.g., rpi or bbb)
meta-architecture Platform architectures (e.g., arm)
meta-vcs-identifier A version control identifier for use in reproducing this image
meta-misc Miscellaneous additional data. Format and contents are up to the user
meta-creation-date Timestamp when the update was created (derived from ZIP metadata). For reproducible builds, set the SOURCE_DATE_EPOCH environment variable.
meta-fwup-version Version of fwup used to create the update (deprecated - no longer added since fwup 1.2.0)
meta-uuid A UUID to represent this firmware. The UUID won't change even if the .fw file is digitally signed after creation (automatically generated)

After setting the above options, it is necessary to create scopes for other options. The currently available scopes are:

Scope Description
file-resource Defines a reference to a file that should be included in the archive
mbr Defines the master boot record contents on the destination
gpt Defines GPT partitions on the destination
task Defines a firmware update task (referenced using -t from the command line)

file-resource

A file-resource specifies a file on the host that should be included in the archive. Each file-resource should be given a unique name so that it can be referred to by other parts of the update configuration. fwup will automatically record the length and BLAKE2b-256 hash of the file in the archive. These fields are used internally to compute progress and verify the contents of the archive. A typical file-resource section looks like this:

file-resource zImage {
        host-path = "output/images/zImage"
}

Resources are usually stored in the data directory of the firmware archive. This is transparent for most users. If you need to make the .fw file work with other software, it is sometimes useful to embed a file into the archive at another location. This can be done by specifying an absolute path resource as follows:

file-resource "/my_custom_metadata" {
        host-path = "path/to/my_custom_metadata_file"
}

Resource concatenation

Sometimes you need to concatenate multiple files together to form one file-resource. While you can sometimes do this using multiple calls to raw_write, that won't work if you don't know the file offsets a priori or the offsets don't fall on block boundaries. Another alternative is to concatenate files as a prep step to fwup. If that's inconvenient, fwup allows multiple paths to be specified in host-path that are separated by semicolons. They will be concatenated in the order they appear.

file-resource kernel_and_rootfs {
        # Concatenate uImage and the rootfs. OpenWRT mtd splitter will
        # separate them back out at runtime.
        host-path = "output/images/uImage;output/images/rootfs.squashfs"
}

File resource validation checks

When creating archives, fwup can perform validation checking on file resources to catch simple errors. These checks can catch common errors like file resources growing too large to fit on the destination or files truncated due to cancelled builds.

Note that these checks are not performed when applying updates, since the actual length (and a hash) is recorded in the archive metadata and used for verification.

The following checks are supported:

Check Description
assert-size-lte If the file size is not less than or equal the specified amount, report an error.
assert-size-gte If the file size is not greater than or equal the specified amount, report an error.

Sizes are given in 512 byte blocks (like everything else in fwup).

Here's an example:

file-resource rootfs.img {
        host-path = "output/images/rootfs.squashfs"
        assert-size-lte = ${ROOTFS_A_PART_COUNT}
}

Files from strings

Sometimes it's useful to create short files inside the fwup config file rather than referencing them. This can be accomplished using the contents key in a file-resource. Variable substitution works in the contents string just like any other string in the fwup configuration file.

file-resource short-file.txt {
        contents = "You're looking at a short\n\
file creating by fwup.\n\
When it was made, FOO was ${FOO}.\n"
}

mbr

A mbr section specifies the contents of the Master Boot Record on the destination media. This section contains the partition table that's read by Linux and the bootloaders for finding the file systems that exist on the media. In comparison to a tool like fdisk, fwup only supports simplistic partition setup, but this is sufficient for many devices. Tools such as fdisk can be used to determine the block offsets and sizes of partitions for the configuration file. Offsets and sizes are given in 512 byte blocks. Here's a potential mbr definition:

mbr mbr-a {
        bootstrap-code-host-path = "path/to/bootstrap-data" # should be 440 bytes
        signature = 0x01020304

        partition 0 {
                block-offset = ${BOOT_PART_OFFSET}
                block-count = ${BOOT_PART_COUNT}
                type = 0x1 # FAT12
                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
        }
}

If you're using an Intel Edison or similar platform, fwup supports generation of the OSIP header in the MBR. This header provides information for where to load the bootloader (e.g.., U-Boot) in memory. The include-osip option controls whether the header is generated. The OSIP and image record (OSII) option names map directly to the header fields with the exception that length, checksum and image count fields are automatically calculated. The following is an example that shows all of the options:

mbr mbr-a {
    include-osip = true
    osip-major = 1
    osip-minor = 0
    osip-num-pointers = 1

    osii 0 {
        os-major = 0
        os-minor = 0
        start-block-offset = ${UBOOT_OFFSET}
        ddr-load-address = 0x01100000
        entry-point = 0x01101000
        image-size-blocks = 0x0000c000
        attribute = 0x0f
    }

    partition 0 {
        block-offset = ${ROOTFS_A_PART_OFFSET}
        block-count = ${ROOTFS_A_PART_COUNT}
        type = 0x83 # Linux
    }
}

Sometimes it's useful to have the final partition fill the remainder of the storage. This is needed if your target's storage size is unknown and you need to use as much of it as possible. The expand option requests that fwup grow the block-count to be as large as possible. When using expand, the block-count is now the minimum partition size. Only the final partition can be expandable. Here's an example:

mbr mbr-a {
        partition 0 {
                block-offset = ${BOOT_PART_OFFSET}
                block-count = ${BOOT_PART_COUNT}
                type = 0x1 # FAT12
                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
        }
}

gpt

A gpt section specifies the contents of a GUID Partition Table. It is similar to the mbr section, but it supports more partitions and uses UUIDs. Here's an example gpt definition:

gpt my-gpt {
    # UUID for the entire disk
    guid = b443fbeb-2c93-481b-88b3-0ecb0aeba911

    partition 0 {
        block-offset = ${EFI_PART_OFFSET}
        block-count = ${EFI_PART_COUNT}
        type = c12a7328-f81f-11d2-ba4b-00a0c93ec93b # EFI type UUID
        guid = 5278721d-0089-4768-85df-b8f1b97e6684 # ID for partition 0 (create with uuidgen)
        name = "efi-part.vfat"
    }
    partition 1 {
        block-offset = ${ROOTFS_PART_OFFSET}
        block-count = ${ROOTFS_PART_COUNT}
        type = 44479540-f297-41b2-9af7-d131d5f0458a # Rootfs type UUID
        guid = fcc205c8-2f1c-4dcd-bef4-7b209aa15cca # Another uuidgen'd UUID
        name = "rootfs.ext2"
        flags = 0xc000000000000
        boot = true
    }
}

See the GPT partition entry header specification for what partition fields mean and how to use them. Of the fields, name, flags, and boot are optional and default to an empty string, zero, or false. The flags field holds the integer value of the partition attribute field. It is a 64-bit number. Bit 2, the legacy BIOS bootable flag, can also be set by specifying boot = true. Both boot and flags can be specified in a partition block.

Call gpt_write to tell fwup to write the protective MBR and primary and backup GPT tables.

U-Boot environment

For systems using the U-Boot bootloader, some support is included for modifying U-Boot environment blocks. In order to take advantage of this, you must declare a uboot-environment section at the top level that describes how the environment block:

uboot-environment my_uboot_env {
    block-offset = 2048
    block-count = 16
}

To use the redundant environment block style, add block-offset-redund with the address where the redundant copy is located:

uboot-environment my_uboot_env {
    block-offset = 2048
    block-count = 16
    block-offset-redund = 2064
}

See the functions in the task section for getting and setting U-Boot variables.

NOTE: Currently, I've only implemented support for U-Boot environments that I use. Notably, this doesn't support big endian targets, and writes to raw NAND parts. Please consider contributing back support for these if you use them.

If fwup's U-Boot support does not meet your needs, it is always possible to create environment images using the mkenvimage utility and raw_write them to the proper locations. This is probably more appropriate when setting lots of variables.

task

The task section specifies a firmware update task. These sections are the main part of the firmware update archive since they describe the conditions upon which an update is applied and the steps to apply the update. Each task section must have a unique name, but when searching for a task, the firmware update tool only does a prefix match. This lets you define multiple tasks that can be evaluated based on conditions on the target hardware. The first matching task is the one that gets applied. This can be useful if the upgrade process is different based on the version of firmware currently on the target, the target architecture, etc. The following table lists the supported constraints:

Constraint Min fwup version Description
require-fat-file-exists(block_offset, filename) 0.7.0 Require that a file exists in the specified FAT filesystem
require-fat-file-match(block_offset, filename, pattern) 0.14.0 Require that filename exists and that pattern matches bytes inside of the file
require-partition-offset(partition, block_offset) 0.7.0 Require that the block offset of a partition be the specified value
require-path-on-device(path, device) 0.13.0 Require that the specified path (e.g., "/") is on the specified partition device (e.g., "/dev/mmcblk0p1")
require-path-at-offset(path, offset) 0.19.0 Require that the specified path (e.g., "/") is at the specified block offset (e.g., 1024). Combine with require-path-on-device.
require-uboot-variable(my_uboot_env, varname, value) 0.10.0 Require that a variable is set to the specified value in the U-Boot environment

The remainder of the task section is a list of event handlers. Event handlers are organized as scopes. An event handler matches during the application of a firmware update when an event occurs. Events include initialization, completion, errors, and files being decompressed from the archive. Since archives are processed in a streaming manner, the order of events is deterministic based on the order that files were added to the archive. If it is important that one event happen before another, make sure that file-resource sections are specified in the desired order. The following table lists supported events:

Event Description
on-init First event sent when the task is applied
on-finish Final event sent assuming no errors are detected during event processing
on-error Sent if an error occurs so that intermediate files can be cleaned up
on-resource <resource name> Sent as events occur. Currently, this is sent as file-resources are processed from the archive.

The event scopes contain a list of actions. Actions can format file systems, copy files to file systems or write to raw locations on the destination.

Action Min fwup version Description
error(message) 0.12.0 Immediately fail a firmware update with an error
execute(command) 0.16.0 Execute a command on the host. Requires the --unsafe flag
fat_mkfs(block_offset, block_count) 0.1.0 Create a FAT file system at the specified block offset and count
fat_write(block_offset, filename) 0.1.0 Write the resource to the FAT file system at the specified block offset
fat_write(block_offset) 1.10.0 Same as the two argument fat_write except the filename is the resource name. This is handled when creating the archive, so it's backwards compatible.
fat_attrib(block_offset, filename, attrib) 0.1.0 Modify a file's attributes. attrib is a string like "RHS" where R=readonly, H=hidden, S=system
fat_mv(block_offset, oldname, newname) 0.1.0 Rename the specified file on a FAT file system
fat_mv!(block_offset, oldname, newname) 0.14.0 Rename the specified file even if newname already exists.
fat_rm(block_offset, filename) 0.1.0 Delete the specified file
fat_mkdir(block_offset, filename) 0.2.0 Create a directory on a FAT file system. This also succeeds if the directory already exists.
fat_setlabel(block_offset, label) 0.2.0 Set the volume label on a FAT file system
fat_touch(block_offset, filename) 0.7.0 Create an empty file if the file doesn't exist (no timestamp update like on Linux)
gpt_write(gpt) 1.4.0 Write the specified GPT to the target
info(message) 0.13.0 Print out an informational message
mbr_write(mbr) 0.1.0 Write the specified mbr to the target
path_write(destination_path) 0.16.0 Write a resource to a path on the host. Requires the --unsafe flag. Passing -d /dev/null works if no destination image.
pipe_write(command) 0.16.0 Pipe a resource through a command on the host. Requires the --unsafe flag
raw_memset(block_offset, block_count, value) 0.10.0 Write the specified byte value repeatedly for the specified blocks
raw_write(block_offset, options) 0.1.0 Write the resource to the specified block offset. Options include cipher and secret.
trim(block_offset, count) 0.15.0 Discard any data previously written to the range. TRIM requests are issued to the device if --enable-trim is passed to fwup.
uboot_recover(my_uboot_env) 0.15.0 If the U-Boot environment is corrupt, reinitialize it. If not, then do nothing
uboot_clearenv(my_uboot_env) 0.10.0 Initialize a clean, variable free U-boot environment
uboot_setenv(my_uboot_env, name, value) 0.10.0 Set the specified U-boot variable
uboot_unsetenv(my_uboot_env, name) 0.10.0 Unset the specified U-boot variable

Minimizing writes to the destination

Fwup tries to reduce the writes to the destination media using the following mechanisms:

  1. An internal block cache summarizes writes to individual blocks. This is outside of OS caching that fwup tries to disable to ensure ordering of writes. (i.e., switching the active filesystem needs to be after the filesystem writes get made)
  2. The --minimize-writes option causes fwup to check if a block on the destination has actually changed before writing it.

The motivation for these features is reduce the number of changes to the disk since each change could be interrupted by a system reset or result in a write failure or corruption. While the chance is remote, some users find peace of mind in the reduced write cycles on FLASH media.

Performance-wise, the internal block caching is almost improves update times. Minimizing writes incurs a block read operation before every write. As one would expect, if the writes are actually redundant, it improves firmware update time. For completely different content, it appears that the additional read does not noticeably affect firmware update time on relatively fast embedded devices (600+ MHz 4-core in testing). Slower single core devices have slightly longer firmware update times.

Delta firmware updates (BETA)

The purpose of delta firmware updates is to reduce firmware update file sizes and their associated costs by sending patches to devices. This requires that one know what firmware is running on the device so that an appropriate patch can be made. As with other features, fwup only addresses the firmware update file processing piece, but assists in this process by 1. uniquely identifying firmware via UUIDs and 2. including xdelta3 decompression support.

This feature is currently BETA, since it may change in backwards incompatible ways based on trial deployments. If you're using this, please avoid deploying it to places that are hard to access just in case.

fwup cannot produce delta .fw archives automatically. However, they are easy to produce manually or via a script. The deployments in progress use scripts to create patches for upgrading all possible firmware versions (keyed off UUID). Here's how:

  1. Decide which file resource is a good candidate for delta updates (you can pick more than one). Call this rootfs.img.

  2. In the fwup.conf, in the on-resource rootfs.img handlers, specify where the currently running rootfs.img contents exist. For example, if you're doing an A/B upgrades, when you upgrade B, point to the A's rootfs for source contents and vice versa for upgrading A. It will look something like this:

    task upgrade.a {
        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})
        }
    }
    task upgrade.b {
        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})
        }
    }
  3. Obtain the firmware file for the software running on the device. Call this original.fw.

  4. Create the firmware file for the new software. Call this update.fw. If you normally sign your firmware files, you can sign it now or sign the resulting patch file depending on what works best for your release process.

  5. Run unzip on both original.fw and update.fw in different directories. The rootfs.img file can be found under the data directory when unzipped.

  6. mkdir -p my_patch/data

  7. xdelta3 -A -S -f -s original/data/rootfs.img update/data/rootfs.img my_patch/data/rootfs.img

  8. cp update.fw my_patch/delta_update.fw

  9. cd my_patch && zip delta_update.fw data/rootfs.img

The delta_update.fw will have the patch for the rootfs.img and should be quite a bit smaller. If not, check that your before and after rootfs.img files don't have a lot of timestamp changes or are already so compressed that the deltas propagate through the entire image.

Even though you're manually modifying the .fw file, fwup stills provide guarantees on the final bits installed on the device. For one, fwup computes Blake 2B hashes on the final contents of the files, so what matters is what comes out of the xdelta3 decompressor and not what is stored in the archive. Most likely though, xdelta3 will detect corruption since it checks Adler32 checksums as it decompresses.

Delta update on-resource source settings

Where to find the source ("before" version) is always specified in on-resource blocks. It can either be source from raw bytes or from files in a FAT-formatted partition. Only one source is supported in each on-resource block.

Key Description
delta-source-raw-offset Set to the starting block offset
delta-source-raw-count Set to the number of blocks in the source region. No reads will be allowed outside of this area.
delta-source-fat-offset Set to the starting block offset of the source FAT partition
delta-source-fat-path Set to the path inside the FAT partition of the source file

Sparse files

Sparse files are files with gaps in them that are only represented on the filesystem in metadata. Not all filesystems support sparse files, but in general, Linux has good support. Creating a sparse file is easy: just seek to a location past the end of file and write some data. The gap is "stored" as a hole in the filesystem metadata. Data is read back from the hole as zeros. Data and holes are restricted to start and end on filesystem block boundaries, so small gaps may be filled in with zeros rather than being stored as a hole.

Why is this important? If you're using fwup to write a large EXT2 partition, you'll find that it contains many gaps. It would be better to just write the EXT2 data and metadata without filling in all of the unused space. Sparse file support in fwup lets you do that. Since EXT2 filesystems legitimately contain long runs of zeros that must be written to Flash, fwup queries the filesystem containing the EXT2 data to find the gaps. Other tools like dd(1) only look for runs of zeros so their sparse file support cannot be used to emulate this. You may see warnings about copying sparse files to Flash and it has to do with tools not writing long runs of zeros. The consequence of fwup querying the filesystem for holes is that this feature only works when firmware update archives are created on operating systems and filesystems that support it. Of course, firmware updates can be applied on systems without support for querying holes in files. Those systems also benefit from not having to write as much to Flash devices. If you instead apply a firmware update to a normal file, though, the OS will likely fill in the gaps with zeros and thus offer no improvement.

There is one VERY important caveat with the sparse file handling: Some zeros in files are important and some are not. If runs in zeros in a file are important and they are written to a file as a "hole", fwup will not write them back. This is catastrophic if the zeros represent things like free blocks on a filesystem. Luckily, the file system formatting utilities write the important zeros to the disk and the OS does not scan bytes to see which ones are runs on zeros and automatically create holes. Programs like dd(1) can do this, though, so it is crucial that you do not run files through dd to make then sparser before passing them to fwup.

This feature is off by default. To turn this feature on, set skip-holes on the resource to true:

file-resource rootfs.img {
        host-path = "output/images/rootfs.img"
        skip-holes = true
}

Disk encryption

The raw_write function has limited support for disk encryption that's compatible with the Linux dm-crypt kernel driver. This makes it possible to write filesystem data in a way that's unreadable at rest. Caveats are in order:

  1. fwup does not address handling of secret keys and improper handling can easily compromise the benefits of encryption
  2. The .fw archive is not encrypted. This mechanism assumes that the secrecy of the archive is protected by other means. Of course, it is possible pre-encrypt the data in the archive, but then you can't have device-specific secret keys.
  3. Only the simplest dm-crypt cipher is currently supported ("aes-cbc-plain"). This has known deficiencies. PRs for other modes that can be incorporated under fwup's Apache License would be appreciated

Various tutorials exist on the Internet for creating encrypted filesystems and mounting filesystems using dm-crypt. fwup is much simpler. It takes a block of bytes to write, encrypts it, and writes it to the destination. For example, if you have a SquashFS-formatted filesystem that you want written encrypted to a disk, you'd have this fragment:

on-resource fs.squashfs {
    raw_write(${PARTITION_START}, "cipher=aes-cbc-plain", "secret=\${SECRET_KEY}")
}

In the above example, the SECRET_KEY is expected to come from an environment variable being set on the device when applying the firmware update. You could, of course, hard-code the secret key in the configuration file to test things out. The key is hex-encoded.

Then, on the device, mount the SquashFS partition but use dm-crypt. The process will look something like this:

losetup /dev/loop0 /dev/mmcblk0p2
cryptsetup open --type=plain --cipher=aes-cbc-plain --key-file=key.txt /dev/loop0 my-filesystem
mount /dev/mapper/my-filesystem /mnt

You will likely need to replace many of the arguments above with ones appropriate for your system.

Reproducible builds

It's possible for the system time to be saved in various places when using fwup. This means that an archive with the same contents, but built at different times results in .fw files with different bytes. See reproducible-builds.org for a discussion on this topic.

fwup obeys the SOURCE_DATE_EPOCH environment variable and will force all timestamps to the value of that variable when needed. Set $SOURCE_DATE_EPOCH to the number of seconds since midnight Jan 1, 1970 (run date +%s) to use this feature.

A better way of comparing .fw archives, though, is to use the firmware UUID. The firmware UUID is computed from the contents of the archive rather than the bit-for-bit representation of the .fw file, itself. The firmware UUID is unaffected by timestamps (with or without SOURCE_DATE_EPOCH) or other things like compression algorithm improvements. This is not to say that SOURCE_DATE_EPOCH is not important, but that the UUID is an additional tool for ensuring that firmware updates are reproducible.

Firmware authentication

Firmware archives can be authenticated using a simple public/private key scheme. To get started, create a public/private key pair by invoking fwup -g. The algorithm used is Ed25519. This generates two file: fwup-key.pub and fwup-key.priv. It is critical to keep the signing key, fwup-key.priv secret.

To sign an archive, pass -s fwup-key.priv to fwup when creating the firmware. The other option is to sign the firmware archive after creation with --sign or -S.

To verify that an archive has been signed, pass -p fwup-key.pub on the command line to any of the commands that read the archive. E.g., -a, -l or -m.

It is important to understand how verification works so that the security of the archive isn't compromised. Firmware updates are applied in one pass to avoid needing a lot of memory or disk space. The consequence of this is that verification is done on the fly. The main metadata for the archive is always verified before any operations occur. Cryptographic hashs (using the BLAKE2b-256 algorithm) of each file contained in the archive is stored in the metadata. The hash for each file is computed on the fly, so a compromised file may not be detected until it has been written to Flash. Since this is obviously bad, the strategy for creating firmware updates is to write them to an unused location first and then switch over at the last possible minute. This is desirable to do anyway, since this strategy also provides some protection against the user disconnecting power midway through the firmware update.

Integration with applications

It is expected that many users will want to integrate fwup with their applications. Many operations can be accomplished by just invoking the fwup executable and parsing the text written to stdout. When applying firmware progress updates are delivered based on commandline options:

  1. Human readable - This is the default. Progress is updated from the text 0% to 100%.
  2. Numeric (-n) - Progess is printed as 0\n to 100\n
  3. Quiet (-q) - No progress is printed

While the above works well for scripts and when errors can be seen by the operator, fwup supports a structured use of stdin/stdout as well. Specify the --framing option to any of the commands to use this option.

The framing feature is influenced by the Erlang VM's port API and should be relatively easy to integrate with non-Erlang VM languages. The framing works around deficiencies in the built-in interprocess communication. For example, by enabling framing, a program can stream a firmware update through fwup's stdin without needing to close its stdout to signal end of file. Another feature aided by framing is knowing what text goes together and whether the text is part of an error message or not. Exit status is still an indicator of success or failure, but the controlling application doesn't need to wait for the program to exit to know what happened.

In --framing mode, all communication with fwup is done in packets (rather than byte streams). A packet starts with a 4 byte length field. The length is a big endian (network byte order) unsigned integer. A zero-length packet (i.e., 4 bytes of zeros) signals end of input.

Field Size Description
Length 4 bytes Packet length as a big endian integer
Data Length bytes Payload

Input and output packets have different formats. For sending input to fwup (like when streaming a .fw file using stdio), the input bytes should be framed into packets however is most convenient. For example, if bytes are received in 4K chunks, then they can be sent to fwup in 4K packets with a zero-length packet at the end. The packets need not be the same size.

All output packets from fwup have a 2 byte type field at the beginning of the packet:

Field Size Description
Length 4 bytes Packet length as a big endian integer
Type 2 bytes See below
Data Length-2 bytes Payload

The following types are defined:

Type 2 byte value Description
Success "OK" The command was executed successfully. The payload is a 2 bytes result code (currently 0 for success) followed by an optional textual message.
Error "ER" A failure occurred. The payload is a 2 byte error code (future use) followed by a textual error message.
Warning "WN" A warning occurred. The payload is a 2 byte error code (future use) followed by a textual error message.
Progress "PR" The next two bytes are the progress (0-100) as a big endian integer.

A related option is --exit-handshake. This option was specifically implemented for Erlang to support integration with its port process feature. It may be useful for other integrations where it's more convenient to wait for a final character coming from a subprocess rather than watching for an exit. The problem with Erlang is that it's easy for the message that the process exited to beat the final characters coming out stdout. When this option is enabled, fwup expects the calling process to close stdin when it's ready for fwup to exit.

FAQ

How do I include a file in the archive that isn't used by fwup

The scenario is that you need to store some metadata or some other information that is useful to another program. For example, you'd like to include some documentation or other notes inside the firmware update archive that the destination device can pull out and present on a UI. To do this, just add file-resource blocks for each file. These blocks don't need to be referenced by an on-resource block.

How do I include the firmware version in the archive

If you are using git, you can invoke fwup as follows:

GITDESCRIBE=`git describe` fwup -c -f myupdate.conf -o out.fw

Then in myupdate.conf add the line:

meta-version = "${GITDESCRIBE}"

On the target device, you can retrieve the version by using -m. For example:

$ fwup -m -i out.fw
meta-product = "Awesome product"
meta-description = "A description"
meta-version = "v0.0.1"
meta-author = "Me"
meta-platform = "bbb"
meta-architecture = "arm"
meta-uuid="07a34e75-b7ea-5ed8-b5d9-80c10daf4939"

What's something cool that you can do with fwup

Ok, this isn't really a FAQ, but for some reason people think this is cool. Many systems that I work on are network connected with ssh. Sometimes I update them by doing this:

$ cat mysoftware.fw | ssh [email protected] \
    'fwup -a -U -d /dev/mmcblk2 -t upgrade && reboot'

The ability to pipe software updates through fwup comes in handy. This has also gotten me out of situations where, for whatever reason, I no longer had enough space to store the update on the device.

How should I implement multiple signing keys

There are several use cases where it's necessary to have multiple signing keys in use at a time. For example, you could want to enforce that all firmware updates are signed in your infrastructure, but not force everyone to go though the official secure path for QA builds. You may also want to only use each key for a limited amount of signings.

Currently, each firmware file can only have one signature. However, the verifier (device) can specify multiple public keys (repeated -p options). While it is possible to call fwup for each key, specifying multiples keys is recommended to run the verification through fwup to support streamed updates and also to simplify this critical code path.

How do I debug

I apply updates to regular files on my laptop (as opposed to eMMC or SDCards) and examine them with a hex editor. A few other routes might be useful too:

  1. Unzip the .fw file to inspect the contents. It's a regular ZIP file and the meta.conf file inside it is the stripped down view of what your configuration looks like after variable substitution, etc.
  2. Add the error() function to do printf-style debugging.
  3. Find an image that works and skip updating some sections. For example, some processors are very picky on the MBR contents and it's easier to get everything else working before tackling partition constraints.

How do I specify the root partition in Linux

There are a few options. Most people can specify root=/dev/mmcblk0p1 or root=/dev/sda1 or something similar on the kernel commandline and everything will work out fine. On systems with multiple drives and an unpredictable boot order, you can specify root=PARTUUID=01234567-01 where the -01 part corresponds to the 1-based partition index and 01234567 is any signature. In your fwup.conf file's MBR block, specify signature = 0x01234567. A third option is to use an initramfs and not worry about any of this.

How do I get the best performance

In general, fwup writes to Flash memory in large blocks so that the update can occur quickly. Obviously, reducing the amount that needs to get written always helps. Beyond that, most optimizations are platform dependent. Linux caches writes so aggressively that writes to Flash memory are nearly as fast as possible. OSX, on the other hand, does very little caching, so doing things like only working with one FAT filesystem at a time can help. In this case, fwup only caches writes to one FAT filesystem at a time, so mixing them will flush caches. OSX is also slow to unmount disks, so keep in mind that performance can only be so fast on some systems.

How do I update /dev/mmcblock0boot0

The special eMMC boot partitions are updatable the same way as the main partition. When I create .fw files for manufacturing, I create two targets, a complete target that updates the main eMMC and a bootloader target that updates mmcblock0boot0. The manufacturing script runs fwup twice: once for the complete target and then again for the bootloader target.

Also, the /dev/mmcblock0boot0 device is forced read-only by the kernel. To unlock it, run:

echo 0 > /sys/block/mmcblk0boot0/force_ro

What's the best way to identify firmware versions

fwup supports several ways:

  1. Store the version in meta-version. This is usually the friendliest for end users.
  2. Store the git hash in meta-vcs-identifier. This is good for developers.
  3. Use the fwup-computed UUID that's available in meta-uuid' and ${FWUP_META_UUID}`.

Of these, the third one is always available since version fwup v1.2.1. The motivation behind it was to unambiguously know whether installed firmware matches the desired firmware. Since it is computed, .fw files generated with previous versions of fwup have UUIDs.

The first two options require the versions to be added to the fwup.conf file. They are usually added using environment variables so that the version numbers are not hardcoded.

How do I get the firmware metadata formatted as JSON

Use jq!

$ fwup -m -i $FW_FILE | jq -n -R 'reduce inputs as $i ({}; . + ($i | (match("([^=]*)=\"(.*)\"") | .captures | {(.[0].string) : .[1].string})))'
{
  "meta-product": "My Awesome Product",
  "meta-version": "0.1.0",
  "meta-author": "All of us",
  "meta-platform": "imx6",
  "meta-architecture": "arm",
  "meta-creation-date": "2018-11-07T14:46:38Z",
  "meta-uuid": "7add3c6d-230c-5bf1-77ec-5f785e91be40"
}

How do I use "raw" NAND Flash

Some "raw" NAND Flash requires a wear leveling layer such as UBI. See the UBI Example fwup.conf for how to integrate fwup with the UBI toolchain.

How do you pronounce fwup

I used to pronounce it "eff-double-you-up", but then coworkers and others started calling it "fwup" (one syllable) and "fwup-dates" when referring to the .fw files. I now use the one syllable version. This has caused issues in the documentation where "an" is used rather than "a". Feel free to send PRs.

Licenses

This utility contains source code with various licenses. The bulk of the code is licensed with the Apache-2.0 license which can be found in the LICENSE file.

All statically-linked 3rd party source code can be found in the src/3rdparty directory. The following sections summarize the included code licenses.

base64.c

Public Domain or Creative Commons CC0. See file for explanatory text.

FatFS

The FAT filesystem code (FatFs) comes from elm-chan.org and has the following license:

FatFs module is a generic FAT file system module for small embedded systems. This is a free software that opened for education, research and commercial developments under license policy of following terms.

Copyright (C) 2015, ChaN, all right reserved.

  • The FatFs module is a free software and there is NO WARRANTY.
  • No restriction on use. You can use, modify and redistribute it for personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
  • Redistributions of source code must retain the above copyright notice.

Monocypher

This package has been dual licensed under the 2-clause BSD and CC-0. See LICENCE.md.

semver.c

fwup uses semver.c for checking versions. semver.c is Copyright (c) Tomás Aparicio and distributed under the MIT License. See LICENSE.

strptime.c

On systems without the function strptime(), a version from Google is included that is distributed under the Apache 2.0 license.

Tiny AES

This code was released into the public domain. See unlicense.txt for details.

Xdelta3

Only the xdelta3 decompressor is currently used by fwup so most of the code in the xdelta3 directory is ignored or disabled. Importantly, fwup's use of xdelta3 does not bring in any xdelta3 dependencies. Xdelta3 is covered by the Apache-2.0 license.

fwup's People

Contributors

arthur-proglove avatar axelson avatar bkuhls avatar bryceschober avatar davidepianca98 avatar edahlseng avatar ejc123 avatar electricshaman avatar fhunleth avatar gregmefford avatar kentaro avatar kfatehi avatar lawik avatar linhdnguyen avatar mattjg908 avatar michaelkschmidt avatar mikaelrobomagi avatar mobileoverlord avatar nl3v avatar pdgonzalez872 avatar philipgiuliani avatar rickcarlino avatar robphoenix avatar takasehideki avatar tapickell avatar tonyarkles avatar tpetazzoni avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fwup's Issues

fwup_0.9.0_amd64.deb package is rejected by Ubuntu 14.04

When trying to install fwup_0.9.0_amd64.deb I get an error: This package is of bad quality

Lintian check results for /tmp/mozilla_jon0/fwup_0.9.0_amd64.deb:
E: fwup: maintainer-name-missing travis@testing-gce-c23388e7-daf4-4bba-91d1-7b6fcd0520f9
E: fwup: maintainer-address-malformed travis@testing-gce-c23388e7-daf4-4bba-91d1-7b6fcd0520f9

I checked version 0.8.2 and it's the same message, although the values in the details are different.
couldn't find anything on the googles, so I just installed it. It seems to work fine. If this is normal, just close this ticket. Thiss issue might help others with the same thing though.

file-resource custom path does't seem to work

I am trying to add file to the fw bundle using the file-resource option in my fwup.conf file, like so:

file-resource "/release.html" {
    host-path = "${NERVES_ROOT}/../_images/release.html"
}

Then when the firmware bundle is made I get

chris@chrisdev:~/projects/ng1a$ ls _images/fw/
data  meta.conf
chris@chrisdev:~/projects/ng1a$ ls _images/fw/data/
MLO  release.html  rootfs.ext2  u-boot.img  uEnv.txt

From the documentation it seems like this should end up in the root of the bundle.

Not compiling because of help2man

I had issues compiling the 0.9.0 version, while 0.8.2 works fine.

./configure runs fine, but make fails with the following error:

make[2]: *** No rule to make target 'fwup.h2m', needed by 'fwup.1'.  Stop.

After removing the following code from src/Makefile.am it worked fine.

if HAVE_HELP2MAN
man_MANS = fwup.1
CLEANFILES = $(man_MANS)
EXTRA_DIST += fwup.h2m

fwup.1: fwup$(EXEEXT) fwup.h2m
    $(HELP2MAN) --no-discard-stderr --output=$@ --no-info --include fwup.h2m \
        -n "configurable embedded firmware update creator and runner" \
        ./fwup$(EXEEXT)
else
    @echo  "Warning: help2man not available, no man page created."
endif

If you have any questions, just ask!

Support modifying uboot environment

My preferred way of swapping old and new partitions is to update the appropriate uboot environment variables rather than re-writing the MBR. This makes testing and debugging easier, and with a redundant uboot environment enabled should be fully power-off safe. (MBR method makes me nervous)

I've been looking at whether to add this directly to fwup or just incorporate it in a wrapper script. Thoughts?

make check on OpenBSD fails (15/140)

=======================================
   fwup 0.17.0: tests/test-suite.log
=======================================

# TOTAL: 140
# PASS:  125
# SKIP:  0
# XFAIL: 0
# FAIL:  15
# XPASS: 0
# ERROR: 0

.. contents:: :depth: 2

FAIL: 038_write_15M
===================

|                                    | 1% (0.20 / 15.00) MBAbort trap (core dumped) 

Test failed!

Leaving test work files in '/home/niko/tmp/fwup/tests/work-038_write_15M.test'
FAIL 038_write_15M.test (exit status: 134)

FAIL: 039_upgrade
=================

|=================================== | 99% (152.56 / 152.56) KBAbort trap (core dumped) 

Test failed!

Leaving test work files in '/home/niko/tmp/fwup/tests/work-039_upgrade.test'
FAIL 039_upgrade.test (exit status: 134)

FAIL: 045_legacy_require_partition1
===================================

|=================================== | 99% (152.56 / 152.56) KBAbort trap (core dumped) 

Test failed!

Leaving test work files in '/home/niko/tmp/fwup/tests/work-045_legacy_require_partition1.test'
FAIL 045_legacy_require_partition1.test (exit status: 134)

FAIL: 052_file_concatenation
============================

|==============================      | 85% (130.70 / 152.05) KBAbort trap (core dumped) 

Test failed!

Leaving test work files in '/home/niko/tmp/fwup/tests/work-052_file_concatenation.test'
FAIL 052_file_concatenation.test (exit status: 134)

FAIL: 073_multistep_fat
=======================

|                                    | 1% (0.15 / 15.16) MBAbort trap (core dumped) 

Test failed!

Leaving test work files in '/home/niko/tmp/fwup/tests/work-073_multistep_fat.test'
FAIL 073_multistep_fat.test (exit status: 134)

FAIL: 074_fat_cache_fail
========================

|=========                           | 25% (1.18 / 4.58) MBAbort trap (core dumped) 

Test failed!

Leaving test work files in '/home/niko/tmp/fwup/tests/work-074_fat_cache_fail.test'
FAIL 074_fat_cache_fail.test (exit status: 134)

FAIL: 075_big_fat_fs
====================

|=                                   | 4% (0.66 / 15.00) MBAbort trap (core dumped) 

Test failed!

Leaving test work files in '/home/niko/tmp/fwup/tests/work-075_big_fat_fs.test'
FAIL 075_big_fat_fs.test (exit status: 134)

FAIL: 082_uboot_upgrade
=======================

|=================================== | 99% (152.56 / 152.56) KBAbort trap (core dumped) 

Test failed!

Leaving test work files in '/home/niko/tmp/fwup/tests/work-082_uboot_upgrade.test'
FAIL 082_uboot_upgrade.test (exit status: 134)

FAIL: 085_raw_memset
====================

|=================================== | 99% (259.58 / 262.14) KBAbort trap (core dumped) 

Test failed!

Leaving test work files in '/home/niko/tmp/fwup/tests/work-085_raw_memset.test'
FAIL 085_raw_memset.test (exit status: 134)

FAIL: 095_sparse_apply
======================

fwup: Unsigned archive '/home/niko/tmp/fwup/tests/work-095_sparse_apply.test/fwup.fw' is not corrupt.
/home/niko/tmp/fwup/tests
fwup: Unsigned archive '/home/niko/tmp/fwup/tests/work-095_sparse_apply.test/new.fw' is not corrupt.
|=================================== | 99% (7.17 / 7.17) KBpthread_mutex_destroy on mutex with waiters!
pthread_mutex_destroy on mutex with waiters!
|====================================| 100% (7.17 / 7.17) KB
Success!
Elapsed time: 0.003s
|===                                 | 9% (0.84 / 9.24) MBAbort trap (core dumped) 

Test failed!

Leaving test work files in '/home/niko/tmp/fwup/tests/work-095_sparse_apply.test'
FAIL 095_sparse_apply.test (exit status: 134)

FAIL: 109_includes
==================

|===============================     | 87% (130.70 / 150.00) KBAbort trap (core dumped) 

Test failed!

Leaving test work files in '/home/niko/tmp/fwup/tests/work-109_includes.test'
FAIL 109_includes.test (exit status: 134)

FAIL: 110_compression_level
===========================

|=========                           | 26% (128.78 / 493.57) KBAbort trap (core dumped) 

Test failed!

Leaving test work files in '/home/niko/tmp/fwup/tests/work-110_compression_level.test'
FAIL 110_compression_level.test (exit status: 134)

FAIL: 111_streaming_exit_fast
=============================

./111_streaming_exit_fast.test[27]: timeout: not found

Test failed!

Leaving test work files in '/home/niko/tmp/fwup/tests/work-111_streaming_exit_fast.test'
FAIL 111_streaming_exit_fast.test (exit status: 127)

FAIL: 125_trimmed_upgrade
=========================

|=================================== | 99% (152.57 / 152.57) KBAbort trap (core dumped) 

Test failed!

Leaving test work files in '/home/niko/tmp/fwup/tests/work-125_trimmed_upgrade.test'
FAIL 125_trimmed_upgrade.test (exit status: 134)

FAIL: 131_raw_key
=================

Firmware signing keys created and saved to fwup-key.pub and fwup-key.priv

Distribute fwup-key.pub with your system so that firmware updates can be
authenticated. Keep fwup-key.priv in a safe location.
43+0 records in
43+0 records out
43 bytes transferred in 0.000 secs (394495 bytes/sec)
86+0 records in
86+0 records out
86 bytes transferred in 0.000 secs (601399 bytes/sec)
/home/niko/tmp/fwup/tests
pthread_mutex_destroy on mutex with waiters!
pthread_mutex_destroy on mutex with waiters!
fwup: Signed archive '/home/niko/tmp/fwup/tests/work-131_raw_key.test/fwup.fw' is not corrupt. Pass a public key to verify the signature.
pthread_mutex_destroy on mutex with waiters!
pthread_mutex_destroy on mutex with waiters!
pthread_mutex_destroy on mutex with waiters!
pthread_mutex_destroy on mutex with waiters!
pthread_mutex_destroy on mutex with waiters!
pthread_mutex_destroy on mutex with waiters!
fwup: Error reading or decoding public key from file '/home/niko/tmp/fwup/tests/work-131_raw_key.test/fwup-key.pub.unpadded'

Test failed!

Leaving test work files in '/home/niko/tmp/fwup/tests/work-131_raw_key.test'
FAIL 131_raw_key.test (exit status: 1)

Unexpected error parsing meta.conf

When running fwup with an upgrade task on an embedded device, an error is produced (almost immediately):

[buf]:66: no such option 'include-osip'
fwup: Unexpected error parsing meta.conf

Interestingly enough, when I run the command on my local machine with the sd card simply inserted as an external device, I don't encounter this command.

A /dev/sdb file gets created if actual device is missing

I'm unsure of when exactly this happened but I likely was running mix firmware.burn -d /dev/sdb to manually choose the device and probably ran it when the SD card was unplugged.

Writes always appear to succeed, password prompt still appears, etc. Even gparted will [mostly] work on the resulting file.

fwup doesn't compile under uclibc (alix) buildroot

Was trying to change my firmware update system to use fwup rather than my own custom code but fwup doesn't seem to compile properly when I put BR2_PACKAGE_FWUP=y in my nerves config. Here is the error log..

fwup_apply.c: In function ‘task_is_applicable’:
fwup_apply.c:43:9: warning: implicit declaration of function ‘pread’ [-Wimplicit-function-declaration]
fwup_apply.c: In function ‘fwup_apply’:
fwup_apply.c:226:56: error: ‘O_CLOEXEC’ undeclared (first use in this function)
fwup_apply.c:226:56: note: each undeclared identifier is reported only once for each function it appears in
make[5]: *** [fwup-fwup_apply.o] Error 1
make[5]: *** Waiting for unfinished jobs....
fwfile.c: In function ‘cfg_to_string’:
fwfile.c:25:5: warning: implicit declaration of function ‘open_memstream’ [-Wimplicit-function-declaration]
fwfile.c:25:16: warning: initialization makes pointer from integer without a cast [enabled by default]
mv -f .deps/fwup-fwfile.Tpo .deps/fwup-fwfile.Po
mv -f .deps/fwup-fatfs.Tpo .deps/fwup-fatfs.Po
mv -f .deps/fwup-cfgfile.Tpo .deps/fwup-cfgfile.Po
functions.c: In function ‘raw_write_run’:
functions.c:185:9: warning: implicit declaration of function ‘pwrite’ [-Wimplicit-function-declaration]
mv -f .deps/fwup-functions.Tpo .deps/fwup-functions.Po
make[5]: Leaving directory /home/garth/echo/examples/hello_alix/_nerves/buildroot/output/build/fwup-v0.0.4/src' make[4]: *** [all-recursive] Error 1 make[4]: Leaving directory/home/garth/echo/examples/hello_alix/_nerves/buildroot/output/build/fwup-v0.0.4'
make[3]: *** [all] Error 2
make[3]: Leaving directory /home/garth/echo/examples/hello_alix/_nerves/buildroot/output/build/fwup-v0.0.4' make[2]: *** [/home/garth/echo/examples/hello_alix/_nerves/buildroot/output/build/fwup-v0.0.4/.stamp_built] Error 2 make[2]: Leaving directory/home/garth/echo/examples/hello_alix/_nerves/buildroot'
make[1]: *** [br-make] Error 2
make[1]: Leaving directory `/home/garth/echo/examples/hello_alix/_nerves'
make: *** [_nerves/.stamp_built] Error 2
garth@debian:~/echo/examples/hello_alix$

Switch SD card size message to power-of-10 units

Currently, you get this:

Use 58.27 GiB memory card found at /dev/sdc? [Yn] 

This is for a MicroSD card that is labeled "64 GB". Since it seems like SSDs and SDCards are all labeled in power-of-10 units and pretty much every other program besides fwup uses power-of-10 units for these devices, change that message to something like this:

Use 62.57 GB memory card found at /dev/sdc? [Yn] 

Upgrade to libconfuse v2.9 to improve backward compatibility

The current version of libconfuse throws an error if it encounters a configuration parameter that it doesn't recognize. This is a big problem since it prevents the addition of a parameters if you want a new firmware file to be applied by an older version of fwup. In many cases, the new parameters are not mandatory for applying the firmware so the error is completely unnecessary. Version v2.9 of libconfuse has support for handling unknown arguments, so it will be possible to ignore these new arguments when parsing meta.conf files inside the .fw files. Errors should still be thrown when encountering unknown parameters when creating .fw files.

At this moment, libconfuse v2.9 hasn't been released. See https://github.com/martinh/libconfuse/blob/master/ChangeLog.md for details.

make check failing on NixOS

The tests start failing on 0.15.0, 0.14.3 builds fine.

fwup 0.15.0: tests/test-suite.log
=======================================
   fwup 0.15.0: tests/test-suite.log
=======================================

# TOTAL: 125
# PASS:  56
# SKIP:  0
# XFAIL: 0
# FAIL:  69
# XPASS: 0
# ERROR: 0

.. contents:: :depth: 2

FAIL: 001_simple_fw
===================


  0%
 99%
100%
Elapsed time: 0.000s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-001_simple_fw.test'
FAIL 001_simple_fw.test (exit status: 1)

FAIL: 002_resource_subdir
=========================


  0%
 33%
 66%
 99%
100%
Elapsed time: 0.000s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-002_resource_subdir.test'
FAIL 002_resource_subdir.test (exit status: 1)

FAIL: 003_write_offset
======================


  0%
 43%
 87%
 99%
100%
Elapsed time: 0.001s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-003_write_offset.test'
FAIL 003_write_offset.test (exit status: 1)

FAIL: 004_env_vars
==================


  0%
 99%
100%
Elapsed time: 0.000s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-004_env_vars.test'
FAIL 004_env_vars.test (exit status: 1)

FAIL: 005_define
================


  0%
 99%
100%
Elapsed time: 0.000s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-005_define.test'
FAIL 005_define.test (exit status: 1)

FAIL: 007_mbr
=============


  0%
 99%
100%
Elapsed time: 0.001s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-007_mbr.test'
FAIL 007_mbr.test (exit status: 1)

FAIL: 008_partial_mbr
=====================


  0%
 99%
100%
Elapsed time: 0.000s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-008_partial_mbr.test'
FAIL 008_partial_mbr.test (exit status: 1)

FAIL: 010_fat_mkfs
==================


  0%
 50%
 99%
100%
Elapsed time: 0.002s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-010_fat_mkfs.test'
FAIL 010_fat_mkfs.test (exit status: 1)

FAIL: 011_fat_setlabel
======================


  0%
 33%
 66%
100%
Elapsed time: 0.001s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-011_fat_setlabel.test'
FAIL 011_fat_setlabel.test (exit status: 1)

FAIL: 012_fat_write
===================


  0%
 99%
100%
Elapsed time: 0.001s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-012_fat_write.test'
FAIL 012_fat_write.test (exit status: 1)

FAIL: 013_fat_mv
================


  0%
 99%
100%
Elapsed time: 0.003s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-013_fat_mv.test'
FAIL 013_fat_mv.test (exit status: 1)

FAIL: 014_fat_cp
================


  0%
 99%
100%
Elapsed time: 0.001s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-014_fat_cp.test'
FAIL 014_fat_cp.test (exit status: 1)

FAIL: 017_fat_rm
================


  0%
 99%
100%
Elapsed time: 0.002s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-017_fat_rm.test'
FAIL 017_fat_rm.test (exit status: 1)

FAIL: 018_numeric_progress
==========================

verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-018_numeric_progress.test'
FAIL 018_numeric_progress.test (exit status: 1)

FAIL: 019_quiet_progress
========================

verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-019_quiet_progress.test'
FAIL 019_quiet_progress.test (exit status: 1)

FAIL: 022_signed_fw
===================

Firmware signing keys created and saved to fwup-key.pub and fwup-key.priv

Distribute fwup-key.pub with your system so that firmware updates can be
authenticated. Keep fwup-key.priv in a safe location.
/tmp/nix-build-fwup-0.15.0.drv-0/source/tests
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-022_signed_fw.test'
FAIL 022_signed_fw.test (exit status: 1)

FAIL: 026_sign_again
====================

Firmware signing keys created and saved to fwup-key.pub and fwup-key.priv

Distribute fwup-key.pub with your system so that firmware updates can be
authenticated. Keep fwup-key.priv in a safe location.
/tmp/nix-build-fwup-0.15.0.drv-0/source/tests
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-026_sign_again.test'
FAIL 026_sign_again.test (exit status: 1)

FAIL: 027_fat_timestamp
=======================


  0%
 99%
100%
Elapsed time: 0.001s
verify-syscalls: open was never called on '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-027_fat_timestamp.test/fwup.img.1'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-027_fat_timestamp.test'
FAIL 027_fat_timestamp.test (exit status: 1)

FAIL: 028_osip
==============


  0%
 99%
100%
Elapsed time: 0.000s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-028_osip.test'
FAIL 028_osip.test (exit status: 1)

FAIL: 029_5G_offset
===================

Sparse files supported

  0%
 43%
 87%
 99%
100%
Elapsed time: 0.001s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-029_5G_offset.test'
FAIL 029_5G_offset.test (exit status: 1)

FAIL: 030_2T_offset
===================

Sparse files supported

  0%
 43%
 87%
 99%
100%
Elapsed time: 0.003s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-030_2T_offset.test'
FAIL 030_2T_offset.test (exit status: 1)

FAIL: 031_fat_mkfs_5G
=====================

Sparse files supported

  0%
 50%
 99%
100%
Elapsed time: 0.106s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-031_fat_mkfs_5G.test'
FAIL 031_fat_mkfs_5G.test (exit status: 1)

FAIL: 032_fat_2T_offset
=======================

Sparse files supported

  0%
 99%
100%
Elapsed time: 0.001s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-032_fat_2T_offset.test'
FAIL 032_fat_2T_offset.test (exit status: 1)

FAIL: 035_streaming
===================


  0%
 99%
100%
Elapsed time: 0.001s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-035_streaming.test'
FAIL 035_streaming.test (exit status: 1)

FAIL: 036_streaming_signed_fw
=============================

Firmware signing keys created and saved to fwup-key.pub and fwup-key.priv

Distribute fwup-key.pub with your system so that firmware updates can be
authenticated. Keep fwup-key.priv in a safe location.
/tmp/nix-build-fwup-0.15.0.drv-0/source/tests
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-036_streaming_signed_fw.test'
FAIL 036_streaming_signed_fw.test (exit status: 1)

FAIL: 038_write_15M
===================


  0%
  1%
  2%
  3%
  4%
  5%
  6%
  7%
  8%
  9%
 10%
 11%
 12%
 13%
 14%
 15%
 16%
 17%
 18%
 19%
 20%
 21%
 22%
 23%
 24%
 25%
 26%
 27%
 28%
 29%
 30%
 31%
 32%
 33%
 34%
 35%
 36%
 37%
 38%
 39%
 40%
 41%
 42%
 43%
 44%
 45%
 46%
 47%
 48%
 49%
 50%
 51%
 52%
 53%
 54%
 55%
 56%
 57%
 58%
 59%
 60%
 61%
 62%
 63%
 64%
 65%
 66%
 67%
 68%
 69%
 70%
 71%
 72%
 73%
 74%
 75%
 76%
 77%
 78%
 79%
 80%
 81%
 82%
 83%
 84%
 85%
 86%
 87%
 88%
 89%
 90%
 91%
 92%
 93%
 94%
 95%
 96%
 97%
 98%
 99%
100%
Elapsed time: 0.058s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-038_write_15M.test'
FAIL 038_write_15M.test (exit status: 1)

FAIL: 039_upgrade
=================


  0%
  1%
 42%
 85%
 99%
100%
Elapsed time: 0.004s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-039_upgrade.test'
FAIL 039_upgrade.test (exit status: 1)

FAIL: 042_fat_am335x
====================


  0%
 50%
 99%
100%
Elapsed time: 0.001s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-042_fat_am335x.test'
FAIL 042_fat_am335x.test (exit status: 1)

FAIL: 043_fat_touch
===================


  0%
 33%
 66%
 99%
100%
Elapsed time: 0.001s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-043_fat_touch.test'
FAIL 043_fat_touch.test (exit status: 1)

FAIL: 044_require_file_exist
============================


  0%
 25%
 50%
 75%
 99%
100%
Elapsed time: 0.000s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-044_require_file_exist.test'
FAIL 044_require_file_exist.test (exit status: 1)

FAIL: 045_legacy_require_partition1
===================================


  0%
  1%
 42%
 85%
 99%
100%
Elapsed time: 0.002s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-045_legacy_require_partition1.test'
FAIL 045_legacy_require_partition1.test (exit status: 1)

FAIL: 047_unknown_apply_succeeds
================================

/tmp/nix-build-fwup-0.15.0.drv-0/source/tests

  0%
100%verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-047_unknown_apply_succeeds.test'
FAIL 047_unknown_apply_succeeds.test (exit status: 1)

FAIL: 052_file_concatenation
============================


  0%
 42%
 85%
 99%
100%
Elapsed time: 0.000s
verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-052_file_concatenation.test'
FAIL 052_file_concatenation.test (exit status: 1)

FAIL: 053_framed_progress
=========================

verify-syscalls: open was never called on 'fwup.img'

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.15.0.drv-0/source/tests/work-053_framed_progress.test'
FAIL 053_framed_progress.test (exit status: 1)

FAIL: 060_framed_streaming
==========================

With the current version, even more tests fail:

fwup 0.18.0: tests/test-suite.log
=======================================
   fwup 0.18.0: tests/test-suite.log
=======================================

# TOTAL: 141
# PASS:  60
# SKIP:  0
# XFAIL: 0
# FAIL:  81
# XPASS: 0
# ERROR: 0

.. contents:: :depth: 2

FAIL: 001_simple_fw
===================


|                                    | 0%
|=================================== | 99% (1.02 / 1.02) KB
|====================================| 100% (1.02 / 1.02) KB
Success!
Elapsed time: 0.000s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-001_simple_fw.test'
FAIL 001_simple_fw.test (exit status: 1)

FAIL: 002_resource_subdir
=========================


|                                    | 0%
|===========                         | 33% (1.02 / 3.07) KB
|=======================             | 66% (2.05 / 3.07) KB
|=================================== | 99% (3.07 / 3.07) KB
|====================================| 100% (3.07 / 3.07) KB
Success!
Elapsed time: 0.000s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-002_resource_subdir.test'
FAIL 002_resource_subdir.test (exit status: 1)

FAIL: 003_write_offset
======================


|                                    | 0%
|===============                     | 43% (65.17 / 150.00) KB
|===============================     | 87% (130.68 / 150.00) KB
|=================================== | 99% (150.00 / 150.00) KB
|====================================| 100% (150.00 / 150.00) KB
Success!
Elapsed time: 0.000s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-003_write_offset.test'
FAIL 003_write_offset.test (exit status: 1)

FAIL: 004_env_vars
==================


|                                    | 0%
|=================================== | 99% (1.02 / 1.02) KB
|====================================| 100% (1.02 / 1.02) KB
Success!
Elapsed time: 0.000s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-004_env_vars.test'
FAIL 004_env_vars.test (exit status: 1)

FAIL: 005_define
================


|                                    | 0%
|=================================== | 99% (1.02 / 1.02) KB
|====================================| 100% (1.02 / 1.02) KB
Success!
Elapsed time: 0.001s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-005_define.test'
FAIL 005_define.test (exit status: 1)

FAIL: 007_mbr
=============


|                                    | 0%
|=================================== | 99% (512.00 / 512.00) bytes
|====================================| 100% (512.00 / 512.00) bytes
Success!
Elapsed time: 0.000s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-007_mbr.test'
FAIL 007_mbr.test (exit status: 1)

FAIL: 008_partial_mbr
=====================


|                                    | 0%
|=================================== | 99% (512.00 / 512.00) bytes
|====================================| 100% (512.00 / 512.00) bytes
Success!
Elapsed time: 0.000s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-008_partial_mbr.test'
FAIL 008_partial_mbr.test (exit status: 1)

FAIL: 010_fat_mkfs
==================


|                                    | 0%
|==================                  | 50% (0.51 / 1.02) KB
|=================================== | 99% (1.02 / 1.02) KB
|====================================| 100% (1.02 / 1.02) KB
Success!
Elapsed time: 0.001s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-010_fat_mkfs.test'
FAIL 010_fat_mkfs.test (exit status: 1)

FAIL: 011_fat_setlabel
======================


|                                    | 0%
|===========                         | 33% (0.51 / 1.54) KB
|=======================             | 66% (1.02 / 1.54) KB
|=================================== | 99% (1.54 / 1.54) KB
|====================================| 100% (1.54 / 1.54) KB
Success!
Elapsed time: 0.001s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-011_fat_setlabel.test'
FAIL 011_fat_setlabel.test (exit status: 1)

FAIL: 012_fat_write
===================


|                                    | 0%
|=========                           | 25% (0.51 / 2.05) KB
|==================                  | 50% (1.02 / 2.05) KB
|=================================== | 99% (2.05 / 2.05) KB
|====================================| 100% (2.05 / 2.05) KB
Success!
Elapsed time: 0.002s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-012_fat_write.test'
FAIL 012_fat_write.test (exit status: 1)

FAIL: 013_fat_mv
================


|                                    | 0%
|=======                             | 20% (0.51 / 2.56) KB
|==============                      | 40% (1.02 / 2.56) KB
|============================        | 80% (2.05 / 2.56) KB
|=================================== | 99% (2.56 / 2.56) KB
|====================================| 100% (2.56 / 2.56) KB
Success!
Elapsed time: 0.001s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-013_fat_mv.test'
FAIL 013_fat_mv.test (exit status: 1)

FAIL: 014_fat_cp
================


|                                    | 0%
|===                                 | 9% (0.51 / 5.63) KB
|======                              | 18% (1.02 / 5.63) KB
|============                        | 36% (2.05 / 5.63) KB
|================                    | 45% (2.56 / 5.63) KB
|===================                 | 54% (3.07 / 5.63) KB
|======================              | 63% (3.58 / 5.63) KB
|=========================           | 72% (4.10 / 5.63) KB
|=============================       | 81% (4.61 / 5.63) KB
|================================    | 90% (5.12 / 5.63) KB
|=================================== | 99% (5.63 / 5.63) KB
|====================================| 100% (5.63 / 5.63) KB
Success!
Elapsed time: 0.005s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-014_fat_cp.test'
FAIL 014_fat_cp.test (exit status: 1)

FAIL: 017_fat_rm
================


|                                    | 0%
|==                                  | 8% (0.51 / 6.14) KB
|=====                               | 16% (1.02 / 6.14) KB
|===========                         | 33% (2.05 / 6.14) KB
|==============                      | 41% (2.56 / 6.14) KB
|==================                  | 50% (3.07 / 6.14) KB
|====================                | 58% (3.58 / 6.14) KB
|=======================             | 66% (4.10 / 6.14) KB
|===========================         | 75% (4.61 / 6.14) KB
|=============================       | 83% (5.12 / 6.14) KB
|================================    | 91% (5.63 / 6.14) KB
|=================================== | 99% (6.14 / 6.14) KB
|====================================| 100% (6.14 / 6.14) KB
Success!
Elapsed time: 0.002s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-017_fat_rm.test'
FAIL 017_fat_rm.test (exit status: 1)

FAIL: 018_numeric_progress
==========================

-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-018_numeric_progress.test'
FAIL 018_numeric_progress.test (exit status: 1)

FAIL: 019_quiet_progress
========================

-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-019_quiet_progress.test'
FAIL 019_quiet_progress.test (exit status: 1)

FAIL: 022_signed_fw
===================

Firmware signing keys created and saved to fwup-key.pub and fwup-key.priv

Distribute fwup-key.pub with your system so that firmware updates can be
authenticated. Keep fwup-key.priv in a safe location.
/tmp/nix-build-fwup-0.18.0.drv-0/source/tests
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-022_signed_fw.test'
FAIL 022_signed_fw.test (exit status: 1)

FAIL: 026_sign_again
====================

Firmware signing keys created and saved to fwup-key.pub and fwup-key.priv

Distribute fwup-key.pub with your system so that firmware updates can be
authenticated. Keep fwup-key.priv in a safe location.
/tmp/nix-build-fwup-0.18.0.drv-0/source/tests
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-026_sign_again.test'
FAIL 026_sign_again.test (exit status: 1)

FAIL: 027_fat_timestamp
=======================


|                                    | 0%
|=========                           | 25% (0.51 / 2.05) KB
|==================                  | 50% (1.02 / 2.05) KB
|=================================== | 99% (2.05 / 2.05) KB
|====================================| 100% (2.05 / 2.05) KB
Success!
Elapsed time: 0.002s
-- verify-syscalls report --
open() was never called on '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-027_fat_timestamp.test/fwup.img.1'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-027_fat_timestamp.test'
FAIL 027_fat_timestamp.test (exit status: 1)

FAIL: 028_osip
==============


|                                    | 0%
|=================================== | 99% (512.00 / 512.00) bytes
|====================================| 100% (512.00 / 512.00) bytes
Success!
Elapsed time: 0.000s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-028_osip.test'
FAIL 028_osip.test (exit status: 1)

FAIL: 029_5G_offset
===================

Sparse files supported

|                                    | 0%
|===============                     | 43% (65.16 / 150.00) KB
|===============================     | 87% (130.68 / 150.00) KB
|=================================== | 99% (150.00 / 150.00) KB
|====================================| 100% (150.00 / 150.00) KB
Success!
Elapsed time: 0.001s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-029_5G_offset.test'
FAIL 029_5G_offset.test (exit status: 1)

FAIL: 030_2T_offset
===================

Sparse files supported

|                                    | 0%
|===============                     | 43% (65.16 / 150.00) KB
|===============================     | 87% (130.68 / 150.00) KB
|=================================== | 99% (150.00 / 150.00) KB
|====================================| 100% (150.00 / 150.00) KB
Success!
Elapsed time: 0.001s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-030_2T_offset.test'
FAIL 030_2T_offset.test (exit status: 1)

FAIL: 031_fat_mkfs_5G
=====================

Sparse files supported

|                                    | 0%
|==================                  | 50% (0.51 / 1.02) KB
|=================================== | 99% (1.02 / 1.02) KB
|====================================| 100% (1.02 / 1.02) KB
Success!
Elapsed time: 0.097s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-031_fat_mkfs_5G.test'
FAIL 031_fat_mkfs_5G.test (exit status: 1)

FAIL: 032_fat_2T_offset
=======================

Sparse files supported

|                                    | 0%
|=====                               | 16% (0.51 / 3.07) KB
|===========                         | 33% (1.02 / 3.07) KB
|=======================             | 66% (2.05 / 3.07) KB
|=============================       | 83% (2.56 / 3.07) KB
|=================================== | 99% (3.07 / 3.07) KB
|====================================| 100% (3.07 / 3.07) KB
Success!
Elapsed time: 0.002s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-032_fat_2T_offset.test'
FAIL 032_fat_2T_offset.test (exit status: 1)

FAIL: 035_streaming
===================


|                                    | 0%
|=================================== | 99% (1.02 / 1.02) KB
|====================================| 100% (1.02 / 1.02) KB
Success!
Elapsed time: 0.000s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-035_streaming.test'
FAIL 035_streaming.test (exit status: 1)

FAIL: 036_streaming_signed_fw
=============================

Firmware signing keys created and saved to fwup-key.pub and fwup-key.priv

Distribute fwup-key.pub with your system so that firmware updates can be
authenticated. Keep fwup-key.priv in a safe location.
/tmp/nix-build-fwup-0.18.0.drv-0/source/tests
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-036_streaming_signed_fw.test'
FAIL 036_streaming_signed_fw.test (exit status: 1)

FAIL: 038_write_15M
===================


|                                    | 0%
|                                    | 1% (0.20 / 15.00) MB
|                                    | 2% (0.33 / 15.00) MB
|=                                   | 3% (0.46 / 15.00) MB
|=                                   | 4% (0.65 / 15.00) MB
|=                                   | 5% (0.79 / 15.00) MB
|==                                  | 6% (0.92 / 15.00) MB
|==                                  | 7% (1.11 / 15.00) MB
|==                                  | 8% (1.24 / 15.00) MB
|===                                 | 9% (1.38 / 15.00) MB
|===                                 | 10% (1.51 / 15.00) MB
|===                                 | 11% (1.70 / 15.00) MB
|====                                | 12% (1.83 / 15.00) MB
|====                                | 13% (1.97 / 15.00) MB
|=====                               | 14% (2.16 / 15.00) MB
|=====                               | 15% (2.29 / 15.00) MB
|=====                               | 16% (2.42 / 15.00) MB
|======                              | 17% (2.55 / 15.00) MB
|======                              | 18% (2.75 / 15.00) MB
|======                              | 19% (2.88 / 15.00) MB
|=======                             | 20% (3.01 / 15.00) MB
|=======                             | 21% (3.21 / 15.00) MB
|=======                             | 22% (3.34 / 15.00) MB
|========                            | 23% (3.47 / 15.00) MB
|========                            | 24% (3.60 / 15.00) MB
|=========                           | 25% (3.80 / 15.00) MB
|=========                           | 26% (3.93 / 15.00) MB
|=========                           | 27% (4.06 / 15.00) MB
|==========                          | 28% (4.26 / 15.00) MB
|==========                          | 29% (4.39 / 15.00) MB
|==========                          | 30% (4.52 / 15.00) MB
|===========                         | 31% (4.65 / 15.00) MB
|===========                         | 32% (4.85 / 15.00) MB
|===========                         | 33% (4.98 / 15.00) MB
|============                        | 34% (5.11 / 15.00) MB
|============                        | 35% (5.31 / 15.00) MB
|============                        | 36% (5.44 / 15.00) MB
|=============                       | 37% (5.57 / 15.00) MB
|=============                       | 38% (5.77 / 15.00) MB
|==============                      | 39% (5.90 / 15.00) MB
|==============                      | 40% (6.03 / 15.00) MB
|==============                      | 41% (6.16 / 15.00) MB
|===============                     | 42% (6.35 / 15.00) MB
|===============                     | 43% (6.49 / 15.00) MB
|===============                     | 44% (6.62 / 15.00) MB
|================                    | 45% (6.81 / 15.00) MB
|================                    | 46% (6.94 / 15.00) MB
|================                    | 47% (7.08 / 15.00) MB
|=================                   | 48% (7.21 / 15.00) MB
|=================                   | 49% (7.40 / 15.00) MB
|==================                  | 50% (7.53 / 15.00) MB
|==================                  | 51% (7.67 / 15.00) MB
|==================                  | 52% (7.86 / 15.00) MB
|===================                 | 53% (7.99 / 15.00) MB
|===================                 | 54% (8.12 / 15.00) MB
|===================                 | 55% (8.25 / 15.00) MB
|====================                | 56% (8.45 / 15.00) MB
|====================                | 57% (8.58 / 15.00) MB
|====================                | 58% (8.71 / 15.00) MB
|=====================               | 59% (8.91 / 15.00) MB
|=====================               | 60% (9.04 / 15.00) MB
|=====================               | 61% (9.17 / 15.00) MB
|======================              | 62% (9.30 / 15.00) MB
|======================              | 63% (9.50 / 15.00) MB
|=======================             | 64% (9.63 / 15.00) MB
|=======================             | 65% (9.76 / 15.00) MB
|=======================             | 66% (9.96 / 15.00) MB
|========================            | 67% (10.09 / 15.00) MB
|========================            | 68% (10.22 / 15.00) MB
|========================            | 69% (10.35 / 15.00) MB
|=========================           | 70% (10.55 / 15.00) MB
|=========================           | 71% (10.68 / 15.00) MB
|=========================           | 72% (10.81 / 15.00) MB
|==========================          | 73% (11.01 / 15.00) MB
|==========================          | 74% (11.14 / 15.00) MB
|===========================         | 75% (11.27 / 15.00) MB
|===========================         | 76% (11.46 / 15.00) MB
|===========================         | 77% (11.60 / 15.00) MB
|============================        | 78% (11.73 / 15.00) MB
|============================        | 79% (11.86 / 15.00) MB
|============================        | 80% (12.05 / 15.00) MB
|=============================       | 81% (12.19 / 15.00) MB
|=============================       | 82% (12.32 / 15.00) MB
|=============================       | 83% (12.51 / 15.00) MB
|==============================      | 84% (12.64 / 15.00) MB
|==============================      | 85% (12.78 / 15.00) MB
|==============================      | 86% (12.91 / 15.00) MB
|===============================     | 87% (13.10 / 15.00) MB
|===============================     | 88% (13.23 / 15.00) MB
|================================    | 89% (13.36 / 15.00) MB
|================================    | 90% (13.56 / 15.00) MB
|================================    | 91% (13.69 / 15.00) MB
|=================================   | 92% (13.82 / 15.00) MB
|=================================   | 93% (13.95 / 15.00) MB
|=================================   | 94% (14.15 / 15.00) MB
|==================================  | 95% (14.28 / 15.00) MB
|==================================  | 96% (14.41 / 15.00) MB
|==================================  | 97% (14.61 / 15.00) MB
|=================================== | 98% (14.74 / 15.00) MB
|=================================== | 99% (14.87 / 15.00) MB
|====================================| 100% (15.00 / 15.00) MB
Success!
Elapsed time: 0.060s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-038_write_15M.test'
FAIL 038_write_15M.test (exit status: 1)

FAIL: 039_upgrade
=================


|                                    | 0%
|                                    | 1% (1.54 / 152.56) KB
|===============                     | 42% (65.25 / 152.56) KB
|==============================      | 85% (130.77 / 152.56) KB
|=================================== | 99% (152.56 / 152.56) KB
|====================================| 100% (152.56 / 152.56) KB
Success!
Elapsed time: 0.003s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-039_upgrade.test'
FAIL 039_upgrade.test (exit status: 1)

FAIL: 042_fat_am335x
====================


|                                    | 0%
|==================                  | 50% (0.51 / 1.02) KB
|=================================== | 99% (1.02 / 1.02) KB
|====================================| 100% (1.02 / 1.02) KB
Success!
Elapsed time: 0.000s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-042_fat_am335x.test'
FAIL 042_fat_am335x.test (exit status: 1)

FAIL: 043_fat_touch
===================


|                                    | 0%
|===========                         | 33% (0.51 / 1.54) KB
|=======================             | 66% (1.02 / 1.54) KB
|=================================== | 99% (1.54 / 1.54) KB
|====================================| 100% (1.54 / 1.54) KB
Success!
Elapsed time: 0.001s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-043_fat_touch.test'
FAIL 043_fat_touch.test (exit status: 1)

FAIL: 044_require_file_exist
============================


|                                    | 0%
|=========                           | 25% (0.51 / 2.05) KB
|==================                  | 50% (1.02 / 2.05) KB
|===========================         | 75% (1.54 / 2.05) KB
|=================================== | 99% (2.05 / 2.05) KB
|====================================| 100% (2.05 / 2.05) KB
Success!
Elapsed time: 0.000s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-044_require_file_exist.test'
FAIL 044_require_file_exist.test (exit status: 1)

FAIL: 045_legacy_require_partition1
===================================


|                                    | 0%
|                                    | 1% (1.54 / 152.56) KB
|===============                     | 42% (65.26 / 152.56) KB
|==============================      | 85% (130.78 / 152.56) KB
|=================================== | 99% (152.56 / 152.56) KB
|====================================| 100% (152.56 / 152.56) KB
Success!
Elapsed time: 0.001s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-045_legacy_require_partition1.test'
FAIL 045_legacy_require_partition1.test (exit status: 1)

FAIL: 047_unknown_apply_succeeds
================================

/tmp/nix-build-fwup-0.18.0.drv-0/source/tests

|                                    | 0%
|====================================| 100%
Success!
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-047_unknown_apply_succeeds.test'
FAIL 047_unknown_apply_succeeds.test (exit status: 1)

FAIL: 052_file_concatenation
============================


|                                    | 0%
|===============                     | 42% (65.18 / 152.05) KB
|==============================      | 85% (130.70 / 152.05) KB
|=================================== | 99% (152.05 / 152.05) KB
|====================================| 100% (152.05 / 152.05) KB
Success!
Elapsed time: 0.001s
-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-052_file_concatenation.test'
FAIL 052_file_concatenation.test (exit status: 1)

FAIL: 053_framed_progress
=========================

-- verify-syscalls report --
open() was never called on 'fwup.img'!
----------------------------

Test failed!

Leaving test work files in '/tmp/nix-build-fwup-0.18.0.drv-0/source/tests/work-053_framed_progress.test'
FAIL 053_framed_progress.test (exit status: 1)

FAIL: 060_framed_streaming
==========================


Formatting FAT FS with offset past 2 GiB

When running the fat_mkfs command to attempt to create a FAT filesystem in a FAT 32 partition, there is an error whenever the offset is exactly 2 GiB or greater. This error seems to be independent of the size of the partition, and only depends on the offset. The error is: A hard error occurred in the low level disk I/O layer.

Test 030 and 032 failing on raspbian

The following two tests are failing on raspian. I looked at them but could not find out why. On my SD Card i have 20 GB of space left.

  • tests/030_2T_offset.test
  • tests/032_fat_2T_offset.test

Can't auto unmount drives with whitespace in their names

To reproduce, format a memory card and create a partition with a space in the name. If you're on a Linux system that creates mount points based on volume names, you should get a space in the directory. Now run fwup to program that memory card and it will fail to unmount the partition.

Add man pages

Now that fwup can be installed from a package manager rather than from source, man pages would be really nice.

Support query-able minimum version support

For intermediate upgrade scenarios, i.e., those where a device needs to upgrade to an intermediate version of software before upgrading to the final version, it is desirable to be able to extract the upgrade path from the .fw file. The current situation is that you can manually set this scenario up on a firmware update server, but it would be less error prone if the .fw file metadata could help out.

One idea: Add a meta-min-version that can be queried using fwup -m and support a require condition to run a semver check on a u-boot environment block variable (similar to require-uboot-variable).

Sparse file unit tests fail on new Apple File System

After upgrading the OSX High Sierra, 4 sparse file tests start failing. APFS supports sparse files, but its heuristic for determining when to make a hole is not as immediately obvious as it is with other filesystems that support sparse files. It may be necessary to disable these tests on OSX in the nearterm.

Unable to install libsodium-dev in the proposed way

On Ubuntu 14.04 installing libsodium-dev did not work for me, I got an unable to find package result.

I installed it from this instead.

sudo add-apt-repository ppa:chris-lea/libsodium
sudo apt-get update && sudo apt-get install libsodium-dev

SDCard autodetector skips /dev/sda

I had been under the impression that /dev/sda would never be an SDCard. Today, I worked with someone who's laptop legitimately assigned the SDCard to /dev/sda. Their root filesystem was on /dev/sdb.

Minor issue with fat_setlabel

It seems that the label provided gets capitalized. I would be great to get a label that is exactly what is entered without alteration. I guess some upper() function gets invoked.

eg.

on-init {
mbr_write(mbr-a)
fat_mkfs(${BOOT_OFFSET}, ${BOOT_COUNT})
fat_setlabel(${BOOT_OFFSET}, "boot")
}

Actual label on SD card: BOOT

Ubuntu 14.04

Add flag to disable auto-eject on OSX

Running two phase upgrades on OSX currently breaks due to auto-eject, since the auto-eject occurs after the first phase and the SDCard is no longer available. Since the nerves-project currently only supports flashing complete images and two phase upgrades, OSX users can only flash complete images at the moment.

Support firmware UUID generation

Problem:

The version number field is not trusted to unambiguously represent the firmware that's running on a device. The vcs_identifier can be used, but isn't guaranteed to be populated. The solution of running a SHA-256 over the .fw file after it has been generated is not desirable since things like signing .fw files would change the computed hash but not alter the contents.

Proposed solution:

Add a virtual meta-uuid field that can be deterministically calculated based on the contents of the .fw file. This could be based on the meta.conf file since that file contains hashes of all of the constituent files. If meta-uuid is calculated rather than stored, it will work on .fw files created with older versions of fwup.

fwup --help issue

/fwup$ fwup --help
Segmentation fault (core dumped)

Running on Virtual Box, Ubuntu 14.04

fwup.1 man page contains error message

Hi,

the fwup.1 man page generated by help2man contains the following line in the DESCRIPTION section:

./fwup:  unrecognized  option '--help'

The reason is help2man calling fwup --help which fwup does not understand. Unfortunately help2man refuses to call a binary with no --help option at all (adding --help-option="" in src/Makefile.am makes help2man fail).

Arch Linux AUR not working because it isnt passing all tests

maybe some dependencies missing in the requirments of the AUR?

PASS: 001_simple_fw.test
PASS: 002_resource_subdir.test
PASS: 003_write_offset.test
PASS: 004_env_vars.test
PASS: 005_define.test
PASS: 006_metadata.test
PASS: 007_mbr.test
PASS: 008_partial_mbr.test
PASS: 009_metadata_cmdline.test
FAIL: 010_fat_mkfs.test
FAIL: 011_fat_setlabel.test
FAIL: 012_fat_write.test
FAIL: 013_fat_mv.test
FAIL: 014_fat_cp.test
PASS: 015_fat_bad_sha2.test
PASS: 016_raw_bad_sha2.test
FAIL: 017_fat_rm.test
PASS: 018_numeric_progress.test
PASS: 019_quiet_progress.test
PASS: 020_normal_progress.test
PASS: 021_create_keys.test
PASS: 022_signed_fw.test
PASS: 023_missing_sig.test
PASS: 024_metadata_sig.test
PASS: 025_bad_sig.test
PASS: 026_sign_again.test
PASS: 027_fat_timestamp.test
PASS: 028_osip.test
PASS: 029_5G_offset.test
PASS: 030_2T_offset.test
FAIL: 031_fat_mkfs_5G.test
FAIL: 032_fat_2T_offset.test
PASS: 033_bad_host_path.test
PASS: 034_missing_host_path.test
PASS: 035_streaming.test
PASS: 036_streaming_signed_fw.test
PASS: 037_streaming_bad_sig.test
PASS: 038_write_15M.test
PASS: 039_upgrade.test
PASS: 041_version.test
PASS: 042_fat_am335x.test
FAIL: 043_fat_touch.test
PASS: 044_require_file_exist.test
PASS: 045_legacy_require_partition1.test
PASS: 046_unknown_create_fails.test
PASS: 047_unknown_apply_succeeds.test
PASS: 048_assert_size_less_than_success.test
PASS: 049_assert_size_less_than_fail.test
PASS: 050_assert_size_greater_than_success.test
PASS: 051_assert_size_greater_than_fail.test
PASS: 052_file_concatenation.test
PASS: 053_framed_progress.test
PASS: 054_framed_metadata.test
PASS: 055_metadata_partial_file.test
PASS: 056_list_tasks.test
PASS: 057_list_tasks_empty.test
PASS: 058_framed_list_tasks.test
PASS: 059_framed_error.test
PASS: 060_framed_streaming.test
PASS: 061_framed_partial_metadata.test
PASS: 062_long_meta_conf.test
PASS: 063_detect.test
PASS: 064_mbr_bootcode.test
FAIL: 065_fat_mkdir.test
FAIL: 066_fat_attrib.test
PASS: 067_usage.test
PASS: 068_readonly_output_error.test
PASS: 069_define_bang.test
PASS: 070_bad_mbr_offset.test
PASS: 071_big_mbr_offset.test
PASS: 072_compression_works.test
FAIL: 073_multistep_fat.test
FAIL: 074_fat_cache_fail.test
FAIL: 075_big_fat_fs.test
PASS: 076_utf8_metadata.test
FAIL: 077_fat_empty_file.test
PASS: 078_partial_mbr2.test
PASS: 079_uboot_setenv.test
PASS: 080_uboot_empty_env.test
PASS: 081_uboot_clearenv.test
PASS: 082_uboot_upgrade.test
PASS: 083_uboot_unsetenv.test
PASS: 084_corrupt_uboot.test
PASS: 085_raw_memset.test
PASS: 086_math.test
PASS: 087_crypto_compat.test
PASS: 088_missing_hash.test
PASS: 089_dev_null.test
PASS: 090_sparse_write.test
PASS: 091_sparse_write2.test
PASS: 092_sparse_write3.test
PASS: 093_sparse_concat.test
PASS: 094_sparse_concat2.test
FAIL: 095_sparse_apply.test
PASS: 096_missing_resource.test
PASS: 097_reproduceable.test
FAIL: 098_sparse_empty.test
FAIL: 099_sparse_lasthole.test
PASS: 100_easy_option.test
PASS: 101_progress_range.test
PASS: 102_multi_requires.test
PASS: 103_error_msg.test
PASS: 104_info_msg.test
PASS: 105_require_path_on_device.test
PASS: 106_large_length_field.test
PASS: 107_string_resource.test
PASS: 108_resource_order.test
PASS: 109_includes.test
PASS: 110_compression_level.test
PASS: 111_streaming_exit_fast.test
PASS: 112_fat_rm_missing_file.test
PASS: 113_fat_mv_error_cases.test
PASS: 114_fat_cp_error_cases.test
PASS: 115_fat_mkdir_error_cases.test
PASS: 116_fat_setlabel_error_cases.test
FAIL: 117_on_error.test
PASS: 118_fat_touch_error_cases.test
PASS: 119_require_fat_file_match.test
PASS: 120_corrupt_fat.test
PASS: 121_missing_file.test
PASS: 122_missing_file_metadata.test
PASS: 123_double_fat_write.test
PASS: 124_uboot_bad_param.test
PASS: 125_trimmed_upgrade.test
PASS: 126_uboot_recover.test
PASS: 127_extra_metadata.test
PASS: 128_blank_offset.test
PASS: 129_mbr_overflow.test
PASS: 130_media_sizes.test
PASS: 131_raw_key.test
PASS: 132_key_as_param.test
PASS: 133_path_write_file.test
PASS: 134_pipe_write_file.test
PASS: 135_execute.test
FAIL: 136_fat_overwrite.test
PASS: 137_path_write_sparse.test
PASS: 138_pipe_write_sparse.test
PASS: 139_mbr_signature.test
PASS: 140_trim.test
PASS: 141_exit_handshake.test
PASS: 142_file_resource_size.test
PASS: 143_include_path.test
PASS: 144_require_version.test
PASS: 145_require_path_at_offset.test
============================================================================
Testsuite summary for fwup 1.0.0
============================================================================
# TOTAL: 144
# PASS:  124
# SKIP:  0
# XFAIL: 0
# FAIL:  20
# XPASS: 0
# ERROR: 0
============================================================================
See tests/test-suite.log
Please report to https://github.com/fhunleth/fwup/issues
============================================================================
make[3]: *** [Makefile:827: test-suite.log] Error 1
make[3]: Leaving directory '/tmp/yaourt-tmp-fabi/aur-fwup/src/fwup/tests'
make[2]: *** [Makefile:935: check-TESTS] Error 2
make[2]: Leaving directory '/tmp/yaourt-tmp-fabi/aur-fwup/src/fwup/tests'
make[1]: *** [Makefile:998: check-am] Error 2
make[1]: Leaving directory '/tmp/yaourt-tmp-fabi/aur-fwup/src/fwup/tests'
make: *** [Makefile:420: check-recursive] Error 1
==> ERROR: A failure occurred in check().
    Aborting...
==> ERROR: Makepkg was unable to build fwup.
==> Restart building fwup ? [y/N]

Autodetection of large drives fails on Linux

The user is programming a 120 GB SSD connected via a SATA->USB3 cable using fwup. The drive is not being autodetected since fwup thinks that it's too large to be a memory card. There should be a better way of detecting removable drives or the user should be given an error that's more helpful.

[WIN 10]fwup burning to SD card not working as expected

Log:
fwup -a -i rpi/blinky.fw -t complete
Use 1.89 GiB memory card found at .\PhysicalDrive2? [y/N] y
100%
they were never bootable by rpi
and sometimes the .txt files were "jibberish"(broken)
example cmdline.txt: Â��œV¾ƒã|“nÙĶõ[á157T•§ñ´6öœ§ lÑúÆeá*iû�Ú–))Žœ(-�¶æPÜ��»�oÕç²�º¾È

but writing to .img file then writing it with win32 disk imager to the sd card it works

Strict variable checking

While updating an fwup.conf file I was renaming variables and missed some. When it tried to execute complete task, it failed with misleading error messages. Fwup should warn / error on unset variables.

Switch crypto library from libsodium to OpenSSL

I'm putting this out there for comment. Over the past couple years, I've receive some interest in switching back to OpenSSL. Some may remember that fwup originally used OpenSSL, but I switch to libsodium because 1. it was far easier for me to understand, 2. a smaller dependency, and 3. there was quite a bit of negative press regarding vulnerabilities in the OpenSSL. The reasons for switching back to OpenSSL are:

  1. Every project that I'm aware of that uses fwup also includes openssl in some other dependency. It seems impossible to avoid openssl, so including it as a dependency is "free". I.e., the concern about having a smaller footprint or simpler set of dependencies with libsodium is not valid in practice.
  2. OpenSSL enables using x.509 certificates for signing. The mechanism that fwup currently uses is simplistic and from what I can tell, implementing chainable and revocable certificates in libsodium would be a lot of work.
  3. Using OpenSSL opens up the use of non-fwup tools for handling crypto tasks. Currently you have to use fwup to generate public and private key pairs and this always seemed silly. There may be libsodium command line tools around, but they're not as common or as easy to find help with as openssl.

Impact of such a change:

  1. It looks like OpenSSL supports the Blake2b hashing algorithm, so unsigned firmware updates should be compatible after the switch.
  2. OpenSSL doesn't support Ed25519 yet. However, I would prefer to drop the current signing implementation if proper x509 support is available.

The second one is the main concern. My observation is that people get stuck on a version of fwup once they deploy - maybe not intentionally, but it seems like there's a level of comfort not changing it if it's working well. If the current signing mechanism can't be dropped, then I'm sure that it could be kept for a little while or made an option since its implementation is pretty simple.

Unable to raw_write single resource to two different offsets

When specifying the same resource to be written to two different offsets it fails with the following message.

fwup: raw_write didn't write anything. Was it called twice in an on-resource for 'rootfs.ext4'?

In my setup both partitions should have the same resource written during factory setup. I would like to avoid having to increase the size of my .fw bundle with a duplicate resource. My config currently looks like this:

    on-resource rootfs.ext4 {
        raw_write(${ROOTFS_A_PART_OFFSET}) # Write to the first rootfs partition
        raw_write(${ROOTFS_B_PART_OFFSET}) # Write to the second rootfs partition
    } 

Is this an intentional design decision?

Add possibility to exclude certain devices

Problem
On a Raspberry the system sdcard is suggested instead of a external attached sd card.

Possible solutions

  1. ~/.fwup.conf file with a list of interfaces to exclude/include
  2. ~/.fwup.conf which allows to set all the defaults of the argument i can pass (so i dont have to specify -d everytime)
  3. Maybe the auto-detect feature should show all attached sd cards and you can set a default (which than would write the config):
Which memory card would you like to use (press d to set as default)?
[*] 29.72 GiB at /dev/mmcblk0
[ ] 7.14 GiB at /dev/sda

Support writing to SDCards from within the Windows Subsystem for Linux

With some work, it's possible to get fwup to both run in the Windows Subsystem for Linux and be able to write to SDCards. Here's a report from @jmerryweather:

steps are as follows:
(1) uninstall any linux version of fwup in WSL
(2) from Windows install fwup using chocolatey
(3) create a 'fwup' file that will will point to fwup.exe, i can send you the version i made, it is based on the VS Code 'code' file
(4) run Bash on Ubuntu on Windows "As Administrator", fwup won't work without doing that, it will instead give errors that there are no sd cards
(5) without 'sudo', run the following: fwup firmware.fw

#!/usr/bin/env bash
#
# Inspiration taken from Microsoft VS Code's Windows 'code' bash file

NAME="fwup"
FWUP_LOCATION="$(dirname "$(realpath "$0")")"

FULLPATH="$FWUP_LOCATION/$NAME.exe"
if grep -q Microsoft /proc/version; then
   # If running under WSL
 "$FULLPATH" "$@"
   exit $?
fi
exit $?

thats the fwup file i put under C:\ProgramData\chocolatey\bin

if we could get the above distributed with the fwup chocolatey package, it would make discovery of the windows fwup much easier

Issues running from app data partition

I am attempting to run a ping-pong update with fwup. I have a separate partition for app data and downloaded the fwup archive to that partition so that I could keep the RootFS small. When running fwup, however, it first tries to unmount all of the partitions. When it tries to unmount the app data partition, it receives a partition in use error, and then exits.

I think that a good solution might be to have fwup ignore any errors that it receives while trying to unmount the partitions, and to continue on. There shouldn't be any errors due to mounted partitions, since in the configuration file we can specify if a particular partition needs to be unmounted before running. Thoughts?

GPT support

It's only a matter of time before we need to support a platform that does not recognize MBR any more. It looks like the newer Intel embedded platforms are going that route.

Adding single files is too tedious

too add files to a partition you need to have steps like:

file-resource bootcode.bin {
    host-path = "${NERVES_SYSTEM}/images/rpi-firmware/bootcode.bin"
}

then in the each task you must:

on-resource bootcode.bin { fat_write(${BOOT_PART_OFFSET}, "bootcode.bin") }

This leads to a ton of duplicated lines. (especially when you have a part_a/part_b system)

It would be nice to just be able to specify a list of files you are concerned with

eject fails on OSX with unhelpful error message

Here's the error:

fwup: eject failed: 0xc010 (49168) (null))

This was reported by @wsmoak on the elixir-lang slack. I'm not sure if improvements to the error message would help debug this particular issue. Check if error 49168 could be a commonly encountered error if the SDCard is busy and produce a better error message.

make check fails with Alpine Linux

Compiling and running the latest commit in master branch.

System Info

  • Distro - Alpine Linux 3.2
  • LibC - MUSL
  • CC - GCC 4.9.2
  • Shell - ZSH 5.0.7

Log

======================================
   fwup 0.3.0: tests/test-suite.log
======================================

# TOTAL: 28
# PASS:  26
# SKIP:  0
# XFAIL: 0
# FAIL:  2
# XPASS: 0
# ERROR: 0

.. contents:: :depth: 2

FAIL: 004_env_vars
==================

fwup: can't open file-resource '/home/admin/src/fwup/tests/work/${TEST_ENV_VAR}'
FAIL 004_env_vars.test (exit status: 1)

FAIL: 005_define
================

fwup: can't open file-resource '/home/admin/src/fwup/tests/work/${TEST_DEFINE}'
FAIL 005_define.test (exit status: 1)

Use monotic time for elapsed time calculation

The elapsed time calculation uses gettimeofday which is not monotonic. On devices that take a while to update their clocks, the jump from 1970 to the current date has actually happened during a firmware update and confused people.

sudo-less install on OSX

Currently fwup requires sudo to scan and write to SDCards. It should be possible to scan for SDCards using the Disk Arbitration framework (no elevated privileges required) and to write to them by getting a file handle from authopen.

Error when running ./configure in Vagrant

In a Vagrant Ubuntu Trusty64 box, when running the ./configure command inside the fwup directory I get the following error:

./configure: line 12447: syntax error near unexpected token `BASH_COMPLETION,'
./configure: line 12447: `    PKG_CHECK_MODULES(BASH_COMPLETION, bash-completion >= 2.0,'

I have tried uninstalling and reinstallling bash-completion but this had no effect. I didn't have this problem on my host laptop, which is Xubuntu 14.04.

Sorry I can't be more help, I really don't know Bash.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.