diff options
author | Jens Arnold <amiconn@rockbox.org> | 2005-11-27 23:55:13 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2005-11-27 23:55:13 +0000 |
commit | dbff1f20eec246d9c9f720b1fa64696fd7671737 (patch) | |
tree | 0a8a73832532bc6b194d5b74f789ba501998e651 /firmware/decompressor/decompressor.c | |
parent | 4923f49c6f89b751c89678d328d6b5adb7d7bcfb (diff) | |
download | rockbox-dbff1f20eec246d9c9f720b1fa64696fd7671737.tar.gz 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/decompressor.c')
-rw-r--r-- | firmware/decompressor/decompressor.c | 150 |
1 files changed, 150 insertions, 0 deletions
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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2005 by Jens Arnold | ||
11 | * | ||
12 | * Self-extracting firmware loader to work around the 200KB size limit | ||
13 | * for archos player and recorder v1 | ||
14 | * Decompresses a built-in UCL-compressed image (method 2e) and executes it. | ||
15 | * | ||
16 | * All files in this archive are subject to the GNU General Public License. | ||
17 | * See the file COPYING in the source tree root for full license agreement. | ||
18 | * | ||
19 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
20 | * KIND, either express or implied. | ||
21 | * | ||
22 | ****************************************************************************/ | ||
23 | |||
24 | #define ICODE_ATTR __attribute__ ((section (".icode"))) | ||
25 | #define UCL_HEADER 26 /* size of the header generated by uclpack */ | ||
26 | |||
27 | /* Symbols defined in the linker script */ | ||
28 | extern char iramcopy[], iramstart[], iramend[]; | ||
29 | extern char stackend[]; | ||
30 | extern char imgstart[], imgend[]; | ||
31 | extern char loadaddress[], dramend[]; | ||
32 | |||
33 | /* Prototypes */ | ||
34 | void start(void) __attribute__ ((section (".start"))); | ||
35 | void main(void) ICODE_ATTR; | ||
36 | int ucl_nrv2e_decompress_8(const unsigned char *src, unsigned char *dst, | ||
37 | unsigned long *dst_len) ICODE_ATTR; | ||
38 | |||
39 | /* Vector table */ | ||
40 | void (*vbr[]) (void) __attribute__ ((section (".vectors"))) = | ||
41 | { | ||
42 | start, (void *)stackend, | ||
43 | start, (void *)stackend, | ||
44 | 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, | ||
45 | 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, | ||
46 | }; | ||
47 | |||
48 | /* Inline copy function */ | ||
49 | static inline void longcopy(long *dst, long *dst_end, const long *src) | ||
50 | __attribute__ ((always_inline)); | ||
51 | static inline void longcopy(long *dst, long *dst_end, const long *src) | ||
52 | { | ||
53 | while (dst < dst_end) | ||
54 | *dst++ = *src++; | ||
55 | } | ||
56 | |||
57 | /* Entry point */ | ||
58 | void start(void) | ||
59 | { | ||
60 | longcopy((long *)iramstart, (long *)iramend, (long *)iramcopy); | ||
61 | main(); | ||
62 | } | ||
63 | |||
64 | /** All subsequent functions are executed from IRAM **/ | ||
65 | |||
66 | /* Thinned out version of the UCL 2e decompression sourcecode | ||
67 | * Original (C) Markus F.X.J Oberhumer under GNU GPL license */ | ||
68 | #define GETBIT(bb, src, ilen) \ | ||
69 | (((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1) | ||
70 | |||
71 | int ucl_nrv2e_decompress_8(const unsigned char *src, unsigned char *dst, | ||
72 | unsigned long *dst_len) | ||
73 | { | ||
74 | unsigned long bb = 0; | ||
75 | unsigned ilen = 0, olen = 0, last_m_off = 1; | ||
76 | |||
77 | for (;;) | ||
78 | { | ||
79 | unsigned m_off, m_len; | ||
80 | |||
81 | while (GETBIT(bb,src,ilen)) | ||
82 | dst[olen++] = src[ilen++]; | ||
83 | |||
84 | m_off = 1; | ||
85 | for (;;) | ||
86 | { | ||
87 | m_off = m_off*2 + GETBIT(bb,src,ilen); | ||
88 | if (GETBIT(bb,src,ilen)) | ||
89 | break; | ||
90 | m_off = (m_off-1)*2 + GETBIT(bb,src,ilen); | ||
91 | } | ||
92 | if (m_off == 2) | ||
93 | { | ||
94 | m_off = last_m_off; | ||
95 | m_len = GETBIT(bb,src,ilen); | ||
96 | } | ||
97 | else | ||
98 | { | ||
99 | m_off = (m_off-3)*256 + src[ilen++]; | ||
100 | if (m_off == 0xffffffff) | ||
101 | break; | ||
102 | m_len = (m_off ^ 0xffffffff) & 1; | ||
103 | m_off >>= 1; | ||
104 | last_m_off = ++m_off; | ||
105 | } | ||
106 | if (m_len) | ||
107 | m_len = 1 + GETBIT(bb,src,ilen); | ||
108 | else if (GETBIT(bb,src,ilen)) | ||
109 | m_len = 3 + GETBIT(bb,src,ilen); | ||
110 | else | ||
111 | { | ||
112 | m_len++; | ||
113 | do { | ||
114 | m_len = m_len*2 + GETBIT(bb,src,ilen); | ||
115 | } while (!GETBIT(bb,src,ilen)); | ||
116 | m_len += 3; | ||
117 | } | ||
118 | m_len += (m_off > 0x500); | ||
119 | { | ||
120 | const unsigned char *m_pos; | ||
121 | m_pos = dst + olen - m_off; | ||
122 | dst[olen++] = *m_pos++; | ||
123 | do dst[olen++] = *m_pos++; while (--m_len > 0); | ||
124 | } | ||
125 | } | ||
126 | *dst_len = olen; | ||
127 | |||
128 | return ilen; | ||
129 | } | ||
130 | |||
131 | /* This will never return */ | ||
132 | void main(void) | ||
133 | { | ||
134 | unsigned long dst_len; /* dummy */ | ||
135 | unsigned long img_len = (unsigned long)(imgend - imgstart); | ||
136 | |||
137 | longcopy((long *)(dramend - img_len), (long *) dramend, | ||
138 | (long *) imgstart); | ||
139 | |||
140 | ucl_nrv2e_decompress_8(dramend - img_len + UCL_HEADER, | ||
141 | loadaddress, &dst_len); | ||
142 | |||
143 | asm( | ||
144 | "mov.l @%0+,r0 \n" | ||
145 | "mov.l @%0+,r15 \n" | ||
146 | "jmp @r0 \n" | ||
147 | "nop \n" | ||
148 | : : "r"(loadaddress) : "r0" | ||
149 | ); | ||
150 | } | ||