From dbff1f20eec246d9c9f720b1fa64696fd7671737 Mon Sep 17 00:00:00 2001 From: Jens Arnold Date: Sun, 27 Nov 2005 23:55:13 +0000 Subject: 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 --- firmware/decompressor/decompressor.c | 150 +++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 firmware/decompressor/decompressor.c (limited to 'firmware/decompressor/decompressor.c') 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" + ); +} -- cgit v1.2.3