@@ -241,9 +241,9 @@ static int ctrl_close(lua_State *L) {
ipc_message msg;
msg.data.procmsg.len = 0;
- if (ipc_postupdate(&msg) != 0 || msg.type != ACK) {
+ if (ipc_reboot(&msg) != 0 || msg.type != ACK) {
lua_pushnil(L);
- lua_pushstring(L, "SWUpdate succeeded but post-update action failed.");
+ lua_pushstring(L, "SWUpdate succeeded but reboot failed.");
return 2;
}
@@ -44,8 +44,7 @@ static int readimage(char **p, int *size) {
/*
* this is called at the end reporting the status
- * of the upgrade and running any post-update actions
- * if successful
+ * of the upgrade and performing a reboot on success if needed
*/
static int endupdate(RECOVERY_STATUS status)
{
@@ -59,7 +58,7 @@ static int endupdate(RECOVERY_STATUS status)
if (status == SUCCESS) {
ipc_message msg;
msg.data.procmsg.len = 0;
- if (ipc_postupdate(&msg) != 0 || msg.type != ACK) {
+ if (ipc_reboot(&msg) != 0 || msg.type != ACK) {
end_status = EXIT_FAILURE;
}
}
@@ -595,19 +595,28 @@ int preupdatecmd(struct swupdate_cfg *swcfg)
return 0;
}
-int postupdate(struct swupdate_cfg *swcfg, const char *info)
+int rebootcmd(struct swupdate_cfg *swcfg, const char *info)
{
+ int ret = 0;
+
swupdate_progress_done(info);
- if (swcfg) {
- if (swcfg->parms.dry_run) {
- DEBUG("Dry run, skipping Post-update command");
- } else {
- DEBUG("Running Post-update command");
- return run_system_cmd(swcfg->postupdatecmd);
- }
+ if (!swcfg)
+ goto finish;
+ if (swcfg->parms.dry_run) {
+ DEBUG("Dry run, skipping reboot");
+ goto finish;
}
- return 0;
+ if (!swcfg->reboot_required) {
+ INFO("No reboot required for this update");
+ goto finish;
+ }
+
+ DEBUG("Rebooting the system");
+ ret = run_system_cmd(swcfg->rebootcmd);
+
+finish:
+ return ret;
}
@@ -429,14 +429,13 @@ void *network_thread (void *data)
pthread_mutex_lock(&stream_mutex);
if (msg.magic == IPC_MAGIC) {
switch (msg.type) {
- case POST_UPDATE:
- if (postupdate(get_swupdate_cfg(),
+ case REBOOT:
+ if (rebootcmd(get_swupdate_cfg(),
msg.data.procmsg.len > 0 ? msg.data.procmsg.buf : NULL) == 0) {
msg.type = ACK;
- sprintf(msg.data.msg, "Post-update actions successfully executed.");
} else {
msg.type = NACK;
- sprintf(msg.data.msg, "Post-update actions failed.");
+ sprintf(msg.data.msg, "Reboot failed.");
}
break;
case SWUPDATE_SUBPROCESS:
@@ -114,7 +114,7 @@ static struct option long_options[] = {
{"output", required_argument, NULL, 'o'},
{"gen-swversions", required_argument, NULL, 's'},
{"preupdate", required_argument, NULL, 'P'},
- {"postupdate", required_argument, NULL, 'p'},
+ {"rebootcmd", required_argument, NULL, 'r'},
{"select", required_argument, NULL, 'e'},
#ifdef CONFIG_SURICATTA
{"suricatta", required_argument, NULL, 'u'},
@@ -140,7 +140,7 @@ static void usage(char *programname)
" -b, --blacklist <list of mtd> : MTDs that must not be scanned for UBI\n"
#endif
" -B, --bootloader : bootloader interface (default: " PREPROCVALUE(BOOTLOADER_DEFAULT) ")\n"
- " -p, --postupdate : execute post-update command\n"
+ " -r, --reboot <command> : execute reboot command\n"
" -P, --preupdate : execute pre-update command\n"
" -e, --select <software>,<mode> : Select software images set and source\n"
" Ex.: stable,main\n"
@@ -274,6 +274,7 @@ static void swupdate_init(struct swupdate_cfg *sw)
LIST_INIT(&sw->bootloader);
LIST_INIT(&sw->extprocs);
sw->cert_purpose = SSL_PURPOSE_DEFAULT;
+ sw->reboot_required = true;
#ifdef CONFIG_MTD
mtd_init();
@@ -319,7 +320,7 @@ static int read_globals_settings(void *elem, void *data)
GET_FIELD_STRING(LIBCFG_PARSER, elem,
"mtd-blacklist", sw->mtdblacklist);
GET_FIELD_STRING(LIBCFG_PARSER, elem,
- "postupdatecmd", sw->postupdatecmd);
+ "rebootcmd", sw->rebootcmd);
GET_FIELD_STRING(LIBCFG_PARSER, elem,
"preupdatecmd", sw->preupdatecmd);
GET_FIELD_STRING(LIBCFG_PARSER, elem,
@@ -761,9 +762,9 @@ int main(int argc, char **argv)
case 'c':
opt_c = true;
break;
- case 'p':
- strlcpy(swcfg.postupdatecmd, optarg,
- sizeof(swcfg.postupdatecmd));
+ case 'r':
+ strlcpy(swcfg.rebootcmd, optarg,
+ sizeof(swcfg.rebootcmd));
break;
case 'P':
strlcpy(swcfg.preupdatecmd, optarg,
@@ -82,7 +82,7 @@ static RECOVERY_STATUS download_from_url(channel_data_t* channel_data)
if (result != FAILURE) {
ipc_message msg;
msg.data.procmsg.len = 0;
- if (ipc_postupdate(&msg) != 0 || msg.type != ACK) {
+ if (ipc_reboot(&msg) != 0 || msg.type != ACK) {
result = FAILURE;
}
}
@@ -57,7 +57,7 @@ method, returning ``true``, or, in case of errors, ``nil`` plus an error message
Finally, the ``close()`` method closes the connection to SWUpdate's control
socket after which it waits for SWUpdate to complete the update transaction and
-executes the post-install command, if given.
+executes the reboot command, if given.
The following example snippet illustrates how to use the control interface binding:
@@ -27,5 +27,3 @@ DESCRIPTION
go quiet, resets verbosity
-v
go verbose, essentially print upgrade status messages from server
--p
- ask the server to run post-update commands if upgrade succeeds
@@ -53,7 +53,7 @@ Where the fields have the meaning:
- magic : a magic number as simple proof of the packet
- type : one of REQ_INSTALL, ACK, NACK,
- GET_STATUS, POST_UPDATE, SWUPDATE_SUBPROCESS, SET_AES_KEY
+ GET_STATUS, REBOOT, SWUPDATE_SUBPROCESS, SET_AES_KEY
- msgdata : a buffer used by the client to send the image
or by SWUpdate to report back notifications and status.
@@ -314,7 +314,7 @@ Restart API
POST /restart
-If configured (see post update command), this request will restart the device.
+If configured (see reboot command), this request will restart the device.
WebSocket API
@@ -26,8 +26,6 @@ after an update.
Command to be execute after an update
-p
send percentage to psplash
--r
- optionally reboot the target after a successful update
-s
path to progress IPC socket in case the default is not taken
-w
@@ -36,4 +34,3 @@ after an update.
don't print progress bar
-h
print a help
-
@@ -521,7 +521,7 @@ Command line parameters
+-------------+----------+--------------------------------------------+
| -P <cmd> | string | Execute pre-update command. |
+-------------+----------+--------------------------------------------+
-| -p <cmd> | string | Execute post-update command. |
+| -r <cmd> | string | Execute reboot command. |
+-------------+----------+--------------------------------------------+
| -q <sel> | string | List for software images set and source |
| | | that are accepted via IPC |
@@ -28,8 +28,8 @@
# preupdatecmd : string
# command to be executed right before the update
# is installed
-# postupdatecmd : string
-# command to be executed after a successful update
+# rebootcmd : string
+# command to be executed after a successful update to reboot the system
# ca-path : string
# path to the Certificate Authority (PEM)
# no-downgrading : string
@@ -258,9 +258,6 @@ suricatta :
# auth-domain : string
# path to auth-domain, if any
# default = none
-# run-postupdate : boolean (default true)
-# run the postupdate command automatically after
-# a successful update
# timeout : timeout in seconds to monitor the connection
# when an update is started. If no data is received
# during this time, connection is closed by the Webserver
@@ -19,7 +19,7 @@ swupdate_file_t check_if_required(struct imglist *list, struct filehdr *pfdh,
int install_images(struct swupdate_cfg *sw);
int install_single_image(struct img_type *img, bool dry_run);
int install_from_file(const char *filename, bool check);
-int postupdate(struct swupdate_cfg *swcfg, const char *info);
+int rebootcmd(struct swupdate_cfg *swcfg, const char *info);
int preupdatecmd(struct swupdate_cfg *swcfg);
int run_prepost_scripts(struct imglist *list, script_fn type);
void cleanup_files(struct swupdate_cfg *software);
@@ -29,7 +29,7 @@ typedef enum {
ACK,
NACK,
GET_STATUS,
- POST_UPDATE,
+ REBOOT,
SWUPDATE_SUBPROCESS,
SET_AES_KEY,
SET_UPDATE_STATE, /* set bootloader ustate */
@@ -143,7 +143,7 @@ int ipc_get_status(ipc_message *msg);
int ipc_get_status_timeout(ipc_message *msg, unsigned int timeout_ms);
int ipc_notify_connect(void);
int ipc_notify_receive(int *connfd, ipc_message *msg);
-int ipc_postupdate(ipc_message *msg);
+int ipc_reboot(ipc_message *msg);
int ipc_send_cmd(ipc_message *msg);
typedef int (*writedata)(char **buf, int *size);
@@ -52,7 +52,7 @@ struct swupdate_cfg {
char output_swversions[SWUPDATE_GENERAL_STRING_SIZE];
char publickeyfname[SWUPDATE_GENERAL_STRING_SIZE];
char aeskeyfname[SWUPDATE_GENERAL_STRING_SIZE];
- char postupdatecmd[SWUPDATE_GENERAL_STRING_SIZE];
+ char rebootcmd[SWUPDATE_GENERAL_STRING_SIZE];
char preupdatecmd[SWUPDATE_GENERAL_STRING_SIZE];
char minimum_version[SWUPDATE_GENERAL_STRING_SIZE];
char maximum_version[SWUPDATE_GENERAL_STRING_SIZE];
@@ -61,7 +61,7 @@ static int prepare_ipc(void) {
return connfd;
}
-int ipc_postupdate(ipc_message *msg) {
+int ipc_reboot(ipc_message *msg) {
int connfd = prepare_ipc();
if (connfd < 0)
return -1;
@@ -84,7 +84,7 @@ int ipc_postupdate(ipc_message *msg) {
msg->data.procmsg.len = strnlen(tmpbuf, sizeof(msg->data.procmsg.buf) - 1);
}
msg->magic = IPC_MAGIC;
- msg->type = POST_UPDATE;
+ msg->type = REBOOT;
int result = write(connfd, msg, sizeof(*msg)) != sizeof(*msg) ||
read(connfd, msg, sizeof(*msg)) != sizeof(*msg);
@@ -69,7 +69,6 @@ struct parent_connection_info {
unsigned long conn_id;
};
-static bool run_postupdate;
static unsigned int watchdog_conn = 0;
static struct mg_http_serve_opts s_http_server_opts;
const char *global_auth_domain;
@@ -352,7 +351,7 @@ static void restart_handler(struct mg_connection *nc, void *ev_data)
return;
}
- int ret = ipc_postupdate(&msg);
+ int ret = ipc_reboot(&msg);
if (ret || msg.type != ACK) {
mg_http_reply(nc, 500, "", "%s", "Failed to queue command\n");
return;
@@ -490,10 +489,10 @@ static void *broadcast_progress_thread(void *data)
broadcast(p, str);
}
- if (msg.status == SUCCESS && msg.source == SOURCE_WEBSERVER && run_postupdate) {
+ if (msg.status == SUCCESS && msg.source == SOURCE_WEBSERVER) {
ipc_message ipc = {};
- ipc_postupdate(&ipc);
+ ipc_reboot(&ipc);
}
if (msg.infolen) {
@@ -796,7 +795,6 @@ static int mongoose_settings(void *elem, void __attribute__ ((__unused__)) *dat
if (strlen(tmp)) {
opts->auth_domain = strdup(tmp);
}
- GET_FIELD_BOOL(LIBCFG_PARSER, elem, "run-postupdate", &run_postupdate);
GET_FIELD_INT(LIBCFG_PARSER, elem, "timeout", (int *)&watchdog_conn);
@@ -855,11 +853,6 @@ int start_mongoose(const char *cfgfname, int argc, char *argv[])
/* No listing directory as default */
opts.listing = false;
- /*
- * Default value is active
- */
- run_postupdate = true;
-
/*
* Default no monitor of connection
*/
@@ -215,7 +215,6 @@ static bool get_common_fields(parsertype p, void *cfg, struct swupdate_cfg *swcf
/*
* As default, reboot is initiated
*/
- swcfg->reboot_required = true;
if((setting = find_node(p, cfg, "reboot", swcfg)) != NULL) {
GET_FIELD_BOOL(p, setting, NULL, &swcfg->reboot_required);
}
@@ -1521,10 +1521,10 @@ cleanup:
ERROR("JSON object should be freed but was not.");
}
if (result == SERVER_OK) {
- INFO("Update successful, executing post-update actions.");
+ INFO("Update successful, rebooting the system.");
ipc_message msg;
memset(&msg, 0, sizeof(msg));
- if (ipc_postupdate(&msg) != 0) {
+ if (ipc_reboot(&msg) != 0) {
result = SERVER_EERR;
} else {
result = msg.type == ACK ? SERVER_OK : SERVER_EERR;
@@ -45,9 +45,9 @@ int __wrap_ipc_wait_for_complete(getstatus callback)
return mock_type(RECOVERY_STATUS);
}
-extern int __real_ipc_postupdate(ipc_message *msg);
-int __wrap_ipc_postupdate(ipc_message *msg);
-int __wrap_ipc_postupdate(ipc_message *msg) {
+extern int __real_ipc_rebootcmd(ipc_message *msg);
+int __wrap_ipc_rebootcmd(ipc_message *msg);
+int __wrap_ipc_rebootcmd(ipc_message *msg) {
msg->type = ACK;
return 0;
}
@@ -45,7 +45,6 @@ static void usage(void) {
" -s <path> : path to swupdate IPC socket\n"
" -q : go quiet, resets verbosity\n"
" -v : go verbose, essentially print upgrade status messages from server\n"
- " -p : ask the server to run post-update commands if upgrade succeeds\n"
);
}
@@ -53,7 +52,6 @@ char buf[256];
int fd = STDIN_FILENO;
int verbose = 1;
bool dry_run = false;
-bool run_postupdate = false;
int end_status = EXIT_SUCCESS;
char *software_set = NULL, *running_mode = NULL;
char *socketpath = NULL;
@@ -96,23 +94,21 @@ static int printstatus(ipc_message *msg)
/*
* this is called at the end reporting the status
- * of the upgrade and running any post-update actions
- * if successful
+ * of the upgrade and performing a reboot on success if needed
*/
static int end(RECOVERY_STATUS status)
{
end_status = (status == SUCCESS) ? EXIT_SUCCESS : EXIT_FAILURE;
- fprintf(stdout, "SWUpdate %s\n",
- status == FAILURE ? "*failed* !" :
- "was successful !");
+ if (status == FAILURE)
+ ERROR("SWUpdate *failed* !");
+ else
+ INFO("SWUpdate was successful !");
- if (status == SUCCESS && run_postupdate) {
- fprintf(stdout, "Executing post-update actions.\n");
+ if (status == SUCCESS) {
ipc_message msg;
msg.data.procmsg.len = 0;
- if (ipc_postupdate(&msg) != 0 || msg.type != ACK) {
- fprintf(stderr, "Running post-update failed!\n");
+ if (ipc_reboot(&msg) != 0 || msg.type != ACK) {
end_status = EXIT_FAILURE;
}
}
@@ -210,9 +206,6 @@ int main(int argc, char *argv[]) {
software_set = optarg;
running_mode = pos;
break;
- case 'p':
- run_postupdate = true;
- break;
case 's':
socketpath = strdup(optarg);
if(!socketpath) {
@@ -240,4 +233,3 @@ int main(int argc, char *argv[]) {
cleanup_and_exit(EXIT_SUCCESS);
}
-
@@ -18,7 +18,6 @@
#include <sys/stat.h>
#include <sys/un.h>
#include <sys/select.h>
-#include <sys/reboot.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
@@ -62,7 +61,6 @@ static void textcolor(int attr, int fg, int bg)
static struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"psplash", no_argument, NULL, 'p'},
- {"reboot", no_argument, NULL, 'r'},
{"wait", no_argument, NULL, 'w'},
{"color", no_argument, NULL, 'c'},
{"socket", required_argument, NULL, 's'},
@@ -79,7 +77,6 @@ static void usage(char *programname)
fprintf(stdout,
" -c, --color : Use colors to show results\n"
" -e, --exec <script> : call the script with the result of update\n"
- " -r, --reboot : reboot after a successful update\n"
" -w, --wait : wait for a connection with SWUpdate\n"
" -p, --psplash : send info to the psplash process\n"
" -s, --socket <path> : path to progress IPC socket\n"
@@ -189,15 +186,6 @@ static void fill_progress_bar(char *bar, size_t size, unsigned int percent)
memset(&bar[filled_len], '-', remain);
}
-static void reboot_device(void)
-{
- sleep(5);
- sync();
- if (reboot(RB_AUTOBOOT) < 0) { /* Should never happen. */
- fprintf(stdout, "Please reset the board.\n");
- }
-}
-
static void run_post_script(char *script, struct progress_msg *msg)
{
char *cmd;
@@ -227,12 +215,10 @@ int main(int argc, char **argv)
char bar[bar_len+1];
int opt_c = 0;
int opt_w = 0;
- int opt_r = 0;
int opt_p = 0;
int c;
char *script = NULL;
bool wait_update = true;
- bool disable_reboot = false;
bool redirected = false;
/* Process options with getopt */
@@ -248,9 +234,6 @@ int main(int argc, char **argv)
case 'p':
opt_p = 1;
break;
- case 'r':
- opt_r = 1;
- break;
case 's':
SOCKET_PROGRESS_PATH = strdup(optarg);
break;
@@ -339,30 +322,11 @@ int main(int argc, char **argv)
* Be sure that string in message are Null terminated
*/
if (msg.infolen > 0) {
- char reboot_mode[20] = { 0 };
- int n, cause;
-
if (msg.infolen >= sizeof(msg.info) - 1) {
msg.infolen = sizeof(msg.info) - 1;
}
msg.info[msg.infolen] = '\0';
fprintf(stdout, "INFO : %s\n", msg.info);
-
- /*
- * Check for no-reboot mode
- * Just do a simple parsing for now. If more messages
- * will be added, JSON lib should be linked.
- * NOTE: Until then, the exact string format is imperative!
- */
- n = sscanf(msg.info, "{\"%d\": { \"reboot-mode\" : \"%19[-a-z]\"}}",
- &cause, reboot_mode);
- if (n == 2) {
- if (cause == CAUSE_REBOOT_MODE) {
- if (!strcmp(reboot_mode, "no-reboot")) {
- disable_reboot = true;
- }
- }
- }
}
msg.cur_image[sizeof(msg.cur_image) - 1] = '\0';
@@ -422,22 +386,7 @@ int main(int argc, char **argv)
psplash_progress(psplash_pipe_path, &msg);
psplash_ok = 0;
}
- if (psplash_ok && disable_reboot) {
- fprintf(stdout,
- "\nReboot disabled or waiting for activation.\n");
- char *buf = alloca(PSPLASH_MSG_SIZE);
- snprintf(buf, PSPLASH_MSG_SIZE - 1,
- "MSG Reboot disabled or waiting for activation.");
- psplash_write_fifo(psplash_pipe_path, buf);
- }
- if ((msg.status == SUCCESS) && (msg.cur_step > 0) && opt_r && !disable_reboot) {
- reboot_device();
- }
- /*
- * Reset per update variables after update.
- */
- disable_reboot = false;
wait_update = true;
break;
case DONE:
@@ -457,10 +406,6 @@ int main(int argc, char **argv)
psplash_progress(psplash_pipe_path, &msg);
psplash_ok = 0;
}
- if (opt_r && strcasestr(msg.info, "firmware")) {
- reboot_device();
- break;
- }
fprintf(stdout, "\nDon't know how to activate this update, doing nothing.\n");
}
break;
This patch tries to consolidate the reboot handling of SWUpdate. Currently, there are multiple places a reboot can be configured. Some use cases cannot be implemented with the current implementation. If one wants to differentiate per update if a reboot of the target is needed, this must be done with the swupdate-progress tool (or any other mechanism listening to the IPC socket). This eliminates the possibility to restart the target via the web interface (mongoose). The web interface triggers the post-update script if one is defined. Defining the post-update eliminates the use case where an update doesn't require a reboot of the target, because the post-update command is executed in any case. The patch tries to move the reboot handling to one place. This change has only been roughly tested so far. I would like to receive some feedback if this something you could imagine to merge in the future. If I missed some use cases (or anything else) - please let me know. Signed-off-by: Daniel Braunwarth <oss@braunwarth.dev> --- bindings/lua_swupdate.c | 4 +- core/install_from_file.c | 5 +-- core/installer.c | 27 ++++++++----- core/network_thread.c | 7 ++-- core/swupdate.c | 13 ++++--- corelib/downloader.c | 2 +- doc/source/bindings.rst | 2 +- doc/source/swupdate-client.rst | 2 - doc/source/swupdate-ipc-interface.rst | 4 +- doc/source/swupdate-progress.rst | 3 -- doc/source/swupdate.rst | 2 +- examples/configuration/swupdate.cfg | 7 +--- include/installer.h | 2 +- include/network_ipc.h | 4 +- include/swupdate.h | 2 +- ipc/network_ipc.c | 4 +- mongoose/mongoose_interface.c | 13 ++----- parser/parser.c | 1 - suricatta/server_hawkbit.c | 4 +- test/test_server_hawkbit.c | 6 +-- tools/swupdate-client.c | 22 ++++------- tools/swupdate-progress.c | 55 --------------------------- 22 files changed, 60 insertions(+), 131 deletions(-)