• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

.circleci/H17-Jul-2021-174165

docs/H03-May-2022-610426

m4/H17-Jul-2021-486422

scripts/H03-May-2022-786493

src/H17-Jul-2021-134,836110,671

tests/H03-May-2022-14,4149,937

.gitattributesH A D17-Jul-202185 65

.gitignoreH A D17-Jul-2021571 5554

.travis.ymlH A D17-Jul-20213.3 KiB118106

CHANGELOG.mdH A D17-Jul-202131 KiB789621

LICENSEH A D17-Jul-202111.1 KiB203169

Makefile.amH A D17-Jul-2021471 2320

README.mdH A D17-Jul-202153.1 KiB1,187942

RELEASE.mdH A D17-Jul-20211.5 KiB2826

TODO.mdH A D17-Jul-2021175 75

VERSIONH A D17-Jul-20216 21

ar-libH A D17-Jul-20215.7 KiB271210

autogen.shH A D17-Jul-2021245 135

configure.acH A D17-Jul-20215.3 KiB137114

fwup.proH A D17-Jul-20218.3 KiB289274

img2fwupH A D03-May-2022859 4334

README.md

1![The fwup pup](docs/fwup-pup.png)
2
3# Overview
4
5[![CircleCI](https://circleci.com/gh/fwup-home/fwup.svg?style=svg)](https://circleci.com/gh/fwup-home/fwup)
6[![Coverage Status](https://coveralls.io/repos/github/fwup-home/fwup/badge.svg)](https://coveralls.io/github/fhunleth/fwup)
7[![Coverity Scan Build Status](https://scan.coverity.com/projects/4094/badge.svg)](https://scan.coverity.com/projects/4094)
8
9`fwup` is a configurable image-based software update utility for embedded
10Linux-based systems. It primarily supports software upgrade strategies that
11update entire root filesystem images at once. This includes strategies like
12swapping back and forth between A and B partitions, recovery partitions, and
13various trial update/failback scenarios. All software update information is
14combined into a ZIP archive that may optionally be cryptographically signed.
15`fwup` has minimal dependencies and runtime requirements. Scripts are
16intentionally limited to make failure scenarios easier to reason about.
17Distribution of software update archives is not a feature. Users can call out to
18`fwup` to run upgrades from external media, stream them from the network, or
19script them using a tool like Ansible if so desired.
20
21Here's a list of features:
22
231. Uses standard ZIP archives to make debugging and transmission simple.
24
251. Simple, but flexible configuration language to enable firmware updates on
26   various platforms and firmware update policies.
27
281. Streaming firmware update processing to simplify target storage requirements.
29
301. Multiple firmware update task options per archive so that one archive can
31   upgrade varying target configurations
32
331. Basic disk partitioning (GPT and MBR) and FAT filesystem manipulation
34
351. Human and machine readable progress.
36
371. Initialize or update SDCards on your development system whether you're
38   running Linux, OSX, BSD, or Windows. MMC and SDCards are automatically
39   detected and unmounted. No need to scan logs or manually unmount.
40
411. Firmware archive digital signature creation and verification
42
431. Delta update support using [VCDIFF](https://en.wikipedia.org/wiki/VCDIFF).
44   See delta update section for details (BETA FEATURE).
45
461. Sparse file support to reduce number of bytes that need to be written when
47   initializing large file systems (see section on sparse files)
48
491. Permissive license (Apache 2.0 License - see end of doc for details)
50
511. Extensively regression tested! Tests also provide examples of
52    functionality.
53
54Internally, `fwup` has many optimizations to speed up low level disk writes over
55what can easily be achieved with `dd(1)`. It orders, Flash erase block aligns,
56and can skip writing large unused sections to minimize write time. It also
57verifies writes to catch corruption before the device reboots to the new
58firmware. The goal is to make updates fast enough for code development and
59reliable enough for production use.
60
61# Installing
62
63The simplest way to install `fwup` is via a package manager or installer.
64
65On OSX, `fwup` is in [homebrew](http://brew.sh/):
66
67```sh
68brew install fwup
69```
70
71On Linux, download and install the appropriate package for your platform:
72
73* [Debian/Ubuntu AMD64 .deb](https://github.com/fwup-home/fwup/releases/download/v1.9.0/fwup_1.9.0_amd64.deb)
74* [Raspbian armhf .deb](https://github.com/fwup-home/fwup/releases/download/v1.9.0/fwup_1.9.0_armhf.deb)
75* Alpine Linux - Install official [apk](https://pkgs.alpinelinux.org/packages?name=fwup&branch=edge)
76* [RedHat/CentOS x86\_64 .rpm](https://github.com/fwup-home/fwup/releases/download/v1.9.0/fwup-1.9.0-1.x86_64.rpm)
77* Arch Linux - See [fwup-git package](https://aur.archlinux.org/packages/fwup-git/) on AUR
78* Buildroot - Support is included upstream since the 2016.05 release
79* Yocto - See [meta-fwup](https://github.com/fwup-home/meta-fwup)
80
81On Windows, `fwup` can be installed from [chocolatey](http://chocolatey.org)
82
83    choco install fwup
84
85Alternatively, download the [fwup executable](https://github.com/fwup-home/fwup/releases/download/v1.9.0/fwup.exe)
86and place it in your path.
87
88If you're using another platform or prefer to build it yourself, download the
89latest [source code release](https://github.com/fwup-home/fwup/releases/download/v1.9.0/fwup-1.9.0.tar.gz)
90or clone this repository. Then read one of the following files:
91
92* [Linux build instructions](docs/build_linux.md)
93* [OSX build instructions](docs/build_osx.md)
94* [Windows build instructions](docs/build_windows.md)
95* [Raspbian build instructions](docs/build_rpi.md)
96* [FreeBSD/NetBSD/OpenBSD build instructions](docs/build_bsd.md)
97
98When building from source, please verify that the regression test pass on your
99system (run `make check`) before using `fwup` in production. While the tests
100usually pass, they have found minor issues in third party libraries in the past
101that really should be fixed.
102
103NOTE: For space-constrained target devices, use `./configure
104--enable-minimal-build` to trim functionality that's rarely used.
105
106# Invoking
107
108If you were given a `.fw` file and just want to install its contents on an
109SDCard, here's an example run on Linux:
110
111```sh
112$ sudo fwup example.fw
113Use 14.92 GiB memory card found at /dev/sdc? [y/N] y
114100%
115Elapsed time: 2.736s
116```
117
118If you're on OSX or Windows, leave off the call to `sudo`.
119
120IMPORTANT: If you're using an older version of `fwup`, you'll have to specify
121more arguments. Run: `fwup -a -i example.fw -t complete`
122
123Here's a list of other options:
124
125```plaintext
126Usage: fwup [OPTION]...
127
128Options:
129  -a, --apply   Apply the firmware update
130  -c, --create  Create the firmware update
131  -d <file> Device file for the memory card
132  -D, --detect List attached SDCards or MMC devices and their sizes
133  -E, --eject Eject removable media after successfully writing firmware.
134  --no-eject Do not eject media after writing firmware
135  --enable-trim Enable use of the hardware TRIM command
136  --exit-handshake Send a Ctrl+Z on exit and wait for stdin to close (Erlang)
137  -f <fwup.conf> Specify the firmware update configuration file
138  -F, --framing Apply framing on stdin/stdout
139  -g, --gen-keys Generate firmware signing keys (fwup-key.pub and fwup-key.priv)
140  -i <input.fw> Specify the input firmware update file (Use - for stdin)
141  -l, --list   List the available tasks in a firmware update
142  -m, --metadata   Print metadata in the firmware update
143  --metadata-key <key> Only output the specified key's value when printing metadata
144  -n   Report numeric progress
145  -o <output.fw> Specify the output file when creating an update (Use - for stdout)
146  -p, --public-key-file <keyfile> A public key file for verifying firmware updates
147  --private-key <key> A private key for signing firmware updates
148  --progress-low <number> When displaying progress, this is the lowest number (normally 0 for 0%)
149  --progress-high <number> When displaying progress, this is the highest number (normally 100 for 100%)
150  --public-key <key> A public key for verifying firmware updates
151  -q, --quiet   Quiet
152  -s, --private-key-file <keyfile> A private key file for signing firmware updates
153  -S, --sign Sign an existing firmware file (specify -i and -o)
154  --sparse-check <path> Check if the OS and file system supports sparse files at path
155  --sparse-check-size <bytes> Hole size to check for --sparse-check
156  -t, --task <task> Task to apply within the firmware update
157  -u, --unmount Unmount all partitions on device first
158  -U, --no-unmount Do not try to unmount partitions on device
159  --unsafe Allow unsafe commands (consider applying only signed archives)
160  -v, --verbose   Verbose
161  -V, --verify  Verify an existing firmware file (specify -i)
162  --verify-writes Verify writes when applying firmware updates to detect corruption (default for writing to device files)
163  --no-verify-writes Do not verify writes when applying firmware updates (default for regular files)
164  --version Print out the version
165  -y   Accept automatically found memory card when applying a firmware update
166  -z   Print the memory card that would be automatically detected and exit
167  -1   Fast compression (for create)
168  -9   Best compression (default)
169
170Examples:
171
172Create a firmware update archive:
173
174  $ fwup -c -f fwup.conf -o myfirmware.fw
175
176Apply the firmware to an attached SDCard. This would normally be run on the host
177where it would auto-detect an SDCard and initialize it using the 'complete' task:
178
179  $ fwup -a -i myfirmware.fw -t complete
180
181Apply the firmware update to /dev/sdc and specify the 'upgrade' task:
182
183  $ fwup -a -d /dev/sdc -i myfirmware.fw -t upgrade
184
185Create an image file from a .fw file for use with dd(1):
186
187  $ fwup -a -d myimage.img -i myfirmware.fw -t complete
188
189Generate a public/private key pair:
190
191  $ fwup -g
192
193Store fwup-key.priv in a safe place and fwup-key.pub on the target. To sign
194an existing archive run:
195
196  $ fwup -S -s fwup-key.priv -i myfirmware.fw -o signedfirmware.fw
197```
198
199# Example usage
200
201The regression tests contain short examples for usage of various script
202elements and are likely the most helpful to read due to their small size.
203
204Other examples can be found in the
205[bbb-buildroot-fwup](https://github.com/fhunleth/bbb-buildroot-fwup) for project
206for the BeagleBone Black and Raspberry Pi. The [Nerves
207Project](https://github.com/nerves-project/nerves_system_br) has more examples
208and is better maintained.
209
210My real world use of `fwup` involves writing the new firmware to a place on the
211Flash that's not in current use and then 'flipping' over to it at the very end.
212The examples tend to reflect that. `fwup` can also be used to overwrite an
213installation in place assuming you're using an initramfs, but that doesn't give
214protection against someone pulling power at a bad time. Also, `fwup`'s one pass
215over the archive feature means that firmware validation is mostly done on the
216fly, so you'll want to verify the archive first (see the `-V` option).
217
218# Helper scripts
219
220While not the original use of `fwup`, it can be convenient to convert other
221files to  `.fw` files. `fwup` comes with the following shell script helper:
222
223* `img2fwup` - convert a raw image file to a `.fw` file
224
225A use case for the `img2fwup` script is to convert a large SDCard image file
226to one that is compressed and checksummed by `fwup` for distribution.
227
228# Versioning
229
230`fwup` uses [semver](https://semver.org) for versioning. For example, if you are
231using 1.0.0, that means no breaking changes until 2.0.0 or new features until
2321.1.0. I highly recommend a conservative approach to upgrading `fwup` once you
233have devices in the field. For example, if you have 1.0.0 devices in the field,
234it's ok to update to 1.1.0, but be very careful about using 1.1.0 features in
235your `fwup.conf` files. They will be ignored by 1.0.0 devices and that may or
236may not be what you want.
237
238# Configuration file format
239
240`fwup` uses the Unix configuration library,
241[libconfuse](https://github.com/libconfuse/libconfuse), so its configuration has some
242similarities to other programs. The configuration file is used to create
243firmware archives. During creation, `fwup` embeds a processed version of the
244configuration file into the archive that has been stripped of comments, has had
245all variables resolved, and has some additional useful metadata added.
246Configuration files are organized into scoped blocks and options are set using
247a `key = value` syntax. Additionally, configuration files may include
248configuration fragments and other files by calling `include("filename")`.
249
250## Environment variables
251
252For integration into build systems and other scripts, `fwup` performs
253variable substitution inside of the configuration files. Keep in
254mind that environment variables are resolved on the host during firmware update
255file creation. Generated firmware files do not contain
256
257Environment variables are referenced as follows:
258
259    key = ${ANY_ENVIRONMENT_VARIABLE}
260
261It is possible to provide default values for environment variables using the
262`:-` symbol:
263
264    key = ${ANY_ENVIRONMENT_VARIABLE:-adefault}
265
266Inside configuration files, it can be useful to define constants that are used
267throughout the file. Constants are referenced identically to environment
268variables. Here is an example:
269
270    define(MY_CONSTANT, 5)
271
272By default, repeated definitions of the same constant do not change that
273constant's value. In other words, the first definition wins. Note that the first
274definition could come from a similarly named environment variable. This makes
275it possible to override a constant in a build script.
276
277In some cases, having the last definition win is preferable for constants that
278never ever should be overridden by the environment or by earlier calls to
279`define`. For this behavior, use `define!`:
280
281    define!(MY_CONSTANT, "Can't override this")
282
283Simple math calculations may also be performed using `define-eval()` and
284`define-eval!()`. For example:
285
286    define-eval(AN_OFFSET, "${PREVIOUS_OFFSET} + ${PREVIOUS_COUNT}")
287
288These two functions were added in release 0.10.0, but since
289they are evaluated at firmware creation time, .fw files created using them are
290compatible with older versions of `fwup`.
291
292Finally, `file-resource` will define a variable named `FWUP_SIZE_<resource_name>` with the size of the resource.  For example
293the following will create a variable named `FWUP_SIZE_zImage`:
294
295```conf
296file-resource zImage {
297        host-path = "output/images/zImage"
298}
299
300execute("echo zImage size is ${FWUP_SIZE_zImage} bytes")
301```
302
303## Global scope
304
305At the global scope, the following options are available:
306
307Key                  | Description
308---------------------|------------
309require-fwup-version | Require a minimum version of fwup to apply this update
310meta-product         | Product name
311meta-description     | Description of product or firmware update
312meta-version         | Firmware version
313meta-author          | Author or company behind the update
314meta-platform        | Platform that this update runs on (e.g., rpi or bbb)
315meta-architecture    | Platform architectures (e.g., arm)
316meta-vcs-identifier  | A version control identifier for use in reproducing this image
317meta-misc            | Miscellaneous additional data. Format and contents are up to the user
318meta-creation-date   | Timestamp when the update was created (derived from ZIP metadata). For reproducible builds, set the [`SOURCE_DATE_EPOCH`](https://reproducible-builds.org/specs/source-date-epoch/#idm55) environment variable.
319meta-fwup-version    | Version of fwup used to create the update (deprecated - no longer added since fwup 1.2.0)
320meta-uuid            | A UUID to represent this firmware. The UUID won't change even if the .fw file is digitally signed after creation (automatically generated)
321
322After setting the above options, it is necessary to create scopes for other options. The
323currently available scopes are:
324
325Scope                | Description
326---------------------|------------
327file-resource        | Defines a reference to a file that should be included in the archive
328mbr                  | Defines the master boot record contents on the destination
329gpt                  | Defines GPT partitions on the destination
330task                 | Defines a firmware update task (referenced using -t from the command line)
331
332## file-resource
333
334A `file-resource` specifies a file on the host that should be included in the
335archive. Each `file-resource` should be given a unique name so that it can be
336referred to by other parts of the update configuration. `fwup` will
337automatically record the length and BLAKE2b-256 hash of the file in the
338archive. These fields are used internally to compute progress and verify the
339contents of the archive. A typical `file-resource` section looks like this:
340
341```conf
342file-resource zImage {
343        host-path = "output/images/zImage"
344}
345```
346
347Resources are usually stored in the `data` directory of the firmware archive.
348This is transparent for most users. If you need to make the `.fw` file
349work with other software, it is sometimes useful to embed a file into
350the archive at another location. This can be done by specifying an absolute
351path resource as follows:
352
353```conf
354file-resource "/my_custom_metadata" {
355        host-path = "path/to/my_custom_metadata_file"
356}
357```
358
359### Resource concatenation
360
361Sometimes you need to concatenate multiple files together to form one
362`file-resource`. While you can sometimes do this using multiple calls to
363`raw_write`, that won't work if you don't know the file offsets a priori or the
364offsets don't fall on block boundaries. Another alternative is to concatenate
365files as a prep step to fwup. If that's inconvenient, `fwup` allows multiple
366paths to be specified in `host-path` that are separated by semicolons. They
367will be concatenated in the order they appear.
368
369```conf
370file-resource kernel_and_rootfs {
371        # Concatenate uImage and the rootfs. OpenWRT mtd splitter will
372        # separate them back out at runtime.
373        host-path = "output/images/uImage;output/images/rootfs.squashfs"
374}
375```
376
377### File resource validation checks
378
379When creating archives, `fwup` can perform validation checking on file
380resources to catch simple errors. These checks can catch common errors like
381file resources growing too large to fit on the destination or files truncated
382due to cancelled builds.
383
384Note that these checks are not performed when applying updates, since the
385actual length (and a hash) is recorded in the archive metadata and used for
386verification.
387
388The following checks are supported:
389
390Check           | Description
391----------------|------------
392assert-size-lte | If the file size is not less than or equal the specified amount, report an error.
393assert-size-gte | If the file size is not greater than or equal the specified amount, report an error.
394
395Sizes are given in 512 byte blocks (like everything else in `fwup`).
396
397Here's an example:
398
399```conf
400file-resource rootfs.img {
401        host-path = "output/images/rootfs.squashfs"
402        assert-size-lte = ${ROOTFS_A_PART_COUNT}
403}
404```
405
406### Files from strings
407
408Sometimes it's useful to create short files inside the `fwup` config file
409rather than referencing them. This can be accomplished using the `contents` key
410in a `file-resource`. Variable substitution works in the `contents` string just
411like any other string in the `fwup` configuration file.
412
413```conf
414file-resource short-file.txt {
415        contents = "You're looking at a short\n\
416file creating by fwup.\n\
417When it was made, FOO was ${FOO}.\n"
418}
419```
420
421## mbr
422
423A `mbr` section specifies the contents of the Master Boot Record on the
424destination media. This section contains the partition table that's read by
425Linux and the bootloaders for finding the file systems that exist on the media.
426In comparison to a tool like `fdisk`, `fwup` only supports simplistic partition
427setup, but this is sufficient for many devices. Tools such as `fdisk` can be
428used to determine the block offsets and sizes of partitions for the
429configuration file. Offsets and sizes are given in 512 byte blocks. Here's a
430potential mbr definition:
431
432```conf
433mbr mbr-a {
434        bootstrap-code-host-path = "path/to/bootstrap-data" # should be 440 bytes
435        signature = 0x01020304
436
437        partition 0 {
438                block-offset = ${BOOT_PART_OFFSET}
439                block-count = ${BOOT_PART_COUNT}
440                type = 0x1 # FAT12
441                boot = true
442        }
443        partition 1 {
444                block-offset = ${ROOTFS_A_PART_OFFSET}
445                block-count = ${ROOTFS_A_PART_COUNT}
446                type = 0x83 # Linux
447        }
448        partition 2 {
449                block-offset = ${ROOTFS_B_PART_OFFSET}
450                block-count = ${ROOTFS_B_PART_COUNT}
451                type = 0x83 # Linux
452        }
453        partition 3 {
454                block-offset = ${APP_PART_OFFSET}
455                block-count = ${APP_PART_COUNT}
456                type = 0x83 # Linux
457        }
458}
459```
460
461If you're using an Intel Edison or similar platform, `fwup` supports generation
462of the OSIP header in the MBR. This header provides information for where to
463load the bootloader (e.g.., U-Boot) in memory. The `include-osip` option
464controls whether the header is generated. The OSIP and image record (OSII)
465option names map directly to the header fields with the exception that length,
466checksum and image count fields are automatically calculated. The following is
467an example that shows all of the options:
468
469```conf
470mbr mbr-a {
471    include-osip = true
472    osip-major = 1
473    osip-minor = 0
474    osip-num-pointers = 1
475
476    osii 0 {
477        os-major = 0
478        os-minor = 0
479        start-block-offset = ${UBOOT_OFFSET}
480        ddr-load-address = 0x01100000
481        entry-point = 0x01101000
482        image-size-blocks = 0x0000c000
483        attribute = 0x0f
484    }
485
486    partition 0 {
487        block-offset = ${ROOTFS_A_PART_OFFSET}
488        block-count = ${ROOTFS_A_PART_COUNT}
489        type = 0x83 # Linux
490    }
491}
492```
493
494Sometimes it's useful to have the final partition fill the remainder of the
495storage. This is needed if your target's storage size is unknown and you need
496to use as much of it as possible. The `expand` option requests that `fwup`
497grow the `block-count` to be as large as possible. When using `expand`, the
498`block-count` is now the minimum partition size. Only the final partition can
499be expandable. Here's an example:
500
501```conf
502mbr mbr-a {
503        partition 0 {
504                block-offset = ${BOOT_PART_OFFSET}
505                block-count = ${BOOT_PART_COUNT}
506                type = 0x1 # FAT12
507                boot = true
508        }
509        partition 1 {
510                block-offset = ${ROOTFS_A_PART_OFFSET}
511                block-count = ${ROOTFS_A_PART_COUNT}
512                type = 0x83 # Linux
513        }
514        partition 2 {
515                block-offset = ${ROOTFS_B_PART_OFFSET}
516                block-count = ${ROOTFS_B_PART_COUNT}
517                type = 0x83 # Linux
518        }
519        partition 3 {
520                block-offset = ${APP_PART_OFFSET}
521                block-count = ${APP_PART_COUNT}
522                type = 0x83 # Linux
523                expand = true
524        }
525}
526```
527
528## gpt
529
530A `gpt` section specifies the contents of a [GUID Partition
531Table](https://en.wikipedia.org/wiki/GUID_Partition_Table). It is similar to the
532`mbr` section, but it supports more partitions and uses UUIDs. Here's an example
533gpt definition:
534
535```conf
536gpt my-gpt {
537    # UUID for the entire disk
538    guid = b443fbeb-2c93-481b-88b3-0ecb0aeba911
539
540    partition 0 {
541        block-offset = ${EFI_PART_OFFSET}
542        block-count = ${EFI_PART_COUNT}
543        type = c12a7328-f81f-11d2-ba4b-00a0c93ec93b # EFI type UUID
544        guid = 5278721d-0089-4768-85df-b8f1b97e6684 # ID for partition 0 (create with uuidgen)
545        name = "efi-part.vfat"
546    }
547    partition 1 {
548        block-offset = ${ROOTFS_PART_OFFSET}
549        block-count = ${ROOTFS_PART_COUNT}
550        type = 44479540-f297-41b2-9af7-d131d5f0458a # Rootfs type UUID
551        guid = fcc205c8-2f1c-4dcd-bef4-7b209aa15cca # Another uuidgen'd UUID
552        name = "rootfs.ext2"
553        flags = 0xc000000000000
554        boot = true
555    }
556}
557```
558
559See the GPT partition entry header specification for what `partition` fields
560mean and how to use them. Of the fields, `name`, `flags`, and `boot` are
561optional and default to an empty string, zero, or false. The `flags` field holds
562the integer value of the partition attribute field. It is a 64-bit number. Bit
5632, the legacy BIOS bootable flag, can also be set by specifying `boot = true`.
564Both `boot` and `flags` can be specified in a `partition` block.
565
566Call `gpt_write` to tell `fwup` to write the protective MBR and primary and
567backup GPT tables.
568
569## U-Boot environment
570
571For systems using the U-Boot bootloader, some support is included for modifying
572U-Boot environment blocks. In order to take advantage of this, you must declare
573a `uboot-environment` section at the top level that describes how the
574environment block:
575
576```conf
577uboot-environment my_uboot_env {
578    block-offset = 2048
579    block-count = 16
580}
581```
582
583To use the redundant environment block style, add block-offset-redund with the
584address where the redundant copy is located:
585
586```conf
587uboot-environment my_uboot_env {
588    block-offset = 2048
589    block-count = 16
590    block-offset-redund = 2064
591}
592```
593
594See the functions in the task section for getting and setting U-Boot variables.
595
596NOTE: Currently, I've only implemented support for U-Boot environments that I
597use. Notably, this doesn't support big endian targets, and writes to raw NAND
598parts. Please consider contributing back support for these if you use them.
599
600If `fwup`'s U-Boot support does not meet your needs, it is always possible to
601create environment images using the `mkenvimage` utility and `raw_write` them to
602the proper locations. This is probably more appropriate when setting lots of
603variables.
604
605## task
606
607The `task` section specifies a firmware update task. These sections are the
608main part of the firmware update archive since they describe the conditions
609upon which an update is applied and the steps to apply the update. Each `task`
610section must have a unique name, but when searching for a task, the firmware
611update tool only does a prefix match. This lets you define multiple tasks that
612can be evaluated based on conditions on the target hardware. The first matching
613task is the one that gets applied. This can be useful if the upgrade process is
614different based on the version of firmware currently on the target, the target
615architecture, etc. The following table lists the supported constraints:
616
617Constraint                                         | Min fwup version | Description
618---------------------------------------------------|------------------|------------
619require-fat-file-exists(block_offset, filename)    | 0.7.0 | Require that a file exists in the specified FAT filesystem
620require-fat-file-match(block_offset, filename, pattern) | 0.14.0 | Require that filename exists and that pattern matches bytes inside of the file
621require-partition-offset(partition, block_offset)  | 0.7.0 | Require that the block offset of a partition be the specified value
622require-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")
623require-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.
624require-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
625
626The remainder of the `task` section is a list of event handlers. Event handlers
627are organized as scopes. An event handler matches during the application of a
628firmware update when an event occurs. Events include initialization,
629completion, errors, and files being decompressed from the archive. Since
630archives are processed in a streaming manner, the order of events is
631deterministic based on the order that files were added to the archive. If it is
632important that one event happen before another, make sure that `file-resource`
633sections are specified in the desired order. The following table lists
634supported events:
635
636Event                         | Description
637------------------------------|------------
638on-init                       | First event sent when the task is applied
639on-finish                     | Final event sent assuming no errors are detected during event processing
640on-error                      | Sent if an error occurs so that intermediate files can be cleaned up
641on-resource &lt;resource name>   | Sent as events occur. Currently, this is sent as `file-resources` are processed from the archive.
642
643The event scopes contain a list of actions. Actions can format file systems, copy files to file systems or
644write to raw locations on the destination.
645
646Action                                  | Min fwup version | Description
647----------------------------------------|------------------|------------
648error(message)                          | 0.12.0 | Immediately fail a firmware update with an error
649execute(command)                        | 0.16.0 | Execute a command on the host. Requires the `--unsafe` flag
650fat_mkfs(block_offset, block_count)     | 0.1.0 | Create a FAT file system at the specified block offset and count
651fat_write(block_offset, filename)       | 0.1.0 | Write the resource to the FAT file system at the specified block offset
652fat_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
653fat_mv(block_offset, oldname, newname)  | 0.1.0 | Rename the specified file on a FAT file system
654fat_mv!(block_offset, oldname, newname) | 0.14.0 | Rename the specified file even if newname already exists.
655fat_rm(block_offset, filename)          | 0.1.0 | Delete the specified file
656fat_mkdir(block_offset, filename)       | 0.2.0 | Create a directory on a FAT file system. This also succeeds if the directory already exists.
657fat_setlabel(block_offset, label)       | 0.2.0 | Set the volume label on a FAT file system
658fat_touch(block_offset, filename)       | 0.7.0 | Create an empty file if the file doesn't exist (no timestamp update like on Linux)
659gpt_write(gpt)                          | 1.4.0 | Write the specified GPT to the target
660info(message)                           | 0.13.0 | Print out an informational message
661mbr_write(mbr)                          | 0.1.0 | Write the specified mbr to the target
662path_write(destination_path)            | 0.16.0 | Write a resource to a path on the host. Requires the `--unsafe` flag
663pipe_write(command)                     | 0.16.0 | Pipe a resource through a command on the host. Requires the `--unsafe` flag
664raw_memset(block_offset, block_count, value) | 0.10.0 | Write the specified byte value repeatedly for the specified blocks
665raw_write(block_offset, options)        | 0.1.0 | Write the resource to the specified block offset. Options include `cipher` and `secret`.
666trim(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.
667uboot_recover(my_uboot_env)             | 0.15.0 | If the U-Boot environment is corrupt, reinitialize it. If not, then do nothing
668uboot_clearenv(my_uboot_env)            | 0.10.0 | Initialize a clean, variable free U-boot environment
669uboot_setenv(my_uboot_env, name, value) | 0.10.0 | Set the specified U-boot variable
670uboot_unsetenv(my_uboot_env, name)      | 0.10.0 | Unset the specified U-boot variable
671
672## Delta firmware updates (BETA)
673
674The purpose of delta firmware updates is to reduce firmware update file sizes
675and their associated costs by sending patches to devices. This requires that one
676know what firmware is running on the device so that an appropriate patch can be
677made. As with other features, `fwup` only addresses the firmware update file
678processing piece, but assists in this process by 1. uniquely identifying
679firmware via UUIDs and 2. including
680[`xdelta3`](https://github.com/jmacd/xdelta/tree/release3_1_apl/xdelta3)
681decompression support.
682
683This feature is currently BETA, since it may change in backwards incompatible
684ways based on trial deployments. If you're using this, please avoid deploying it
685to places that are hard to access just in case.
686
687`fwup` cannot produce delta `.fw` archives automatically. However, they are
688easy to produce manually or via a script. The deployments in progress use
689scripts to create patches for upgrading all possible firmware versions (keyed
690off UUID). Here's how:
691
6921. Decide which file resource is a good candidate for delta updates (you can
693   pick more than one). Call this `rootfs.img`.
6942. In the `fwup.conf`, in the `on-resource rootfs.img` handlers, specify where
695   the currently running rootfs.img contents exist. For example, if you're
696   doing an A/B upgrades, when you upgrade B, point to the A's rootfs for
697   source contents and vice versa for upgrading A. It will look something
698   like this:
699
700   ```txt
701   task upgrade.a {
702       on-resource rootfs.img {
703           delta-source-raw-offset=${ROOTFS_B_PART_OFFSET}
704           delta-source-raw-count=${ROOTFS_B_PART_COUNT}
705           raw_write(${ROOTFS_A_PART_OFFSET})
706       }
707   }
708   task upgrade.b {
709       on-resource rootfs.img {
710           delta-source-raw-offset=${ROOTFS_A_PART_OFFSET}
711           delta-source-raw-count=${ROOTFS_A_PART_COUNT}
712           raw_write(${ROOTFS_B_PART_OFFSET})
713       }
714   }
715   ```
716
7173. Obtain the firmware file for the software running on the device. Call this
718   `original.fw`.
7194. Create the firmware file for the new software. Call this `update.fw`. If
720   you normally sign your firmware files, you can sign it now or sign the
721   resulting patch file depending on what works best for your release process.
7225. Run `unzip` on both `original.fw` and `update.fw` in different directories.
723   The `rootfs.img` file can be found under the `data` directory when unzipped.
7246. `mkdir -p my_patch/data`
7257. `xdelta3 -A -S -f -s original/data/rootfs.img update/data/rootfs.img my_patch/data/rootfs.img`
7268. `cp update.fw my_patch/delta_update.fw`
7279. `cd my_patch && zip delta_update.fw data/rootfs.img`
728
729The `delta_update.fw` will have the patch for the `rootfs.img` and should be
730quite a bit smaller. If not, check that your before and after `rootfs.img` files
731don't have a lot of timestamp changes or are already so compressed that the
732deltas propagate through the entire image.
733
734Even though you're manually modifying the `.fw` file, `fwup` stills provide
735guarantees on the final bits installed on the device. For one, `fwup` computes
736Blake 2B hashes on the final contents of the files, so what matters is what
737comes out of the `xdelta3` decompressor and not what is stored in the archive.
738Most likely though, `xdelta3` will detect corruption since it checks Adler32
739checksums as it decompresses.
740
741### Delta update on-resource source settings
742
743Where to find the source ("before" version) is always specified in `on-resource`
744blocks. It can either be source from raw bytes or from files in a FAT-formatted
745partition. Only one source is supported in each `on-resource` block.
746
747Key                               | Description
748----------------------------------|------------
749delta-source-raw-offset           | Set to the starting block offset
750delta-source-raw-count            | Set to the number of blocks in the source region. No reads will be allowed outside of this area.
751delta-source-fat-offset           | Not implemented yet
752delta-source-fat-path             | Not implemented yet
753
754## Sparse files
755
756Sparse files are files with gaps in them that are only represented on the
757filesystem in metadata. Not all filesystems support sparse files, but in
758general, Linux has good support. Creating a sparse file is easy: just seek to a
759location past the end of file and write some data. The gap is "stored" as a
760hole in the filesystem metadata. Data is read back from the hole as zeros. Data
761and holes are restricted to start and end on filesystem block boundaries, so
762small gaps may be filled in with zeros rather than being stored as a hole.
763
764Why is this important? If you're using `fwup` to write a large EXT2 partition,
765you'll find that it contains many gaps. It would be better to just write the
766EXT2 data and metadata without filling in all of the unused space. Sparse file
767support in `fwup` lets you do that. Since EXT2 filesystems legitimately contain
768long runs of zeros that must be written to Flash, `fwup` queries the filesystem
769containing the EXT2 data to find the gaps. Other tools like `dd(1)` only look
770for runs of zeros so their sparse file support cannot be used to emulate this.
771You may see warnings about copying sparse files to Flash and it has to do with
772tools not writing long runs of zeros. The consequence of `fwup` querying the
773filesystem for holes is that this feature only works when firmware update
774archives are created on operating systems and filesystems that support it. Of
775course, firmware updates can be applied on systems without support for querying
776holes in files. Those systems also benefit from not having to write as much to
777Flash devices. If you instead apply a firmware update to a normal file, though,
778the OS will likely fill in the gaps with zeros and thus offer no improvement.
779
780There is one VERY important caveat with the sparse file handling: Some zeros in
781files are important and some are not. If runs in zeros in a file are important
782and they are written to a file as a "hole", `fwup` will not write them back.
783This is catastrophic if the zeros represent things like free blocks on a
784filesystem. Luckily, the file system formatting utilities write the important
785zeros to the disk and the OS does not scan bytes to see which ones are runs on
786zeros and automatically create holes. Programs like `dd(1)` can do this, though,
787so it is crucial that you do not run files through `dd` to make then sparser
788before passing them to `fwup`.
789
790This feature is off by default. To turn this feature on, set `skip-holes` on
791the resource to `true`:
792
793```conf
794file-resource rootfs.img {
795        host-path = "output/images/rootfs.img"
796        skip-holes = true
797}
798```
799
800## Disk encryption
801
802The `raw_write` function has limited support for disk encryption that's
803compatible with the Linux `dm-crypt` kernel driver. This makes it possible to
804write filesystem data in a way that's unreadable at rest. Caveats are in order:
805
8061. `fwup` does not address handling of secret keys and improper handling can
807   easily compromise the benefits of encryption
8082. The `.fw` archive is not encrypted. This mechanism assumes that the secrecy
809   of the archive is protected by other means. Of course, it is possible
810   pre-encrypt the data in the archive, but then you can't have device-specific
811   secret keys.
8123. Only the simplest `dm-crypt` cipher is currently supported ("aes-cbc-plain").
813   This has known deficiencies. PRs for other modes that can be incorporated
814   under `fwup`'s Apache License would be appreciated
815
816Various tutorials exist on the Internet for creating encrypted filesystems and
817mounting filesystems using `dm-crypt`. `fwup` is much simpler. It takes a block
818of bytes to write, encrypts it, and writes it to the destination. For example,
819if you have a SquashFS-formatted filesystem that you want written encrypted to a
820disk, you'd have this fragment:
821
822```conf
823on-resource fs.squashfs {
824    raw_write(${PARTITION_START}, "cipher=aes-cbc-plain", "secret=\${SECRET_KEY}")
825}
826```
827
828In the above example, the `SECRET_KEY` is expected to come from an environment
829variable being set on the device when applying the firmware update. You could,
830of course, hard-code the secret key in the configuration file to test things
831out. The key is hex-encoded.
832
833Then, on the device, mount the SquashFS partition but use `dm-crypt`. The
834process will look something like this:
835
836```sh
837losetup /dev/loop0 /dev/mmcblk0p2
838cryptsetup open --type=plain --cipher=aes-cbc-plain --key-file=key.txt /dev/loop0 my-filesystem
839mount /dev/mapper/my-filesystem /mnt
840```
841
842You will likely need to replace many of the arguments above with ones
843appropriate for your system.
844
845## Reproducible builds
846
847It's possible for the system time to be saved in various places when using
848`fwup`. This means that an archive with the same contents, but built at
849different times results in `.fw` files with different bytes. See
850[reproducible-builds.org](https://reproducible-builds.org/) for a discussion on
851this topic.
852
853`fwup` obeys the
854[`SOURCE_DATE_EPOCH`](https://reproducible-builds.org/docs/source-date-epoch/)
855 environment variable and will force all timestamps to the value of that
856variable when needed. Set `$SOURCE_DATE_EPOCH` to the number of seconds since
857midnight Jan 1, 1970 (run `date +%s`) to use this feature.
858
859A better way of comparing `.fw` archives, though, is to use the firmware UUID.
860The firmware UUID is computed from the contents of the archive rather than the
861bit-for-bit representation of the `.fw` file, itself. The firmware UUID is
862unaffected by timestamps (with or without `SOURCE_DATE_EPOCH`) or other things
863like compression algorithm improvements. This is not to say that
864`SOURCE_DATE_EPOCH` is not important, but that the UUID is an additional tool
865for ensuring that firmware updates are reproducible.
866
867# Firmware authentication
868
869Firmware archives can be authenticated using a simple public/private key
870scheme. To get started, create a public/private key pair by invoking `fwup -g`.
871The algorithm used is [Ed25519](http://ed25519.cr.yp.to/). This generates two
872file: `fwup-key.pub` and `fwup-key.priv`. It is critical to keep the signing
873key, `fwup-key.priv` secret.
874
875To sign an archive, pass `-s fwup-key.priv` to fwup when creating the firmware.
876The other option is to sign the firmware archive after creation with `--sign`
877or `-S`.
878
879To verify that an archive has been signed, pass `-p fwup-key.pub` on the
880command line to any of the commands that read the archive. E.g., `-a`, `-l` or
881`-m`.
882
883It is important to understand how verification works so that the security of
884the archive isn't compromised. Firmware updates are applied in one pass to
885avoid needing a lot of memory or disk space. The consequence of this is that
886verification is done on the fly. The main metadata for the archive is always
887verified before any operations occur. Cryptographic hashs (using the
888[BLAKE2b-256](https://blake2.net/) algorithm) of each file contained in the
889archive is stored in the metadata. The hash for each file is computed on the
890fly, so a compromised file may not be detected until it has been written to
891Flash. Since this is obviously bad, the strategy for creating firmware updates
892is to write them to an unused location first and then switch over at the last
893possible minute. This is desirable to do anyway, since this strategy also
894provides some protection against the user disconnecting power midway through
895the firmware update.
896
897# Integration with applications
898
899It is expected that many users will want to integrate `fwup` with their
900applications. Many operations can be accomplished by just invoking the `fwup`
901executable and parsing the text written to `stdout`. When applying firmware
902progress updates are delivered based on commandline options:
903
904  1. Human readable - This is the default. Progress is updated from the text `0%` to `100%`.
905  1. Numeric (`-n`) - Progess is printed as `0\n` to `100\n`
906  1. Quiet (`-q`) - No progress is printed
907
908While the above works well for scripts and when errors can be seen by the
909operator, `fwup` supports a structured use of `stdin`/`stdout` as well. Specify
910the `--framing` option to any of the commands to use this option.
911
912The framing feature is influenced by the Erlang VM's port API and should be
913relatively easy to integrate with non-Erlang VM languages. The framing works
914around deficiencies in the built-in interprocess communication. For example, by
915enabling framing, a program can stream a firmware update through `fwup's`
916`stdin` without needing to close its `stdout` to signal end of file. Another
917feature aided by framing is knowing what text goes together and whether the
918text is part of an error message or not. Exit status is still an indicator of
919success or failure, but the controlling application doesn't need to wait for
920the program to exit to know what happened.
921
922In `--framing` mode, all communication with `fwup` is done in packets (rather
923than byte streams). A packet starts with a 4 byte length field. The length is a
924big endian (network byte order) unsigned integer. A zero-length packet (i.e., 4
925bytes of zeros) signals end of input.
926
927Field          | Size         | Description
928---------------|--------------|-------------
929Length         | 4 bytes      | Packet length as a big endian integer
930Data           | Length bytes | Payload
931
932Input and output packets have different formats. For sending input to `fwup`
933(like when streaming a `.fw` file using stdio), the input bytes should be
934framed into packets however is most convenient. For example, if bytes are
935received in 4K chunks, then they can be sent to `fwup` in 4K packets with a
936zero-length packet at the end. The packets need not be the same size.
937
938All output packets from `fwup` have a 2 byte type field at the beginning of the
939packet:
940
941Field          | Size           | Description
942---------------|----------------|-------------
943Length         | 4 bytes        | Packet length as a big endian integer
944Type           | 2 bytes        | See below
945Data           | Length-2 bytes | Payload
946
947The following types are defined:
948
949Type           | 2 byte value | Description
950---------------|--------------|------------
951Success        | "OK"         | The command was executed successfully. The payload is a 2 bytes result code (currently 0 for success) followed by an optional textual message.
952Error          | "ER"         | A failure occurred. The payload is a 2 byte error code (future use) followed by a textual error message.
953Warning        | "WN"         | A warning occurred. The payload is a 2 byte error code (future use) followed by a textual error message.
954Progress       | "PR"         | The next two bytes are the progress (0-100) as a big endian integer.
955
956A related option is `--exit-handshake`. This option was specifically implemented
957for Erlang to support integration with its port process feature. It may be
958useful for other integrations where it's more convenient to wait for a final
959character coming from a subprocess rather than watching for an exit. The
960problem with Erlang is that it's easy for the message that the process exited to
961beat the final characters coming out stdout. When this option is enabled, `fwup`
962expects the calling process to close `stdin` when it's ready for `fwup` to exit.
963
964# FAQ
965
966## How do I include a file in the archive that isn't used by fwup
967
968The scenario is that you need to store some metadata or some other information
969that is useful to another program. For example, you'd like to include some
970documentation or other notes inside the firmware update archive that the
971destination device can pull out and present on a UI. To do this, just add
972`file-resource` blocks for each file. These blocks don't need to be referenced
973by an `on-resource` block.
974
975## How do I include the firmware version in the archive
976
977If you are using git, you can invoke `fwup` as follows:
978
979```sh
980GITDESCRIBE=`git describe` fwup -c -f myupdate.conf -o out.fw
981```
982
983Then in `myupdate.conf` add the line:
984
985```conf
986meta-version = "${GITDESCRIBE}"
987```
988
989On the target device, you can retrieve the version by using `-m`. For example:
990
991```sh
992$ fwup -m -i out.fw
993meta-product = "Awesome product"
994meta-description = "A description"
995meta-version = "v0.0.1"
996meta-author = "Me"
997meta-platform = "bbb"
998meta-architecture = "arm"
999meta-uuid="07a34e75-b7ea-5ed8-b5d9-80c10daf4939"
1000```
1001
1002## What's something cool that you can do with fwup
1003
1004Ok, this isn't really a FAQ, but for some reason people think this is cool. Many
1005systems that I work on are network connected with ssh. Sometimes I update them
1006by doing this:
1007
1008```sh
1009$ cat mysoftware.fw | ssh root@192.168.1.20 \
1010    'fwup -a -U -d /dev/mmcblk2 -t upgrade && reboot'
1011```
1012
1013The ability to pipe software updates through `fwup` comes in handy. This has
1014also gotten me out of situations where, for whatever reason, I no longer had enough
1015space to store the update on the device.
1016
1017## How should I implement multiple signing keys
1018
1019There are several use cases where it's necessary to have multiple signing keys
1020in use at a time. For example, you could want to enforce that all firmware
1021updates are signed in your infrastructure, but not force everyone to go though
1022the official secure path for QA builds. You may also want to only use each key
1023for a limited amount of signings.
1024
1025Currently, each firmware file can only have one signature. However, the
1026verifier (device) can specify multiple public keys (repeated -p options). While
1027it is possible to call `fwup` for each key, specifying multiples keys is
1028recommended to run the verification through fwup to support streamed updates
1029and also to simplify this critical code path.
1030
1031## How do I debug
1032
1033I apply updates to regular files on my laptop (as opposed to eMMC or SDCards)
1034and examine them with a hex editor. A few other routes might be useful too:
1035
10361. Unzip the .fw file to inspect the contents. It's a regular ZIP file and
1037   the `meta.conf` file inside it is the stripped down view of what your
1038   configuration looks like after variable substitution, etc.
10391. Add the `error()` function to do printf-style debugging.
10401. Find an image that works and skip updating some sections. For example,
1041   some processors are very picky on the MBR contents and it's easier to
1042   get everything else working before tackling partition constraints.
1043
1044## How do I specify the root partition in Linux
1045
1046There are a few options. Most people can specify `root=/dev/mmcblk0p1` or
1047`root=/dev/sda1` or something similar on the kernel commandline and everything
1048will work out fine. On systems with multiple drives and an unpredictable boot
1049order, you can specify `root=PARTUUID=01234567-01` where the `-01` part
1050corresponds to the 1-based partition index and `01234567` is any signature. In
1051your `fwup.conf` file's MBR block, specify `signature = 0x01234567`. A third
1052option is to use an initramfs and not worry about any of this.
1053
1054## How do I get the best performance
1055
1056In general, `fwup` writes to Flash memory in large blocks so that the update
1057can occur quickly. Obviously, reducing the amount that needs to get written
1058always helps. Beyond that, most optimizations are platform dependent. Linux
1059caches writes so aggressively that writes to Flash memory are nearly as fast as
1060possible. OSX, on the other hand, does very little caching, so doing things
1061like only working with one FAT filesystem at a time can help. In this case,
1062`fwup` only caches writes to one FAT filesystem at a time, so mixing them will
1063flush caches. OSX is also slow to unmount disks, so keep in mind that
1064performance can only be so fast on some systems.
1065
1066## How do I update /dev/mmcblock0boot0
1067
1068The special eMMC boot partitions are updatable the same way as the main
1069partition. When I create .fw files for manufacturing, I create two targets, a
1070`complete` target that updates the main eMMC and a `bootloader` target that
1071updates `mmcblock0boot0`. The manufacturing script runs `fwup` twice: once for
1072the `complete` target and then again for the `bootloader` target.
1073
1074Also, the `/dev/mmcblock0boot0` device is forced read-only by the kernel. To
1075unlock it, run:
1076
1077```sh
1078echo 0 > /sys/block/mmcblk0boot0/force_ro
1079```
1080
1081## What's the best way to identify firmware versions
1082
1083fwup supports several ways:
1084
10851. Store the version in `meta-version`. This is usually the friendliest for
1086   end users.
10872. Store the `git` hash in `meta-vcs-identifier`. This is good for developers.
10883. Use the `fwup`-computed UUID that's available in `meta-uuid' and
1089   `${FWUP_META_UUID}`.
1090
1091Of these, the third one is always available since version fwup `v1.2.1`. The
1092motivation behind it was to unambiguously know whether installed firmware
1093matches the desired firmware. Since it is computed, `.fw` files generated with
1094previous versions of fwup have UUIDs.
1095
1096The first two options require the versions to be added to the `fwup.conf` file.
1097They are usually added using environment variables so that the version numbers
1098are not hardcoded.
1099
1100## How do I get the firmware metadata formatted as JSON
1101
1102Use `jq`!
1103
1104```sh
1105$ fwup -m -i $FW_FILE | jq -n -R 'reduce inputs as $i ({}; . + ($i | (match("([^=]*)=\"(.*)\"") | .captures | {(.[0].string) : .[1].string})))'
1106{
1107  "meta-product": "My Awesome Product",
1108  "meta-version": "0.1.0",
1109  "meta-author": "All of us",
1110  "meta-platform": "imx6",
1111  "meta-architecture": "arm",
1112  "meta-creation-date": "2018-11-07T14:46:38Z",
1113  "meta-uuid": "7add3c6d-230c-5bf1-77ec-5f785e91be40"
1114}
1115```
1116
1117## How do I use "raw" NAND Flash
1118
1119Some "raw" NAND Flash requires a wear leveling layer such as UBI.  See
1120the [UBI Example fwup.conf](docs/ubi_example/fwup.conf) for how to integrate
1121fwup with the [UBI toolchain](http://www.linux-mtd.infradead.org/doc/ubi.html).
1122
1123## How do you pronounce fwup
1124
1125I used to pronounce it "eff-double-you-up", but then coworkers and others
1126started calling it "fwup" (one syllable) and "fwup-dates" when referring to the
1127`.fw` files. I now use the one syllable version. This has caused issues in the
1128documentation where "an" is used rather than "a". Feel free to send PRs.
1129
1130# Licenses
1131
1132This utility contains source code with various licenses. The bulk of the code is
1133licensed with the Apache-2.0 license which can be found in the `LICENSE` file.
1134
1135All statically-linked 3rd party source code can be found in the `src/3rdparty`
1136directory. The following sections summarize the included code licenses.
1137
1138## base64.c
1139
1140Public Domain or Creative Commons CC0. See file for explanatory text.
1141
1142## FatFS
1143
1144The FAT filesystem code (FatFs) comes from [elm-chan.org](http://elm-chan.org/fsw/ff/00index_e.html)
1145and has the following license:
1146
1147>>>
1148FatFs module is a generic FAT file system module for small embedded systems.
1149This is a free software that opened for education, research and commercial
1150developments under license policy of following terms.
1151
1152 Copyright (C) 2015, ChaN, all right reserved.
1153
1154* The FatFs module is a free software and there is NO WARRANTY.
1155* No restriction on use. You can use, modify and redistribute it for
1156  personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
1157* Redistributions of source code must retain the above copyright notice.
1158>>>
1159
1160## Monocypher
1161
1162This package has been dual licensed under the 2-clause BSD and CC-0. See
1163[LICENCE.md](src/3rdparty/monocypher-3.0.0/LICENCE.md).
1164
1165## semver.c
1166
1167`fwup` uses [semver.c](https://github.com/h2non/semver.c) for checking versions.
1168`semver.c` is Copyright (c) Tomás Aparicio and distributed under the MIT
1169License. See [LICENSE](src/3rdparty/semver.c/LICENSE).
1170
1171## strptime.c
1172
1173On systems without the function strptime(), a version from Google is
1174included that is distributed under the Apache 2.0 license.
1175
1176## Tiny AES
1177
1178This code was released into the public domain. See
1179[unlicense.txt](src/3rdparty/tiny-AES-c/unlicense.txt) for details.
1180
1181## Xdelta3
1182
1183Only the xdelta3 decompressor is currently used by `fwup` so most of the code in
1184the `xdelta3` directory is ignored or disabled. Importantly, `fwup`'s use of
1185xdelta3 does not bring in any xdelta3 dependencies. Xdelta3 is covered by the
1186Apache-2.0 license.
1187