diff options
-rw-r--r-- | utils/AMS/hacking/Makefile | 35 | ||||
-rw-r--r-- | utils/AMS/hacking/extract_fw.c | 129 | ||||
-rw-r--r-- | utils/AMS/hacking/mkamsboot.c | 195 | ||||
-rw-r--r-- | utils/AMS/hacking/nrv2e_d8.S | 9 | ||||
-rw-r--r-- | utils/AMS/hacking/test.S | 31 |
5 files changed, 304 insertions, 95 deletions
diff --git a/utils/AMS/hacking/Makefile b/utils/AMS/hacking/Makefile index 7a10c20ae4..8f48d611c8 100644 --- a/utils/AMS/hacking/Makefile +++ b/utils/AMS/hacking/Makefile | |||
@@ -1,4 +1,3 @@ | |||
1 | |||
2 | # Change INFILE to point to your original firmware file | 1 | # Change INFILE to point to your original firmware file |
3 | INFILE=$(HOME)/FW/AMS/CLIP/m300a-1.1.17A.bin | 2 | INFILE=$(HOME)/FW/AMS/CLIP/m300a-1.1.17A.bin |
4 | 3 | ||
@@ -6,6 +5,8 @@ INFILE=$(HOME)/FW/AMS/CLIP/m300a-1.1.17A.bin | |||
6 | # (e.g.) m300a.bin | 5 | # (e.g.) m300a.bin |
7 | OUTFILE=patched.bin | 6 | OUTFILE=patched.bin |
8 | 7 | ||
8 | # The uclpack command | ||
9 | UCLPACK=../../../tools/uclpack | ||
9 | 10 | ||
10 | all: amsinfo $(OUTFILE) | 11 | all: amsinfo $(OUTFILE) |
11 | 12 | ||
@@ -15,6 +16,9 @@ amsinfo: amsinfo.c | |||
15 | mkamsboot: mkamsboot.c | 16 | mkamsboot: mkamsboot.c |
16 | gcc -o mkamsboot -W -Wall mkamsboot.c | 17 | gcc -o mkamsboot -W -Wall mkamsboot.c |
17 | 18 | ||
19 | extract_fw: extract_fw.c | ||
20 | gcc -o extract_fw -W -Wall extract_fw.c | ||
21 | |||
18 | # Rules for our test ARM application - assemble, link, then extract | 22 | # Rules for our test ARM application - assemble, link, then extract |
19 | # the binary code | 23 | # the binary code |
20 | 24 | ||
@@ -22,13 +26,34 @@ test.o: test.S | |||
22 | arm-elf-as -o test.o test.S | 26 | arm-elf-as -o test.o test.S |
23 | 27 | ||
24 | test.elf: test.o | 28 | test.elf: test.o |
25 | arm-elf-ld -e 0 -o test.elf test.o | 29 | arm-elf-ld -e 0 -Ttext=0 -o test.elf test.o |
26 | 30 | ||
27 | test.bin: test.elf | 31 | test.bin: test.elf |
28 | arm-elf-objcopy -O binary test.elf test.bin | 32 | arm-elf-objcopy -O binary test.elf test.bin |
29 | 33 | ||
30 | $(OUTFILE): mkamsboot test.bin $(INFILE) | 34 | # Rules for the ucl unpack function - this is inserted in the padding at |
31 | ./mkamsboot $(INFILE) test.bin $(OUTFILE) | 35 | # the end of the original firmware block |
36 | nrv2e_d8.o: nrv2e_d8.S | ||
37 | arm-elf-gcc -DPURE_THUMB -c -o nrv2e_d8.o nrv2e_d8.S | ||
38 | |||
39 | # NOTE: this function has no absolute references, so the link address (-e) | ||
40 | # is irrelevant. We just link at address 0. | ||
41 | nrv2e_d8.elf: nrv2e_d8.o | ||
42 | arm-elf-ld -e 0 -Ttext=0 -o nrv2e_d8.elf nrv2e_d8.o | ||
43 | |||
44 | nrv2e_d8.bin: nrv2e_d8.elf | ||
45 | arm-elf-objcopy -O binary nrv2e_d8.elf nrv2e_d8.bin | ||
46 | |||
47 | firmware_block.ucl: firmware_block.bin | ||
48 | $(UCLPACK) --best --2e firmware_block.bin firmware_block.ucl | ||
49 | |||
50 | firmware_block.bin: $(INFILE) extract_fw | ||
51 | ./extract_fw $(INFILE) firmware_block.bin | ||
52 | |||
53 | $(OUTFILE): mkamsboot firmware_block.ucl test.bin nrv2e_d8.bin $(INFILE) | ||
54 | ./mkamsboot $(INFILE) firmware_block.ucl test.bin nrv2e_d8.bin $(OUTFILE) | ||
32 | 55 | ||
33 | clean: | 56 | clean: |
34 | rm -fr amsinfo mkamsboot test.bin test.o test.elf $(OUTFILE) *~ | 57 | rm -fr amsinfo mkamsboot test.o test.elf test.bin extract_fw \ |
58 | nrv2e_d8.o nrv2e_d8.elf nrv2e_d8.bin firmware_block.bin \ | ||
59 | firmware_block.ucl $(OUTFILE) *~ | ||
diff --git a/utils/AMS/hacking/extract_fw.c b/utils/AMS/hacking/extract_fw.c new file mode 100644 index 0000000000..e91d1f8de1 --- /dev/null +++ b/utils/AMS/hacking/extract_fw.c | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | |||
3 | extract_fw.c - extract the main firmware image from a Sansa V2 (AMS) firmware | ||
4 | file | ||
5 | |||
6 | Copyright (C) Dave Chapman 2008 | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA | ||
21 | |||
22 | */ | ||
23 | |||
24 | |||
25 | #include <stdio.h> | ||
26 | #include <stdlib.h> | ||
27 | #include <stdint.h> | ||
28 | #include <sys/types.h> | ||
29 | #include <sys/stat.h> | ||
30 | #include <fcntl.h> | ||
31 | #include <unistd.h> | ||
32 | #include <string.h> | ||
33 | |||
34 | |||
35 | /* Win32 compatibility */ | ||
36 | #ifndef O_BINARY | ||
37 | #define O_BINARY 0 | ||
38 | #endif | ||
39 | |||
40 | |||
41 | static off_t filesize(int fd) { | ||
42 | struct stat buf; | ||
43 | |||
44 | if (fstat(fd,&buf) < 0) { | ||
45 | perror("[ERR] Checking filesize of input file"); | ||
46 | return -1; | ||
47 | } else { | ||
48 | return(buf.st_size); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | static uint32_t get_uint32le(unsigned char* p) | ||
53 | { | ||
54 | return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); | ||
55 | } | ||
56 | |||
57 | void usage(void) | ||
58 | { | ||
59 | printf("Usage: extract_fw <firmware file> <output file>\n"); | ||
60 | |||
61 | exit(1); | ||
62 | } | ||
63 | |||
64 | int main(int argc, char* argv[]) | ||
65 | { | ||
66 | char *infile, *outfile; | ||
67 | int fdin, fdout; | ||
68 | off_t len; | ||
69 | uint32_t n; | ||
70 | unsigned char* buf; | ||
71 | uint32_t firmware_size; | ||
72 | |||
73 | if(argc != 3) { | ||
74 | usage(); | ||
75 | } | ||
76 | |||
77 | infile = argv[1]; | ||
78 | outfile = argv[2]; | ||
79 | |||
80 | /* Open the firmware file */ | ||
81 | fdin = open(infile,O_RDONLY|O_BINARY); | ||
82 | |||
83 | if (fdin < 0) { | ||
84 | fprintf(stderr,"[ERR] Could not open %s for reading\n",infile); | ||
85 | return 1; | ||
86 | } | ||
87 | |||
88 | if ((len = filesize(fdin)) < 0) | ||
89 | return 1; | ||
90 | |||
91 | /* We will need no more memory than the total size plus the bootloader size | ||
92 | padded to a boundary */ | ||
93 | if ((buf = malloc(len)) == NULL) { | ||
94 | fprintf(stderr,"[ERR] Could not allocate buffer for input file (%d bytes)\n",(int)len); | ||
95 | return 1; | ||
96 | } | ||
97 | |||
98 | n = read(fdin, buf, len); | ||
99 | |||
100 | if (n != (uint32_t)len) { | ||
101 | fprintf(stderr,"[ERR] Could not read firmware file\n"); | ||
102 | return 1; | ||
103 | } | ||
104 | |||
105 | close(fdin); | ||
106 | |||
107 | /* Get the firmware size */ | ||
108 | firmware_size = get_uint32le(&buf[0x0c]); | ||
109 | |||
110 | fdout = open(outfile, O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666); | ||
111 | |||
112 | if (fdout < 0) { | ||
113 | fprintf(stderr,"[ERR] Could not open %s for writing\n",outfile); | ||
114 | return 1; | ||
115 | } | ||
116 | |||
117 | n = write(fdout, buf + 0x400, firmware_size); | ||
118 | |||
119 | if (n != (uint32_t)firmware_size) { | ||
120 | fprintf(stderr,"[ERR] Could not write firmware block\n"); | ||
121 | return 1; | ||
122 | } | ||
123 | |||
124 | /* Clean up */ | ||
125 | close(fdout); | ||
126 | free(buf); | ||
127 | |||
128 | return 0; | ||
129 | } | ||
diff --git a/utils/AMS/hacking/mkamsboot.c b/utils/AMS/hacking/mkamsboot.c index 30ca66e43b..ea434bc893 100644 --- a/utils/AMS/hacking/mkamsboot.c +++ b/utils/AMS/hacking/mkamsboot.c | |||
@@ -26,26 +26,33 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA | |||
26 | 26 | ||
27 | Insert a Rockbox bootloader into an AMS original firmware file. | 27 | Insert a Rockbox bootloader into an AMS original firmware file. |
28 | 28 | ||
29 | The first instruction in an AMS firmware file is always of the form: | 29 | We replace the main firmware block (bytes 0x400..padded_firmware_size+0x400) |
30 | with the following: | ||
30 | 31 | ||
31 | ldr pc, [pc, #xxx] | 32 | Bytes 0..(firmware_size-ucl_size) - Our bootloader code |
33 | Bytes (firmware_size-ucl_size)..firmware_size - UCL compressed OF image | ||
34 | Bytes firmware_size..padded_firmware_size - UCL decompress function | ||
32 | 35 | ||
33 | where [pc, #xxx] contains the entry point of the firmware - e.g. 0x00000138 | 36 | mkamsboot writes the following values at offsets into our bootloader code: |
34 | 37 | ||
35 | mkamsboot appends the Rockbox bootloader to the end of the original | 38 | 0x20 - Entry point (plus 1 - for thumb mode) of the ucl_unpack function |
36 | firmware block in the firmware file and shifts the remaining contents of the firmware file to make space for it. | 39 | 0x24 - Location of the UCL compressed version of the original firmware block |
37 | 40 | ||
38 | It also replaces the contents of [pc, #xxx] with the entry point of | 41 | mkamsboot then corrects the length (to include the UCL decompress |
39 | our bootloader - i.e. the length of the original firmware block plus 4 | 42 | function) and checksum in the main firmware headers (both copies), |
40 | bytes. | 43 | creating a new legal firmware file which can be installed on the |
44 | device. | ||
41 | 45 | ||
42 | It then stores the original entry point from [pc, #xxx] in the first | 46 | Our bootloader first checks for the "dual-boot" keypress, and then either: |
43 | four bytes of the Rockbox bootloader image, which is used by the | ||
44 | bootloader to dual-boot. | ||
45 | 47 | ||
46 | Finally, mkamsboot corrects the length and checksum in the main | 48 | a) Branches to the ucl_unpack function, which will then branch to 0x0 after |
47 | firmware headers (both copies), creating a new legal firmware file | 49 | decompressing the OF. |
48 | which can be installed on the device. | 50 | |
51 | b) Continues running with our test code | ||
52 | |||
53 | This method uses no RAM outside the padded area of the original | ||
54 | firmware block - the UCL compression can happen in-place when the | ||
55 | compressed image is stored at the end of the destination buffer. | ||
49 | 56 | ||
50 | */ | 57 | */ |
51 | 58 | ||
@@ -106,35 +113,35 @@ static int calc_checksum(unsigned char* buf, uint32_t n) | |||
106 | 113 | ||
107 | void usage(void) | 114 | void usage(void) |
108 | { | 115 | { |
109 | printf("Usage: mkamsboot <firmware file> <boot file> <output file>\n"); | 116 | printf("Usage: mkamsboot <firmware file> <ucl image> <boot file> <ucl unpack file> <output file>\n"); |
110 | 117 | ||
111 | exit(1); | 118 | exit(1); |
112 | } | 119 | } |
113 | 120 | ||
114 | int main(int argc, char* argv[]) | 121 | int main(int argc, char* argv[]) |
115 | { | 122 | { |
116 | char *infile, *bootfile, *outfile; | 123 | char *infile, *uclfile, *bootfile, *uclunpackfile, *outfile; |
117 | int fdin, fdboot,fdout; | 124 | int fdin, fducl, fdboot, fduclunpack, fdout; |
118 | off_t len; | 125 | off_t len; |
119 | uint32_t n; | 126 | uint32_t n; |
120 | unsigned char* buf; | 127 | unsigned char* buf; |
121 | uint32_t ldr; | ||
122 | uint32_t origoffset; | ||
123 | uint32_t firmware_size; | 128 | uint32_t firmware_size; |
124 | uint32_t firmware_paddedsize; | 129 | uint32_t firmware_paddedsize; |
125 | uint32_t bootloader_size; | 130 | uint32_t bootloader_size; |
126 | uint32_t new_paddedsize; | 131 | uint32_t ucl_size; |
132 | uint32_t uclunpack_size; | ||
127 | uint32_t sum,filesum; | 133 | uint32_t sum,filesum; |
128 | uint32_t new_length; | ||
129 | uint32_t i; | 134 | uint32_t i; |
130 | 135 | ||
131 | if(argc != 4) { | 136 | if(argc != 6) { |
132 | usage(); | 137 | usage(); |
133 | } | 138 | } |
134 | 139 | ||
135 | infile = argv[1]; | 140 | infile = argv[1]; |
136 | bootfile = argv[2]; | 141 | uclfile = argv[2]; |
137 | outfile = argv[3]; | 142 | bootfile = argv[3]; |
143 | uclunpackfile = argv[4]; | ||
144 | outfile = argv[5]; | ||
138 | 145 | ||
139 | /* Open the bootloader file */ | 146 | /* Open the bootloader file */ |
140 | fdboot = open(bootfile, O_RDONLY|O_BINARY); | 147 | fdboot = open(bootfile, O_RDONLY|O_BINARY); |
@@ -147,6 +154,28 @@ int main(int argc, char* argv[]) | |||
147 | bootloader_size = filesize(fdboot); | 154 | bootloader_size = filesize(fdboot); |
148 | 155 | ||
149 | 156 | ||
157 | /* Open the UCL-compressed image of the firmware block */ | ||
158 | fduclunpack = open(uclunpackfile, O_RDONLY|O_BINARY); | ||
159 | if (fduclunpack < 0) | ||
160 | { | ||
161 | fprintf(stderr,"[ERR] Could not open %s for reading\n",uclunpackfile); | ||
162 | return 1; | ||
163 | } | ||
164 | |||
165 | uclunpack_size = filesize(fduclunpack); | ||
166 | |||
167 | |||
168 | /* Open the UCL-compressed image of the firmware block */ | ||
169 | fducl = open(uclfile, O_RDONLY|O_BINARY); | ||
170 | if (fducl < 0) | ||
171 | { | ||
172 | fprintf(stderr,"[ERR] Could not open %s for reading\n",uclfile); | ||
173 | return 1; | ||
174 | } | ||
175 | |||
176 | ucl_size = filesize(fducl); | ||
177 | |||
178 | |||
150 | /* Open the firmware file */ | 179 | /* Open the firmware file */ |
151 | fdin = open(infile,O_RDONLY|O_BINARY); | 180 | fdin = open(infile,O_RDONLY|O_BINARY); |
152 | 181 | ||
@@ -158,9 +187,8 @@ int main(int argc, char* argv[]) | |||
158 | if ((len = filesize(fdin)) < 0) | 187 | if ((len = filesize(fdin)) < 0) |
159 | return 1; | 188 | return 1; |
160 | 189 | ||
161 | /* We will need no more memory than the total size plus the bootloader size | 190 | /* Allocate memory for the OF image - we don't change the size */ |
162 | padded to a boundary */ | 191 | if ((buf = malloc(len)) == NULL) { |
163 | if ((buf = malloc(len + PAD_TO_BOUNDARY(bootloader_size))) == NULL) { | ||
164 | fprintf(stderr,"[ERR] Could not allocate buffer for input file (%d bytes)\n",(int)len); | 192 | fprintf(stderr,"[ERR] Could not allocate buffer for input file (%d bytes)\n",(int)len); |
165 | return 1; | 193 | return 1; |
166 | } | 194 | } |
@@ -181,91 +209,83 @@ int main(int argc, char* argv[]) | |||
181 | 209 | ||
182 | firmware_paddedsize = PAD_TO_BOUNDARY(firmware_size); | 210 | firmware_paddedsize = PAD_TO_BOUNDARY(firmware_size); |
183 | 211 | ||
184 | /* Total new size */ | 212 | fprintf(stderr,"Original firmware size - %d bytes\n",firmware_size); |
185 | new_paddedsize = PAD_TO_BOUNDARY(firmware_size + bootloader_size); | 213 | fprintf(stderr,"Padded firmware size - %d bytes\n",firmware_paddedsize); |
186 | 214 | fprintf(stderr,"Bootloader size - %d bytes\n",bootloader_size); | |
187 | /* Total new size of firmware file */ | 215 | fprintf(stderr,"UCL image size - %d bytes\n",ucl_size); |
188 | new_length = len + (new_paddedsize - firmware_paddedsize); | 216 | fprintf(stderr,"UCL unpack function size - %d bytes\n",uclunpack_size); |
217 | fprintf(stderr,"Original total size of firmware - %d bytes\n",(int)len); | ||
218 | |||
219 | /* Check we have room for our bootloader - in the future, we could UCL | ||
220 | pack this image as well if we need to. */ | ||
221 | if (bootloader_size > (firmware_size - ucl_size)) { | ||
222 | fprintf(stderr,"[ERR] Bootloader too large (%d bytes, %d available)\n", | ||
223 | bootloader_size, firmware_size - ucl_size); | ||
224 | return 1; | ||
225 | } | ||
189 | 226 | ||
190 | fprintf(stderr,"Original firmware size - 0x%08x\n",firmware_size); | 227 | /* Check we have enough room for the UCL unpack function. This |
191 | fprintf(stderr,"Padded firmware size - 0x%08x\n",firmware_paddedsize); | 228 | needs to be outside the firmware block, so if we wanted to |
192 | fprintf(stderr,"Bootloader size - 0x%08x\n",bootloader_size); | 229 | support every firmware version, we could store this function in |
193 | fprintf(stderr,"New padded size - 0x%08x\n",new_paddedsize); | 230 | the main firmware block, and then copy it to an unused part of |
194 | fprintf(stderr,"Original total size of firmware - 0x%08x\n",(int)len); | 231 | RAM. */ |
195 | fprintf(stderr,"New total size of firmware - 0x%08x\n",new_length); | 232 | if (uclunpack_size > (firmware_paddedsize - firmware_size)) { |
233 | fprintf(stderr,"[ERR] UCL unpack function too large (%d bytes, %d available)\n", | ||
234 | uclunpack_size, firmware_paddedsize - firmware_size); | ||
235 | return 1; | ||
236 | } | ||
196 | 237 | ||
197 | if (firmware_paddedsize != new_paddedsize) { | 238 | /* Zero the original firmware area - not needed, but helps debugging */ |
198 | /* We don't know how to safely increase the firmware size, so abort */ | 239 | memset(buf + 0x400, 0, firmware_size); |
199 | 240 | ||
200 | fprintf(stderr, | 241 | /* Locate our bootloader code at the start of the firmware block */ |
201 | "[ERR] Bootloader too large (%d bytes - %d bytes available), aborting.\n", | 242 | n = read(fdboot, buf + 0x400, bootloader_size); |
202 | bootloader_size, firmware_paddedsize - firmware_size); | ||
203 | 243 | ||
244 | if (n != bootloader_size) { | ||
245 | fprintf(stderr,"[ERR] Could not load bootloader file\n"); | ||
204 | return 1; | 246 | return 1; |
205 | } | 247 | } |
248 | close(fdboot); | ||
206 | 249 | ||
207 | ldr = get_uint32le(&buf[0x400]); | 250 | /* Locate the compressed image of the original firmware block at the end |
251 | of the firmware block */ | ||
252 | n = read(fducl, buf + 0x400 + firmware_size - ucl_size, ucl_size); | ||
208 | 253 | ||
209 | if ((ldr & 0xfffff000) != 0xe59ff000) { | 254 | if (n != ucl_size) { |
210 | fprintf(stderr,"[ERR] Firmware file doesn't start with an \"ldr pc, [pc, #xx]\" instruction.\n"); | 255 | fprintf(stderr,"[ERR] Could not load ucl file\n"); |
211 | return 1; | 256 | return 1; |
212 | } | 257 | } |
213 | origoffset = (ldr&0xfff) + 8; | 258 | close(fducl); |
214 | |||
215 | printf("original firmware entry point: 0x%08x\n",get_uint32le(buf + 0x400 + origoffset)); | ||
216 | printf("New entry point: 0x%08x\n", firmware_size + 4); | ||
217 | |||
218 | #if 0 | ||
219 | /* Replace the "Product: Express" string with "Rockbox" */ | ||
220 | i = 0x400 + firmware_size - 7; | ||
221 | while ((i > 0x400) && (memcmp(&buf[i],"Express",7)!=0)) | ||
222 | i--; | ||
223 | 259 | ||
224 | i = (i + 3) & ~0x3; | ||
225 | |||
226 | if (i >= 0x400) { | ||
227 | printf("Replacing \"Express\" string at offset 0x%08x\n",i); | ||
228 | memcpy(&buf[i],"Rockbox",7); | ||
229 | } else { | ||
230 | printf("Could not find \"Express\" string to replace\n"); | ||
231 | } | ||
232 | #endif | ||
233 | 260 | ||
234 | n = read(fdboot, buf + 0x400 + firmware_size, bootloader_size); | 261 | /* Locate our UCL unpack function in the padding after the firmware block */ |
262 | n = read(fduclunpack, buf + 0x400 + firmware_size, uclunpack_size); | ||
235 | 263 | ||
236 | if (n != bootloader_size) { | 264 | if (n != uclunpack_size) { |
237 | fprintf(stderr,"[ERR] Could not bootloader file\n"); | 265 | fprintf(stderr,"[ERR] Could not load uclunpack file\n"); |
238 | return 1; | 266 | return 1; |
239 | } | 267 | } |
240 | close(fdboot); | 268 | close(fduclunpack); |
241 | 269 | ||
242 | /* Replace first word of the bootloader with the original entry point */ | 270 | put_uint32le(&buf[0x420], firmware_size + 1); /* UCL unpack entry point */ |
243 | put_uint32le(buf + 0x400 + firmware_size, get_uint32le(buf + 0x400 + origoffset)); | 271 | put_uint32le(&buf[0x424], firmware_size - ucl_size); /* Location of OF */ |
244 | |||
245 | #if 1 | ||
246 | put_uint32le(buf + 0x400 + origoffset, firmware_size + 4); | ||
247 | #endif | ||
248 | 272 | ||
249 | /* Update checksum */ | 273 | /* Update checksum */ |
250 | sum = calc_checksum(buf + 0x400,firmware_size + bootloader_size); | 274 | sum = calc_checksum(buf + 0x400,firmware_size + uclunpack_size); |
251 | 275 | ||
252 | put_uint32le(&buf[0x04], sum); | 276 | put_uint32le(&buf[0x04], sum); |
253 | put_uint32le(&buf[0x204], sum); | 277 | put_uint32le(&buf[0x204], sum); |
254 | 278 | ||
255 | /* Update firmware block count */ | ||
256 | put_uint32le(&buf[0x08], new_paddedsize / 0x200); | ||
257 | put_uint32le(&buf[0x208], new_paddedsize / 0x200); | ||
258 | |||
259 | /* Update firmware size */ | 279 | /* Update firmware size */ |
260 | put_uint32le(&buf[0x0c], firmware_size + bootloader_size); | 280 | put_uint32le(&buf[0x0c], firmware_size + uclunpack_size); |
261 | put_uint32le(&buf[0x20c], firmware_size + bootloader_size); | 281 | put_uint32le(&buf[0x20c], firmware_size + uclunpack_size); |
262 | 282 | ||
263 | /* Update the whole-file checksum */ | 283 | /* Update the whole-file checksum */ |
264 | filesum = 0; | 284 | filesum = 0; |
265 | for (i=0;i < new_length - 4; i+=4) | 285 | for (i=0;i < (unsigned)len - 4; i+=4) |
266 | filesum += get_uint32le(&buf[i]); | 286 | filesum += get_uint32le(&buf[i]); |
267 | 287 | ||
268 | put_uint32le(buf + new_length - 4, filesum); | 288 | put_uint32le(buf + len - 4, filesum); |
269 | 289 | ||
270 | 290 | ||
271 | /* Write the new firmware */ | 291 | /* Write the new firmware */ |
@@ -276,7 +296,12 @@ int main(int argc, char* argv[]) | |||
276 | return 1; | 296 | return 1; |
277 | } | 297 | } |
278 | 298 | ||
279 | write(fdout, buf, new_length); | 299 | n = write(fdout, buf, len); |
300 | |||
301 | if (n != (unsigned)len) { | ||
302 | fprintf(stderr,"[ERR] Could not write firmware file\n"); | ||
303 | return 1; | ||
304 | } | ||
280 | 305 | ||
281 | close(fdout); | 306 | close(fdout); |
282 | 307 | ||
diff --git a/utils/AMS/hacking/nrv2e_d8.S b/utils/AMS/hacking/nrv2e_d8.S index 88df64a58f..89cb76dead 100644 --- a/utils/AMS/hacking/nrv2e_d8.S +++ b/utils/AMS/hacking/nrv2e_d8.S | |||
@@ -77,13 +77,15 @@ ucl_nrv2e_decompress_8: .globl ucl_nrv2e_decompress_8 @ ARM mode | |||
77 | For SAFE mode: at call, *plen_dst must be allowed length of output buffer. | 77 | For SAFE mode: at call, *plen_dst must be allowed length of output buffer. |
78 | */ | 78 | */ |
79 | adr r12,1+.thumb_nrv2e_d8; bx r12 @ enter THUMB mode | 79 | adr r12,1+.thumb_nrv2e_d8; bx r12 @ enter THUMB mode |
80 | #endif | ||
80 | .code 16 @ THUMB mode | 81 | .code 16 @ THUMB mode |
81 | .thumb_func | 82 | .thumb_func |
82 | #endif | ||
83 | 83 | ||
84 | .thumb_nrv2e_d8: | 84 | .thumb_nrv2e_d8: |
85 | #if 0 | ||
85 | push {r2,r3, r4,r5,r6,r7, lr} | 86 | push {r2,r3, r4,r5,r6,r7, lr} |
86 | #define sp_DST0 0 /* stack offset of original dst */ | 87 | #define sp_DST0 0 /* stack offset of original dst */ |
88 | #endif | ||
87 | add srclim,len,src @ srclim= eof_src; | 89 | add srclim,len,src @ srclim= eof_src; |
88 | #if 1==SAFE /*{*/ | 90 | #if 1==SAFE /*{*/ |
89 | ldr tmp,[r3] @ len_dst | 91 | ldr tmp,[r3] @ len_dst |
@@ -103,12 +105,17 @@ bad_src_n2e: # return value will be 1 | |||
103 | add src,#1 | 105 | add src,#1 |
104 | #endif /*}*/ | 106 | #endif /*}*/ |
105 | eof_n2e: | 107 | eof_n2e: |
108 | #if 0 | ||
106 | pop {r3,r4} @ r3= orig_dst; r4= plen_dst | 109 | pop {r3,r4} @ r3= orig_dst; r4= plen_dst |
107 | sub src,srclim @ 0 if actual src length equals expected length | 110 | sub src,srclim @ 0 if actual src length equals expected length |
108 | sub dst,r3 @ actual dst length | 111 | sub dst,r3 @ actual dst length |
109 | str dst,[r4] | 112 | str dst,[r4] |
110 | pop {r4,r5,r6,r7 /*,pc*/} | 113 | pop {r4,r5,r6,r7 /*,pc*/} |
111 | pop {r1}; bx r1 @ "pop {,pc}" fails return to ARM mode on ARMv4T | 114 | pop {r1}; bx r1 @ "pop {,pc}" fails return to ARM mode on ARMv4T |
115 | #else | ||
116 | mov r0, #0 | ||
117 | bx r0 /* Branch to 0x0, switch to ARM mode */ | ||
118 | #endif | ||
112 | 119 | ||
113 | get1_n2e: @ In: Carry set [from adding 0x80000000 (1<<31) to itself] | 120 | get1_n2e: @ In: Carry set [from adding 0x80000000 (1<<31) to itself] |
114 | ldrb bits,[src] @ zero-extend next byte | 121 | ldrb bits,[src] @ zero-extend next byte |
diff --git a/utils/AMS/hacking/test.S b/utils/AMS/hacking/test.S index 52f54bdaf6..d4bb2143bb 100644 --- a/utils/AMS/hacking/test.S +++ b/utils/AMS/hacking/test.S | |||
@@ -1,11 +1,34 @@ | |||
1 | /* int ucl_nrv2e_decompress_8(const unsigned char *src, unsigned char *dst, | ||
2 | unsigned long *dst_len) */ | ||
1 | 3 | ||
2 | /* This value is filled in by mkamsboot */ | 4 | .text |
3 | originalentry: .word 0 | 5 | .global ucl_nrv2e_decompress_8 |
4 | 6 | ||
7 | |||
8 | /* Vectors */ | ||
9 | ldr pc, =start | ||
10 | .word 0 | ||
11 | .word 0 | ||
12 | .word 0 | ||
13 | .word 0 | ||
14 | .word 0 | ||
15 | .word 0 | ||
16 | .word 0 | ||
17 | |||
18 | /* These values are filled in by mkamsboot - don't move them from offset 0x20 */ | ||
19 | ucl_unpack: .word 0 /* Entry point (plus 1 - for thumb) of ucl_unpack */ | ||
20 | ucl_start: .word 0 /* Start of the ucl-compressed OF image */ | ||
21 | |||
22 | |||
23 | start: | ||
5 | /* A delay loop - just to prove we're running */ | 24 | /* A delay loop - just to prove we're running */ |
6 | mov r1, #0x500000 /* Approximately 5 seconds */ | 25 | mov r1, #0x500000 /* Approximately 5 seconds */ |
7 | loop: subs r1, r1, #1 | 26 | loop: subs r1, r1, #1 |
8 | bne loop | 27 | bne loop |
9 | 28 | ||
10 | /* Now branch back to the original firmware's entry point */ | 29 | /* Call the ucl decompress function, which will branch to 0x0 |
11 | ldr pc, originalentry | 30 | on completion */ |
31 | ldr r0, ucl_start /* Source */ | ||
32 | mov r1, #0 /* Destination */ | ||
33 | ldr r2, ucl_unpack | ||
34 | bx r2 | ||