summaryrefslogtreecommitdiffstats
path: root/firmware/decompressor
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2005-11-27 23:55:13 +0000
committerJens Arnold <amiconn@rockbox.org>2005-11-27 23:55:13 +0000
commitdbff1f20eec246d9c9f720b1fa64696fd7671737 (patch)
tree0a8a73832532bc6b194d5b74f789ba501998e651 /firmware/decompressor
parent4923f49c6f89b751c89678d328d6b5adb7d7bcfb (diff)
downloadrockbox-dbff1f20eec246d9c9f720b1fa64696fd7671737.tar.gz
rockbox-dbff1f20eec246d9c9f720b1fa64696fd7671737.tar.bz2
rockbox-dbff1f20eec246d9c9f720b1fa64696fd7671737.zip
Archos targets: Self-extractor for on-disk firmware images to work around the file size limit. Re-uses rockbox.ucl. Not yet integrated with build system.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8089 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/decompressor')
-rw-r--r--firmware/decompressor/Makefile42
-rw-r--r--firmware/decompressor/decompressor.c150
-rwxr-xr-xfirmware/decompressor/link.lds74
3 files changed, 266 insertions, 0 deletions
diff --git a/firmware/decompressor/Makefile b/firmware/decompressor/Makefile
new file mode 100644
index 0000000000..99e91aa35e
--- /dev/null
+++ b/firmware/decompressor/Makefile
@@ -0,0 +1,42 @@
+# __________ __ ___.
+# Open \______ \ ____ ____ | | _\_ |__ _______ ___
+# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+# \/ \/ \/ \/ \/
+# $Id$
+#
+
+CC = sh-elf-gcc
+LD = sh-elf-ld
+AR = sh-elf-ar
+AS = sh-elf-as
+OC = sh-elf-objcopy
+
+TOOLSDIR=../../tools
+OBJDIR := .
+# FIXME: get proper value from build system
+MEMORYSIZE = 2
+
+
+LDS := link.lds
+LINKFILE = $(OBJDIR)/linkage.lds
+OBJS := $(OBJDIR)/decompressor.o $(OBJDIR)/rockboxucl.o
+
+CFLAGS = -O -W -Wall -m1 -nostdlib -ffreestanding -Wstrict-prototypes -fomit-frame-pointer -fschedule-insns
+
+$(OBJDIR)/compressed.bin : $(OBJDIR)/compressed.elf
+ @echo "OBJCOPY "`basename $@`
+ @$(OC) -O binary $< $@
+
+$(OBJDIR)/compressed.elf : $(OBJS) $(LINKFILE)
+ @echo "LD rockbox.elf"
+ @$(CC) $(GCCOPTS) -Os -nostdlib -o $@ $(OBJS) -T$(LINKFILE) -Wl,-Map,$(OBJDIR)/compressed.map
+
+$(LINKFILE): $(LDS)
+ @echo "Build LDS file"
+ @cat $< | $(CC) -DMEMORYSIZE=$(MEMORYSIZE) $(INCLUDES) $(TARGET) $(DEFINES) -E -P $(ROMBUILD) - >$@
+
+$(OBJDIR)/rockboxucl.o: $(OBJDIR)/rockbox.ucl
+ @echo "OBJCOPY rockbox.ucl"
+ @$(OC) -I binary -O elf32-sh -B sh --rename-section .data=.image,alloc,load,data,contents $< $@
diff --git a/firmware/decompressor/decompressor.c b/firmware/decompressor/decompressor.c
new file mode 100644
index 0000000000..1223ff2f05
--- /dev/null
+++ b/firmware/decompressor/decompressor.c
@@ -0,0 +1,150 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 by Jens Arnold
+ *
+ * Self-extracting firmware loader to work around the 200KB size limit
+ * for archos player and recorder v1
+ * Decompresses a built-in UCL-compressed image (method 2e) and executes it.
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#define ICODE_ATTR __attribute__ ((section (".icode")))
+#define UCL_HEADER 26 /* size of the header generated by uclpack */
+
+/* Symbols defined in the linker script */
+extern char iramcopy[], iramstart[], iramend[];
+extern char stackend[];
+extern char imgstart[], imgend[];
+extern char loadaddress[], dramend[];
+
+/* Prototypes */
+void start(void) __attribute__ ((section (".start")));
+void main(void) ICODE_ATTR;
+int ucl_nrv2e_decompress_8(const unsigned char *src, unsigned char *dst,
+ unsigned long *dst_len) ICODE_ATTR;
+
+/* Vector table */
+void (*vbr[]) (void) __attribute__ ((section (".vectors"))) =
+{
+ start, (void *)stackend,
+ start, (void *)stackend,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+};
+
+/* Inline copy function */
+static inline void longcopy(long *dst, long *dst_end, const long *src)
+ __attribute__ ((always_inline));
+static inline void longcopy(long *dst, long *dst_end, const long *src)
+{
+ while (dst < dst_end)
+ *dst++ = *src++;
+}
+
+/* Entry point */
+void start(void)
+{
+ longcopy((long *)iramstart, (long *)iramend, (long *)iramcopy);
+ main();
+}
+
+/** All subsequent functions are executed from IRAM **/
+
+/* Thinned out version of the UCL 2e decompression sourcecode
+ * Original (C) Markus F.X.J Oberhumer under GNU GPL license */
+#define GETBIT(bb, src, ilen) \
+ (((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1)
+
+int ucl_nrv2e_decompress_8(const unsigned char *src, unsigned char *dst,
+ unsigned long *dst_len)
+{
+ unsigned long bb = 0;
+ unsigned ilen = 0, olen = 0, last_m_off = 1;
+
+ for (;;)
+ {
+ unsigned m_off, m_len;
+
+ while (GETBIT(bb,src,ilen))
+ dst[olen++] = src[ilen++];
+
+ m_off = 1;
+ for (;;)
+ {
+ m_off = m_off*2 + GETBIT(bb,src,ilen);
+ if (GETBIT(bb,src,ilen))
+ break;
+ m_off = (m_off-1)*2 + GETBIT(bb,src,ilen);
+ }
+ if (m_off == 2)
+ {
+ m_off = last_m_off;
+ m_len = GETBIT(bb,src,ilen);
+ }
+ else
+ {
+ m_off = (m_off-3)*256 + src[ilen++];
+ if (m_off == 0xffffffff)
+ break;
+ m_len = (m_off ^ 0xffffffff) & 1;
+ m_off >>= 1;
+ last_m_off = ++m_off;
+ }
+ if (m_len)
+ m_len = 1 + GETBIT(bb,src,ilen);
+ else if (GETBIT(bb,src,ilen))
+ m_len = 3 + GETBIT(bb,src,ilen);
+ else
+ {
+ m_len++;
+ do {
+ m_len = m_len*2 + GETBIT(bb,src,ilen);
+ } while (!GETBIT(bb,src,ilen));
+ m_len += 3;
+ }
+ m_len += (m_off > 0x500);
+ {
+ const unsigned char *m_pos;
+ m_pos = dst + olen - m_off;
+ dst[olen++] = *m_pos++;
+ do dst[olen++] = *m_pos++; while (--m_len > 0);
+ }
+ }
+ *dst_len = olen;
+
+ return ilen;
+}
+
+/* This will never return */
+void main(void)
+{
+ unsigned long dst_len; /* dummy */
+ unsigned long img_len = (unsigned long)(imgend - imgstart);
+
+ longcopy((long *)(dramend - img_len), (long *) dramend,
+ (long *) imgstart);
+
+ ucl_nrv2e_decompress_8(dramend - img_len + UCL_HEADER,
+ loadaddress, &dst_len);
+
+ asm(
+ "mov.l @%0+,r0 \n"
+ "mov.l @%0+,r15 \n"
+ "jmp @r0 \n"
+ "nop \n"
+ : : "r"(loadaddress) : "r0"
+ );
+}
diff --git a/firmware/decompressor/link.lds b/firmware/decompressor/link.lds
new file mode 100755
index 0000000000..9cb4be8830
--- /dev/null
+++ b/firmware/decompressor/link.lds
@@ -0,0 +1,74 @@
+OUTPUT_FORMAT(elf32-sh)
+
+#define DRAMORIG 0x09000000
+#define DRAMSIZE (MEMORYSIZE * 0x00100000)
+#define IRAMORIG 0x0f000000
+#define IRAMSIZE 0x00001000
+
+MEMORY
+{
+ IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE
+ DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE
+}
+
+SECTIONS
+{
+ .vectors :
+ {
+ _loadaddress = .;
+ _dramend = . + DRAMSIZE;
+ *(.vectors)
+ . = ALIGN(0x200);
+ } > DRAM
+
+ .text :
+ {
+ *(.start)
+ *(.text)
+ . = ALIGN(0x4);
+ } > DRAM
+
+ .rodata :
+ {
+ *(.rodata*)
+ *(.rodata.str1.1)
+ *(.rodata.str1.4)
+ . = ALIGN(0x4);
+ } > DRAM
+
+ .data :
+ {
+ *(.data)
+ . = ALIGN(0x4);
+ _imgstart = .;
+ *(.image)
+ . = ALIGN(0x4);
+ _imgend = .;
+ _iramcopy = .;
+ } > DRAM
+
+ .iram IRAMORIG : AT ( _iramcopy )
+ {
+ _iramstart = .;
+ *(.icode)
+ *(.idata)
+ . = ALIGN(0x4);
+ _iramend = .;
+ } > IRAM
+
+ .stack :
+ {
+ _stackbegin = .;
+ *(.stack)
+ . += 0x0800;
+ _stackend = .;
+ } > IRAM
+
+ .bss :
+ {
+ _edata = .;
+ *(.bss)
+ . = ALIGN(0x4);
+ _end = .;
+ } > DRAM
+}