diff --git a/meta-digi-dey/recipes-core/packagegroups/packagegroup-dey-core.bb b/meta-digi-dey/recipes-core/packagegroups/packagegroup-dey-core.bb index 7b6c6baa7..dbe3987d2 100644 --- a/meta-digi-dey/recipes-core/packagegroups/packagegroup-dey-core.bb +++ b/meta-digi-dey/recipes-core/packagegroups/packagegroup-dey-core.bb @@ -39,6 +39,7 @@ RDEPENDS_${PN} = "\ modutils-initscripts \ netbase \ os-release \ + recovery-utils \ sysinfo \ usbutils \ ${VIRTUAL-RUNTIME_dev_manager} \ diff --git a/meta-digi-dey/recipes-core/recovery/recovery-utils.bb b/meta-digi-dey/recipes-core/recovery/recovery-utils.bb new file mode 100644 index 000000000..d8e2f0009 --- /dev/null +++ b/meta-digi-dey/recipes-core/recovery/recovery-utils.bb @@ -0,0 +1,17 @@ +# Copyright (C) 2017 Digi International + +SUMMARY = "Recovery reboot utilities" +LICENSE = "MPL-2.0" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MPL-2.0;md5=815ca599c9df247a0c7f619bab123dad" + +DEPENDS = "u-boot-fw-utils" + +PV = "0.1" + +SRC_URI = "file://${BPN}" + +S = "${WORKDIR}/${BPN}" + +do_install() { + oe_runmake DESTDIR=${D} install +} diff --git a/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/Makefile b/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/Makefile new file mode 100644 index 000000000..1fbf05f6a --- /dev/null +++ b/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/Makefile @@ -0,0 +1,29 @@ +# +# Copyright (c) 2017, Digi International Inc. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at http://mozilla.org/MPL/2.0/. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +SUBDIRS := lib recovery-reboot + +all: $(SUBDIRS) + +recovery-reboot: lib + +.PHONY: $(SUBDIRS) +$(SUBDIRS): + $(MAKE) -C $@ + +.PHONY: clean install +clean install: + for a in $(SUBDIRS); do $(MAKE) -C $$a $@; done diff --git a/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/README.md b/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/README.md new file mode 100644 index 000000000..013bd2e1c --- /dev/null +++ b/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/README.md @@ -0,0 +1,13 @@ +Recovery utils +============== + +**recovery-utils** allows to configure recovery commands and reboot into +recovery mode. + +Provides: +* **librecovery** static library which implements the supported recovery +commands. +* **recovery-reboot** command line example application to configure and +reboot into recovery mode. +* **update-firmware** command supporting only the firmware update recovery +command. diff --git a/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/include/recovery.h b/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/include/recovery.h new file mode 100644 index 000000000..4f7dfddb3 --- /dev/null +++ b/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/include/recovery.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017, Digi International Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at http://mozilla.org/MPL/2.0/. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Description: Recovery boot library + * + */ + +#ifndef RECOVERY_H +#define RECOVERY_H + +/* + * Configure recovery commands to update the firmware. + * + * Params: + * 'swu_path' (input) Path to the update package + * + * Return: 0 on sucess, -1 on failure + */ +int update_firmware(const char *swu_path); + +/* + * Reboot into recovery mode. + * + * Params: + * 'reboot_timeout' (input) Timeout to perform the reboot + * + * Return: -1 on failure, otherwise it does not return + */ +int reboot_recovery(unsigned int reboot_timeout); + +/* + * Configure recovery commands to format 'update' partition. + * + * Return: 0 on sucess, -1 on failure + */ +int wipe_update_partition(void); + +#endif /* RECOVERY_H */ diff --git a/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/lib/Makefile b/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/lib/Makefile new file mode 100644 index 000000000..dc2f89823 --- /dev/null +++ b/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/lib/Makefile @@ -0,0 +1,35 @@ +# +# Copyright (c) 2017, Digi International Inc. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at http://mozilla.org/MPL/2.0/. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +LIBRECOVERY_AR = librecovery.a + +CFLAGS += -Wall + +all: $(LIBRECOVERY_AR) + +$(LIBRECOVERY_AR): recovery.o + $(AR) -rcs $@ $^ + +.PHONY: install +install: $(LIBRECOVERY_AR) + install -d $(DESTDIR)/usr/lib/pkgconfig $(DESTDIR)/usr/include/librecovery + install -m 0644 $(LIBRECOVERY_AR) $(DESTDIR)/usr/lib/ + install -m 0644 recovery.pc $(DESTDIR)/usr/lib/pkgconfig/ + install -m 0644 ../include/recovery.h $(DESTDIR)/usr/include/librecovery/ + +.PHONY: clean +clean: + -rm -f *.o $(LIBRECOVERY_AR) diff --git a/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/lib/recovery.c b/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/lib/recovery.c new file mode 100644 index 000000000..491a443d3 --- /dev/null +++ b/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/lib/recovery.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2017, Digi International Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at http://mozilla.org/MPL/2.0/. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Description: Recovery boot library + * + */ + +#include +#include +#include +#include +#include + +#include + +/* + * Function: append_recovery_command + * Description: append configuration to the 'recovery_command' variable + */ +static int append_recovery_command(const char *value) +{ + const char *old_recovery_cmd; + char *new_recovery_cmd; + int rcvr_cmd_len; + int ret = 0; + + ret = uboot_getenv("recovery_command", &old_recovery_cmd); + if (ret) { + fprintf(stderr, "Error: getenv 'recovery_command'\n"); + goto err; + } + + /* Length of old recovery command (+1 for the space) */ + rcvr_cmd_len = (old_recovery_cmd) ? (strlen(old_recovery_cmd) + 1) : 0; + + /* Add new value's length + '\0' */ + rcvr_cmd_len += strlen(value) + 1; + + new_recovery_cmd = calloc(1, rcvr_cmd_len); + if (!new_recovery_cmd) { + fprintf(stderr, "Error: calloc 'new_recovery_cmd'\n"); + goto err; + } + + /* Set new recovery command appending to previous value */ + if (old_recovery_cmd) { + strcpy(new_recovery_cmd, old_recovery_cmd); + strcat(new_recovery_cmd, " "); + } + strcat(new_recovery_cmd, value); + + ret = uboot_setenv("recovery_command", new_recovery_cmd); + if (ret) + fprintf(stderr, "Error: setenv 'recovery_command'\n"); + + free(new_recovery_cmd); + +err: + return ret ? -1 : 0; +} + +/* + * Function: update_firmware + * Description: configure recovery commands to update the firmware + */ +int update_firmware(const char *swu_path) +{ + char *fwupdate_cmd; + int ret = -1; + + /* Verify input parameter */ + if (!swu_path) { + fprintf(stderr, "Error: NULL 'swu_path'\n"); + goto err; + } + + fwupdate_cmd = + calloc(1, strlen("update_package=") + strlen(swu_path) + 1); + if (!fwupdate_cmd) { + fprintf(stderr, "Error: calloc 'fwupdate_cmd'\n"); + goto err; + } + + sprintf(fwupdate_cmd, "update_package=%s", swu_path); + + ret = append_recovery_command(fwupdate_cmd); + + free(fwupdate_cmd); + +err: + return ret ? -1 : 0; +} + +/* + * Function: reboot_recovery + * Description: reboot into recovery mode + */ +int reboot_recovery(unsigned int reboot_timeout) +{ + int ret = 0; + + sync(); + + /* Configure system to boot into recovery mode */ + ret = uboot_setenv("boot_recovery", "yes"); + if (ret) { + fprintf(stderr, "Error: setenv 'boot_recovery'\n"); + goto err; + } + + printf("\nThe recovery commands have been properly configured and " + "the system will reboot into recovery mode in %d seconds " + "(^C to cancel).\n\n", reboot_timeout); + fflush(stdout); + sleep(reboot_timeout); + reboot(RB_AUTOBOOT); + +err: + return ret; +} + +/* + * Function: wipe_update_partition + * Description: configure recovery commands to format 'update' partition + */ +int wipe_update_partition(void) +{ + return append_recovery_command("wipe_update"); +} diff --git a/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/lib/recovery.pc b/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/lib/recovery.pc new file mode 100644 index 000000000..f5e8cc36b --- /dev/null +++ b/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/lib/recovery.pc @@ -0,0 +1,13 @@ +prefix=/usr +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: recovery +Description: recovery functionality library +Version:1.0 + +Requires: +Libs: -L${libdir} -lrecovery +Libs.private: -lubootenv +Cflags: -I${includedir}/librecovery -I${includedir} diff --git a/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/recovery-reboot/Makefile b/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/recovery-reboot/Makefile new file mode 100644 index 000000000..fbb89852d --- /dev/null +++ b/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/recovery-reboot/Makefile @@ -0,0 +1,47 @@ +# +# Copyright (c) 2017, Digi International Inc. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at http://mozilla.org/MPL/2.0/. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +PROGRAM := recovery-reboot + +GIT_REVISION := $(shell git rev-parse --verify --short=7 HEAD 2>/dev/null) + +CFLAGS += -Wall -DGIT_REVISION=\"$(if $(GIT_REVISION),-g$(GIT_REVISION))\" + +# +# In general, when a library is installed in the toolchain the correct way to +# set the flags would be: +# +# CFLAGS += $(shell pkg-config --cflags recovery) +# LDLIBS += $(shell pkg-config --libs --static recovery) +# +# But in this case as we want to use the library not installed and from the +# local build directory, we adjust manually the flags. +# +CFLAGS += -I../include +LDFLAGS += -L../lib +LDLIBS += -lrecovery -lubootenv + +all: $(PROGRAM) + +.PHONY: install +install: $(PROGRAM) + install -d $(DESTDIR)/usr/bin + install -m 0755 $(PROGRAM) $(DESTDIR)/usr/bin/ + ln -sf $(PROGRAM) $(DESTDIR)/usr/bin/update-firmware + +.PHONY: clean +clean: + -rm -f *.o $(PROGRAM) diff --git a/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/recovery-reboot/recovery-reboot.c b/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/recovery-reboot/recovery-reboot.c new file mode 100644 index 000000000..d1e49bd44 --- /dev/null +++ b/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/recovery-reboot/recovery-reboot.c @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2017, Digi International Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at http://mozilla.org/MPL/2.0/. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Description: Reboot into recovery mode setting recovery commands + * + */ + +#define _GNU_SOURCE /* For GNU version of basename */ + +#include +#include +#include +#include + +#include + +#define VERSION "0.1" GIT_REVISION + +#define REBOOT_TIMEOUT 10 + +#define CMD_RECOVERY "recovery-reboot" +#define CMD_UPDATEFW "update-firmware" + +#define RECOVERY_USAGE \ + "Reboot into recovery mode setting recovery commands.\n" \ + "Copyright(c) Digi International Inc.\n" \ + "\n" \ + "Version: %s\n" \ + "\n" \ + "Usage: %s [options] []\n\n" \ + " -u --update-firmware Perform firmware update\n" \ + " -w --wipe-update-partition Wipe 'update' partition\n" \ + " -T --reboot-timeout= Reboot after N seconds (default %d)\n" \ + " --help Print help and exit\n" \ + "\n" \ + " Absolute path to the firmware update package\n" \ + "\n" + +#define UPDATEFW_USAGE \ + "Update the firmware using the recovery reboot.\n" \ + "Copyright(c) Digi International Inc.\n" \ + "\n" \ + "Version: %s\n" \ + "\n" \ + "Usage: %s [options] \n\n" \ + " -T --reboot-timeout= Reboot after N seconds (default %d)\n" \ + " --help Print help and exit\n" \ + "\n" \ + " Absolute path to the firmware update package\n" \ + "\n" + +/* Check if application was called as update-firmware */ +#define IS_UPDATEFW(cmd) (!strcmp(cmd, CMD_UPDATEFW)) + +/* Actual command name */ +static char *cmd_name; + +/* Command line options */ +static char *swu_package; +static int wipe_update; +static int update_fw; +static int reboot_timeout = REBOOT_TIMEOUT; + +/* + * Function: usage_and_exit + * Description: show usage information and exit with 'exitval' return value + */ +static void usage_and_exit(int exitval) +{ + if (IS_UPDATEFW(cmd_name)) + fprintf(stdout, UPDATEFW_USAGE, VERSION, CMD_UPDATEFW, + REBOOT_TIMEOUT); + else + fprintf(stdout, RECOVERY_USAGE, VERSION, CMD_RECOVERY, + REBOOT_TIMEOUT); + + exit(exitval); +} + +/* + * Function: parse_options + * Description: parse command line options + */ +static void parse_options(int argc, char *argv[]) +{ + static int opt_index, opt; + static const char *short_options = "uwT:"; + static const struct option long_options[] = { + {"update-firmware", no_argument, NULL, 'u'}, + {"wipe-update-partition", no_argument, NULL, 'w'}, + {"reboot-timeout", required_argument, NULL, 'T'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + char *endptr; + + if (argc == 1) + usage_and_exit(EXIT_SUCCESS); + + while (1) { + opt = + getopt_long(argc, argv, short_options, long_options, + &opt_index); + if (opt == -1) + break; + + switch (opt) { + case 'u': + update_fw = 1; + break; + case 'w': + wipe_update = 1; + break; + case 'T': + reboot_timeout = (int)strtol(optarg, &endptr, 10); + if (*endptr) { + printf("Error: incorrect timeout argument\n"); + exit(EXIT_FAILURE); + } + break; + case 'h': + usage_and_exit(EXIT_SUCCESS); + break; + default: + usage_and_exit(EXIT_FAILURE); + break; + } + } + + /* If command is 'update-firmware' reset the options */ + if (IS_UPDATEFW(cmd_name)) { + update_fw = 1; + wipe_update = 0; + } + + if (update_fw) { + if (argc == (optind + 1)) { + swu_package = argv[optind]; + } else { + printf("Error: missing SWU package argument\n"); + exit(EXIT_FAILURE); + } + } +} + +int main(int argc, char *argv[]) +{ + int ret = 0; + + cmd_name = basename(argv[0]); + if (!cmd_name) { + printf("Error: basename command\n"); + goto out; + } + + /* Read and parse command line */ + parse_options(argc, argv); + + if (swu_package) { + /* Configure recovery commands to update the firmware */ + ret = update_firmware(swu_package); + if (ret) { + printf("Error: update_firmware\n"); + goto out; + } + } + + if (wipe_update) { + /* Configure recovery commands to format 'update' partition */ + ret = wipe_update_partition(); + if (ret) { + printf("Error: wipe_update_partition\n"); + goto out; + } + } + + /* Reboot to recovery */ + ret = reboot_recovery(reboot_timeout); + if (ret) { + printf("Error: reboot_recovery\n"); + goto out; + } + +out: + return ret; +}