From d492f25c54b4134fd6632156efee07670ab4004f Mon Sep 17 00:00:00 2001 From: Amaury Pouly Date: Tue, 1 Nov 2016 17:04:26 +0100 Subject: nwztools: add preliminary dualboot and dualboot install script At the moment, the script install_duaboot does the following: - rename SpiderApp to SpiderApp.of (unless it already exists) - install payload as SpiderApp - fixes permissions Since SpiderApp is the main app, it will execute instead of the OF. The current dualboot code (dualboot.c) is still a preliminary but the current version displays an "all tools" menu to choose for. When exitting the menu using BACK, it will run the OF. With the modifications made by the install script, it should not be possible to break the device. In the worst case scenario, the dualboot code crashes and it restarted by the sysmgrd, or hangs. A safe way to recover is to plug the USB cable and reset the device: the system manager will then start the USB app and one can reflash the device if necessary. Change-Id: Id9edab0347538ad2a8651a28aea7fd083feaa626 --- utils/nwztools/plattools/Makefile | 5 +- utils/nwztools/plattools/dualboot.c | 181 ++++++++++++++++++++++++++++++++++++ utils/nwztools/plattools/nwz_lib.c | 39 +++++++- utils/nwztools/plattools/nwz_lib.h | 5 +- 4 files changed, 227 insertions(+), 3 deletions(-) create mode 100644 utils/nwztools/plattools/dualboot.c (limited to 'utils/nwztools/plattools') diff --git a/utils/nwztools/plattools/Makefile b/utils/nwztools/plattools/Makefile index 8251afaf0a..f4e88cd778 100644 --- a/utils/nwztools/plattools/Makefile +++ b/utils/nwztools/plattools/Makefile @@ -7,7 +7,7 @@ INCLUDES=-I. LIB_FILES=nwz_lib.c nwz_lib_devlist.c TOOL_FILES=dest_tool.c test_adc.c test_adc.c test_bl.c test_display.c \ test_keys.c test_power.c test_ts.c -ALL_ELF=$(patsubst %.c,%.elf,$(TOOL_FILES)) all_tools.elf +ALL_ELF=$(patsubst %.c,%.elf,$(TOOL_FILES)) all_tools.elf dualboot.elf all: $(ALL_ELF) @@ -17,5 +17,8 @@ all: $(ALL_ELF) all_tools.elf: all_tools.c $(TOOL_FILES) $(LIB_FILES) $(CC) $(CFLAGS) -DNWZ_EMBED_TOOLS $(INCLUDES) -o $@ $^ +dualboot.elf: dualboot.c all_tools.c $(TOOL_FILES) $(LIB_FILES) + $(CC) $(CFLAGS) -DNWZ_DUALBOOT -DNWZ_EMBED_TOOLS $(INCLUDES) -o $@ $^ + clean: rm -rf $(ALL_ELF) diff --git a/utils/nwztools/plattools/dualboot.c b/utils/nwztools/plattools/dualboot.c new file mode 100644 index 0000000000..965fabed72 --- /dev/null +++ b/utils/nwztools/plattools/dualboot.c @@ -0,0 +1,181 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2011 by Amaury Pouly + * + * Based on Rockbox iriver bootloader by Linus Nielsen Feltzing + * and the ipodlinux bootloader by Daniel Palffy and Bernard Leach + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "nwz_lib.h" +#include "nwz_plattools.h" +#include + +/* Important Note: this bootloader is carefully written so that in case of + * error, the OF is run. This seems like the safest option since the OF is + * always there and might do magic things. */ + +bool boot_rockbox(void) +{ + /* get time */ + struct timeval deadline; + if(gettimeofday(&deadline, NULL) != 0) + { + nwz_lcdmsg(false, 0, 2, "Cannot get time"); + sleep(2); + return false; + } + /* open input device */ + int input_fd = nwz_key_open(); + if(input_fd < 0) + { + nwz_lcdmsg(false, 0, 2, "Cannot open input device"); + sleep(2); + return false; + } + deadline.tv_sec += 5; + /* wait for user action */ + bool boot_rb = false; + while(true) + { + /* get time */ + struct timeval cur_time; + if(gettimeofday(&cur_time, NULL) != 0) + { + nwz_lcdmsg(false, 0, 4, "Cannot get time"); + sleep(2); + break; + } + /* check timeout */ + if(cur_time.tv_sec > deadline.tv_sec) + break; + if(cur_time.tv_sec == deadline.tv_sec && cur_time.tv_usec >= deadline.tv_usec) + break; + /* print message */ + int sec_left = deadline.tv_sec - cur_time.tv_sec; + sec_left += (deadline.tv_usec - cur_time.tv_usec + 999999) / 1000000; /* round up */ + nwz_lcdmsgf(false, 0, 2, "Booting OF in %d seconds ", sec_left); + nwz_lcdmsg(false, 0, 3, "Press BACK to boot RB"); + /* wait for a key (1s) */ + int ret = nwz_key_wait_event(input_fd, 1000000); + if(ret != 1) + continue; + struct input_event evt; + if(nwz_key_read_event(input_fd, &evt) != 1) + continue; + if(nwz_key_event_get_keycode(&evt) == NWZ_KEY_BACK && !nwz_key_event_is_press(&evt)) + { + boot_rb = true; + break; + } + } + nwz_key_close(input_fd); + return boot_rb; +} + +static char *boot_rb_argv[] = +{ + "lcdmsg", + "-c", + "-l", + "0,3", + "Hello from RB", + NULL +}; + +static void wait_key(void) +{ + int input_fd = nwz_key_open(); + /* display input state in a loop */ + while(1) + { + /* wait for event (10ms) */ + int ret = nwz_key_wait_event(input_fd, 10000); + if(ret != 1) + continue; + struct input_event evt; + if(nwz_key_read_event(input_fd, &evt) != 1) + continue; + if(nwz_key_event_get_keycode(&evt) == NWZ_KEY_BACK && !nwz_key_event_is_press(&evt)) + break; + } + /* finish nicely */ + nwz_key_close(input_fd); +} + +int NWZ_TOOL_MAIN(all_tools)(int argc, char **argv); + +int main(int argc, char **argv) +{ +#if 0 + nwz_lcdmsg(true, 0, 0, "dualboot"); + if(boot_rockbox()) + { + /* boot rockox */ + nwz_lcdmsg(true, 0, 3, "Booting rockbox..."); + execvp("/usr/local/bin/lcdmsg", boot_rb_argv); + nwz_lcdmsg(false, 0, 4, "failed."); + sleep(5); + } + /* if for some reason, running rockbox failed, then try to run the OF */ + /* boot OF */ + nwz_lcdmsg(true, 0, 3, "Booting OF..."); + execvp("/usr/local/bin/SpiderApp.of", argv); + nwz_lcdmsg(false, 0, 4, "failed."); + sleep(5); + /* if we reach this point, everything failed, so return an error so that + * sysmgrd knows something is wrong */ + return 1; +#elif 0 + const char *args_mount[] = {"mount", NULL}; + int status; + char *output = nwz_run_pipe("mount", args_mount, &status); + nwz_lcdmsgf(true, 0, 0, "%d\n%s", status, output); + free(output); + wait_key(); + const char *args_ls[] = {"ls", "/var", NULL}; + output = nwz_run_pipe("ls", args_ls, &status); + nwz_lcdmsgf(true, 0, 0, "%d\n%s", status, output); + free(output); + wait_key(); + const char *args_glogctl[] = {"glogctl", "flush", NULL}; + output = nwz_run_pipe("/usr/local/bin/glogctl", args_glogctl, &status); + nwz_lcdmsgf(true, 0, 0, "%d\n%s", status, output); + free(output); + wait_key(); + system("cp /var/GEMINILOG* /contents/"); + sync(); + execvp("/usr/local/bin/SpiderApp.of", argv); + return 0; +#else + /* make sure backlight is on */ + int fb_fd = nwz_fb_open(true); + if(fb_fd >= 0) + { + struct nwz_fb_brightness bl; + nwz_fb_get_brightness(fb_fd, &bl); + bl.level = NWZ_FB_BL_MAX_LEVEL; + nwz_fb_set_brightness(fb_fd, &bl); + nwz_fb_close(fb_fd); + } + /* run all tools menu */ + NWZ_TOOL_MAIN(all_tools)(argc, argv); + /* run OF */ + execvp("/usr/local/bin/SpiderApp.of", argv); + return 0; +#endif +} diff --git a/utils/nwztools/plattools/nwz_lib.c b/utils/nwztools/plattools/nwz_lib.c index 4f49bec909..087db8834a 100644 --- a/utils/nwztools/plattools/nwz_lib.c +++ b/utils/nwztools/plattools/nwz_lib.c @@ -30,7 +30,7 @@ const char *nwz_get_model_name(unsigned long model_id) return NULL; } -void nwz_run(const char *file, const char *args[], bool wait) +int nwz_run(const char *file, const char *args[], bool wait) { pid_t child_pid = fork(); if(child_pid != 0) @@ -39,7 +39,10 @@ void nwz_run(const char *file, const char *args[], bool wait) { int status; waitpid(child_pid, &status, 0); + return status; } + else + return 0; } else { @@ -48,6 +51,40 @@ void nwz_run(const char *file, const char *args[], bool wait) } } +char *nwz_run_pipe(const char *file, const char *args[], int *status) +{ + int pipe_fds[2]; + pipe(pipe_fds); + pid_t child_pid = fork(); + if(child_pid == 0) + { + dup2(pipe_fds[1], 1); /* redirect stdout */ + dup2(pipe_fds[1], 2); /* redirect stderr */ + close(pipe_fds[0]); /* close reading */ + close(pipe_fds[1]); /* close writing */ + execvp(file, (char * const *)args); + _exit(1); + } + else + { + close(pipe_fds[1]); /* close writing */ + char buffer[1024]; + char *output = malloc(1); + ssize_t count; + size_t size = 0; + while((count = read(pipe_fds[0], buffer, sizeof(buffer))) > 0) + { + output = realloc(output, size + count + 1); + memcpy(output + size, buffer, count); + size += count; + } + close(pipe_fds[0]); + output[size] = 0; + waitpid(child_pid, status, 0); + return output; + } +} + void nwz_lcdmsg(bool clear, int x, int y, const char *msg) { const char *path_lcdmsg = "/usr/local/bin/lcdmsg"; diff --git a/utils/nwztools/plattools/nwz_lib.h b/utils/nwztools/plattools/nwz_lib.h index 90d122003a..df0105a13d 100644 --- a/utils/nwztools/plattools/nwz_lib.h +++ b/utils/nwztools/plattools/nwz_lib.h @@ -30,6 +30,7 @@ #include #include #include +#include #include "nwz_keys.h" #include "nwz_fb.h" @@ -47,7 +48,9 @@ const char *nwz_get_model_name(unsigned long model_id); /* run a program and exit with nonzero status in case of error * argument list must be NULL terminated */ -void nwz_run(const char *file, const char *args[], bool wait); +int nwz_run(const char *file, const char *args[], bool wait); +/* run a program and return program output */ +char *nwz_run_pipe(const char *file, const char *args[], int *status); /* invoke /usr/bin/lcdmsg to display a message using the small font, optionally * clearing the screen before */ -- cgit v1.2.3