From 13259259bc53657617844660f2664f4b4fb4ac02 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 10 Jun 2014 16:50:15 +0100 Subject: add upgraded support for nand flashing Signed-off-by: John Crispin --- CMakeLists.txt | 8 ++++++ system.c | 45 ++++++++++++++++++++++++++++++++++ upgraded.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ watchdog.c | 9 +++++++ watchdog.h | 1 + 5 files changed, 140 insertions(+) create mode 100644 upgraded.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c89947..2b72ad3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,14 @@ INSTALL(TARGETS udevtrigger ) +ADD_EXECUTABLE(upgraded upgraded.c watchdog.c) +TARGET_LINK_LIBRARIES(upgraded ubox.a rt.a -static) +set_target_properties(upgraded PROPERTIES LINK_SEARCH_END_STATIC 1) +INSTALL(TARGETS upgraded + RUNTIME DESTINATION sbin +) + + ADD_EXECUTABLE(askfirst utils/askfirst.c) INSTALL(TARGETS askfirst RUNTIME DESTINATION sbin diff --git a/system.c b/system.c index d5bf000..2110035 100644 --- a/system.c +++ b/system.c @@ -286,18 +286,63 @@ static int proc_signal(struct ubus_context *ctx, struct ubus_object *obj, return 0; } +enum { + NAND_FOLDER, + __NAND_MAX +}; + +static const struct blobmsg_policy nand_policy[__NAND_MAX] = { + [NAND_FOLDER] = { .name = "folder", .type = BLOBMSG_TYPE_STRING }, +}; + +static void +procd_spawn_upgraded(char *folder) +{ + char *wdt_fd = watchdog_fd(); + char *argv[] = { "/tmp/upgraded", NULL, NULL}; + + argv[1] = folder; + + DEBUG(2, "Exec to upgraded now\n"); + if (wdt_fd) { + watchdog_no_cloexec(); + setenv("WDTFD", wdt_fd, 1); + } + execvp(argv[0], argv); +} + +static int nand_set(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct blob_attr *tb[__NAND_MAX]; + + if (!msg) + return UBUS_STATUS_INVALID_ARGUMENT; + + blobmsg_parse(nand_policy, __NAND_MAX, tb, blob_data(msg), blob_len(msg)); + if (!tb[NAND_FOLDER]) + return UBUS_STATUS_INVALID_ARGUMENT; + + procd_spawn_upgraded(blobmsg_get_string(tb[NAND_FOLDER])); + fprintf(stderr, "Yikees, something went wrong. no /sbin/upgraded ?\n"); + return 0; +} + static void procd_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj) { notify = obj->has_subscribers; } + static const struct ubus_method system_methods[] = { UBUS_METHOD_NOARG("board", system_board), UBUS_METHOD_NOARG("info", system_info), UBUS_METHOD_NOARG("upgrade", system_upgrade), UBUS_METHOD("watchdog", watchdog_set, watchdog_policy), UBUS_METHOD("signal", proc_signal, signal_policy), + UBUS_METHOD("nandupgrade", nand_set, nand_policy), }; static struct ubus_object_type system_object_type = diff --git a/upgraded.c b/upgraded.c new file mode 100644 index 0000000..345a30a --- /dev/null +++ b/upgraded.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2013 Felix Fietkau + * Copyright (C) 2013 John Crispin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +#include +#include +#include +#include + +#include + +#include "watchdog.h" + +static struct uloop_process upgrade_proc; +unsigned int debug = 2; + +static void upgrade_proc_cb(struct uloop_process *proc, int ret) +{ + if (ret) + fprintf(stderr, "sysupgrade aborted with return code: %d\n", ret); + uloop_end(); +} + +static void sysupgarde(char *folder) +{ + char *args[] = { "/sbin/sysupgrade", "nand", NULL, NULL }; + + args[2] = folder; + upgrade_proc.cb = upgrade_proc_cb; + upgrade_proc.pid = fork(); + if (!upgrade_proc.pid) { + execvp(args[0], args); + fprintf(stderr, "Failed to fork sysupgrade\n"); + exit(-1); + } + if (upgrade_proc.pid <= 0) { + fprintf(stderr, "Failed to start sysupgarde\n"); + uloop_end(); + } +} + +int main(int argc, char **argv) +{ + pid_t p = getpid(); + + chdir("/tmp"); + + if (p != 1) { + fprintf(stderr, "this tool needs to run as pid 1\n"); + return -1; + } + if (argc != 2) { + fprintf(stderr, "sysupgrade stage 2 failed, no folder specified\n"); + return -1; + } + + uloop_init(); + watchdog_init(0); + sysupgarde(argv[1]); + uloop_run(); + + reboot(RB_AUTOBOOT); + + return 0; +} diff --git a/watchdog.c b/watchdog.c index de9556c..399f6af 100644 --- a/watchdog.c +++ b/watchdog.c @@ -119,3 +119,12 @@ void watchdog_init(int preinit) DEBUG(4, "Opened watchdog with timeout %ds\n", watchdog_timeout(0)); } + + +void watchdog_no_cloexec(void) +{ + if (wdt_fd < 0) + return; + + fcntl(wdt_fd, F_SETFD, fcntl(wdt_fd, F_GETFD) & ~FD_CLOEXEC); +} diff --git a/watchdog.h b/watchdog.h index cebbc33..a774dd7 100644 --- a/watchdog.h +++ b/watchdog.h @@ -21,5 +21,6 @@ int watchdog_timeout(int timeout); int watchdog_frequency(int frequency); void watchdog_set_stopped(bool val); bool watchdog_get_stopped(void); +void watchdog_no_cloexec(void); #endif -- cgit v1.2.3