meta-digi-dey: add new 'recovery-utils' recipe

recovery-utils allows to configure recovery commands and reboot into
recovery mode.

Internal recovery-utils.git SHA1: 5555d4c736e3

https://jira.digi.com/browse/DEL-3358

Signed-off-by: Javier Viguera <javier.viguera@digi.com>
This commit is contained in:
Javier Viguera 2017-01-11 17:51:07 +01:00
parent f787a22ef1
commit 9c3f8245e1
10 changed files with 544 additions and 0 deletions

View File

@ -39,6 +39,7 @@ RDEPENDS_${PN} = "\
modutils-initscripts \ modutils-initscripts \
netbase \ netbase \
os-release \ os-release \
recovery-utils \
sysinfo \ sysinfo \
usbutils \ usbutils \
${VIRTUAL-RUNTIME_dev_manager} \ ${VIRTUAL-RUNTIME_dev_manager} \

View File

@ -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
}

View File

@ -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

View File

@ -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.

View File

@ -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 */

View File

@ -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)

View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/reboot.h>
#include <unistd.h>
#include <libubootenv/ubootenv.h>
/*
* 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");
}

View File

@ -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}

View File

@ -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)

View File

@ -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 <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <recovery.h>
#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] [<SWU-package-path>]\n\n" \
" -u --update-firmware Perform firmware update\n" \
" -w --wipe-update-partition Wipe 'update' partition\n" \
" -T --reboot-timeout=<N> Reboot after N seconds (default %d)\n" \
" --help Print help and exit\n" \
"\n" \
"<SWU-package-path> 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] <SWU-package-path>\n\n" \
" -T --reboot-timeout=<N> Reboot after N seconds (default %d)\n" \
" --help Print help and exit\n" \
"\n" \
"<SWU-package-path> 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;
}