Skip to content

Commit d6d8213

Browse files
committed
Allow specifying a fallback task
In very specific cases, it might be desirable to fallback to another task when the target task fails. Most commonly this will be falling back to the `complete` task when the `upgrade` fails due to the firmware not having a previous firmware. The fallback will only occur if the failure is withing the tasks functions so checks before and after the task do not trigger a fallback (i.e. issues with archive or config file) This is inspired by nerves-project/nerves#682
1 parent 3dde4b2 commit d6d8213

File tree

5 files changed

+78
-7
lines changed

5 files changed

+78
-7
lines changed

src/fwup.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ static void print_usage()
110110
printf(" --sparse-check <path> Check if the OS and file system supports sparse files at path\n");
111111
printf(" --sparse-check-size <bytes> Hole size to check for --sparse-check\n");
112112
printf(" -t, --task <task> Task to apply within the firmware update\n");
113+
printf(" -T, --fallback-task <task> Fallback task to apply within the firmware update if the first task fails\n");
113114
printf(" -u, --unmount Unmount all partitions on device first\n");
114115
printf(" -U, --no-unmount Do not try to unmount partitions on device\n");
115116
printf(" --unsafe Allow unsafe commands (consider applying only signed archives)\n");
@@ -207,6 +208,7 @@ static struct option long_options[] = {
207208
{"sparse-check-size", required_argument, 0, OPTION_SPARSE_CHECK_SIZE},
208209
{"sign", no_argument, 0, 'S'},
209210
{"task", required_argument, 0, 't'},
211+
{"fallback-task", required_argument, 0, 'T'},
210212
{"unmount", no_argument, 0, 'u'},
211213
{"no-unmount", no_argument, 0, 'U'},
212214
{"unsafe", no_argument, 0, OPTION_UNSAFE},
@@ -376,6 +378,7 @@ int main(int argc, char **argv)
376378
const char *input_filename = NULL;
377379
const char *output_filename = NULL;
378380
const char *task = NULL;
381+
const char *fallback_task = NULL;
379382
#ifndef FWUP_MINIMAL
380383
const char *configfile = "fwupdate.conf";
381384
const char *sparse_check = NULL;
@@ -413,7 +416,7 @@ int main(int argc, char **argv)
413416
atexit(mmc_finalize);
414417

415418
int opt;
416-
while ((opt = getopt_long(argc, argv, "acd:DEf:Fghi:lmno:p:qSs:t:VvUuyZz123456789", long_options, NULL)) != -1) {
419+
while ((opt = getopt_long(argc, argv, "acd:DEf:Fghi:lmno:p:qSs:t:T:VvUuyZz123456789", long_options, NULL)) != -1) {
417420
switch (opt) {
418421
case 'a': // --apply
419422
command = CMD_APPLY;
@@ -520,6 +523,9 @@ int main(int argc, char **argv)
520523
case 't': // --task
521524
task = optarg;
522525
break;
526+
case 'T': // --fallback-task
527+
fallback_task = optarg;
528+
break;
523529
case 'v': // --verbose
524530
fwup_verbose = true;
525531
break;
@@ -713,6 +719,7 @@ int main(int argc, char **argv)
713719

714720
if (fwup_apply(input_filename,
715721
task,
722+
fallback_task,
716723
output_fd,
717724
end_offset,
718725
&progress,

src/fwup_apply.c

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,7 @@ static int run_task(struct fun_context *fctx, struct fwup_apply_data *pd)
454454

455455
int fwup_apply(const char *fw_filename,
456456
const char *task_prefix,
457+
const char *fb_task_prefix,
457458
int output_fd,
458459
off_t end_offset,
459460
struct fwup_progress *progress,
@@ -512,14 +513,28 @@ int fwup_apply(const char *fw_filename,
512513

513514
// Go through all of the tasks and find a matcher
514515
fctx.task = find_task(&fctx, task_prefix);
515-
if (fctx.task == 0)
516+
cfg_t *fallback_task = 0;
517+
if (fb_task_prefix != NULL) {
518+
fallback_task = find_task(&fctx, fb_task_prefix);
519+
}
520+
521+
if (fctx.task == 0 && fb_task_prefix == NULL)
516522
ERR_CLEANUP_MSG("Couldn't find applicable task '%s'. If task is available, the task's requirements may not be met.", task_prefix);
517523

518-
// Compute the total progress units
519-
OK_OR_CLEANUP(compute_progress(&fctx));
524+
if (fctx.task == 0 && fallback_task == 0)
525+
ERR_CLEANUP_MSG("Couldn't find applicable task '%s' or fallback task '%s'. If either task is available, the requirements may not be met.", task_prefix, fb_task_prefix);
526+
527+
if (fctx.task == 0) {
528+
fctx.task = fallback_task;
529+
fwup_warnx("'%s' task not found. Using fallback task '%s'", task_prefix, fb_task_prefix);
530+
}
520531

521-
// Run
522-
OK_OR_CLEANUP(run_task(&fctx, &pd));
532+
fallback:
533+
// Compute the total progress units
534+
OK_OR_CLEANUP(compute_progress(&fctx));
535+
536+
// Run
537+
OK_OR_CLEANUP(run_task(&fctx, &pd));
523538

524539
// Flush everything
525540
fatfs_closefs();
@@ -535,6 +550,11 @@ int fwup_apply(const char *fw_filename,
535550
progress_report_complete(fctx.progress);
536551

537552
cleanup:
553+
if (fallback_task != 0 && fctx.task != fallback_task) {
554+
fctx.task = fallback_task;
555+
goto fallback;
556+
}
557+
538558
// Close the output
539559
if (fctx.output) {
540560
// In the error case, flush in case the on-error

src/fwup_apply.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ struct fwup_progress;
2323

2424
int fwup_apply(const char *fw_filename,
2525
const char *task,
26+
const char *fb_task,
2627
int output_fd,
2728
off_t end_offset,
2829
struct fwup_progress *progress,

tests/192_fallback_task.test

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/bin/sh
2+
3+
#
4+
# Test the fallback task ability when initial task fails
5+
#
6+
7+
. "$(cd "$(dirname "$0")" && pwd)/common.sh"
8+
9+
cat >$CONFIG <<EOF
10+
file-resource TEST {
11+
host-path = "${TESTFILE_1K}"
12+
}
13+
14+
task complete {
15+
on-resource TEST { raw_write(0) }
16+
}
17+
EOF
18+
19+
cat >$EXPECTED_META_CONF <<EOF
20+
file-resource "TEST" {
21+
length=1024
22+
blake2b-256="b25c2dfe31707f5572d9a3670d0dcfe5d59ccb010e6aba3b81aad133eb5e378b"
23+
}
24+
task "complete" {
25+
on-resource "TEST" {
26+
funlist = {"2", "raw_write", "0"}
27+
}
28+
}
29+
EOF
30+
31+
$FWUP_CREATE -c -f $CONFIG -o $FWFILE
32+
33+
# Check that the zip file was created as expected
34+
check_meta_conf
35+
cmp $TESTFILE_1K $UNZIPDIR/data/TEST
36+
37+
# The upgrade task does not exist, so it should fallback to the complete task
38+
$FWUP_APPLY -a -d $IMGFILE -i $FWFILE -t upgrade -T complete --verify-writes
39+
cmp_bytes 1024 $IMGFILE $TESTFILE_1K
40+
41+
# Check that the verify logic works on this file
42+
$FWUP_VERIFY -V -i $FWFILE

tests/Makefile.am

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ TESTS = 001_simple_fw.test \
191191
188_uboot_redundant_bad_param.test \
192192
189_uboot_redundant_recover.test \
193193
190_one_metadata_cmdline.test \
194-
191_disk_crypto_via_env.test
194+
191_disk_crypto_via_env.test \
195+
192_fallback_test.test
195196

196197
EXTRA_DIST = $(TESTS) common.sh 1K.bin 1K-corrupt.bin 150K.bin

0 commit comments

Comments
 (0)