diff --git a/src/fwup.c b/src/fwup.c index fb4b1ccc..11dc9e0d 100644 --- a/src/fwup.c +++ b/src/fwup.c @@ -110,6 +110,7 @@ static void print_usage() printf(" --sparse-check Check if the OS and file system supports sparse files at path\n"); printf(" --sparse-check-size Hole size to check for --sparse-check\n"); printf(" -t, --task Task to apply within the firmware update\n"); + printf(" -T, --fallback-task Fallback task to apply within the firmware update if the first task fails\n"); printf(" -u, --unmount Unmount all partitions on device first\n"); printf(" -U, --no-unmount Do not try to unmount partitions on device\n"); printf(" --unsafe Allow unsafe commands (consider applying only signed archives)\n"); @@ -207,6 +208,7 @@ static struct option long_options[] = { {"sparse-check-size", required_argument, 0, OPTION_SPARSE_CHECK_SIZE}, {"sign", no_argument, 0, 'S'}, {"task", required_argument, 0, 't'}, + {"fallback-task", required_argument, 0, 'T'}, {"unmount", no_argument, 0, 'u'}, {"no-unmount", no_argument, 0, 'U'}, {"unsafe", no_argument, 0, OPTION_UNSAFE}, @@ -376,6 +378,7 @@ int main(int argc, char **argv) const char *input_filename = NULL; const char *output_filename = NULL; const char *task = NULL; + const char *fallback_task = NULL; #ifndef FWUP_MINIMAL const char *configfile = "fwupdate.conf"; const char *sparse_check = NULL; @@ -413,7 +416,7 @@ int main(int argc, char **argv) atexit(mmc_finalize); int opt; - while ((opt = getopt_long(argc, argv, "acd:DEf:Fghi:lmno:p:qSs:t:VvUuyZz123456789", long_options, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "acd:DEf:Fghi:lmno:p:qSs:t:T:VvUuyZz123456789", long_options, NULL)) != -1) { switch (opt) { case 'a': // --apply command = CMD_APPLY; @@ -520,6 +523,9 @@ int main(int argc, char **argv) case 't': // --task task = optarg; break; + case 'T': // --fallback-task + fallback_task = optarg; + break; case 'v': // --verbose fwup_verbose = true; break; @@ -713,6 +719,7 @@ int main(int argc, char **argv) if (fwup_apply(input_filename, task, + fallback_task, output_fd, end_offset, &progress, diff --git a/src/fwup_apply.c b/src/fwup_apply.c index 65eac9bb..6346f8ec 100644 --- a/src/fwup_apply.c +++ b/src/fwup_apply.c @@ -454,6 +454,7 @@ static int run_task(struct fun_context *fctx, struct fwup_apply_data *pd) int fwup_apply(const char *fw_filename, const char *task_prefix, + const char *fb_task_prefix, int output_fd, off_t end_offset, struct fwup_progress *progress, @@ -512,14 +513,28 @@ int fwup_apply(const char *fw_filename, // Go through all of the tasks and find a matcher fctx.task = find_task(&fctx, task_prefix); - if (fctx.task == 0) + cfg_t *fallback_task = 0; + if (fb_task_prefix != NULL) { + fallback_task = find_task(&fctx, fb_task_prefix); + } + + if (fctx.task == 0 && fb_task_prefix == NULL) ERR_CLEANUP_MSG("Couldn't find applicable task '%s'. If task is available, the task's requirements may not be met.", task_prefix); - // Compute the total progress units - OK_OR_CLEANUP(compute_progress(&fctx)); + if (fctx.task == 0 && fallback_task == 0) + 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); + + if (fctx.task == 0) { + fctx.task = fallback_task; + fwup_warnx("'%s' task not found. Using fallback task '%s'", task_prefix, fb_task_prefix); + } - // Run - OK_OR_CLEANUP(run_task(&fctx, &pd)); + fallback: + // Compute the total progress units + OK_OR_CLEANUP(compute_progress(&fctx)); + + // Run + OK_OR_CLEANUP(run_task(&fctx, &pd)); // Flush everything fatfs_closefs(); @@ -535,6 +550,11 @@ int fwup_apply(const char *fw_filename, progress_report_complete(fctx.progress); cleanup: + if (fallback_task != 0 && fctx.task != fallback_task) { + fctx.task = fallback_task; + goto fallback; + } + // Close the output if (fctx.output) { // In the error case, flush in case the on-error diff --git a/src/fwup_apply.h b/src/fwup_apply.h index 250c8598..a26cbf44 100644 --- a/src/fwup_apply.h +++ b/src/fwup_apply.h @@ -23,6 +23,7 @@ struct fwup_progress; int fwup_apply(const char *fw_filename, const char *task, + const char *fb_task, int output_fd, off_t end_offset, struct fwup_progress *progress, diff --git a/tests/192_fallback_task.test b/tests/192_fallback_task.test new file mode 100755 index 00000000..a1f8667a --- /dev/null +++ b/tests/192_fallback_task.test @@ -0,0 +1,42 @@ +#!/bin/sh + +# +# Test the fallback task ability when initial task fails +# + +. "$(cd "$(dirname "$0")" && pwd)/common.sh" + +cat >$CONFIG <$EXPECTED_META_CONF <