add upgraded support for nand flashing
authorJohn Crispin <blogic@openwrt.org>
Tue, 10 Jun 2014 15:50:15 +0000 (16:50 +0100)
committerJohn Crispin <blogic@openwrt.org>
Tue, 10 Jun 2014 22:06:12 +0000 (23:06 +0100)
Signed-off-by: John Crispin <blogic@openwrt.org>
CMakeLists.txt
system.c
upgraded.c [new file with mode: 0644]
watchdog.c
watchdog.h

index 4c899479a6ed37d9522a7e713ce8adfc9ed99538..2b72ad36af17e5e3577da4d44e83ec456e0cd113 100644 (file)
@@ -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
index d5bf0003f2fdc9c39e6c489f76e56531de070380..2110035fee6f5b8744dfa7c866e1f6390a666904 100644 (file)
--- 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 (file)
index 0000000..345a30a
--- /dev/null
@@ -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;
+}
index de9556c482d84933abf8bfd067d652a52be003c0..399f6af7f1a9cff0be7d91dcdcb9e1d63e1b4ea7 100644 (file)
@@ -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);
+}
index cebbc33088d762839837fdad84a3e9e4adea4c41..a774dd734d0a6e92855993471ae01d07c83766cb 100644 (file)
@@ -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