diff --git a/utils/nwztools/plattools/data/Makefile b/utils/nwztools/plattools/data/Makefile
new file mode 100644
index 0000000000..86f3bb339c
--- /dev/null
+++ b/utils/nwztools/plattools/data/Makefile
@@ -0,0 +1,8 @@
+TOOLS_DIR=../../../../tools/
+all: rockbox_icon.h tools_icon.h
+
+%.h: %.bmp
+ $(TOOLS_DIR)/bmp2rb -f 4 $^ > $@
+
+clean:
+ rm -rf *.h
diff --git a/utils/nwztools/plattools/data/Oxygen480-categories-preferences-system.svg b/utils/nwztools/plattools/data/Oxygen480-categories-preferences-system.svg
new file mode 100644
index 0000000000..0835251992
--- /dev/null
+++ b/utils/nwztools/plattools/data/Oxygen480-categories-preferences-system.svg
@@ -0,0 +1,334 @@
+
+
+
\ No newline at end of file
diff --git a/utils/nwztools/plattools/data/make_images.sh b/utils/nwztools/plattools/data/make_images.sh
new file mode 100755
index 0000000000..7ac21dc17a
--- /dev/null
+++ b/utils/nwztools/plattools/data/make_images.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+#
+# This script contains the code used to produce all the images.
+# Because of the variety of tools needed to achieve that, the result is also
+# included in the repository but this makes it easier to modify the data
+# to add more content
+#
+
+# path to root of repository
+ROOT_DIR=../../../../
+
+# final resolution
+NWZ_WIDTH=130
+NWZ_HEIGHT=130
+
+# path to rockbox icon
+RB_ICON_PATH=$ROOT_DIR/docs/logo/rockbox-icon.svg
+# path to tools icon (currently stolen from KDE Oxygen icon set)
+TOOL_ICON_PATH=Oxygen480-categories-preferences-system.svg
+
+# convert_svg width height input output
+function convert_svg
+{
+ local width="$1"
+ local height="$2"
+ local input="$3"
+ local output="$4"
+ TMP=tmp.png
+ # convert from SVG to PNG
+ inkscape -z -e $TMP -w $width -h $height $input
+ if [ "$?" != 0 ]; then
+ echo "SVG -> PNG conversion failed"
+ exit 1
+ fi
+ # convert from PNG to BMP, force using "version 3" because the OF don't like
+ # "recent" BMP
+ convert -channel RGB $TMP -define bmp:format=bmp3 ${output}_icon.bmp
+ if [ "$?" != 0 ]; then
+ rm -f $TMP
+ echo "PNG -> BMP conversion failed"
+ exit 1
+ fi
+ # remove temporary
+ rm -f $TMP
+}
+
+# start by creating the bitmap files from rockbox-icon.svg for all resolutions
+# we make a detour by svg because inkscape can only export to SVG
+# NOTE: we use image magick to convert to bmp but the OF tools don't like BMPv5
+# and contrary to what the documentation says, image magick tends to produce
+# those by default unless asked otherwise
+convert_svg $NWZ_WIDTH $NWZ_HEIGHT $RB_ICON_PATH rockbox
+convert_svg $NWZ_WIDTH $NWZ_HEIGHT $TOOL_ICON_PATH tools
diff --git a/utils/nwztools/plattools/data/rockbox_icon.bmp b/utils/nwztools/plattools/data/rockbox_icon.bmp
new file mode 100644
index 0000000000..69e6792e7b
Binary files /dev/null and b/utils/nwztools/plattools/data/rockbox_icon.bmp differ
diff --git a/utils/nwztools/plattools/data/tools_icon.bmp b/utils/nwztools/plattools/data/tools_icon.bmp
new file mode 100644
index 0000000000..f9fccf0306
Binary files /dev/null and b/utils/nwztools/plattools/data/tools_icon.bmp differ
diff --git a/utils/nwztools/plattools/dualboot.c b/utils/nwztools/plattools/dualboot.c
index a5d04fa4ed..c6d07c7508 100644
--- a/utils/nwztools/plattools/dualboot.c
+++ b/utils/nwztools/plattools/dualboot.c
@@ -24,6 +24,64 @@
#include "nwz_lib.h"
#include "nwz_plattools.h"
#include
+#include
+
+/* all images must have the following size */
+#define ICON_WIDTH 130
+#define ICON_HEIGHT 130
+
+/* images */
+#include "data/rockbox_icon.h"
+#if BMPWIDTH_rockbox_icon != ICON_WIDTH || BMPHEIGHT_rockbox_icon != ICON_HEIGHT
+#error rockbox_icon has the wrong resolution
+#endif
+#include "data/tools_icon.h"
+#if BMPWIDTH_tools_icon != ICON_WIDTH || BMPHEIGHT_tools_icon != ICON_HEIGHT
+#error tools_icon has the wrong resolution
+#endif
+/* buffer for Sony image, filled from NVP */
+unsigned short sony_icon[ICON_WIDTH * ICON_HEIGHT];
+/* resolution */
+static int width, height, bpp;
+
+/* return icon y position (x is always centered) */
+int get_icon_y(void)
+{
+ /* adjust so that this contains the Sony logo and produces a nice logo
+ * when used with rockbox */
+ if(height == 320)
+ return 70;
+ else if(height == 320)
+ return 100;
+ else
+ return height / 2 - ICON_HEIGHT + 30; /* guess, probably won't work */
+}
+
+/* Sony logo extraction */
+bool extract_sony_logo(void)
+{
+ /* only support bpp of 16 */
+ if(bpp != 16)
+ return false;
+ /* load the entire image from the nvp */
+ int bti_size = nwz_nvp_read(NWZ_NVP_BTI, NULL);
+ if(bti_size < 0)
+ return false;
+ unsigned short *bti = malloc(bti_size);
+ if(nwz_nvp_read(NWZ_NVP_BTI, bti) != bti_size)
+ return false;
+ /* compute the offset in the image of the logo itself */
+ int x_off = (width - ICON_WIDTH) / 2; /* logo is centered horizontally */
+ int y_off = get_icon_y();
+ /* extract part of the image */
+ for(int y = 0; y < ICON_HEIGHT; y++)
+ {
+ memcpy(sony_icon + ICON_WIDTH * y,
+ bti + width * (y + y_off) + x_off, ICON_WIDTH * sizeof(unsigned short));
+ }
+ free(bti);
+ return true;
+}
/* 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
@@ -36,13 +94,28 @@ enum boot_mode
BOOT_OF
};
+void draw_icon(int left, int top, const unsigned short *icon, unsigned short *fb_mmap)
+{
+ for(int y = 0; y < ICON_HEIGHT; y++)
+ {
+ memcpy(fb_mmap + width * (y + top) + left, icon + ICON_WIDTH * y,
+ ICON_WIDTH * sizeof(unsigned short));
+ }
+}
+
enum boot_mode get_boot_mode(void)
{
- /* get time */
- struct timeval deadline;
- if(gettimeofday(&deadline, NULL) != 0)
+ if(bpp != 16)
{
- nwz_lcdmsg(false, 0, 2, "Cannot get time");
+ nwz_lcdmsg(true, 0, 2, "Unsupported bpp");
+ sleep(2);
+ return BOOT_OF;
+ }
+ /* open framebuffer */
+ int fb_fd = nwz_fb_open(true);
+ if(fb_fd < 0)
+ {
+ nwz_lcdmsg(true, 0, 2, "Cannot open input device");
sleep(2);
return BOOT_OF;
}
@@ -50,70 +123,131 @@ enum boot_mode get_boot_mode(void)
int input_fd = nwz_key_open();
if(input_fd < 0)
{
- nwz_lcdmsg(false, 0, 2, "Cannot open input device");
+ nwz_fb_close(fb_fd);
+ nwz_lcdmsg(true, 0, 2, "Cannot open input device");
+ sleep(2);
+ return BOOT_OF;
+ }
+ int fb_size = width * height * bpp / 2;
+ void *fb_mmap = nwz_fb_mmap(fb_fd, 0, fb_size);
+ void *fb_mmap_p1 = nwz_fb_mmap(fb_fd, NWZ_FB_LCD_PAGE_OFFSET, fb_size);
+ if(fb_mmap == NULL || fb_mmap_p1 == NULL)
+ {
+ nwz_fb_close(fb_fd);
+ nwz_key_close(input_fd);
+ nwz_lcdmsg(true, 0, 2, "Cannot map framebuffer");
sleep(2);
return BOOT_OF;
}
- deadline.tv_sec += 5;
/* wait for user action */
enum boot_mode mode = BOOT_OF;
+ /* NOTE on drawing: since screen is redrawn automatically, and we invoke
+ * external programs to draw, we can't hope to fit it in the frame time
+ * and it will flicker. To avoid this, we use the fact that all programs
+ * only write to page 0. So we setup the lcd to update from page 1. When
+ * we need to update the screen, we ask it to draw from page 0, then copy
+ * page 0 to page 1 and then switch back to page 1 */
+ memset(fb_mmap_p1, 0xff, fb_size); /* clear page 1 */
+ nwz_fb_set_page(fb_fd, 1);
+ bool redraw = true;
while(true)
{
- /* get time */
- struct timeval cur_time;
- if(gettimeofday(&cur_time, NULL) != 0)
+ if(redraw)
{
- nwz_lcdmsg(false, 0, 4, "Cannot get time");
- sleep(2);
- break;
+ /* redraw screen on page 0: clear screen */
+ memset(fb_mmap, 0, fb_size);
+ /* display top text */
+ nwz_display_text_center(width, 0, true, NWZ_COLOR(255, 201, 0),
+ NWZ_COLOR(0, 0, 0), 0, "SELECT PLAYER");
+ /* display icon */
+ const unsigned short *icon = (mode == BOOT_OF) ? sony_icon :
+ (mode == BOOT_ROCKBOX) ? rockbox_icon : tools_icon;
+ draw_icon((width - ICON_WIDTH) / 2, get_icon_y(), icon, fb_mmap);
+ /* display bottom description */
+ const char *desc = (mode == BOOT_OF) ? "SONY" :
+ (mode == BOOT_ROCKBOX) ? "ROCKBOX" : "DEBUG TOOLS";
+ nwz_display_text_center(width, get_icon_y() + ICON_HEIGHT + 30, true,
+ NWZ_COLOR(255, 201, 0), NWZ_COLOR(0, 0, 0), 0, desc);
+ /* display arrows */
+ int arrow_y = get_icon_y() + ICON_HEIGHT / 2 - NWZ_FONT_H(true) / 2;
+ nwz_display_text(NWZ_FONT_W(true) / 2, arrow_y, true,
+ NWZ_COLOR(255, 201, 0), NWZ_COLOR(0, 0, 0), 0, "<");
+ nwz_display_text(width - 3 * NWZ_FONT_W(true) / 2, arrow_y, true,
+ NWZ_COLOR(255, 201, 0), NWZ_COLOR(0, 0, 0), 0, ">");
+ /* switch to page 1 */
+ nwz_fb_set_page(fb_fd, 0);
+ /* copy page 0 to page 1 */
+ memcpy(fb_mmap_p1, fb_mmap, fb_size);
+ /* switch back to page 1 */
+ nwz_fb_set_page(fb_fd, 1);
+
+ redraw = false;
}
- /* 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 run tools");
- nwz_lcdmsg(false, 0, 3, "Press PLAY to boot RB");
- /* wait for a key (1s) */
- int ret = nwz_key_wait_event(input_fd, 1000000);
+
+ /* wait for a key */
+ int ret = nwz_key_wait_event(input_fd, -1);
if(ret != 1)
continue;
struct input_event evt;
if(nwz_key_read_event(input_fd, &evt) != 1)
continue;
+ /* only act on release */
if(nwz_key_event_is_press(&evt))
continue;
- if(nwz_key_event_get_keycode(&evt) == NWZ_KEY_PLAY)
- {
- mode = BOOT_ROCKBOX;
+ int key_code = nwz_key_event_get_keycode(&evt);
+ /* play -> stop loop and return mode */
+ if(key_code == NWZ_KEY_PLAY)
break;
+ /* left/right/up/down: change mode */
+ if(key_code == NWZ_KEY_LEFT || key_code == NWZ_KEY_DOWN)
+ {
+ if(mode == BOOT_ROCKBOX)
+ mode = BOOT_OF;
+ else if(mode == BOOT_OF)
+ mode = BOOT_TOOLS;
+ else
+ mode = BOOT_ROCKBOX;
+ redraw = true;
}
- else if(nwz_key_event_get_keycode(&evt) == NWZ_KEY_BACK)
+ if(key_code == NWZ_KEY_RIGHT || key_code == NWZ_KEY_UP)
{
- mode = BOOT_TOOLS;
- break;
+ if(mode == BOOT_ROCKBOX)
+ mode = BOOT_TOOLS;
+ else if(mode == BOOT_OF)
+ mode = BOOT_ROCKBOX;
+ else
+ mode = BOOT_OF;
+ redraw = true;
}
}
+ /* switch back to page 0 */
+ nwz_fb_set_page(fb_fd, 0);
nwz_key_close(input_fd);
+ nwz_fb_close(fb_fd);
return mode;
}
static char *boot_rb_argv[] =
{
- "lcdmsg",
- "-c",
- "-l",
- "0,3",
- "Hello from RB",
+ "rockbox.sony",
NULL
};
int NWZ_TOOL_MAIN(all_tools)(int argc, char **argv);
+void error_screen(const char *msg)
+{
+ nwz_lcdmsg(true, 0, 0, msg);
+ sleep(3);
+}
+
+void create_sony_logo(void)
+{
+ for(int y = 0; y < ICON_HEIGHT; y++)
+ for(int x = 0; x < ICON_WIDTH; x++)
+ sony_icon[y * ICON_WIDTH + x] = 0xf81f;
+}
+
int main(int argc, char **argv)
{
/* make sure backlight is on and we are running the standard lcd mode */
@@ -125,9 +259,20 @@ int main(int argc, char **argv)
bl.level = NWZ_FB_BL_MAX_LEVEL;
nwz_fb_set_brightness(fb_fd, &bl);
nwz_fb_set_standard_mode(fb_fd);
+ /* get resolution */
+ /* we also need to get the native resolution */
+ if(nwz_fb_get_resolution(fb_fd, &width, &height, &bpp) != 0)
+ {
+ /* safe one */
+ width = 240;
+ height = 320;
+ bpp = 16;
+ }
nwz_fb_close(fb_fd);
}
- nwz_lcdmsg(true, 0, 0, "dualboot");
+ /* extract logo */
+ if(!extract_sony_logo())
+ create_sony_logo();
/* run all tools menu */
enum boot_mode mode = get_boot_mode();
if(mode == BOOT_TOOLS)
@@ -137,19 +282,19 @@ int main(int argc, char **argv)
}
else if(mode == BOOT_ROCKBOX)
{
- /* boot rockox */
- nwz_lcdmsg(true, 0, 3, "Booting rockbox...");
- /* in the future, we will run rockbox here, for now we just print a
- * message */
- execvp("/usr/local/bin/lcdmsg", boot_rb_argv);
+ /* Rockbox expects /.rockbox to contain themes, rocks, etc, but we
+ * cannot easily create this symlink because the root filesystem is
+ * mounted read-only. Although we could remount it read-write temporarily,
+ * this is neededlessly complicated and we defer this job to the dualboot
+ * install script */
+ execvp("/contents/.rockbox/rockbox.sony", boot_rb_argv);
/* fallback to OF in case of failure */
- nwz_lcdmsg(false, 0, 4, "failed.");
+ error_screen("Cannot boot Rockbox");
sleep(5);
}
/* boot OF */
- nwz_lcdmsg(true, 0, 3, "Booting OF...");
execvp("/usr/local/bin/SpiderApp.of", argv);
- nwz_lcdmsg(false, 0, 4, "failed.");
+ error_screen("Cannot boot OF");
sleep(5);
/* if we reach this point, everything failed, so return an error so that
* sysmgrd knows something is wrong */
diff --git a/utils/nwztools/plattools/nwz_lib.c b/utils/nwztools/plattools/nwz_lib.c
index 70dc070fc9..a81d352ff0 100644
--- a/utils/nwztools/plattools/nwz_lib.c
+++ b/utils/nwztools/plattools/nwz_lib.c
@@ -156,6 +156,13 @@ void nwz_display_text(int x, int y, bool big_font, nwz_color_t foreground_col,
nwz_run(path_display, args, true);
}
+void nwz_display_text_center(int width, int y, bool big_font, nwz_color_t fg,
+ nwz_color_t bg, int alpha, const char *text)
+{
+ int txt_w = NWZ_FONT_W(big_font) * strlen(text);
+ nwz_display_text((width - txt_w) / 2, y, big_font, fg, bg, alpha, text);
+}
+
void nwz_display_textf(int x, int y, bool big_font, nwz_color_t foreground_col,
nwz_color_t background_col, int alpha, const char *fmt, ...)
{
@@ -167,6 +174,17 @@ void nwz_display_textf(int x, int y, bool big_font, nwz_color_t foreground_col,
nwz_display_text(x, y, big_font, foreground_col, background_col, alpha, buffer);
}
+void nwz_display_textf_center(int width, int y, bool big_font, nwz_color_t fg,
+ nwz_color_t bg, int alpha, const char *fmt, ...)
+{
+ char buffer[1024];
+ va_list args;
+ va_start(args, fmt);
+ vsprintf(buffer, fmt, args);
+ va_end(args);
+ nwz_display_text_center(width, y, big_font, fg, bg, alpha, buffer);
+}
+
void nwz_display_bitmap(int x, int y, const char *file, int left, int top,
int width, int height, nwz_color_t key_col, int bmp_alpha)
{
@@ -319,6 +337,21 @@ int nwz_fb_set_brightness(int fd, struct nwz_fb_brightness *bl)
return 1;
}
+int nwz_fb_set_page(int fd, int page)
+{
+ /* set page mode to no transparency and no rotation */
+ struct nwz_fb_image_info mode_info;
+ mode_info.tc_enable = 0;
+ mode_info.t_color = 0;
+ mode_info.alpha = 0;
+ mode_info.rot = 0;
+ mode_info.page = page;
+ mode_info.update = NWZ_FB_ONLY_2D_MODE;
+ if(ioctl(fd, NWZ_FB_UPDATE, &mode_info) < 0)
+ return -2;
+ return 0;
+}
+
int nwz_fb_set_standard_mode(int fd)
{
/* disable timer (apparently useless with LCD) */
@@ -327,17 +360,7 @@ int nwz_fb_set_standard_mode(int fd)
update_timer.timeout = NWZ_FB_DEFAULT_TIMEOUT;
if(ioctl(fd, NWZ_FB_UPDATE_TIMER, &update_timer) < 0)
return -1;
- /* set page 0 mode to no transparency and no rotation */
- struct nwz_fb_image_info mode_info;
- mode_info.tc_enable = 0;
- mode_info.t_color = 0;
- mode_info.alpha = 0;
- mode_info.rot = 0;
- mode_info.page = 0;
- mode_info.update = NWZ_FB_ONLY_2D_MODE;
- if(ioctl(fd, NWZ_FB_UPDATE, &mode_info) < 0)
- return -2;
- return 0;
+ return nwz_fb_set_page(fd, 0);
}
int nwz_fb_get_resolution(int fd, int *x, int *y, int *bpp)
@@ -354,6 +377,11 @@ int nwz_fb_get_resolution(int fd, int *x, int *y, int *bpp)
return 0;
}
+void *nwz_fb_mmap(int fd, int offset, int size)
+{
+ return mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t)offset);
+}
+
int nwz_adc_open(void)
{
return open(NWZ_ADC_DEV, O_RDONLY);
diff --git a/utils/nwztools/plattools/nwz_lib.h b/utils/nwztools/plattools/nwz_lib.h
index 18d7f9dd07..23bb80986d 100644
--- a/utils/nwztools/plattools/nwz_lib.h
+++ b/utils/nwztools/plattools/nwz_lib.h
@@ -32,6 +32,7 @@
#include
#include
#include
+#include
#include "nwz_keys.h"
#include "nwz_fb.h"
@@ -72,11 +73,19 @@ typedef int nwz_color_t;
#define NWZ_COLOR_GREEN(col) (((col) >> 8) & 0xff)
#define NWZ_COLOR_BLUE(col) ((col) & 0xff)
#define NWZ_COLOR_NO_KEY (1 << 24)
+
+#define NWZ_FONT_W(big_font) ((big_font) ? 14 : 8)
+#define NWZ_FONT_H(big_font) ((big_font) ? 24 : 14)
+
void nwz_display_clear(nwz_color_t color);
void nwz_display_text(int x, int y, bool big_font, nwz_color_t foreground_col,
nwz_color_t background_col, int background_alpha, const char *text);
+void nwz_display_text_center(int width, int y, bool big_font, nwz_color_t foreground_col,
+ nwz_color_t background_col, int background_alpha, const char *text);
void nwz_display_textf(int x, int y, bool big_font, nwz_color_t foreground_col,
nwz_color_t background_col, int background_alpha, const char *fmt, ...);
+void nwz_display_textf_center(int width, int y, bool big_font, nwz_color_t foreground_col,
+ nwz_color_t background_col, int background_alpha, const char *fmt, ...);
void nwz_display_bitmap(int x, int y, const char *file, int left, int top,
int width, int height, nwz_color_t key, int bmp_alpha);
@@ -113,6 +122,10 @@ int nwz_fb_set_brightness(int fd, struct nwz_fb_brightness *bl);
/* setup framebuffer to its standard mode: LCD output, page 0, no transparency
* and no rotation, 2D only updates */
int nwz_fb_set_standard_mode(int fd);
+/* change framebuffer page and update screen */
+int nwz_fb_set_page(int fd, int page);
+/* map framebuffer */
+void *nwz_fb_mmap(int fd, int offset, int size);
/* open adc device */
int nwz_adc_open(void);
diff --git a/utils/nwztools/scripts/install_dualboot.sh b/utils/nwztools/scripts/install_dualboot.sh
index ece5b9e3a3..08c24b7b5f 100644
--- a/utils/nwztools/scripts/install_dualboot.sh
+++ b/utils/nwztools/scripts/install_dualboot.sh
@@ -10,7 +10,6 @@ nvpflag fup 0xFFFFFFFF
# FIXME document this
#
-
# go to /tmp
cd /tmp
@@ -30,6 +29,9 @@ if [ "$?" != 0 ]; then
exit 0
fi
+# redirect all output to a log file
+exec > "$CONTENTS/install_dualboot_log.txt" 2>&1
+
# import constants
. /install_script/constant.txt
_UPDATE_FN_=`nvpstr ufn`
@@ -66,6 +68,7 @@ fi
lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,9 "Install rockbox"
fwpchk -f /contents/$_UPDATE_FN_.UPG -c -1 $SPIDERAPP_PATH
if [ "$?" != 0 ]; then
+ umount "$ROOTFS_TMP_DIR"
lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: no file to extract"
sleep 3
exit 0
@@ -74,40 +77,45 @@ fi
# make it executable and change user/group
chmod 775 $SPIDERAPP_PATH
if [ "$?" != 0 ]; then
+ umount "$ROOTFS_TMP_DIR"
lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: cannot make it executable"
sleep 3
exit 0
fi
chown 500:500 $SPIDERAPP_PATH
if [ "$?" != 0 ]; then
+ umount "$ROOTFS_TMP_DIR"
lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: cannot change owner"
sleep 3
exit 0
fi
-# # change main application
-# lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,9 "Modify app list"
-# sed -i 's/Rockbox/SpiderApp/' $ROOTFS_TMP_DIR/etc/AppList.conf
-# if [ "$?" != 0 ]; then
-# lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,14 "ERROR: sed failed"
-# sleep 3
-# exit 0
-# fi
-# # and fix ownership
-# chown 500:500 $ROOTFS_TMP_DIR/etc/AppList.conf
-# if [ "$?" != 0 ]; then
-# lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,14 "ERROR: cannot change group"
-# sleep 3
-# exit 0
-# fi
-cat $ROOTFS_TMP_DIR/etc/AppList.conf >$CONTENTS/AppList.conf
-ls -l $ROOTFS_TMP_DIR/usr/local/bin/ >$CONTENTS/ls.txt
-ls -l $ROOTFS_TMP_DIR/etc/ >$CONTENTS/ls2.txt
+# 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"
+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"
+ sleep 3
+ exit 0
+fi
+
+# change user/group
+chown -h 500:500 "$ROOTFS_TMP_DIR/.rockbox"
+if [ "$?" != 0 ]; then
+ umount "$ROOTFS_TMP_DIR"
+ lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: cannot change symlink owner"
+ sleep 3
+ exit 0
+fi
# unmount root partition
-lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,10 "Unmount root filesystem"
+lcdmsg -f /usr/local/bin/font_08x12.bmp -l 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"
sleep 3
exit 0
@@ -125,5 +133,6 @@ lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "Rebooting in 3 seconds."
sleep 3
sync
+echo "Installation successful"
# finish
exit 0