summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt8
-rw-r--r--system.c45
-rw-r--r--upgraded.c77
-rw-r--r--watchdog.c9
-rw-r--r--watchdog.h1
5 files changed, 140 insertions, 0 deletions
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 <nbd@openwrt.org>
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ *
+ * 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 <sys/reboot.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libubox/uloop.h>
+
+#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