diff options
-rw-r--r-- | firmware/decompressor/Makefile | 42 | ||||
-rw-r--r-- | firmware/decompressor/decompressor.c | 150 | ||||
-rwxr-xr-x | firmware/decompressor/link.lds | 74 |
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 @@ | |||
1 | # __________ __ ___. | ||
2 | # Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
3 | # Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
4 | # Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
5 | # Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
6 | # \/ \/ \/ \/ \/ | ||
7 | # $Id$ | ||
8 | # | ||
9 | |||
10 | CC = sh-elf-gcc | ||
11 | LD = sh-elf-ld | ||
12 | AR = sh-elf-ar | ||
13 | AS = sh-elf-as | ||
14 | OC = sh-elf-objcopy | ||
15 | |||
16 | TOOLSDIR=../../tools | ||
17 | OBJDIR := . | ||
18 | # FIXME: get proper value from build system | ||
19 | MEMORYSIZE = 2 | ||
20 | |||
21 | |||
22 | LDS := link.lds | ||
23 | LINKFILE = $(OBJDIR)/linkage.lds | ||
24 | OBJS := $(OBJDIR)/decompressor.o $(OBJDIR)/rockboxucl.o | ||
25 | |||
26 | CFLAGS = -O -W -Wall -m1 -nostdlib -ffreestanding -Wstrict-prototypes -fomit-frame-pointer -fschedule-insns | ||
27 | |||
28 | $(OBJDIR)/compressed.bin : $(OBJDIR)/compressed.elf | ||
29 | @echo "OBJCOPY "`basename $@` | ||
30 | @$(OC) -O binary $< $@ | ||
31 | |||
32 | $(OBJDIR)/compressed.elf : $(OBJS) $(LINKFILE) | ||
33 | @echo "LD rockbox.elf" | ||
34 | @$(CC) $(GCCOPTS) -Os -nostdlib -o $@ $(OBJS) -T$(LINKFILE) -Wl,-Map,$(OBJDIR)/compressed.map | ||
35 | |||
36 | $(LINKFILE): $(LDS) | ||
37 | @echo "Build LDS file" | ||
38 | @cat $< | $(CC) -DMEMORYSIZE=$(MEMORYSIZE) $(INCLUDES) $(TARGET) $(DEFINES) -E -P $(ROMBUILD) - >$@ | ||
39 | |||
40 | $(OBJDIR)/rockboxucl.o: $(OBJDIR)/rockbox.ucl | ||
41 | @echo "OBJCOPY rockbox.ucl" | ||
42 | @$(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 @@ | |||
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 | } | ||
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 @@ | |||
1 | OUTPUT_FORMAT(elf32-sh) | ||
2 | |||
3 | #define DRAMORIG 0x09000000 | ||
4 | #define DRAMSIZE (MEMORYSIZE * 0x00100000) | ||
5 | #define IRAMORIG 0x0f000000 | ||
6 | #define IRAMSIZE 0x00001000 | ||
7 | |||
8 | MEMORY | ||
9 | { | ||
10 | IRAM : ORIGIN = IRAMORIG, LENGTH = IRAMSIZE | ||
11 | DRAM : ORIGIN = DRAMORIG, LENGTH = DRAMSIZE | ||
12 | } | ||
13 | |||
14 | SECTIONS | ||
15 | { | ||
16 | .vectors : | ||
17 | { | ||
18 | _loadaddress = .; | ||
19 | _dramend = . + DRAMSIZE; | ||
20 | *(.vectors) | ||
21 | . = ALIGN(0x200); | ||
22 | } > DRAM | ||
23 | |||
24 | .text : | ||
25 | { | ||
26 | *(.start) | ||
27 | *(.text) | ||
28 | . = ALIGN(0x4); | ||
29 | } > DRAM | ||
30 | |||
31 | .rodata : | ||
32 | { | ||
33 | *(.rodata*) | ||
34 | *(.rodata.str1.1) | ||
35 | *(.rodata.str1.4) | ||
36 | . = ALIGN(0x4); | ||
37 | } > DRAM | ||
38 | |||
39 | .data : | ||
40 | { | ||
41 | *(.data) | ||
42 | . = ALIGN(0x4); | ||
43 | _imgstart = .; | ||
44 | *(.image) | ||
45 | . = ALIGN(0x4); | ||
46 | _imgend = .; | ||
47 | _iramcopy = .; | ||
48 | } > DRAM | ||
49 | |||
50 | .iram IRAMORIG : AT ( _iramcopy ) | ||
51 | { | ||
52 | _iramstart = .; | ||
53 | *(.icode) | ||
54 | *(.idata) | ||
55 | . = ALIGN(0x4); | ||
56 | _iramend = .; | ||
57 | } > IRAM | ||
58 | |||
59 | .stack : | ||
60 | { | ||
61 | _stackbegin = .; | ||
62 | *(.stack) | ||
63 | . += 0x0800; | ||
64 | _stackend = .; | ||
65 | } > IRAM | ||
66 | |||
67 | .bss : | ||
68 | { | ||
69 | _edata = .; | ||
70 | *(.bss) | ||
71 | . = ALIGN(0x4); | ||
72 | _end = .; | ||
73 | } > DRAM | ||
74 | } | ||