summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2017-09-17 22:16:50 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2017-09-17 22:16:50 +0200
commit7de1d8b70ff3e062f394dd4ab23c0bf51e1cc2c9 (patch)
tree5988df37e1cc3b83ecd7f1aa170bc60665ce72d9
parentac59669d460397b628f08dfcc7b6df6eec272091 (diff)
downloadrockbox-7de1d8b.tar.gz
rockbox-7de1d8b.zip
mknwzboot: add support for uninstallation
There is not need for a bootloader file to create an uninstall firmware so one needs to provide a model. Also cleanup the install script a bit by factoring message into a function, also print them to the log so that the user can report what was printed on the screen easily. The uninstall script is quite trivial, it remounts the rootfs and restores the backed up OF to its right place. Change-Id: I1f5c0efeb965fdc7fe17f45c2753c0f52c34f7f1
-rw-r--r--rbutil/mknwzboot/Makefile9
-rw-r--r--rbutil/mknwzboot/install_script.sh51
-rw-r--r--rbutil/mknwzboot/main.c29
-rw-r--r--rbutil/mknwzboot/mknwzboot.c60
-rw-r--r--rbutil/mknwzboot/mknwzboot.h1
-rw-r--r--rbutil/mknwzboot/uninstall_script.sh122
6 files changed, 247 insertions, 25 deletions
diff --git a/rbutil/mknwzboot/Makefile b/rbutil/mknwzboot/Makefile
index 9530ac369e..fd80106b83 100644
--- a/rbutil/mknwzboot/Makefile
+++ b/rbutil/mknwzboot/Makefile
@@ -18,7 +18,7 @@ OUTPUT = mknwzboot
# inputs for lib
UPGTOOLS_SOURCES = misc.c upg.c fwp.c mg.cpp md5.cpp
-LIBSOURCES := mknwzboot.c install_script.c \
+LIBSOURCES := mknwzboot.c install_script.c uninstall_script.c \
$(addprefix $(UPGTOOLS_DIR),$(UPGTOOLS_SOURCES))
# inputs for binary only
SOURCES := $(LIBSOURCES) main.c
@@ -30,6 +30,9 @@ include ../libtools.make
install_script.c install_script.h: install_script.sh $(BIN2C)
$(BIN2C) install_script.sh install_script
+uninstall_script.c uninstall_script.h: uninstall_script.sh $(BIN2C)
+ $(BIN2C) uninstall_script.sh uninstall_script
+
# explicit dependencies on install_script.{c,h} and mknwzboot.h
-$(OBJDIR)mknwzboot.o: install_script.h install_script.c mknwzboot.h
-$(OBJDIR)main.o: install_script.h install_script.c main.c mknwzboot.h
+$(OBJDIR)mknwzboot.o: install_script.h install_script.c uninstall_script.h uninstall_script.c mknwzboot.h
+$(OBJDIR)main.o: main.c mknwzboot.h
diff --git a/rbutil/mknwzboot/install_script.sh b/rbutil/mknwzboot/install_script.sh
index 18296d257e..76bd12c4d5 100644
--- a/rbutil/mknwzboot/install_script.sh
+++ b/rbutil/mknwzboot/install_script.sh
@@ -1,5 +1,11 @@
#!/bin/sh
+# NOTE: busybox is using ash, a very posix and very pedantic shell, make sure
+# you test your scripts with
+# busybox sh -n <script>
+# and if you really, really don't want to download busybox to try it, then go
+# ahead and brick your device
+
# The updater script on the NWZ has a major bug/feature:
# it does NOT clear the update flag if the update scrit fails
# thus causing a update/reboot loop and a bricked device
@@ -13,14 +19,24 @@ cd /tmp
CONTENTS="/contents"
CONTENTS_PART=`mount | grep contents | awk '{ print $1 }'`
-lcdmsg -c -f /usr/local/bin/font_08x12.bmp -l 0,3 "Contents partition:\n$CONTENTS_PART"
+# print a message to the screen and also on the standard output
+# lcdprint x,y msg
+lcdprint ()
+{
+ echo $2
+ lcdmsg -f /usr/local/bin/font_08x12.bmp -l $1 "$2"
+}
+
+# clear screen
+lcdmsg -c ""
+lcdprint 0,3 "Contents partition:\n$CONTENTS_PART"
# We need to remount the contents partition in read-write mode be able to
# write something on it
-lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,6 "Remount $CONTENTS rw"
+lcdprint 0,6 "Remount $CONTENTS rw"
mount -o remount,rw $CONTENTS_PART $CONTENTS
if [ "$?" != 0 ]; then
- lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: remount failed"
+ lcdprint 0,15 "ERROR: remount failed"
sleep 3
exit 0
fi
@@ -35,10 +51,10 @@ ROOTFS_TMP_DIR=/tmp/rootfs
SPIDERAPP_PATH=$ROOTFS_TMP_DIR/usr/local/bin/SpiderApp
# mount root partition
-lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,7 "Mount root filesystem"
+lcdprint 0,7 "Mount root filesystem"
mkdir $ROOTFS_TMP_DIR
if [ "$?" != 0 ]; then
- lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: mkdir failed"
+ lcdprint 0,15 "ERROR: mkdir failed"
sleep 3
exit 0
fi
@@ -58,13 +74,13 @@ if [ "$?" != 0 ]; then
mount -t ext2 $COMMON_ROOTFS_PARTITION $ROOTFS_TMP_DIR
fi
if [ "$?" != 0 ]; then
- lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: mount failed"
+ lcdprint 0,15 "ERROR: mount failed"
sleep 3
exit 0
fi
# rename the previous main application unless there is already a copy
-lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,8 "Backup OF"
+lcdprint 0,8 "Backup OF"
if [ ! -e $SPIDERAPP_PATH.of ]; then
mv $SPIDERAPP_PATH $SPIDERAPP_PATH.of
fi
@@ -75,12 +91,12 @@ fi
#
# we need a small trick here: we want to pipe directly the output of the decryption
# tool to tar, to avoid using space in /tmp/ or on the user partition
-lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,9 "Install rockbox"
+lcdprint 0,9 "Install rockbox"
FIFO_FILE=/tmp/rb.fifo
mkfifo $FIFO_FILE
if [ "$?" != 0 ]; then
umount "$ROOTFS_TMP_DIR"
- lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: cannot create fifo"
+ lcdprint 0,15 "ERROR: cannot create fifo"
sleep 3
exit 0
fi
@@ -89,7 +105,7 @@ fwpchk -f /contents/$_UPDATE_FN_.UPG -c -1 $FIFO_FILE &
tar -C $ROOTFS_TMP_DIR -xvf $FIFO_FILE
if [ "$?" != 0 ]; then
umount "$ROOTFS_TMP_DIR"
- lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: extraction failed"
+ lcdprint 0,15 "ERROR: extraction failed"
sleep 3
exit 0
fi
@@ -97,46 +113,45 @@ fi
wait
if [ "$?" != 0 ]; then
umount "$ROOTFS_TMP_DIR"
- lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: no file to extract"
+ lcdprint 0,15 "ERROR: no file to extract"
sleep 3
exit 0
fi
# create a symlink from /.rockbox to /contents/.rockbox (see dualboot code
# for why)
-lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,10 "Create rockbox symlink"
+lcdprint 0,10 "Create rockbox symlink"
rm -f "$ROOTFS_TMP_DIR/.rockbox"
ln -s "$CONTENTS/.rockbox" "$ROOTFS_TMP_DIR/.rockbox"
if [ "$?" != 0 ]; then
umount "$ROOTFS_TMP_DIR"
- lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: cannot create rockbox symlink"
+ lcdprint 0,15 "ERROR: cannot create rockbox symlink"
sleep 3
exit 0
fi
# unmount root partition
-lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,11 "Unmount root filesystem"
+lcdprint 0,11 "Unmount root filesystem"
sync
if [ "$?" != 0 ]; then
umount "$ROOTFS_TMP_DIR"
- lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: sync failed"
+ lcdprint 0,15 "ERROR: sync failed"
sleep 3
exit 0
fi
umount $ROOTFS_TMP_DIR
if [ "$?" != 0 ]; then
- lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: umount failed"
+ lcdprint 0,15 "ERROR: umount failed"
sleep 3
exit 0
fi
# Success screen
-lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "Rebooting in 3 seconds."
+lcdprint 0,15 "Rebooting in 3 seconds."
sleep 3
sync
echo "Installation successful"
# finish
exit 0
-
diff --git a/rbutil/mknwzboot/main.c b/rbutil/mknwzboot/main.c
index a36c24eaf5..491a18043b 100644
--- a/rbutil/mknwzboot/main.c
+++ b/rbutil/mknwzboot/main.c
@@ -34,6 +34,8 @@ static void usage(void)
printf(" -b <file> Set boot file\n");
printf(" -d/--debug Enable debug output\n");
printf(" -x Dump device informations\n");
+ printf(" -u Create uninstall update\n");
+ printf(" -m <model> Specify model\n");
exit(1);
}
@@ -42,6 +44,8 @@ int main(int argc, char *argv[])
char *outfile = NULL;
char *bootfile = NULL;
bool debug = false;
+ bool install = true;
+ const char *model = NULL;
if(argc == 1)
usage();
@@ -55,10 +59,12 @@ int main(int argc, char *argv[])
{"boot-file", required_argument, 0, 'b'},
{"debug", no_argument, 0, 'd'},
{"dev-info", no_argument, 0, 'x'},
+ {"uninstall", no_argument, 0, 'u'},
+ {"model", required_argument, 0, 'm'},
{0, 0, 0, 0}
};
- int c = getopt_long(argc, argv, "ho:b:dx", long_options, NULL);
+ int c = getopt_long(argc, argv, "ho:b:dxum:", long_options, NULL);
if(c == -1)
break;
switch(c)
@@ -77,6 +83,12 @@ int main(int argc, char *argv[])
break;
case 'x':
dump_nwz_dev_info("");
+ return 0;
+ case 'u':
+ install = false;
+ break;
+ case 'm':
+ model = optarg;
break;
default:
abort();
@@ -88,9 +100,14 @@ int main(int argc, char *argv[])
printf("You must specify an output file\n");
return 1;
}
- if(!bootfile)
+ if(install && !bootfile)
+ {
+ printf("You must specify a boot file for installation\n");
+ return 1;
+ }
+ if(!install && !model)
{
- printf("You must specify a boot file\n");
+ printf("You must provide a model for uninstallation\n");
return 1;
}
if(optind != argc)
@@ -99,7 +116,11 @@ int main(int argc, char *argv[])
return 1;
}
- int err = mknwzboot(bootfile, outfile, debug);
+ int err;
+ if(install)
+ err = mknwzboot(bootfile, outfile, debug);
+ else
+ err = mknwzboot_uninst(model, outfile, debug);
printf("Result: %d\n", err);
return err;
}
diff --git a/rbutil/mknwzboot/mknwzboot.c b/rbutil/mknwzboot/mknwzboot.c
index b41692c9fd..2e574a94d7 100644
--- a/rbutil/mknwzboot/mknwzboot.c
+++ b/rbutil/mknwzboot/mknwzboot.c
@@ -27,6 +27,7 @@
#include "upg.h"
#include "install_script.h"
+#include "uninstall_script.h"
struct nwz_model_desc_t
{
@@ -145,6 +146,24 @@ static int find_model(uint8_t *boot, size_t boot_size)
return model;
}
+static int find_model2(const char *model_str)
+{
+ /* since it can be confusing for the user, we accept both rbmodel and codename */
+ /* find model by comparing magic scramble value */
+ int model = 0;
+ for(; model < NR_NWZ_MODELS; model++)
+ if(strcmp(nwz_models[model].rb_model_name, model_str) == 0 ||
+ strcmp(nwz_models[model].codename, model_str) == 0)
+ break;
+ if(model == NR_NWZ_MODELS)
+ {
+ printf("[ERR] Unknown model: %s\n", model_str);
+ return -1;
+ }
+ printf("[INFO] Bootloader file for %s\n", nwz_models[model].model_name);
+ return model;
+}
+
static bool get_model_keysig(int model, char key[NWZ_KEY_SIZE], char sig[NWZ_SIG_SIZE])
{
const char *codename = nwz_models[model].codename;
@@ -231,3 +250,44 @@ int mknwzboot(const char *bootfile, const char *outfile, bool debug)
free(upg_buf);
return 0;
}
+
+int mknwzboot_uninst(const char *model_string, const char *outfile, bool debug)
+{
+ /* check that it is a valid scrambled file */
+ int model = find_model2(model_string);
+ if(model < 0)
+ {
+ printf("[ERR] Invalid model\n");
+ return 2;
+ }
+ /* find keys */
+ char key[NWZ_KEY_SIZE];
+ char sig[NWZ_SIG_SIZE];
+ if(!get_model_keysig(model, key, sig))
+ {
+ printf("[ERR][INTERNAL] Cannot get keys for model\n");
+ return 3;
+ }
+ /* create the upg file */
+ struct upg_file_t *upg = upg_new();
+ /* first file is the uninstall script: we have to copy data because upg_free()
+ * will free it */
+ upg_append(upg, memdup(uninstall_script, LEN_uninstall_script), LEN_uninstall_script);
+ /* write file to buffer */
+ size_t upg_size;
+ void *upg_buf = upg_write_memory(upg, key, sig, &upg_size, &debug, nwz_printf);
+ upg_free(upg);
+ if(upg_buf == NULL)
+ {
+ printf("[ERR] Cannot create UPG file\n");
+ return 4;
+ }
+ if(!write_file(outfile, upg_buf, upg_size))
+ {
+ free(upg_buf);
+ printf("[ERR] Cannpt write UPG file\n");
+ return 5;
+ }
+ free(upg_buf);
+ return 0;
+}
diff --git a/rbutil/mknwzboot/mknwzboot.h b/rbutil/mknwzboot/mknwzboot.h
index f46dd75d5c..31f2c6355e 100644
--- a/rbutil/mknwzboot/mknwzboot.h
+++ b/rbutil/mknwzboot/mknwzboot.h
@@ -33,6 +33,7 @@ extern "C" {
void dump_nwz_dev_info(const char *prefix);
/* return 0 on success */
int mknwzboot(const char *bootfile, const char *outfile, bool debug);
+int mknwzboot_uninst(const char *model, const char *outfile, bool debug);
#ifdef __cplusplus
}
diff --git a/rbutil/mknwzboot/uninstall_script.sh b/rbutil/mknwzboot/uninstall_script.sh
new file mode 100644
index 0000000000..0e409c63cd
--- /dev/null
+++ b/rbutil/mknwzboot/uninstall_script.sh
@@ -0,0 +1,122 @@
+#!/bin/sh
+
+# NOTE: busybox is using ash, a very posix and very pedantic shell, make sure
+# you test your scripts with
+# busybox sh -n <script>
+# and if you really, really don't want to download busybox to try it, then go
+# ahead and brick your device
+
+# The updater script on the NWZ has a major bug/feature:
+# it does NOT clear the update flag if the update scrit fails
+# thus causing a update/reboot loop and a bricked device
+# always clear to make sure we don't end up being screwed
+nvpflag fup 0xFFFFFFFF
+
+# go to /tmp
+cd /tmp
+
+# get content partition path
+CONTENTS="/contents"
+CONTENTS_PART=`mount | grep contents | awk '{ print $1 }'`
+
+# print a message to the screen and also on the standard output
+# lcdprint x,y msg
+lcdprint ()
+{
+ echo $2
+ lcdmsg -f /usr/local/bin/font_08x12.bmp -l $1 "$2"
+}
+
+# clear screen
+lcdmsg -c ""
+lcdprint 0,3 "Contents partition:\n$CONTENTS_PART"
+
+# We need to remount the contents partition in read-write mode be able to
+# write something on it
+lcdprint 0,6 "Remount $CONTENTS rw"
+mount -o remount,rw $CONTENTS_PART $CONTENTS
+if [ "$?" != 0 ]; then
+ lcdprint 0,15 "ERROR: remount failed"
+ sleep 3
+ exit 0
+fi
+
+# redirect all output to a log file
+exec > "$CONTENTS/uninstall_dualboot_log.txt" 2>&1
+
+# import constants
+. /install_script/constant.txt
+ROOTFS_TMP_DIR=/tmp/rootfs
+SPIDERAPP_PATH=$ROOTFS_TMP_DIR/usr/local/bin/SpiderApp
+
+# mount root partition
+lcdprint 0,7 "Mount root filesystem"
+mkdir $ROOTFS_TMP_DIR
+if [ "$?" != 0 ]; then
+ lcdprint 0,15 "ERROR: mkdir failed"
+ sleep 3
+ exit 0
+fi
+
+# If there is an ext4 mounter, try it. Otherwise or on failure, try ext3 and
+# then ext2.
+# NOTE some platforms probably use an mtd and this might need some fixing
+if [ -e /usr/local/bin/icx_mount.ext4 ]; then
+ /usr/local/bin/icx_mount.ext4 $COMMON_ROOTFS_PARTITION $ROOTFS_TMP_DIR
+else
+ false
+fi
+if [ "$?" != 0 ]; then
+ mount -t ext3 $COMMON_ROOTFS_PARTITION $ROOTFS_TMP_DIR
+fi
+if [ "$?" != 0 ]; then
+ mount -t ext2 $COMMON_ROOTFS_PARTITION $ROOTFS_TMP_DIR
+fi
+if [ "$?" != 0 ]; then
+ lcdprint 0,15 "ERROR: mount failed"
+ sleep 3
+ exit 0
+fi
+
+# the installer renames the OF to $SPIDERAPP_PATH.of so if it does not exists
+# print an error
+lcdprint 0,8 "Restore OF"
+if [ ! -e $SPIDERAPP_PATH.of ]; then
+ lcdprint 0,15 "ERROR: cannot find OF"
+ lcdprint 0,16 "ERROR: is Rockbox installed?"
+ sleep 3
+ exit 0
+fi
+# restore the OF
+mv $SPIDERAPP_PATH.of $SPIDERAPP_PATH
+if [ "$?" != 0 ]; then
+ lcdprint 0,15 "ERROR: restore failed"
+ sleep 3
+ exit 0
+fi
+
+# unmount root partition
+lcdprint 0,11 "Unmount root filesystem"
+sync
+if [ "$?" != 0 ]; then
+ umount "$ROOTFS_TMP_DIR"
+ lcdprint 0,15 "ERROR: sync failed"
+ sleep 3
+ exit 0
+fi
+
+umount $ROOTFS_TMP_DIR
+if [ "$?" != 0 ]; then
+ lcdprint 0,15 "ERROR: umount failed"
+ sleep 3
+ exit 0
+fi
+
+# Success screen
+lcdprint 0,15 "Rebooting in 3 seconds."
+sleep 3
+sync
+
+echo "Uninstallation successful"
+# finish
+exit 0