diff options
author | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2021-12-15 21:04:28 +0100 |
---|---|---|
committer | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2021-12-24 18:05:53 +0100 |
commit | c876d3bbefe0dc00c27ca0c12d29da5874946962 (patch) | |
tree | 69f468a185a369b01998314bc3ecc19b70f4fcaa /utils/mkamsboot/dualboot | |
parent | 6c6f0757d7a902feb293be165d1490c42bc8e7ad (diff) | |
download | rockbox-c876d3bbefe0dc00c27ca0c12d29da5874946962.tar.gz rockbox-c876d3bbefe0dc00c27ca0c12d29da5874946962.zip |
rbutil: Merge rbutil with utils folder.
rbutil uses several components from the utils folder, and can be
considered part of utils too. Having it in a separate folder is an
arbitrary split that doesn't help anymore these days, so merge them.
This also allows other utils to easily use libtools.make without the
need to navigate to a different folder.
Change-Id: I3fc2f4de19e3e776553efb5dea5f779dfec0dc21
Diffstat (limited to 'utils/mkamsboot/dualboot')
-rw-r--r-- | utils/mkamsboot/dualboot/.gitignore | 3 | ||||
-rw-r--r-- | utils/mkamsboot/dualboot/Makefile | 61 | ||||
-rw-r--r-- | utils/mkamsboot/dualboot/bin2c.c | 140 | ||||
-rw-r--r-- | utils/mkamsboot/dualboot/dualboot.S | 307 | ||||
-rw-r--r-- | utils/mkamsboot/dualboot/nrv2e_d8.S | 198 |
5 files changed, 709 insertions, 0 deletions
diff --git a/utils/mkamsboot/dualboot/.gitignore b/utils/mkamsboot/dualboot/.gitignore new file mode 100644 index 0000000000..a0ed5f4ee1 --- /dev/null +++ b/utils/mkamsboot/dualboot/.gitignore | |||
@@ -0,0 +1,3 @@ | |||
1 | *.arm-bin | ||
2 | *.o | ||
3 | bin2c | ||
diff --git a/utils/mkamsboot/dualboot/Makefile b/utils/mkamsboot/dualboot/Makefile new file mode 100644 index 0000000000..0aa1e3f7d9 --- /dev/null +++ b/utils/mkamsboot/dualboot/Makefile | |||
@@ -0,0 +1,61 @@ | |||
1 | CC=gcc | ||
2 | CROSS_PREFIX?=arm-elf-eabi | ||
3 | # Edit the following variables (plus copy/paste another set of rules) when | ||
4 | # adding a new target. mkamsboot.c also needs to be edited to refer to these | ||
5 | # new images. | ||
6 | |||
7 | BOOTOBJS = nrv2e_d8.o dualboot_clip.o dualboot_e200v2.o dualboot_c200v2.o dualboot_m200v4.o dualboot_fuze.o dualboot_clipv2.o dualboot_clipplus.o dualboot_fuzev2.o dualboot_clipzip.o | ||
8 | BOOTBINS = nrv2e_d8.arm-bin dualboot_clip.arm-bin dualboot_e200v2.arm-bin dualboot_c200v2.arm-bin dualboot_m200v4.arm-bin dualboot_fuze.arm-bin dualboot_clipv2.arm-bin dualboot_clipplus.arm-bin dualboot_fuzev2.arm-bin dualboot_clipzip.arm-bin | ||
9 | |||
10 | all: ../dualboot.h ../dualboot.c | ||
11 | |||
12 | # Dualboot bootloaders | ||
13 | |||
14 | dualboot_clip.o: dualboot.S | ||
15 | $(CROSS_PREFIX)-$(CC) -DSANSA_CLIP -c -o dualboot_clip.o dualboot.S | ||
16 | |||
17 | dualboot_fuze.o: dualboot.S | ||
18 | $(CROSS_PREFIX)-$(CC) -DSANSA_FUZE -c -o dualboot_fuze.o dualboot.S | ||
19 | |||
20 | dualboot_e200v2.o: dualboot.S | ||
21 | $(CROSS_PREFIX)-$(CC) -DSANSA_E200V2 -c -o dualboot_e200v2.o dualboot.S | ||
22 | |||
23 | dualboot_m200v4.o: dualboot.S | ||
24 | $(CROSS_PREFIX)-$(CC) -DSANSA_M200V4 -c -o dualboot_m200v4.o dualboot.S | ||
25 | |||
26 | dualboot_c200v2.o: dualboot.S | ||
27 | $(CROSS_PREFIX)-$(CC) -DSANSA_C200V2 -c -o dualboot_c200v2.o dualboot.S | ||
28 | |||
29 | dualboot_clipv2.o: dualboot.S | ||
30 | $(CROSS_PREFIX)-$(CC) -DSANSA_CLIPV2 -c -o dualboot_clipv2.o dualboot.S | ||
31 | |||
32 | dualboot_clipplus.o: dualboot.S | ||
33 | $(CROSS_PREFIX)-$(CC) -DSANSA_CLIPPLUS -c -o dualboot_clipplus.o dualboot.S | ||
34 | |||
35 | dualboot_fuzev2.o: dualboot.S | ||
36 | $(CROSS_PREFIX)-$(CC) -DSANSA_FUZEV2 -c -o dualboot_fuzev2.o dualboot.S | ||
37 | |||
38 | dualboot_clipzip.o: dualboot.S | ||
39 | $(CROSS_PREFIX)-$(CC) -DSANSA_CLIPZIP -c -o dualboot_clipzip.o dualboot.S | ||
40 | |||
41 | # Rules for the ucl unpack function | ||
42 | nrv2e_d8.o: nrv2e_d8.S | ||
43 | $(CROSS_PREFIX)-$(CC) -DPURE_THUMB -c -o nrv2e_d8.o nrv2e_d8.S | ||
44 | |||
45 | # Rules for the ARM code embedded in mkamsboot - assemble, link, then extract | ||
46 | # the binary code and finally convert to .h for building in mkamsboot | ||
47 | |||
48 | %.arm-elf: %.o | ||
49 | $(CROSS_PREFIX)-ld -e 0 -Ttext=0 -o $@ $< | ||
50 | |||
51 | %.arm-bin: %.arm-elf | ||
52 | $(CROSS_PREFIX)-objcopy -O binary $< $@ | ||
53 | |||
54 | ../dualboot.c ../dualboot.h: $(BOOTBINS) bin2c | ||
55 | ./bin2c ../dualboot $(BOOTBINS) | ||
56 | |||
57 | bin2c: bin2c.c | ||
58 | $(CC) -o bin2c bin2c.c | ||
59 | |||
60 | clean: | ||
61 | rm -f *~ bin2c $(BOOTBINS) $(BOOTOBJS) | ||
diff --git a/utils/mkamsboot/dualboot/bin2c.c b/utils/mkamsboot/dualboot/bin2c.c new file mode 100644 index 0000000000..b02af88a4d --- /dev/null +++ b/utils/mkamsboot/dualboot/bin2c.c | |||
@@ -0,0 +1,140 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2007 Dave Chapman | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include <stdio.h> | ||
23 | #include <string.h> | ||
24 | #include <sys/types.h> | ||
25 | #include <sys/stat.h> | ||
26 | #include <unistd.h> | ||
27 | #include <fcntl.h> | ||
28 | #include <stdlib.h> | ||
29 | #include <libgen.h> | ||
30 | |||
31 | #ifndef O_BINARY | ||
32 | #define O_BINARY 0 | ||
33 | #endif | ||
34 | |||
35 | static off_t filesize(int fd) | ||
36 | { | ||
37 | struct stat buf; | ||
38 | |||
39 | fstat(fd,&buf); | ||
40 | return buf.st_size; | ||
41 | } | ||
42 | |||
43 | static void write_cfile(const unsigned char* buf, off_t len, FILE* fp, const char *name) | ||
44 | { | ||
45 | int i; | ||
46 | |||
47 | fprintf(fp,"unsigned char %s[%ld] = {",name,len); | ||
48 | |||
49 | for (i=0;i<len;i++) { | ||
50 | if ((i % 16) == 0) { | ||
51 | fprintf(fp,"\n "); | ||
52 | } | ||
53 | if (i == (len-1)) { | ||
54 | fprintf(fp,"0x%02x",buf[i]); | ||
55 | } else if ((i % 16) == 15) { | ||
56 | fprintf(fp,"0x%02x,",buf[i]); | ||
57 | } else { | ||
58 | fprintf(fp,"0x%02x, ",buf[i]); | ||
59 | } | ||
60 | } | ||
61 | fprintf(fp,"\n};\n"); | ||
62 | } | ||
63 | |||
64 | int main (int argc, char* argv[]) | ||
65 | { | ||
66 | char* cname; | ||
67 | int i; | ||
68 | FILE *cfile, *hfile; | ||
69 | char cfilename[256], hfilename[256]; | ||
70 | |||
71 | if (argc < 3) { | ||
72 | fprintf(stderr,"Usage: bin2c cname file1 [file2 [file3 ...]]\n"); | ||
73 | return 1; | ||
74 | } | ||
75 | |||
76 | cname=argv[1]; | ||
77 | |||
78 | snprintf(cfilename,256,"%s.c",cname); | ||
79 | cfile = fopen(cfilename,"w+"); | ||
80 | if (cfile == NULL) { | ||
81 | fprintf(stderr,"Couldn't open %s\n",cfilename); | ||
82 | return 2; | ||
83 | } | ||
84 | |||
85 | snprintf(hfilename,256,"%s.h",cname); | ||
86 | hfile = fopen(hfilename,"w+"); | ||
87 | if (hfile == NULL) { | ||
88 | fprintf(stderr,"Couldn't open %s\n",hfilename); | ||
89 | fclose(cfile); | ||
90 | return 3; | ||
91 | } | ||
92 | |||
93 | fprintf(cfile,"/* Generated by bin2c */\n\n"); | ||
94 | fprintf(cfile,"#include \"%s\"\n\n", basename(hfilename)); | ||
95 | fprintf(hfile,"/* Generated by bin2c */\n\n"); | ||
96 | |||
97 | for(i=0; i < argc - 2; i++) { | ||
98 | unsigned char* buf; | ||
99 | off_t len; | ||
100 | off_t orig_len; | ||
101 | char *ext; | ||
102 | char *array = argv[2+i]; | ||
103 | |||
104 | int fd = open(array,O_RDONLY|O_BINARY); | ||
105 | if (fd < 0) { | ||
106 | fprintf(stderr,"Can not open %s\n",argv[2+i]); | ||
107 | fclose(cfile); | ||
108 | fclose(hfile); | ||
109 | return 4; | ||
110 | } | ||
111 | |||
112 | orig_len = filesize(fd); | ||
113 | /* pad to 32bit */ | ||
114 | len = (orig_len + 3) & ~3; | ||
115 | |||
116 | buf = malloc(len); | ||
117 | if (read(fd,buf,orig_len) < orig_len) { | ||
118 | fprintf(stderr,"Short read, aborting\n"); | ||
119 | return 5; | ||
120 | } | ||
121 | |||
122 | /* pad to 32bit with zeros */ | ||
123 | if (len > orig_len) | ||
124 | memset(buf+orig_len, 0, len-orig_len); | ||
125 | |||
126 | /* remove file extension */ | ||
127 | ext = strchr (array, '.'); | ||
128 | if (ext != NULL) | ||
129 | *ext = '\0'; | ||
130 | write_cfile (buf, len, cfile, array); | ||
131 | fprintf(hfile,"extern unsigned char %s[%ld];\n",array,len); | ||
132 | |||
133 | close(fd); | ||
134 | } | ||
135 | |||
136 | fclose(cfile); | ||
137 | fclose(hfile); | ||
138 | |||
139 | return 0; | ||
140 | } | ||
diff --git a/utils/mkamsboot/dualboot/dualboot.S b/utils/mkamsboot/dualboot/dualboot.S new file mode 100644 index 0000000000..4e4dbe5505 --- /dev/null +++ b/utils/mkamsboot/dualboot/dualboot.S | |||
@@ -0,0 +1,307 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2008 Rafaël Carré | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | .text | ||
23 | |||
24 | /* AS3525 hardware registers */ | ||
25 | .set GPIOA, 0xC80B0000 | ||
26 | .set GPIOB, 0xC80C0000 | ||
27 | .set GPIOC, 0xC80D0000 | ||
28 | .set GPIOD, 0xC80E0000 | ||
29 | .set CGU_PROC, 0xC80F0010 | ||
30 | .set CGU_PERI, 0xC80F0014 | ||
31 | .set CGU_DBOP, 0xC80F0038 | ||
32 | .set CCU_IO, 0xC810000C | ||
33 | .set DBOP, 0xC8120000 | ||
34 | .set I2C_BASE, 0xC8070000 | ||
35 | .set I2C_DATA, 0x00 | ||
36 | .set I2C_SLAD0, 0x04 | ||
37 | .set I2C_CNTRL, 0x0c | ||
38 | .set I2C_DACNT, 0x10 | ||
39 | .set I2C_CPSR0, 0x1c | ||
40 | .set I2C_CPSR1, 0x20 | ||
41 | .set I2C_IMR, 0x24 | ||
42 | .set I2C_SR, 0x30 | ||
43 | .set I2C_SADDR, 0x44 | ||
44 | .set AS3514_I2C_ADDR, 0x46 | ||
45 | .set AS3514_IRQ_ENRD0, 0x25 | ||
46 | .set PCLK, 24000000 | ||
47 | .set I2C_CLK, 400000 | ||
48 | .set I2C_PRESCALER, ((PCLK + I2C_CLK -1) / I2C_CLK) | ||
49 | .set I2C_PRESCALER_LOW, (I2C_PRESCALER & 0xff) | ||
50 | .set I2C_PRESCALER_HIGH, (I2C_PRESCALER >> 8) | ||
51 | #if I2C_PRESCALER_HIGH > 3 | ||
52 | #error i2c prescaler too big! | ||
53 | #endif | ||
54 | |||
55 | b start @ skip our data | ||
56 | |||
57 | /* These values are filled in by mkamsboot - don't move them from offset 0x4 */ | ||
58 | |||
59 | uclunpack_end: .word 0 /* End of the ucl_unpack function */ | ||
60 | uclunpack_size: .word 0 /* Size in bytes of the ucl_unpack function */ | ||
61 | |||
62 | ucl_of_end: .word 0 /* End of the ucl-compressed OF image */ | ||
63 | ucl_of_size: .word 0 /* Size in bytes of the compressed OF image */ | ||
64 | |||
65 | ucl_rb_end: .word 0 /* End of the ucl-compressed RB image */ | ||
66 | ucl_rb_size: .word 0 /* Size in bytes of the compressed RB image */ | ||
67 | |||
68 | ucl_dest: .word 0 /* End of our destination buffer (end of memory) */ | ||
69 | |||
70 | start: | ||
71 | /* First copy the UCL unpack function to the end of RAM */ | ||
72 | ldr r0, uclunpack_end /* Source */ | ||
73 | ldr r1, uclunpack_size /* Source length */ | ||
74 | sub r2, r0, r1 /* Source start - 1*/ | ||
75 | |||
76 | ldr r3, ucl_dest /* Destination end */ | ||
77 | |||
78 | uclcopy: | ||
79 | ldrb r4, [r0], #-1 | ||
80 | strb r4, [r3], #-1 | ||
81 | cmp r2, r0 | ||
82 | bne uclcopy | ||
83 | |||
84 | /* store the new destination buffer */ | ||
85 | str r3, ucl_dest | ||
86 | |||
87 | /* enable gpio clock */ | ||
88 | ldr r0, =CGU_PERI | ||
89 | ldr r1, [r0] | ||
90 | orr r1, r1, #(1<<16) | ||
91 | str r1, [r0] | ||
92 | |||
93 | /* Here are model specific tests for dual boot (test left button) */ | ||
94 | |||
95 | #ifdef SANSA_CLIP | ||
96 | .set row, (1<<5) /* enable output on C5 */ | ||
97 | .set col, (1<<0) /* read keyscan column B0 */ | ||
98 | |||
99 | ldr r0, =GPIOC | ||
100 | mov r1, #row | ||
101 | str r1, [r0, #0x400] | ||
102 | str r1, [r0, #(4*row)] | ||
103 | |||
104 | ldr r0, =GPIOB | ||
105 | mov r1, #0 | ||
106 | str r1, [r0, #0x400] | ||
107 | ldr r1, [r0, #(4*col)] | ||
108 | |||
109 | cmp r1, #0 | ||
110 | bne boot_of | ||
111 | #elif defined(SANSA_CLIPV2) | ||
112 | .set row, (1<<4) /* enable output on D4 */ | ||
113 | .set col, (1<<0) /* read keyscan column D0 */ | ||
114 | |||
115 | ldr r0, =CCU_IO | ||
116 | ldr r1, [r0] | ||
117 | bic r1, r1, #(3<<2) @ XPD works as general purpose IO | ||
118 | str r1, [r0] | ||
119 | |||
120 | ldr r0, =GPIOD | ||
121 | mov r1, #((1<<5)|(1<<4)|(1<<3)) /* all rows as output */ | ||
122 | str r1, [r0, #0x400] | ||
123 | |||
124 | /* all rows high */ | ||
125 | mov r1, #(1<<3) | ||
126 | str r1, [r0, #(4*(1<<3))] | ||
127 | mov r1, #(1<<4) | ||
128 | str r1, [r0, #(4*(1<<4))] | ||
129 | mov r1, #(1<<5) | ||
130 | str r1, [r0, #(4*(1<<5))] | ||
131 | |||
132 | mov r1, #0 /* button row low */ | ||
133 | str r1, [r0, #(4*row)] | ||
134 | |||
135 | mov r1, #5 /* small delay */ | ||
136 | 1: subs r1, r1, #1 | ||
137 | bne 1b | ||
138 | |||
139 | ldr r1, [r0, #(4*col)] | ||
140 | |||
141 | cmp r1, #0 | ||
142 | beq boot_of | ||
143 | #elif defined(SANSA_E200V2) || defined(SANSA_FUZE) | ||
144 | ldr r0, =GPIOC | ||
145 | mov r1, #0 | ||
146 | str r1, [r0, #0x400] | ||
147 | ldr r1, [r0, #0x20] /* read pin C3 */ | ||
148 | |||
149 | cmp r1, #0 /* C3 = #0 means button pressed */ | ||
150 | beq boot_of | ||
151 | |||
152 | #elif defined(SANSA_FUZEV2) | ||
153 | ldr r0, =GPIOC | ||
154 | mov r1, #0 | ||
155 | str r1, [r0, #0x400] | ||
156 | ldr r1, [r0, #0x20] /* read pin C3 */ | ||
157 | |||
158 | cmp r1, #0 /* C3 != #0 means button pressed */ | ||
159 | bne boot_of | ||
160 | |||
161 | #elif defined(SANSA_CLIPPLUS) | ||
162 | @ read pins | ||
163 | ldr r0, =GPIOC | ||
164 | ldr r1, [r0, #4*(1<<3)] @ read pin C3 "|<<" | ||
165 | |||
166 | ldr r0, =GPIOA | ||
167 | ldr r2, [r0, #4*(1<<1)] @ read pin A1 "Home" | ||
168 | |||
169 | orr r2, r2, r1 @ c3 || A1 | ||
170 | |||
171 | cmp r2, #0 @ test input from pins | ||
172 | bne boot_of @ branch directly to OF if either pin high | ||
173 | |||
174 | #elif defined(SANSA_CLIPZIP) | ||
175 | @ read pins | ||
176 | ldr r0, =GPIOA | ||
177 | ldr r1, [r0, #4*(1<<6)] @ read GPIO A6 "vol-" | ||
178 | |||
179 | cmp r1, #0 @ test input from pins | ||
180 | bne boot_of @ branch directly to OF if either pin high | ||
181 | |||
182 | ldr r0, =GPIOC | ||
183 | |||
184 | ldr r1, [r0, #0x400] | ||
185 | orr r1, r1, #((1<<1)|(1<<2)) @ output | ||
186 | bic r1, r1, #(1<<5) @ input | ||
187 | str r1, [r0, #0x400] | ||
188 | |||
189 | mov r1, #0 | ||
190 | str r1, [r0, #4*(1<<1)] @ zero C1 | ||
191 | mov r1, #(1<<2) | ||
192 | str r1, [r0, #4*(1<<2)] @ set C2 | ||
193 | |||
194 | mov r1, #50 /* small delay */ | ||
195 | 1: subs r1, r1, #1 | ||
196 | bne 1b | ||
197 | |||
198 | ldr r1, [r0, #4*(1<<5)] @ read C5 = left | ||
199 | |||
200 | cmp r1, #0 | ||
201 | bne boot_of | ||
202 | |||
203 | #elif defined(SANSA_C200V2) | ||
204 | .set BUTTON_LEFT, (1<< 2) | ||
205 | .set BUTTON_DOWN, (1<< 3) | ||
206 | .set BUTTON_SELECT, (1<< 4) | ||
207 | .set BUTTON_UP, (1<< 5) | ||
208 | .set BUTTON_RIGHT, (1<< 6) | ||
209 | .set BUTTON_HOLD, (1<<12) | ||
210 | |||
211 | ldr r0, =CGU_DBOP | ||
212 | mov r1, #(1<<3) @ DBOP freq = PCLK, clock enabled | ||
213 | str r1, [r0] | ||
214 | |||
215 | @ AFSEL needs to be set for this to work | ||
216 | ldr r2, =GPIOB | ||
217 | mov r1, #0xc | ||
218 | str r1, [r2, #0x420] @ GPIOB_AFSEL | ||
219 | ldr r2, =GPIOC | ||
220 | mov r1, #0xff | ||
221 | str r1, [r2, #0x420] @ GPIOC_AFSEL | ||
222 | |||
223 | ldr r0, =DBOP | ||
224 | @ TIMPOL doesn't matter here since we don't need | ||
225 | @ the control signals. | ||
226 | |||
227 | @ 16 bit data width | ||
228 | @ enable write | ||
229 | @ tri-state output | ||
230 | ldr r1, =0x00091000 | ||
231 | str r1, [r0, #8] @ DBOP_CTRL | ||
232 | |||
233 | ldr r1, =0xf0ff @ precharge | ||
234 | str r1, [r0, #0x10] @ DBOP_DOUT | ||
235 | |||
236 | 2: ldr r1, [r0, #0xc] @ DOBP_STAT | ||
237 | ands r1, r1, #(1<<10) | ||
238 | beq 2b @ make sure fifo is empty | ||
239 | |||
240 | @ 16 bit data width | ||
241 | @ start read | ||
242 | @ tri-state output | ||
243 | @ strobe time 31 | ||
244 | ldr r1, =0x0008901f | ||
245 | str r1, [r0, #8] @ DBOP_CTRL | ||
246 | |||
247 | 3: ldr r1, [r0, #0xc] @ DOBP_STAT | ||
248 | ands r1, r1, #(1<<16) | ||
249 | beq 3b @ wait for valid data | ||
250 | |||
251 | ldrh r1, [r0, #0x14] @ DBOP_DIN | ||
252 | |||
253 | tst r1, #BUTTON_LEFT @ boot of? | ||
254 | beq boot_of | ||
255 | #elif defined(SANSA_M200V4) | ||
256 | .set row, (1<<5) /* enable output on A5 */ | ||
257 | .set col, (1<<0) /* read keyscan column A0 */ | ||
258 | |||
259 | ldr r0, =GPIOA | ||
260 | mov r1, #row | ||
261 | str r1, [r0, #0x400] | ||
262 | str r1, [r0, #(4*row)] | ||
263 | |||
264 | ldr r2, [r0, #(4*col)] | ||
265 | |||
266 | /* check value read (1 means button pressed) */ | ||
267 | cmp r2, #0 | ||
268 | bne boot_of | ||
269 | #else | ||
270 | #error No target-specific key check defined! | ||
271 | #endif | ||
272 | |||
273 | /* The dualboot button was not held, so we boot rockbox */ | ||
274 | ldr r0, ucl_rb_end /* Address of compressed image */ | ||
275 | ldr r1, ucl_rb_size /* Compressed size */ | ||
276 | b decompress | ||
277 | |||
278 | boot_of: | ||
279 | ldr r0, ucl_of_end /* Address of compressed image */ | ||
280 | ldr r1, ucl_of_size /* Compressed size */ | ||
281 | |||
282 | |||
283 | decompress: | ||
284 | /* At this point: */ | ||
285 | /* r0 = source_end for UCL image to copy */ | ||
286 | /* r1 = size of UCL image to copy */ | ||
287 | |||
288 | ldr r3, ucl_dest | ||
289 | add r5, r3, #2 /* r5 is entry point of copy of uclunpack */ | ||
290 | /* function, plus one (for thumb mode */ | ||
291 | |||
292 | sub r4, r3, r1 /* r4 := destination_start - 1 */ | ||
293 | |||
294 | fw_copy: | ||
295 | ldrb r2, [r0], #-1 | ||
296 | strb r2, [r3], #-1 | ||
297 | cmp r3, r4 /* Stop when we reached dest_start-1 */ | ||
298 | bne fw_copy | ||
299 | |||
300 | /* Call the ucl decompress function, which will branch to 0x0 */ | ||
301 | /* on completion */ | ||
302 | add r0, r3, #1 /* r0 := Start of compressed image */ | ||
303 | /* r1 already contains compressed size */ | ||
304 | mov r2, #0 /* r2 := Destination for unpacking */ | ||
305 | bx r5 /* Branch to uclunpack, switching to thumb */ | ||
306 | |||
307 | /* never reached : uclunpack will branch to the reset vector (0x0) */ | ||
diff --git a/utils/mkamsboot/dualboot/nrv2e_d8.S b/utils/mkamsboot/dualboot/nrv2e_d8.S new file mode 100644 index 0000000000..d24fb94b2a --- /dev/null +++ b/utils/mkamsboot/dualboot/nrv2e_d8.S | |||
@@ -0,0 +1,198 @@ | |||
1 | /* arm_nrv2e_d8.S -- ARM decompressor for NRV2E | ||
2 | |||
3 | This file is part of the UPX executable compressor. | ||
4 | |||
5 | Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer | ||
6 | Copyright (C) 1996-2008 Laszlo Molnar | ||
7 | Copyright (C) 2000-2008 John F. Reiser | ||
8 | All Rights Reserved. | ||
9 | |||
10 | UPX and the UCL library are free software; you can redistribute them | ||
11 | and/or modify them under the terms of the GNU General Public License as | ||
12 | published by the Free Software Foundation; either version 2 of | ||
13 | the License, or (at your option) any later version. | ||
14 | |||
15 | This program is distributed in the hope that it will be useful, | ||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | GNU General Public License for more details. | ||
19 | |||
20 | You should have received a copy of the GNU General Public License | ||
21 | along with this program; see the file COPYING. | ||
22 | If not, write to the Free Software Foundation, Inc., | ||
23 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
24 | |||
25 | Markus F.X.J. Oberhumer Laszlo Molnar | ||
26 | <markus@oberhumer.com> <ml1050@users.sourceforge.net> | ||
27 | |||
28 | John F. Reiser | ||
29 | <jreiser@users.sourceforge.net> | ||
30 | */ | ||
31 | #define SAFE 0 /* 1 for src+dst bounds checking: cost 40 bytes */ | ||
32 | |||
33 | #define src r0 | ||
34 | #define len r1 /* overlaps 'cnt' */ | ||
35 | #define dst r2 | ||
36 | #define tmp r3 | ||
37 | #define bits r4 | ||
38 | #define off r5 | ||
39 | #define wrnk r6 /* 0x500 M2_MAX_OFFSET before "wrinkle" */ | ||
40 | #define srclim r7 | ||
41 | #if 1==SAFE /*{*/ | ||
42 | #define dstlim r12 | ||
43 | #endif /*}*/ | ||
44 | |||
45 | #define cnt r1 /* overlaps 'len' while reading an offset */ | ||
46 | |||
47 | #if 1==SAFE /*{*/ | ||
48 | #define CHECK_SRC cmp src,srclim; bhs bad_src_n2e | ||
49 | #define CHECK_DST cmp dst,dstlim; bhs bad_dst_n2e | ||
50 | #else /*}{*/ | ||
51 | #define CHECK_SRC /*empty*/ | ||
52 | #define CHECK_DST /*empty*/ | ||
53 | #endif /*}*/ | ||
54 | |||
55 | #if 0 /*{ DEBUG only: check newly-decompressed against original dst */ | ||
56 | #define CHECK_BYTE \ | ||
57 | push {wrnk}; \ | ||
58 | ldrb wrnk,[dst]; \ | ||
59 | cmp wrnk,tmp; beq 0f; bkpt; \ | ||
60 | 0: pop {wrnk} | ||
61 | #else /*}{*/ | ||
62 | #define CHECK_BYTE /*empty*/ | ||
63 | #endif /*}*/ | ||
64 | |||
65 | /* "mov lr,pc; bxx ..." implements conditional subroutine call | ||
66 | * | ||
67 | * NOTE: the lsb will not be set, so you MUST NOT use 'bx lr' to return, | ||
68 | * else the T bit will be cleared and processor will go in ARM state */ | ||
69 | #define GETBIT add bits,bits; mov lr,pc; beq get1_n2e | ||
70 | |||
71 | #define getnextb(reg) GETBIT; adc reg,reg | ||
72 | #define jnextb0 GETBIT; bcc | ||
73 | #define jnextb1 GETBIT; bcs | ||
74 | |||
75 | #ifndef PURE_THUMB | ||
76 | ucl_nrv2e_decompress_8: .globl ucl_nrv2e_decompress_8 @ ARM mode | ||
77 | .type ucl_nrv2e_decompress_8, %function | ||
78 | /* error = (*)(char const *src, int len_src, char *dst, int *plen_dst) | ||
79 | Actual decompressed length is stored through plen_dst. | ||
80 | For SAFE mode: at call, *plen_dst must be allowed length of output buffer. | ||
81 | */ | ||
82 | adr r12,1+.thumb_nrv2e_d8; bx r12 @ enter THUMB mode | ||
83 | #endif | ||
84 | .code 16 @ THUMB mode | ||
85 | .thumb_func | ||
86 | |||
87 | .thumb_nrv2e_d8: | ||
88 | #if 0 | ||
89 | push {r2,r3, r4,r5,r6,r7, lr} | ||
90 | #define sp_DST0 0 /* stack offset of original dst */ | ||
91 | #endif | ||
92 | add srclim,len,src @ srclim= eof_src; | ||
93 | #if 1==SAFE /*{*/ | ||
94 | ldr tmp,[r3] @ len_dst | ||
95 | add tmp,dst | ||
96 | mov dstlim,tmp | ||
97 | #endif /*}*/ | ||
98 | mov bits,#1; neg off,bits @ off= -1 initial condition | ||
99 | lsl bits,#31 @ 1<<31: refill next time | ||
100 | mov wrnk,#5 | ||
101 | lsl wrnk,#8 @ 0x500 @ nrv2e M2_MAX_OFFSET | ||
102 | b top_n2e | ||
103 | |||
104 | #if 1==SAFE /*{*/ | ||
105 | bad_dst_n2e: # return value will be 2 | ||
106 | add src,srclim,#1 | ||
107 | bad_src_n2e: # return value will be 1 | ||
108 | add src,#1 | ||
109 | #endif /*}*/ | ||
110 | eof_n2e: | ||
111 | #if 0 | ||
112 | pop {r3,r4} @ r3= orig_dst; r4= plen_dst | ||
113 | sub src,srclim @ 0 if actual src length equals expected length | ||
114 | sub dst,r3 @ actual dst length | ||
115 | str dst,[r4] | ||
116 | pop {r4,r5,r6,r7 /*,pc*/} | ||
117 | pop {r1}; bx r1 @ "pop {,pc}" fails return to ARM mode on ARMv4T | ||
118 | #else | ||
119 | mov r0, #0 | ||
120 | bx r0 /* Branch to 0x0, switch to ARM mode */ | ||
121 | #endif | ||
122 | |||
123 | get1_n2e: @ In: Carry set [from adding 0x80000000 (1<<31) to itself] | ||
124 | ldrb bits,[src] @ zero-extend next byte | ||
125 | adc bits,bits @ double and insert CarryIn as low bit | ||
126 | CHECK_SRC | ||
127 | add src,#1 | ||
128 | lsl bits,#24 @ move to top byte, and set CarryOut from old bit 8 | ||
129 | /* NOTE: the following instruction will not work on ARMv7+, because | ||
130 | * it will update the T bit and return into ARM state */ | ||
131 | mov pc,lr @ return, stay in current (THUMB) mode | ||
132 | |||
133 | lit_n2e: | ||
134 | CHECK_SRC; ldrb tmp,[src]; add src,#1 | ||
135 | CHECK_BYTE | ||
136 | CHECK_DST; strb tmp,[dst]; add dst,#1 | ||
137 | top_n2e: | ||
138 | jnextb1 lit_n2e | ||
139 | mov cnt,#1; b getoff_n2e | ||
140 | |||
141 | off_n2e: | ||
142 | sub cnt,#1 | ||
143 | getnextb(cnt) | ||
144 | getoff_n2e: | ||
145 | getnextb(cnt) | ||
146 | jnextb0 off_n2e | ||
147 | |||
148 | sub tmp,cnt,#3 @ set Carry | ||
149 | mov len,#0 @ Carry unaffected | ||
150 | blo offprev_n2e @ cnt was 2; tests Carry only | ||
151 | lsl tmp,#8 | ||
152 | CHECK_SRC; ldrb off,[src]; add src,#1 @ low 7+1 bits | ||
153 | orr off,tmp | ||
154 | mvn off,off; beq eof_n2e @ off= ~off | ||
155 | asr off,#1; bcs lenlast_n2e | ||
156 | b lenmore_n2e | ||
157 | |||
158 | offprev_n2e: | ||
159 | jnextb1 lenlast_n2e | ||
160 | lenmore_n2e: | ||
161 | mov len,#1 | ||
162 | jnextb1 lenlast_n2e | ||
163 | len_n2e: | ||
164 | getnextb(len) | ||
165 | jnextb0 len_n2e | ||
166 | add len,#6-2 | ||
167 | b gotlen_n2e | ||
168 | |||
169 | lenlast_n2e: | ||
170 | getnextb(len) @ 0,1,2,3 | ||
171 | add len,#2 | ||
172 | gotlen_n2e: @ 'cmn': add the inputs, set condition codes, discard the sum | ||
173 | cmn wrnk,off; bcs near_n2e @ within M2_MAX_OFFSET | ||
174 | add len,#1 @ too far away, so minimum match length is 3 | ||
175 | near_n2e: | ||
176 | #if 1==SAFE /*{*/ | ||
177 | ldr tmp,[sp,#sp_DST0] | ||
178 | sub tmp,dst | ||
179 | sub tmp,off; bhi bad_dst_n2e @ reaching back too far | ||
180 | |||
181 | add tmp,dst,cnt | ||
182 | cmp tmp,dstlim; bhi bad_dst_n2e @ too much output | ||
183 | #endif /*}*/ | ||
184 | ldrb tmp,[dst] @ force cacheline allocate | ||
185 | copy_n2e: | ||
186 | ldrb tmp,[dst,off] | ||
187 | CHECK_BYTE | ||
188 | strb tmp,[dst]; add dst,#1 | ||
189 | sub len,#1; bne copy_n2e | ||
190 | b top_n2e | ||
191 | |||
192 | #ifndef PURE_THUMB | ||
193 | .size ucl_nrv2e_decompress_8, .-ucl_nrv2e_decompress_8 | ||
194 | #endif | ||
195 | |||
196 | /* | ||
197 | vi:ts=8:et:nowrap | ||
198 | */ | ||